linux/drivers/iommu/intel/cap_audit.c
<<
>>
Prefs
   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
  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, 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
  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, 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
 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
 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
 166out:
 167        rcu_read_unlock();
 168        return 0;
 169}
 170
 171int 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
 187bool intel_cap_smts_sanity(void)
 188{
 189        return ecap_smts(intel_iommu_ecap_sanity);
 190}
 191
 192bool intel_cap_pasid_sanity(void)
 193{
 194        return ecap_pasid(intel_iommu_ecap_sanity);
 195}
 196
 197bool intel_cap_nest_sanity(void)
 198{
 199        return ecap_nest(intel_iommu_ecap_sanity);
 200}
 201
 202bool intel_cap_flts_sanity(void)
 203{
 204        return ecap_flts(intel_iommu_ecap_sanity);
 205}
 206