Linux Audio

Check our new training course

Loading...
Note: File does not exist in v5.4.
  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 "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, fl5lp_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, fl5lp_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}