1 | /* SPDX-License-Identifier: GPL-2.0 */ |
2 | /* |
3 | * cap_audit.h - audit iommu capabilities header |
4 | * |
5 | * Copyright (C) 2021 Intel Corporation |
6 | * |
7 | * Author: Kyung Min Park <kyung.min.park@intel.com> |
8 | */ |
9 | |
10 | /* |
11 | * Capability Register Mask |
12 | */ |
13 | #define CAP_FL5LP_MASK BIT_ULL(60) |
14 | #define CAP_PI_MASK BIT_ULL(59) |
15 | #define CAP_FL1GP_MASK BIT_ULL(56) |
16 | #define CAP_RD_MASK BIT_ULL(55) |
17 | #define CAP_WD_MASK BIT_ULL(54) |
18 | #define CAP_MAMV_MASK GENMASK_ULL(53, 48) |
19 | #define CAP_NFR_MASK GENMASK_ULL(47, 40) |
20 | #define CAP_PSI_MASK BIT_ULL(39) |
21 | #define CAP_SLLPS_MASK GENMASK_ULL(37, 34) |
22 | #define CAP_FRO_MASK GENMASK_ULL(33, 24) |
23 | #define CAP_ZLR_MASK BIT_ULL(22) |
24 | #define CAP_MGAW_MASK GENMASK_ULL(21, 16) |
25 | #define CAP_SAGAW_MASK GENMASK_ULL(12, 8) |
26 | #define CAP_CM_MASK BIT_ULL(7) |
27 | #define CAP_PHMR_MASK BIT_ULL(6) |
28 | #define CAP_PLMR_MASK BIT_ULL(5) |
29 | #define CAP_RWBF_MASK BIT_ULL(4) |
30 | #define CAP_AFL_MASK BIT_ULL(3) |
31 | #define CAP_NDOMS_MASK GENMASK_ULL(2, 0) |
32 | |
33 | /* |
34 | * Extended Capability Register Mask |
35 | */ |
36 | #define ECAP_RPS_MASK BIT_ULL(49) |
37 | #define ECAP_SMPWC_MASK BIT_ULL(48) |
38 | #define ECAP_FLTS_MASK BIT_ULL(47) |
39 | #define ECAP_SLTS_MASK BIT_ULL(46) |
40 | #define ECAP_SLADS_MASK BIT_ULL(45) |
41 | #define ECAP_VCS_MASK BIT_ULL(44) |
42 | #define ECAP_SMTS_MASK BIT_ULL(43) |
43 | #define ECAP_PDS_MASK BIT_ULL(42) |
44 | #define ECAP_DIT_MASK BIT_ULL(41) |
45 | #define ECAP_PASID_MASK BIT_ULL(40) |
46 | #define ECAP_PSS_MASK GENMASK_ULL(39, 35) |
47 | #define ECAP_EAFS_MASK BIT_ULL(34) |
48 | #define ECAP_NWFS_MASK BIT_ULL(33) |
49 | #define ECAP_SRS_MASK BIT_ULL(31) |
50 | #define ECAP_ERS_MASK BIT_ULL(30) |
51 | #define ECAP_PRS_MASK BIT_ULL(29) |
52 | #define ECAP_NEST_MASK BIT_ULL(26) |
53 | #define ECAP_MTS_MASK BIT_ULL(25) |
54 | #define ECAP_MHMV_MASK GENMASK_ULL(23, 20) |
55 | #define ECAP_IRO_MASK GENMASK_ULL(17, 8) |
56 | #define ECAP_SC_MASK BIT_ULL(7) |
57 | #define ECAP_PT_MASK BIT_ULL(6) |
58 | #define ECAP_EIM_MASK BIT_ULL(4) |
59 | #define ECAP_DT_MASK BIT_ULL(2) |
60 | #define ECAP_QI_MASK BIT_ULL(1) |
61 | #define ECAP_C_MASK BIT_ULL(0) |
62 | |
63 | /* |
64 | * u64 intel_iommu_cap_sanity, intel_iommu_ecap_sanity will be adjusted as each |
65 | * IOMMU gets audited. |
66 | */ |
67 | #define DO_CHECK_FEATURE_MISMATCH(a, b, cap, feature, MASK) \ |
68 | do { \ |
69 | if (cap##_##feature(a) != cap##_##feature(b)) { \ |
70 | intel_iommu_##cap##_sanity &= ~(MASK); \ |
71 | pr_info("IOMMU feature %s inconsistent", #feature); \ |
72 | } \ |
73 | } while (0) |
74 | |
75 | #define CHECK_FEATURE_MISMATCH(a, b, cap, feature, MASK) \ |
76 | DO_CHECK_FEATURE_MISMATCH((a)->cap, (b)->cap, cap, feature, MASK) |
77 | |
78 | #define CHECK_FEATURE_MISMATCH_HOTPLUG(b, cap, feature, MASK) \ |
79 | do { \ |
80 | if (cap##_##feature(intel_iommu_##cap##_sanity)) \ |
81 | DO_CHECK_FEATURE_MISMATCH(intel_iommu_##cap##_sanity, \ |
82 | (b)->cap, cap, feature, MASK); \ |
83 | } while (0) |
84 | |
85 | #define MINIMAL_FEATURE_IOMMU(iommu, cap, MASK) \ |
86 | do { \ |
87 | u64 min_feature = intel_iommu_##cap##_sanity & (MASK); \ |
88 | min_feature = min_t(u64, min_feature, (iommu)->cap & (MASK)); \ |
89 | intel_iommu_##cap##_sanity = (intel_iommu_##cap##_sanity & ~(MASK)) | \ |
90 | min_feature; \ |
91 | } while (0) |
92 | |
93 | #define MINIMAL_FEATURE_HOTPLUG(iommu, cap, feature, MASK, mismatch) \ |
94 | do { \ |
95 | if ((intel_iommu_##cap##_sanity & (MASK)) > \ |
96 | (cap##_##feature((iommu)->cap))) \ |
97 | mismatch = true; \ |
98 | else \ |
99 | (iommu)->cap = ((iommu)->cap & ~(MASK)) | \ |
100 | (intel_iommu_##cap##_sanity & (MASK)); \ |
101 | } while (0) |
102 | |
103 | enum cap_audit_type { |
104 | CAP_AUDIT_STATIC_DMAR, |
105 | CAP_AUDIT_STATIC_IRQR, |
106 | CAP_AUDIT_HOTPLUG_DMAR, |
107 | CAP_AUDIT_HOTPLUG_IRQR, |
108 | }; |
109 | |
110 | bool intel_cap_smts_sanity(void); |
111 | bool intel_cap_pasid_sanity(void); |
112 | bool intel_cap_nest_sanity(void); |
113 | bool intel_cap_flts_sanity(void); |
114 | bool intel_cap_slts_sanity(void); |
115 | |
116 | static inline bool scalable_mode_support(void) |
117 | { |
118 | return (intel_iommu_sm && intel_cap_smts_sanity()); |
119 | } |
120 | |
121 | static inline bool pasid_mode_support(void) |
122 | { |
123 | return scalable_mode_support() && intel_cap_pasid_sanity(); |
124 | } |
125 | |
126 | static inline bool nested_mode_support(void) |
127 | { |
128 | return scalable_mode_support() && intel_cap_nest_sanity(); |
129 | } |
130 | |
131 | int intel_cap_audit(enum cap_audit_type type, struct intel_iommu *iommu); |
132 | |