162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * cap_audit.h - audit iommu capabilities header 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (C) 2021 Intel Corporation 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * Author: Kyung Min Park <kyung.min.park@intel.com> 862306a36Sopenharmony_ci */ 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci/* 1162306a36Sopenharmony_ci * Capability Register Mask 1262306a36Sopenharmony_ci */ 1362306a36Sopenharmony_ci#define CAP_FL5LP_MASK BIT_ULL(60) 1462306a36Sopenharmony_ci#define CAP_PI_MASK BIT_ULL(59) 1562306a36Sopenharmony_ci#define CAP_FL1GP_MASK BIT_ULL(56) 1662306a36Sopenharmony_ci#define CAP_RD_MASK BIT_ULL(55) 1762306a36Sopenharmony_ci#define CAP_WD_MASK BIT_ULL(54) 1862306a36Sopenharmony_ci#define CAP_MAMV_MASK GENMASK_ULL(53, 48) 1962306a36Sopenharmony_ci#define CAP_NFR_MASK GENMASK_ULL(47, 40) 2062306a36Sopenharmony_ci#define CAP_PSI_MASK BIT_ULL(39) 2162306a36Sopenharmony_ci#define CAP_SLLPS_MASK GENMASK_ULL(37, 34) 2262306a36Sopenharmony_ci#define CAP_FRO_MASK GENMASK_ULL(33, 24) 2362306a36Sopenharmony_ci#define CAP_ZLR_MASK BIT_ULL(22) 2462306a36Sopenharmony_ci#define CAP_MGAW_MASK GENMASK_ULL(21, 16) 2562306a36Sopenharmony_ci#define CAP_SAGAW_MASK GENMASK_ULL(12, 8) 2662306a36Sopenharmony_ci#define CAP_CM_MASK BIT_ULL(7) 2762306a36Sopenharmony_ci#define CAP_PHMR_MASK BIT_ULL(6) 2862306a36Sopenharmony_ci#define CAP_PLMR_MASK BIT_ULL(5) 2962306a36Sopenharmony_ci#define CAP_RWBF_MASK BIT_ULL(4) 3062306a36Sopenharmony_ci#define CAP_AFL_MASK BIT_ULL(3) 3162306a36Sopenharmony_ci#define CAP_NDOMS_MASK GENMASK_ULL(2, 0) 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_ci/* 3462306a36Sopenharmony_ci * Extended Capability Register Mask 3562306a36Sopenharmony_ci */ 3662306a36Sopenharmony_ci#define ECAP_RPS_MASK BIT_ULL(49) 3762306a36Sopenharmony_ci#define ECAP_SMPWC_MASK BIT_ULL(48) 3862306a36Sopenharmony_ci#define ECAP_FLTS_MASK BIT_ULL(47) 3962306a36Sopenharmony_ci#define ECAP_SLTS_MASK BIT_ULL(46) 4062306a36Sopenharmony_ci#define ECAP_SLADS_MASK BIT_ULL(45) 4162306a36Sopenharmony_ci#define ECAP_VCS_MASK BIT_ULL(44) 4262306a36Sopenharmony_ci#define ECAP_SMTS_MASK BIT_ULL(43) 4362306a36Sopenharmony_ci#define ECAP_PDS_MASK BIT_ULL(42) 4462306a36Sopenharmony_ci#define ECAP_DIT_MASK BIT_ULL(41) 4562306a36Sopenharmony_ci#define ECAP_PASID_MASK BIT_ULL(40) 4662306a36Sopenharmony_ci#define ECAP_PSS_MASK GENMASK_ULL(39, 35) 4762306a36Sopenharmony_ci#define ECAP_EAFS_MASK BIT_ULL(34) 4862306a36Sopenharmony_ci#define ECAP_NWFS_MASK BIT_ULL(33) 4962306a36Sopenharmony_ci#define ECAP_SRS_MASK BIT_ULL(31) 5062306a36Sopenharmony_ci#define ECAP_ERS_MASK BIT_ULL(30) 5162306a36Sopenharmony_ci#define ECAP_PRS_MASK BIT_ULL(29) 5262306a36Sopenharmony_ci#define ECAP_NEST_MASK BIT_ULL(26) 5362306a36Sopenharmony_ci#define ECAP_MTS_MASK BIT_ULL(25) 5462306a36Sopenharmony_ci#define ECAP_MHMV_MASK GENMASK_ULL(23, 20) 5562306a36Sopenharmony_ci#define ECAP_IRO_MASK GENMASK_ULL(17, 8) 5662306a36Sopenharmony_ci#define ECAP_SC_MASK BIT_ULL(7) 5762306a36Sopenharmony_ci#define ECAP_PT_MASK BIT_ULL(6) 5862306a36Sopenharmony_ci#define ECAP_EIM_MASK BIT_ULL(4) 5962306a36Sopenharmony_ci#define ECAP_DT_MASK BIT_ULL(2) 6062306a36Sopenharmony_ci#define ECAP_QI_MASK BIT_ULL(1) 6162306a36Sopenharmony_ci#define ECAP_C_MASK BIT_ULL(0) 6262306a36Sopenharmony_ci 6362306a36Sopenharmony_ci/* 6462306a36Sopenharmony_ci * u64 intel_iommu_cap_sanity, intel_iommu_ecap_sanity will be adjusted as each 6562306a36Sopenharmony_ci * IOMMU gets audited. 6662306a36Sopenharmony_ci */ 6762306a36Sopenharmony_ci#define DO_CHECK_FEATURE_MISMATCH(a, b, cap, feature, MASK) \ 6862306a36Sopenharmony_cido { \ 6962306a36Sopenharmony_ci if (cap##_##feature(a) != cap##_##feature(b)) { \ 7062306a36Sopenharmony_ci intel_iommu_##cap##_sanity &= ~(MASK); \ 7162306a36Sopenharmony_ci pr_info("IOMMU feature %s inconsistent", #feature); \ 7262306a36Sopenharmony_ci } \ 7362306a36Sopenharmony_ci} while (0) 7462306a36Sopenharmony_ci 7562306a36Sopenharmony_ci#define CHECK_FEATURE_MISMATCH(a, b, cap, feature, MASK) \ 7662306a36Sopenharmony_ci DO_CHECK_FEATURE_MISMATCH((a)->cap, (b)->cap, cap, feature, MASK) 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_ci#define CHECK_FEATURE_MISMATCH_HOTPLUG(b, cap, feature, MASK) \ 7962306a36Sopenharmony_cido { \ 8062306a36Sopenharmony_ci if (cap##_##feature(intel_iommu_##cap##_sanity)) \ 8162306a36Sopenharmony_ci DO_CHECK_FEATURE_MISMATCH(intel_iommu_##cap##_sanity, \ 8262306a36Sopenharmony_ci (b)->cap, cap, feature, MASK); \ 8362306a36Sopenharmony_ci} while (0) 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_ci#define MINIMAL_FEATURE_IOMMU(iommu, cap, MASK) \ 8662306a36Sopenharmony_cido { \ 8762306a36Sopenharmony_ci u64 min_feature = intel_iommu_##cap##_sanity & (MASK); \ 8862306a36Sopenharmony_ci min_feature = min_t(u64, min_feature, (iommu)->cap & (MASK)); \ 8962306a36Sopenharmony_ci intel_iommu_##cap##_sanity = (intel_iommu_##cap##_sanity & ~(MASK)) | \ 9062306a36Sopenharmony_ci min_feature; \ 9162306a36Sopenharmony_ci} while (0) 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_ci#define MINIMAL_FEATURE_HOTPLUG(iommu, cap, feature, MASK, mismatch) \ 9462306a36Sopenharmony_cido { \ 9562306a36Sopenharmony_ci if ((intel_iommu_##cap##_sanity & (MASK)) > \ 9662306a36Sopenharmony_ci (cap##_##feature((iommu)->cap))) \ 9762306a36Sopenharmony_ci mismatch = true; \ 9862306a36Sopenharmony_ci else \ 9962306a36Sopenharmony_ci (iommu)->cap = ((iommu)->cap & ~(MASK)) | \ 10062306a36Sopenharmony_ci (intel_iommu_##cap##_sanity & (MASK)); \ 10162306a36Sopenharmony_ci} while (0) 10262306a36Sopenharmony_ci 10362306a36Sopenharmony_cienum cap_audit_type { 10462306a36Sopenharmony_ci CAP_AUDIT_STATIC_DMAR, 10562306a36Sopenharmony_ci CAP_AUDIT_STATIC_IRQR, 10662306a36Sopenharmony_ci CAP_AUDIT_HOTPLUG_DMAR, 10762306a36Sopenharmony_ci CAP_AUDIT_HOTPLUG_IRQR, 10862306a36Sopenharmony_ci}; 10962306a36Sopenharmony_ci 11062306a36Sopenharmony_cibool intel_cap_smts_sanity(void); 11162306a36Sopenharmony_cibool intel_cap_pasid_sanity(void); 11262306a36Sopenharmony_cibool intel_cap_nest_sanity(void); 11362306a36Sopenharmony_cibool intel_cap_flts_sanity(void); 11462306a36Sopenharmony_cibool intel_cap_slts_sanity(void); 11562306a36Sopenharmony_ci 11662306a36Sopenharmony_cistatic inline bool scalable_mode_support(void) 11762306a36Sopenharmony_ci{ 11862306a36Sopenharmony_ci return (intel_iommu_sm && intel_cap_smts_sanity()); 11962306a36Sopenharmony_ci} 12062306a36Sopenharmony_ci 12162306a36Sopenharmony_cistatic inline bool pasid_mode_support(void) 12262306a36Sopenharmony_ci{ 12362306a36Sopenharmony_ci return scalable_mode_support() && intel_cap_pasid_sanity(); 12462306a36Sopenharmony_ci} 12562306a36Sopenharmony_ci 12662306a36Sopenharmony_cistatic inline bool nested_mode_support(void) 12762306a36Sopenharmony_ci{ 12862306a36Sopenharmony_ci return scalable_mode_support() && intel_cap_nest_sanity(); 12962306a36Sopenharmony_ci} 13062306a36Sopenharmony_ci 13162306a36Sopenharmony_ciint intel_cap_audit(enum cap_audit_type type, struct intel_iommu *iommu); 132