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 16 static u64 intel_iommu_cap_sanity; 17 static u64 intel_iommu_ecap_sanity; 18 19 static 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 26 static 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 75 static 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 133 out: 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 143 static 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 148 rcu_read_lock(); 149 if (list_empty(&dmar_drhd_units)) 150 goto out; 151 152 for_each_active_iommu(i, d) { 153 if (!iommu) { 154 intel_iommu_ecap_sanity = i->ecap; 155 intel_iommu_cap_sanity = i->cap; 156 iommu = i; 157 continue; 158 } 159 160 if (type == CAP_AUDIT_STATIC_DMAR) 161 check_dmar_capabilities(iommu, i); 162 else 163 check_irq_capabilities(iommu, i); 164 } 165 166 out: 167 rcu_read_unlock(); 168 return 0; 169 } 170 171 int intel_cap_audit(enum cap_audit_type type, struct intel_iommu *iommu) 172 { 173 switch (type) { 174 case CAP_AUDIT_STATIC_DMAR: 175 case CAP_AUDIT_STATIC_IRQR: 176 return cap_audit_static(iommu, type); 177 case CAP_AUDIT_HOTPLUG_DMAR: 178 case CAP_AUDIT_HOTPLUG_IRQR: 179 return cap_audit_hotplug(iommu, type); 180 default: 181 break; 182 } 183 184 return -EFAULT; 185 } 186 187 bool intel_cap_smts_sanity(void) 188 { 189 return ecap_smts(intel_iommu_ecap_sanity); 190 } 191 192 bool intel_cap_pasid_sanity(void) 193 { 194 return ecap_pasid(intel_iommu_ecap_sanity); 195 } 196 197 bool intel_cap_nest_sanity(void) 198 { 199 return ecap_nest(intel_iommu_ecap_sanity); 200 } 201 202 bool intel_cap_flts_sanity(void) 203 { 204 return ecap_flts(intel_iommu_ecap_sanity); 205 } 206