cap_audit.c (8294B)
1// SPDX-License-Identifier: GPL-2.0 2/* 3 * cap_audit.c - audit iommu capabilities for boot time and hot plug 4 * 5 * Copyright (C) 2021 Intel Corporation 6 * 7 * Author: Kyung Min Park <kyung.min.park@intel.com> 8 * Lu Baolu <baolu.lu@linux.intel.com> 9 */ 10 11#define pr_fmt(fmt) "DMAR: " fmt 12 13#include <linux/intel-iommu.h> 14#include "cap_audit.h" 15 16static u64 intel_iommu_cap_sanity; 17static u64 intel_iommu_ecap_sanity; 18 19static inline void check_irq_capabilities(struct intel_iommu *a, 20 struct intel_iommu *b) 21{ 22 CHECK_FEATURE_MISMATCH(a, b, cap, pi_support, CAP_PI_MASK); 23 CHECK_FEATURE_MISMATCH(a, b, ecap, eim_support, ECAP_EIM_MASK); 24} 25 26static inline void check_dmar_capabilities(struct intel_iommu *a, 27 struct intel_iommu *b) 28{ 29 MINIMAL_FEATURE_IOMMU(b, cap, CAP_MAMV_MASK); 30 MINIMAL_FEATURE_IOMMU(b, cap, CAP_NFR_MASK); 31 MINIMAL_FEATURE_IOMMU(b, cap, CAP_SLLPS_MASK); 32 MINIMAL_FEATURE_IOMMU(b, cap, CAP_FRO_MASK); 33 MINIMAL_FEATURE_IOMMU(b, cap, CAP_MGAW_MASK); 34 MINIMAL_FEATURE_IOMMU(b, cap, CAP_SAGAW_MASK); 35 MINIMAL_FEATURE_IOMMU(b, cap, CAP_NDOMS_MASK); 36 MINIMAL_FEATURE_IOMMU(b, ecap, ECAP_PSS_MASK); 37 MINIMAL_FEATURE_IOMMU(b, ecap, ECAP_MHMV_MASK); 38 MINIMAL_FEATURE_IOMMU(b, ecap, ECAP_IRO_MASK); 39 40 CHECK_FEATURE_MISMATCH(a, b, cap, 5lp_support, CAP_FL5LP_MASK); 41 CHECK_FEATURE_MISMATCH(a, b, cap, fl1gp_support, CAP_FL1GP_MASK); 42 CHECK_FEATURE_MISMATCH(a, b, cap, read_drain, CAP_RD_MASK); 43 CHECK_FEATURE_MISMATCH(a, b, cap, write_drain, CAP_WD_MASK); 44 CHECK_FEATURE_MISMATCH(a, b, cap, pgsel_inv, CAP_PSI_MASK); 45 CHECK_FEATURE_MISMATCH(a, b, cap, zlr, CAP_ZLR_MASK); 46 CHECK_FEATURE_MISMATCH(a, b, cap, caching_mode, CAP_CM_MASK); 47 CHECK_FEATURE_MISMATCH(a, b, cap, phmr, CAP_PHMR_MASK); 48 CHECK_FEATURE_MISMATCH(a, b, cap, plmr, CAP_PLMR_MASK); 49 CHECK_FEATURE_MISMATCH(a, b, cap, rwbf, CAP_RWBF_MASK); 50 CHECK_FEATURE_MISMATCH(a, b, cap, afl, CAP_AFL_MASK); 51 CHECK_FEATURE_MISMATCH(a, b, ecap, rps, ECAP_RPS_MASK); 52 CHECK_FEATURE_MISMATCH(a, b, ecap, smpwc, ECAP_SMPWC_MASK); 53 CHECK_FEATURE_MISMATCH(a, b, ecap, flts, ECAP_FLTS_MASK); 54 CHECK_FEATURE_MISMATCH(a, b, ecap, slts, ECAP_SLTS_MASK); 55 CHECK_FEATURE_MISMATCH(a, b, ecap, nwfs, ECAP_NWFS_MASK); 56 CHECK_FEATURE_MISMATCH(a, b, ecap, slads, ECAP_SLADS_MASK); 57 CHECK_FEATURE_MISMATCH(a, b, ecap, vcs, ECAP_VCS_MASK); 58 CHECK_FEATURE_MISMATCH(a, b, ecap, smts, ECAP_SMTS_MASK); 59 CHECK_FEATURE_MISMATCH(a, b, ecap, pds, ECAP_PDS_MASK); 60 CHECK_FEATURE_MISMATCH(a, b, ecap, dit, ECAP_DIT_MASK); 61 CHECK_FEATURE_MISMATCH(a, b, ecap, pasid, ECAP_PASID_MASK); 62 CHECK_FEATURE_MISMATCH(a, b, ecap, eafs, ECAP_EAFS_MASK); 63 CHECK_FEATURE_MISMATCH(a, b, ecap, srs, ECAP_SRS_MASK); 64 CHECK_FEATURE_MISMATCH(a, b, ecap, ers, ECAP_ERS_MASK); 65 CHECK_FEATURE_MISMATCH(a, b, ecap, prs, ECAP_PRS_MASK); 66 CHECK_FEATURE_MISMATCH(a, b, ecap, nest, ECAP_NEST_MASK); 67 CHECK_FEATURE_MISMATCH(a, b, ecap, mts, ECAP_MTS_MASK); 68 CHECK_FEATURE_MISMATCH(a, b, ecap, sc_support, ECAP_SC_MASK); 69 CHECK_FEATURE_MISMATCH(a, b, ecap, pass_through, ECAP_PT_MASK); 70 CHECK_FEATURE_MISMATCH(a, b, ecap, dev_iotlb_support, ECAP_DT_MASK); 71 CHECK_FEATURE_MISMATCH(a, b, ecap, qis, ECAP_QI_MASK); 72 CHECK_FEATURE_MISMATCH(a, b, ecap, coherent, ECAP_C_MASK); 73} 74 75static int cap_audit_hotplug(struct intel_iommu *iommu, enum cap_audit_type type) 76{ 77 bool mismatch = false; 78 u64 old_cap = intel_iommu_cap_sanity; 79 u64 old_ecap = intel_iommu_ecap_sanity; 80 81 if (type == CAP_AUDIT_HOTPLUG_IRQR) { 82 CHECK_FEATURE_MISMATCH_HOTPLUG(iommu, cap, pi_support, CAP_PI_MASK); 83 CHECK_FEATURE_MISMATCH_HOTPLUG(iommu, ecap, eim_support, ECAP_EIM_MASK); 84 goto out; 85 } 86 87 CHECK_FEATURE_MISMATCH_HOTPLUG(iommu, cap, 5lp_support, CAP_FL5LP_MASK); 88 CHECK_FEATURE_MISMATCH_HOTPLUG(iommu, cap, fl1gp_support, CAP_FL1GP_MASK); 89 CHECK_FEATURE_MISMATCH_HOTPLUG(iommu, cap, read_drain, CAP_RD_MASK); 90 CHECK_FEATURE_MISMATCH_HOTPLUG(iommu, cap, write_drain, CAP_WD_MASK); 91 CHECK_FEATURE_MISMATCH_HOTPLUG(iommu, cap, pgsel_inv, CAP_PSI_MASK); 92 CHECK_FEATURE_MISMATCH_HOTPLUG(iommu, cap, zlr, CAP_ZLR_MASK); 93 CHECK_FEATURE_MISMATCH_HOTPLUG(iommu, cap, caching_mode, CAP_CM_MASK); 94 CHECK_FEATURE_MISMATCH_HOTPLUG(iommu, cap, phmr, CAP_PHMR_MASK); 95 CHECK_FEATURE_MISMATCH_HOTPLUG(iommu, cap, plmr, CAP_PLMR_MASK); 96 CHECK_FEATURE_MISMATCH_HOTPLUG(iommu, cap, rwbf, CAP_RWBF_MASK); 97 CHECK_FEATURE_MISMATCH_HOTPLUG(iommu, cap, afl, CAP_AFL_MASK); 98 CHECK_FEATURE_MISMATCH_HOTPLUG(iommu, ecap, rps, ECAP_RPS_MASK); 99 CHECK_FEATURE_MISMATCH_HOTPLUG(iommu, ecap, smpwc, ECAP_SMPWC_MASK); 100 CHECK_FEATURE_MISMATCH_HOTPLUG(iommu, ecap, flts, ECAP_FLTS_MASK); 101 CHECK_FEATURE_MISMATCH_HOTPLUG(iommu, ecap, slts, ECAP_SLTS_MASK); 102 CHECK_FEATURE_MISMATCH_HOTPLUG(iommu, ecap, nwfs, ECAP_NWFS_MASK); 103 CHECK_FEATURE_MISMATCH_HOTPLUG(iommu, ecap, slads, ECAP_SLADS_MASK); 104 CHECK_FEATURE_MISMATCH_HOTPLUG(iommu, ecap, vcs, ECAP_VCS_MASK); 105 CHECK_FEATURE_MISMATCH_HOTPLUG(iommu, ecap, smts, ECAP_SMTS_MASK); 106 CHECK_FEATURE_MISMATCH_HOTPLUG(iommu, ecap, pds, ECAP_PDS_MASK); 107 CHECK_FEATURE_MISMATCH_HOTPLUG(iommu, ecap, dit, ECAP_DIT_MASK); 108 CHECK_FEATURE_MISMATCH_HOTPLUG(iommu, ecap, pasid, ECAP_PASID_MASK); 109 CHECK_FEATURE_MISMATCH_HOTPLUG(iommu, ecap, eafs, ECAP_EAFS_MASK); 110 CHECK_FEATURE_MISMATCH_HOTPLUG(iommu, ecap, srs, ECAP_SRS_MASK); 111 CHECK_FEATURE_MISMATCH_HOTPLUG(iommu, ecap, ers, ECAP_ERS_MASK); 112 CHECK_FEATURE_MISMATCH_HOTPLUG(iommu, ecap, prs, ECAP_PRS_MASK); 113 CHECK_FEATURE_MISMATCH_HOTPLUG(iommu, ecap, nest, ECAP_NEST_MASK); 114 CHECK_FEATURE_MISMATCH_HOTPLUG(iommu, ecap, mts, ECAP_MTS_MASK); 115 CHECK_FEATURE_MISMATCH_HOTPLUG(iommu, ecap, sc_support, ECAP_SC_MASK); 116 CHECK_FEATURE_MISMATCH_HOTPLUG(iommu, ecap, pass_through, ECAP_PT_MASK); 117 CHECK_FEATURE_MISMATCH_HOTPLUG(iommu, ecap, dev_iotlb_support, ECAP_DT_MASK); 118 CHECK_FEATURE_MISMATCH_HOTPLUG(iommu, ecap, qis, ECAP_QI_MASK); 119 CHECK_FEATURE_MISMATCH_HOTPLUG(iommu, ecap, coherent, ECAP_C_MASK); 120 121 /* Abort hot plug if the hot plug iommu feature is smaller than global */ 122 MINIMAL_FEATURE_HOTPLUG(iommu, cap, max_amask_val, CAP_MAMV_MASK, mismatch); 123 MINIMAL_FEATURE_HOTPLUG(iommu, cap, num_fault_regs, CAP_NFR_MASK, mismatch); 124 MINIMAL_FEATURE_HOTPLUG(iommu, cap, super_page_val, CAP_SLLPS_MASK, mismatch); 125 MINIMAL_FEATURE_HOTPLUG(iommu, cap, fault_reg_offset, CAP_FRO_MASK, mismatch); 126 MINIMAL_FEATURE_HOTPLUG(iommu, cap, mgaw, CAP_MGAW_MASK, mismatch); 127 MINIMAL_FEATURE_HOTPLUG(iommu, cap, sagaw, CAP_SAGAW_MASK, mismatch); 128 MINIMAL_FEATURE_HOTPLUG(iommu, cap, ndoms, CAP_NDOMS_MASK, mismatch); 129 MINIMAL_FEATURE_HOTPLUG(iommu, ecap, pss, ECAP_PSS_MASK, mismatch); 130 MINIMAL_FEATURE_HOTPLUG(iommu, ecap, max_handle_mask, ECAP_MHMV_MASK, mismatch); 131 MINIMAL_FEATURE_HOTPLUG(iommu, ecap, iotlb_offset, ECAP_IRO_MASK, mismatch); 132 133out: 134 if (mismatch) { 135 intel_iommu_cap_sanity = old_cap; 136 intel_iommu_ecap_sanity = old_ecap; 137 return -EFAULT; 138 } 139 140 return 0; 141} 142 143static int cap_audit_static(struct intel_iommu *iommu, enum cap_audit_type type) 144{ 145 struct dmar_drhd_unit *d; 146 struct intel_iommu *i; 147 int rc = 0; 148 149 rcu_read_lock(); 150 if (list_empty(&dmar_drhd_units)) 151 goto out; 152 153 for_each_active_iommu(i, d) { 154 if (!iommu) { 155 intel_iommu_ecap_sanity = i->ecap; 156 intel_iommu_cap_sanity = i->cap; 157 iommu = i; 158 continue; 159 } 160 161 if (type == CAP_AUDIT_STATIC_DMAR) 162 check_dmar_capabilities(iommu, i); 163 else 164 check_irq_capabilities(iommu, i); 165 } 166 167 /* 168 * If the system is sane to support scalable mode, either SL or FL 169 * should be sane. 170 */ 171 if (intel_cap_smts_sanity() && 172 !intel_cap_flts_sanity() && !intel_cap_slts_sanity()) 173 rc = -EOPNOTSUPP; 174 175out: 176 rcu_read_unlock(); 177 return rc; 178} 179 180int intel_cap_audit(enum cap_audit_type type, struct intel_iommu *iommu) 181{ 182 switch (type) { 183 case CAP_AUDIT_STATIC_DMAR: 184 case CAP_AUDIT_STATIC_IRQR: 185 return cap_audit_static(iommu, type); 186 case CAP_AUDIT_HOTPLUG_DMAR: 187 case CAP_AUDIT_HOTPLUG_IRQR: 188 return cap_audit_hotplug(iommu, type); 189 default: 190 break; 191 } 192 193 return -EFAULT; 194} 195 196bool intel_cap_smts_sanity(void) 197{ 198 return ecap_smts(intel_iommu_ecap_sanity); 199} 200 201bool intel_cap_pasid_sanity(void) 202{ 203 return ecap_pasid(intel_iommu_ecap_sanity); 204} 205 206bool intel_cap_nest_sanity(void) 207{ 208 return ecap_nest(intel_iommu_ecap_sanity); 209} 210 211bool intel_cap_flts_sanity(void) 212{ 213 return ecap_flts(intel_iommu_ecap_sanity); 214} 215 216bool intel_cap_slts_sanity(void) 217{ 218 return ecap_slts(intel_iommu_ecap_sanity); 219}