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, smts, ECAP_SMTS_MASK);
58	CHECK_FEATURE_MISMATCH(a, b, ecap, pds, ECAP_PDS_MASK);
59	CHECK_FEATURE_MISMATCH(a, b, ecap, dit, ECAP_DIT_MASK);
60	CHECK_FEATURE_MISMATCH(a, b, ecap, pasid, ECAP_PASID_MASK);
61	CHECK_FEATURE_MISMATCH(a, b, ecap, eafs, ECAP_EAFS_MASK);
62	CHECK_FEATURE_MISMATCH(a, b, ecap, srs, ECAP_SRS_MASK);
63	CHECK_FEATURE_MISMATCH(a, b, ecap, ers, ECAP_ERS_MASK);
64	CHECK_FEATURE_MISMATCH(a, b, ecap, prs, ECAP_PRS_MASK);
65	CHECK_FEATURE_MISMATCH(a, b, ecap, nest, ECAP_NEST_MASK);
66	CHECK_FEATURE_MISMATCH(a, b, ecap, mts, ECAP_MTS_MASK);
67	CHECK_FEATURE_MISMATCH(a, b, ecap, sc_support, ECAP_SC_MASK);
68	CHECK_FEATURE_MISMATCH(a, b, ecap, pass_through, ECAP_PT_MASK);
69	CHECK_FEATURE_MISMATCH(a, b, ecap, dev_iotlb_support, ECAP_DT_MASK);
70	CHECK_FEATURE_MISMATCH(a, b, ecap, qis, ECAP_QI_MASK);
71	CHECK_FEATURE_MISMATCH(a, b, ecap, coherent, ECAP_C_MASK);
72}
73
74static int cap_audit_hotplug(struct intel_iommu *iommu, enum cap_audit_type type)
75{
76	bool mismatch = false;
77	u64 old_cap = intel_iommu_cap_sanity;
78	u64 old_ecap = intel_iommu_ecap_sanity;
79
80	if (type == CAP_AUDIT_HOTPLUG_IRQR) {
81		CHECK_FEATURE_MISMATCH_HOTPLUG(iommu, cap, pi_support, CAP_PI_MASK);
82		CHECK_FEATURE_MISMATCH_HOTPLUG(iommu, ecap, eim_support, ECAP_EIM_MASK);
83		goto out;
84	}
85
86	CHECK_FEATURE_MISMATCH_HOTPLUG(iommu, cap, fl5lp_support, CAP_FL5LP_MASK);
87	CHECK_FEATURE_MISMATCH_HOTPLUG(iommu, cap, fl1gp_support, CAP_FL1GP_MASK);
88	CHECK_FEATURE_MISMATCH_HOTPLUG(iommu, cap, read_drain, CAP_RD_MASK);
89	CHECK_FEATURE_MISMATCH_HOTPLUG(iommu, cap, write_drain, CAP_WD_MASK);
90	CHECK_FEATURE_MISMATCH_HOTPLUG(iommu, cap, pgsel_inv, CAP_PSI_MASK);
91	CHECK_FEATURE_MISMATCH_HOTPLUG(iommu, cap, zlr, CAP_ZLR_MASK);
92	CHECK_FEATURE_MISMATCH_HOTPLUG(iommu, cap, caching_mode, CAP_CM_MASK);
93	CHECK_FEATURE_MISMATCH_HOTPLUG(iommu, cap, phmr, CAP_PHMR_MASK);
94	CHECK_FEATURE_MISMATCH_HOTPLUG(iommu, cap, plmr, CAP_PLMR_MASK);
95	CHECK_FEATURE_MISMATCH_HOTPLUG(iommu, cap, rwbf, CAP_RWBF_MASK);
96	CHECK_FEATURE_MISMATCH_HOTPLUG(iommu, cap, afl, CAP_AFL_MASK);
97	CHECK_FEATURE_MISMATCH_HOTPLUG(iommu, ecap, rps, ECAP_RPS_MASK);
98	CHECK_FEATURE_MISMATCH_HOTPLUG(iommu, ecap, smpwc, ECAP_SMPWC_MASK);
99	CHECK_FEATURE_MISMATCH_HOTPLUG(iommu, ecap, flts, ECAP_FLTS_MASK);
100	CHECK_FEATURE_MISMATCH_HOTPLUG(iommu, ecap, slts, ECAP_SLTS_MASK);
101	CHECK_FEATURE_MISMATCH_HOTPLUG(iommu, ecap, nwfs, ECAP_NWFS_MASK);
102	CHECK_FEATURE_MISMATCH_HOTPLUG(iommu, ecap, slads, ECAP_SLADS_MASK);
103	CHECK_FEATURE_MISMATCH_HOTPLUG(iommu, ecap, smts, ECAP_SMTS_MASK);
104	CHECK_FEATURE_MISMATCH_HOTPLUG(iommu, ecap, pds, ECAP_PDS_MASK);
105	CHECK_FEATURE_MISMATCH_HOTPLUG(iommu, ecap, dit, ECAP_DIT_MASK);
106	CHECK_FEATURE_MISMATCH_HOTPLUG(iommu, ecap, pasid, ECAP_PASID_MASK);
107	CHECK_FEATURE_MISMATCH_HOTPLUG(iommu, ecap, eafs, ECAP_EAFS_MASK);
108	CHECK_FEATURE_MISMATCH_HOTPLUG(iommu, ecap, srs, ECAP_SRS_MASK);
109	CHECK_FEATURE_MISMATCH_HOTPLUG(iommu, ecap, ers, ECAP_ERS_MASK);
110	CHECK_FEATURE_MISMATCH_HOTPLUG(iommu, ecap, prs, ECAP_PRS_MASK);
111	CHECK_FEATURE_MISMATCH_HOTPLUG(iommu, ecap, nest, ECAP_NEST_MASK);
112	CHECK_FEATURE_MISMATCH_HOTPLUG(iommu, ecap, mts, ECAP_MTS_MASK);
113	CHECK_FEATURE_MISMATCH_HOTPLUG(iommu, ecap, sc_support, ECAP_SC_MASK);
114	CHECK_FEATURE_MISMATCH_HOTPLUG(iommu, ecap, pass_through, ECAP_PT_MASK);
115	CHECK_FEATURE_MISMATCH_HOTPLUG(iommu, ecap, dev_iotlb_support, ECAP_DT_MASK);
116	CHECK_FEATURE_MISMATCH_HOTPLUG(iommu, ecap, qis, ECAP_QI_MASK);
117	CHECK_FEATURE_MISMATCH_HOTPLUG(iommu, ecap, coherent, ECAP_C_MASK);
118
119	/* Abort hot plug if the hot plug iommu feature is smaller than global */
120	MINIMAL_FEATURE_HOTPLUG(iommu, cap, max_amask_val, CAP_MAMV_MASK, mismatch);
121	MINIMAL_FEATURE_HOTPLUG(iommu, cap, num_fault_regs, CAP_NFR_MASK, mismatch);
122	MINIMAL_FEATURE_HOTPLUG(iommu, cap, super_page_val, CAP_SLLPS_MASK, mismatch);
123	MINIMAL_FEATURE_HOTPLUG(iommu, cap, fault_reg_offset, CAP_FRO_MASK, mismatch);
124	MINIMAL_FEATURE_HOTPLUG(iommu, cap, mgaw, CAP_MGAW_MASK, mismatch);
125	MINIMAL_FEATURE_HOTPLUG(iommu, cap, sagaw, CAP_SAGAW_MASK, mismatch);
126	MINIMAL_FEATURE_HOTPLUG(iommu, cap, ndoms, CAP_NDOMS_MASK, mismatch);
127	MINIMAL_FEATURE_HOTPLUG(iommu, ecap, pss, ECAP_PSS_MASK, mismatch);
128	MINIMAL_FEATURE_HOTPLUG(iommu, ecap, max_handle_mask, ECAP_MHMV_MASK, mismatch);
129	MINIMAL_FEATURE_HOTPLUG(iommu, ecap, iotlb_offset, ECAP_IRO_MASK, mismatch);
130
131out:
132	if (mismatch) {
133		intel_iommu_cap_sanity = old_cap;
134		intel_iommu_ecap_sanity = old_ecap;
135		return -EFAULT;
136	}
137
138	return 0;
139}
140
141static int cap_audit_static(struct intel_iommu *iommu, enum cap_audit_type type)
142{
143	struct dmar_drhd_unit *d;
144	struct intel_iommu *i;
145	int rc = 0;
146
147	rcu_read_lock();
148	if (list_empty(&dmar_drhd_units))
149		goto out;
150
151	for_each_active_iommu(i, d) {
152		if (!iommu) {
153			intel_iommu_ecap_sanity = i->ecap;
154			intel_iommu_cap_sanity = i->cap;
155			iommu = i;
156			continue;
157		}
158
159		if (type == CAP_AUDIT_STATIC_DMAR)
160			check_dmar_capabilities(iommu, i);
161		else
162			check_irq_capabilities(iommu, i);
163	}
164
165	/*
166	 * If the system is sane to support scalable mode, either SL or FL
167	 * should be sane.
168	 */
169	if (intel_cap_smts_sanity() &&
170	    !intel_cap_flts_sanity() && !intel_cap_slts_sanity())
171		rc = -EOPNOTSUPP;
172
173out:
174	rcu_read_unlock();
175	return rc;
176}
177
178int intel_cap_audit(enum cap_audit_type type, struct intel_iommu *iommu)
179{
180	switch (type) {
181	case CAP_AUDIT_STATIC_DMAR:
182	case CAP_AUDIT_STATIC_IRQR:
183		return cap_audit_static(iommu, type);
184	case CAP_AUDIT_HOTPLUG_DMAR:
185	case CAP_AUDIT_HOTPLUG_IRQR:
186		return cap_audit_hotplug(iommu, type);
187	default:
188		break;
189	}
190
191	return -EFAULT;
192}
193
194bool intel_cap_smts_sanity(void)
195{
196	return ecap_smts(intel_iommu_ecap_sanity);
197}
198
199bool intel_cap_pasid_sanity(void)
200{
201	return ecap_pasid(intel_iommu_ecap_sanity);
202}
203
204bool intel_cap_nest_sanity(void)
205{
206	return ecap_nest(intel_iommu_ecap_sanity);
207}
208
209bool intel_cap_flts_sanity(void)
210{
211	return ecap_flts(intel_iommu_ecap_sanity);
212}
213
214bool intel_cap_slts_sanity(void)
215{
216	return ecap_slts(intel_iommu_ecap_sanity);
217}
218