Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0-only */
0002 /*
0003  * Copyright (c) 2006, Intel Corporation.
0004  *
0005  * Copyright (C) Ashok Raj <ashok.raj@intel.com>
0006  * Copyright (C) Shaohua Li <shaohua.li@intel.com>
0007  */
0008 
0009 #ifndef __DMAR_H__
0010 #define __DMAR_H__
0011 
0012 #include <linux/acpi.h>
0013 #include <linux/types.h>
0014 #include <linux/msi.h>
0015 #include <linux/irqreturn.h>
0016 #include <linux/rwsem.h>
0017 #include <linux/rculist.h>
0018 
0019 struct acpi_dmar_header;
0020 
0021 #define DMAR_UNITS_SUPPORTED    1024
0022 
0023 /* DMAR Flags */
0024 #define DMAR_INTR_REMAP     0x1
0025 #define DMAR_X2APIC_OPT_OUT 0x2
0026 #define DMAR_PLATFORM_OPT_IN    0x4
0027 
0028 struct intel_iommu;
0029 
0030 struct dmar_dev_scope {
0031     struct device __rcu *dev;
0032     u8 bus;
0033     u8 devfn;
0034 };
0035 
0036 #ifdef CONFIG_DMAR_TABLE
0037 extern struct acpi_table_header *dmar_tbl;
0038 struct dmar_drhd_unit {
0039     struct list_head list;      /* list of drhd units   */
0040     struct  acpi_dmar_header *hdr;  /* ACPI header      */
0041     u64 reg_base_addr;      /* register base address*/
0042     struct  dmar_dev_scope *devices;/* target device array  */
0043     int devices_cnt;        /* target device count  */
0044     u16 segment;        /* PCI domain       */
0045     u8  ignored:1;      /* ignore drhd      */
0046     u8  include_all:1;
0047     u8  gfx_dedicated:1;    /* graphic dedicated    */
0048     struct intel_iommu *iommu;
0049 };
0050 
0051 struct dmar_pci_path {
0052     u8 bus;
0053     u8 device;
0054     u8 function;
0055 };
0056 
0057 struct dmar_pci_notify_info {
0058     struct pci_dev          *dev;
0059     unsigned long           event;
0060     int             bus;
0061     u16             seg;
0062     u16             level;
0063     struct dmar_pci_path        path[];
0064 }  __attribute__((packed));
0065 
0066 extern struct rw_semaphore dmar_global_lock;
0067 extern struct list_head dmar_drhd_units;
0068 
0069 #define for_each_drhd_unit(drhd)                    \
0070     list_for_each_entry_rcu(drhd, &dmar_drhd_units, list,       \
0071                 dmar_rcu_check())
0072 
0073 #define for_each_active_drhd_unit(drhd)                 \
0074     list_for_each_entry_rcu(drhd, &dmar_drhd_units, list,       \
0075                 dmar_rcu_check())           \
0076         if (drhd->ignored) {} else
0077 
0078 #define for_each_active_iommu(i, drhd)                  \
0079     list_for_each_entry_rcu(drhd, &dmar_drhd_units, list,       \
0080                 dmar_rcu_check())           \
0081         if (i=drhd->iommu, drhd->ignored) {} else
0082 
0083 #define for_each_iommu(i, drhd)                     \
0084     list_for_each_entry_rcu(drhd, &dmar_drhd_units, list,       \
0085                 dmar_rcu_check())           \
0086         if (i=drhd->iommu, 0) {} else 
0087 
0088 static inline bool dmar_rcu_check(void)
0089 {
0090     return rwsem_is_locked(&dmar_global_lock) ||
0091            system_state == SYSTEM_BOOTING;
0092 }
0093 
0094 #define dmar_rcu_dereference(p) rcu_dereference_check((p), dmar_rcu_check())
0095 
0096 #define for_each_dev_scope(devs, cnt, i, tmp)               \
0097     for ((i) = 0; ((tmp) = (i) < (cnt) ?                \
0098         dmar_rcu_dereference((devs)[(i)].dev) : NULL, (i) < (cnt)); \
0099         (i)++)
0100 
0101 #define for_each_active_dev_scope(devs, cnt, i, tmp)            \
0102     for_each_dev_scope((devs), (cnt), (i), (tmp))           \
0103         if (!(tmp)) { continue; } else
0104 
0105 extern int dmar_table_init(void);
0106 extern int dmar_dev_scope_init(void);
0107 extern void dmar_register_bus_notifier(void);
0108 extern int dmar_parse_dev_scope(void *start, void *end, int *cnt,
0109                 struct dmar_dev_scope **devices, u16 segment);
0110 extern void *dmar_alloc_dev_scope(void *start, void *end, int *cnt);
0111 extern void dmar_free_dev_scope(struct dmar_dev_scope **devices, int *cnt);
0112 extern int dmar_insert_dev_scope(struct dmar_pci_notify_info *info,
0113                  void *start, void*end, u16 segment,
0114                  struct dmar_dev_scope *devices,
0115                  int devices_cnt);
0116 extern int dmar_remove_dev_scope(struct dmar_pci_notify_info *info,
0117                  u16 segment, struct dmar_dev_scope *devices,
0118                  int count);
0119 /* Intel IOMMU detection */
0120 void detect_intel_iommu(void);
0121 extern int enable_drhd_fault_handling(void);
0122 extern int dmar_device_add(acpi_handle handle);
0123 extern int dmar_device_remove(acpi_handle handle);
0124 
0125 static inline int dmar_res_noop(struct acpi_dmar_header *hdr, void *arg)
0126 {
0127     return 0;
0128 }
0129 
0130 #ifdef CONFIG_DMAR_DEBUG
0131 void dmar_fault_dump_ptes(struct intel_iommu *iommu, u16 source_id,
0132               unsigned long long addr, u32 pasid);
0133 #else
0134 static inline void dmar_fault_dump_ptes(struct intel_iommu *iommu, u16 source_id,
0135                     unsigned long long addr, u32 pasid) {}
0136 #endif
0137 
0138 #ifdef CONFIG_INTEL_IOMMU
0139 extern int iommu_detected, no_iommu;
0140 extern int intel_iommu_init(void);
0141 extern void intel_iommu_shutdown(void);
0142 extern int dmar_parse_one_rmrr(struct acpi_dmar_header *header, void *arg);
0143 extern int dmar_parse_one_atsr(struct acpi_dmar_header *header, void *arg);
0144 extern int dmar_check_one_atsr(struct acpi_dmar_header *hdr, void *arg);
0145 extern int dmar_parse_one_satc(struct acpi_dmar_header *hdr, void *arg);
0146 extern int dmar_release_one_atsr(struct acpi_dmar_header *hdr, void *arg);
0147 extern int dmar_iommu_hotplug(struct dmar_drhd_unit *dmaru, bool insert);
0148 extern int dmar_iommu_notify_scope_dev(struct dmar_pci_notify_info *info);
0149 #else /* !CONFIG_INTEL_IOMMU: */
0150 static inline int intel_iommu_init(void) { return -ENODEV; }
0151 static inline void intel_iommu_shutdown(void) { }
0152 
0153 #define dmar_parse_one_rmrr     dmar_res_noop
0154 #define dmar_parse_one_atsr     dmar_res_noop
0155 #define dmar_check_one_atsr     dmar_res_noop
0156 #define dmar_release_one_atsr       dmar_res_noop
0157 #define dmar_parse_one_satc     dmar_res_noop
0158 
0159 static inline int dmar_iommu_notify_scope_dev(struct dmar_pci_notify_info *info)
0160 {
0161     return 0;
0162 }
0163 
0164 static inline int dmar_iommu_hotplug(struct dmar_drhd_unit *dmaru, bool insert)
0165 {
0166     return 0;
0167 }
0168 #endif /* CONFIG_INTEL_IOMMU */
0169 
0170 #ifdef CONFIG_IRQ_REMAP
0171 extern int dmar_ir_hotplug(struct dmar_drhd_unit *dmaru, bool insert);
0172 #else  /* CONFIG_IRQ_REMAP */
0173 static inline int dmar_ir_hotplug(struct dmar_drhd_unit *dmaru, bool insert)
0174 { return 0; }
0175 #endif /* CONFIG_IRQ_REMAP */
0176 
0177 extern bool dmar_platform_optin(void);
0178 
0179 #else /* CONFIG_DMAR_TABLE */
0180 
0181 static inline int dmar_device_add(void *handle)
0182 {
0183     return 0;
0184 }
0185 
0186 static inline int dmar_device_remove(void *handle)
0187 {
0188     return 0;
0189 }
0190 
0191 static inline bool dmar_platform_optin(void)
0192 {
0193     return false;
0194 }
0195 
0196 static inline void detect_intel_iommu(void)
0197 {
0198 }
0199 
0200 #endif /* CONFIG_DMAR_TABLE */
0201 
0202 struct irte {
0203     union {
0204         /* Shared between remapped and posted mode*/
0205         struct {
0206             __u64   present     : 1,  /*  0      */
0207                 fpd     : 1,  /*  1      */
0208                 __res0      : 6,  /*  2 -  6 */
0209                 avail       : 4,  /*  8 - 11 */
0210                 __res1      : 3,  /* 12 - 14 */
0211                 pst     : 1,  /* 15      */
0212                 vector      : 8,  /* 16 - 23 */
0213                 __res2      : 40; /* 24 - 63 */
0214         };
0215 
0216         /* Remapped mode */
0217         struct {
0218             __u64   r_present   : 1,  /*  0      */
0219                 r_fpd       : 1,  /*  1      */
0220                 dst_mode    : 1,  /*  2      */
0221                 redir_hint  : 1,  /*  3      */
0222                 trigger_mode    : 1,  /*  4      */
0223                 dlvry_mode  : 3,  /*  5 -  7 */
0224                 r_avail     : 4,  /*  8 - 11 */
0225                 r_res0      : 4,  /* 12 - 15 */
0226                 r_vector    : 8,  /* 16 - 23 */
0227                 r_res1      : 8,  /* 24 - 31 */
0228                 dest_id     : 32; /* 32 - 63 */
0229         };
0230 
0231         /* Posted mode */
0232         struct {
0233             __u64   p_present   : 1,  /*  0      */
0234                 p_fpd       : 1,  /*  1      */
0235                 p_res0      : 6,  /*  2 -  7 */
0236                 p_avail     : 4,  /*  8 - 11 */
0237                 p_res1      : 2,  /* 12 - 13 */
0238                 p_urgent    : 1,  /* 14      */
0239                 p_pst       : 1,  /* 15      */
0240                 p_vector    : 8,  /* 16 - 23 */
0241                 p_res2      : 14, /* 24 - 37 */
0242                 pda_l       : 26; /* 38 - 63 */
0243         };
0244         __u64 low;
0245     };
0246 
0247     union {
0248         /* Shared between remapped and posted mode*/
0249         struct {
0250             __u64   sid     : 16,  /* 64 - 79  */
0251                 sq      : 2,   /* 80 - 81  */
0252                 svt     : 2,   /* 82 - 83  */
0253                 __res3      : 44;  /* 84 - 127 */
0254         };
0255 
0256         /* Posted mode*/
0257         struct {
0258             __u64   p_sid       : 16,  /* 64 - 79  */
0259                 p_sq        : 2,   /* 80 - 81  */
0260                 p_svt       : 2,   /* 82 - 83  */
0261                 p_res3      : 12,  /* 84 - 95  */
0262                 pda_h       : 32;  /* 96 - 127 */
0263         };
0264         __u64 high;
0265     };
0266 };
0267 
0268 static inline void dmar_copy_shared_irte(struct irte *dst, struct irte *src)
0269 {
0270     dst->present    = src->present;
0271     dst->fpd    = src->fpd;
0272     dst->avail  = src->avail;
0273     dst->pst    = src->pst;
0274     dst->vector = src->vector;
0275     dst->sid    = src->sid;
0276     dst->sq     = src->sq;
0277     dst->svt    = src->svt;
0278 }
0279 
0280 #define PDA_LOW_BIT    26
0281 #define PDA_HIGH_BIT   32
0282 
0283 /* Can't use the common MSI interrupt functions
0284  * since DMAR is not a pci device
0285  */
0286 struct irq_data;
0287 extern void dmar_msi_unmask(struct irq_data *data);
0288 extern void dmar_msi_mask(struct irq_data *data);
0289 extern void dmar_msi_read(int irq, struct msi_msg *msg);
0290 extern void dmar_msi_write(int irq, struct msi_msg *msg);
0291 extern int dmar_set_interrupt(struct intel_iommu *iommu);
0292 extern irqreturn_t dmar_fault(int irq, void *dev_id);
0293 extern int dmar_alloc_hwirq(int id, int node, void *arg);
0294 extern void dmar_free_hwirq(int irq);
0295 
0296 #endif /* __DMAR_H__ */