at v6.1 8.2 kB view raw
1/* SPDX-License-Identifier: GPL-2.0-only */ 2/* 3 * Copyright (c) 2006, Intel Corporation. 4 * 5 * Copyright (C) Ashok Raj <ashok.raj@intel.com> 6 * Copyright (C) Shaohua Li <shaohua.li@intel.com> 7 */ 8 9#ifndef __DMAR_H__ 10#define __DMAR_H__ 11 12#include <linux/acpi.h> 13#include <linux/types.h> 14#include <linux/msi.h> 15#include <linux/irqreturn.h> 16#include <linux/rwsem.h> 17#include <linux/rculist.h> 18 19struct acpi_dmar_header; 20 21#define DMAR_UNITS_SUPPORTED 1024 22 23/* DMAR Flags */ 24#define DMAR_INTR_REMAP 0x1 25#define DMAR_X2APIC_OPT_OUT 0x2 26#define DMAR_PLATFORM_OPT_IN 0x4 27 28struct intel_iommu; 29 30struct dmar_dev_scope { 31 struct device __rcu *dev; 32 u8 bus; 33 u8 devfn; 34}; 35 36#ifdef CONFIG_DMAR_TABLE 37extern struct acpi_table_header *dmar_tbl; 38struct dmar_drhd_unit { 39 struct list_head list; /* list of drhd units */ 40 struct acpi_dmar_header *hdr; /* ACPI header */ 41 u64 reg_base_addr; /* register base address*/ 42 struct dmar_dev_scope *devices;/* target device array */ 43 int devices_cnt; /* target device count */ 44 u16 segment; /* PCI domain */ 45 u8 ignored:1; /* ignore drhd */ 46 u8 include_all:1; 47 u8 gfx_dedicated:1; /* graphic dedicated */ 48 struct intel_iommu *iommu; 49}; 50 51struct dmar_pci_path { 52 u8 bus; 53 u8 device; 54 u8 function; 55}; 56 57struct dmar_pci_notify_info { 58 struct pci_dev *dev; 59 unsigned long event; 60 int bus; 61 u16 seg; 62 u16 level; 63 struct dmar_pci_path path[]; 64} __attribute__((packed)); 65 66extern struct rw_semaphore dmar_global_lock; 67extern struct list_head dmar_drhd_units; 68 69#define for_each_drhd_unit(drhd) \ 70 list_for_each_entry_rcu(drhd, &dmar_drhd_units, list, \ 71 dmar_rcu_check()) 72 73#define for_each_active_drhd_unit(drhd) \ 74 list_for_each_entry_rcu(drhd, &dmar_drhd_units, list, \ 75 dmar_rcu_check()) \ 76 if (drhd->ignored) {} else 77 78#define for_each_active_iommu(i, drhd) \ 79 list_for_each_entry_rcu(drhd, &dmar_drhd_units, list, \ 80 dmar_rcu_check()) \ 81 if (i=drhd->iommu, drhd->ignored) {} else 82 83#define for_each_iommu(i, drhd) \ 84 list_for_each_entry_rcu(drhd, &dmar_drhd_units, list, \ 85 dmar_rcu_check()) \ 86 if (i=drhd->iommu, 0) {} else 87 88static inline bool dmar_rcu_check(void) 89{ 90 return rwsem_is_locked(&dmar_global_lock) || 91 system_state == SYSTEM_BOOTING; 92} 93 94#define dmar_rcu_dereference(p) rcu_dereference_check((p), dmar_rcu_check()) 95 96#define for_each_dev_scope(devs, cnt, i, tmp) \ 97 for ((i) = 0; ((tmp) = (i) < (cnt) ? \ 98 dmar_rcu_dereference((devs)[(i)].dev) : NULL, (i) < (cnt)); \ 99 (i)++) 100 101#define for_each_active_dev_scope(devs, cnt, i, tmp) \ 102 for_each_dev_scope((devs), (cnt), (i), (tmp)) \ 103 if (!(tmp)) { continue; } else 104 105extern int dmar_table_init(void); 106extern int dmar_dev_scope_init(void); 107extern void dmar_register_bus_notifier(void); 108extern int dmar_parse_dev_scope(void *start, void *end, int *cnt, 109 struct dmar_dev_scope **devices, u16 segment); 110extern void *dmar_alloc_dev_scope(void *start, void *end, int *cnt); 111extern void dmar_free_dev_scope(struct dmar_dev_scope **devices, int *cnt); 112extern int dmar_insert_dev_scope(struct dmar_pci_notify_info *info, 113 void *start, void*end, u16 segment, 114 struct dmar_dev_scope *devices, 115 int devices_cnt); 116extern int dmar_remove_dev_scope(struct dmar_pci_notify_info *info, 117 u16 segment, struct dmar_dev_scope *devices, 118 int count); 119/* Intel IOMMU detection */ 120void detect_intel_iommu(void); 121extern int enable_drhd_fault_handling(void); 122extern int dmar_device_add(acpi_handle handle); 123extern int dmar_device_remove(acpi_handle handle); 124 125static inline int dmar_res_noop(struct acpi_dmar_header *hdr, void *arg) 126{ 127 return 0; 128} 129 130#ifdef CONFIG_DMAR_DEBUG 131void dmar_fault_dump_ptes(struct intel_iommu *iommu, u16 source_id, 132 unsigned long long addr, u32 pasid); 133#else 134static inline void dmar_fault_dump_ptes(struct intel_iommu *iommu, u16 source_id, 135 unsigned long long addr, u32 pasid) {} 136#endif 137 138#ifdef CONFIG_INTEL_IOMMU 139extern int iommu_detected, no_iommu; 140extern int intel_iommu_init(void); 141extern void intel_iommu_shutdown(void); 142extern int dmar_parse_one_rmrr(struct acpi_dmar_header *header, void *arg); 143extern int dmar_parse_one_atsr(struct acpi_dmar_header *header, void *arg); 144extern int dmar_check_one_atsr(struct acpi_dmar_header *hdr, void *arg); 145extern int dmar_parse_one_satc(struct acpi_dmar_header *hdr, void *arg); 146extern int dmar_release_one_atsr(struct acpi_dmar_header *hdr, void *arg); 147extern int dmar_iommu_hotplug(struct dmar_drhd_unit *dmaru, bool insert); 148extern int dmar_iommu_notify_scope_dev(struct dmar_pci_notify_info *info); 149#else /* !CONFIG_INTEL_IOMMU: */ 150static inline int intel_iommu_init(void) { return -ENODEV; } 151static inline void intel_iommu_shutdown(void) { } 152 153#define dmar_parse_one_rmrr dmar_res_noop 154#define dmar_parse_one_atsr dmar_res_noop 155#define dmar_check_one_atsr dmar_res_noop 156#define dmar_release_one_atsr dmar_res_noop 157#define dmar_parse_one_satc dmar_res_noop 158 159static inline int dmar_iommu_notify_scope_dev(struct dmar_pci_notify_info *info) 160{ 161 return 0; 162} 163 164static inline int dmar_iommu_hotplug(struct dmar_drhd_unit *dmaru, bool insert) 165{ 166 return 0; 167} 168#endif /* CONFIG_INTEL_IOMMU */ 169 170#ifdef CONFIG_IRQ_REMAP 171extern int dmar_ir_hotplug(struct dmar_drhd_unit *dmaru, bool insert); 172#else /* CONFIG_IRQ_REMAP */ 173static inline int dmar_ir_hotplug(struct dmar_drhd_unit *dmaru, bool insert) 174{ return 0; } 175#endif /* CONFIG_IRQ_REMAP */ 176 177extern bool dmar_platform_optin(void); 178 179#else /* CONFIG_DMAR_TABLE */ 180 181static inline int dmar_device_add(void *handle) 182{ 183 return 0; 184} 185 186static inline int dmar_device_remove(void *handle) 187{ 188 return 0; 189} 190 191static inline bool dmar_platform_optin(void) 192{ 193 return false; 194} 195 196static inline void detect_intel_iommu(void) 197{ 198} 199 200#endif /* CONFIG_DMAR_TABLE */ 201 202struct irte { 203 union { 204 /* Shared between remapped and posted mode*/ 205 struct { 206 __u64 present : 1, /* 0 */ 207 fpd : 1, /* 1 */ 208 __res0 : 6, /* 2 - 6 */ 209 avail : 4, /* 8 - 11 */ 210 __res1 : 3, /* 12 - 14 */ 211 pst : 1, /* 15 */ 212 vector : 8, /* 16 - 23 */ 213 __res2 : 40; /* 24 - 63 */ 214 }; 215 216 /* Remapped mode */ 217 struct { 218 __u64 r_present : 1, /* 0 */ 219 r_fpd : 1, /* 1 */ 220 dst_mode : 1, /* 2 */ 221 redir_hint : 1, /* 3 */ 222 trigger_mode : 1, /* 4 */ 223 dlvry_mode : 3, /* 5 - 7 */ 224 r_avail : 4, /* 8 - 11 */ 225 r_res0 : 4, /* 12 - 15 */ 226 r_vector : 8, /* 16 - 23 */ 227 r_res1 : 8, /* 24 - 31 */ 228 dest_id : 32; /* 32 - 63 */ 229 }; 230 231 /* Posted mode */ 232 struct { 233 __u64 p_present : 1, /* 0 */ 234 p_fpd : 1, /* 1 */ 235 p_res0 : 6, /* 2 - 7 */ 236 p_avail : 4, /* 8 - 11 */ 237 p_res1 : 2, /* 12 - 13 */ 238 p_urgent : 1, /* 14 */ 239 p_pst : 1, /* 15 */ 240 p_vector : 8, /* 16 - 23 */ 241 p_res2 : 14, /* 24 - 37 */ 242 pda_l : 26; /* 38 - 63 */ 243 }; 244 __u64 low; 245 }; 246 247 union { 248 /* Shared between remapped and posted mode*/ 249 struct { 250 __u64 sid : 16, /* 64 - 79 */ 251 sq : 2, /* 80 - 81 */ 252 svt : 2, /* 82 - 83 */ 253 __res3 : 44; /* 84 - 127 */ 254 }; 255 256 /* Posted mode*/ 257 struct { 258 __u64 p_sid : 16, /* 64 - 79 */ 259 p_sq : 2, /* 80 - 81 */ 260 p_svt : 2, /* 82 - 83 */ 261 p_res3 : 12, /* 84 - 95 */ 262 pda_h : 32; /* 96 - 127 */ 263 }; 264 __u64 high; 265 }; 266}; 267 268static inline void dmar_copy_shared_irte(struct irte *dst, struct irte *src) 269{ 270 dst->present = src->present; 271 dst->fpd = src->fpd; 272 dst->avail = src->avail; 273 dst->pst = src->pst; 274 dst->vector = src->vector; 275 dst->sid = src->sid; 276 dst->sq = src->sq; 277 dst->svt = src->svt; 278} 279 280#define PDA_LOW_BIT 26 281#define PDA_HIGH_BIT 32 282 283/* Can't use the common MSI interrupt functions 284 * since DMAR is not a pci device 285 */ 286struct irq_data; 287extern void dmar_msi_unmask(struct irq_data *data); 288extern void dmar_msi_mask(struct irq_data *data); 289extern void dmar_msi_read(int irq, struct msi_msg *msg); 290extern void dmar_msi_write(int irq, struct msi_msg *msg); 291extern int dmar_set_interrupt(struct intel_iommu *iommu); 292extern irqreturn_t dmar_fault(int irq, void *dev_id); 293extern int dmar_alloc_hwirq(int id, int node, void *arg); 294extern void dmar_free_hwirq(int irq); 295 296#endif /* __DMAR_H__ */