diff options
Diffstat (limited to 'include/linux/dmar.h')
| -rw-r--r-- | include/linux/dmar.h | 188 |
1 files changed, 152 insertions, 36 deletions
diff --git a/include/linux/dmar.h b/include/linux/dmar.h index 56c73b84755..23c8db12956 100644 --- a/include/linux/dmar.h +++ b/include/linux/dmar.h @@ -24,63 +24,179 @@ #include <linux/acpi.h> #include <linux/types.h> #include <linux/msi.h> +#include <linux/irqreturn.h> +#include <linux/rwsem.h> +#include <linux/rcupdate.h> -#ifdef CONFIG_DMAR -struct intel_iommu; - -extern const char *dmar_get_fault_reason(u8 fault_reason); - -/* Can't use the common MSI interrupt functions - * since DMAR is not a pci device - */ -extern void dmar_msi_unmask(unsigned int irq); -extern void dmar_msi_mask(unsigned int irq); -extern void dmar_msi_read(int irq, struct msi_msg *msg); -extern void dmar_msi_write(int irq, struct msi_msg *msg); -extern int dmar_set_interrupt(struct intel_iommu *iommu); -extern int arch_setup_dmar_msi(unsigned int irq); +struct acpi_dmar_header; -/* Intel IOMMU detection and initialization functions */ -extern void detect_intel_iommu(void); -extern int intel_iommu_init(void); +/* DMAR Flags */ +#define DMAR_INTR_REMAP 0x1 +#define DMAR_X2APIC_OPT_OUT 0x2 -extern int dmar_table_init(void); -extern int early_dmar_detect(void); +struct intel_iommu; -extern struct list_head dmar_drhd_units; -extern struct list_head dmar_rmrr_units; +struct dmar_dev_scope { + struct device __rcu *dev; + u8 bus; + u8 devfn; +}; +#ifdef CONFIG_DMAR_TABLE +extern struct acpi_table_header *dmar_tbl; struct dmar_drhd_unit { struct list_head list; /* list of drhd units */ + struct acpi_dmar_header *hdr; /* ACPI header */ u64 reg_base_addr; /* register base address*/ - struct pci_dev **devices; /* target device array */ + struct dmar_dev_scope *devices;/* target device array */ int devices_cnt; /* target device count */ + u16 segment; /* PCI domain */ u8 ignored:1; /* ignore drhd */ u8 include_all:1; struct intel_iommu *iommu; }; -struct dmar_rmrr_unit { - struct list_head list; /* list of rmrr units */ - u64 base_address; /* reserved base address*/ - u64 end_address; /* reserved end address */ - struct pci_dev **devices; /* target devices */ - int devices_cnt; /* target device count */ -}; +struct dmar_pci_notify_info { + struct pci_dev *dev; + unsigned long event; + int bus; + u16 seg; + u16 level; + struct acpi_dmar_pci_path path[]; +} __attribute__((packed)); + +extern struct rw_semaphore dmar_global_lock; +extern struct list_head dmar_drhd_units; #define for_each_drhd_unit(drhd) \ - list_for_each_entry(drhd, &dmar_drhd_units, list) -#define for_each_rmrr_units(rmrr) \ - list_for_each_entry(rmrr, &dmar_rmrr_units, list) + list_for_each_entry_rcu(drhd, &dmar_drhd_units, list) + +#define for_each_active_drhd_unit(drhd) \ + list_for_each_entry_rcu(drhd, &dmar_drhd_units, list) \ + if (drhd->ignored) {} else + +#define for_each_active_iommu(i, drhd) \ + list_for_each_entry_rcu(drhd, &dmar_drhd_units, list) \ + if (i=drhd->iommu, drhd->ignored) {} else + +#define for_each_iommu(i, drhd) \ + list_for_each_entry_rcu(drhd, &dmar_drhd_units, list) \ + if (i=drhd->iommu, 0) {} else + +static inline bool dmar_rcu_check(void) +{ + return rwsem_is_locked(&dmar_global_lock) || + system_state == SYSTEM_BOOTING; +} + +#define dmar_rcu_dereference(p) rcu_dereference_check((p), dmar_rcu_check()) + +#define for_each_dev_scope(a, c, p, d) \ + for ((p) = 0; ((d) = (p) < (c) ? dmar_rcu_dereference((a)[(p)].dev) : \ + NULL, (p) < (c)); (p)++) + +#define for_each_active_dev_scope(a, c, p, d) \ + for_each_dev_scope((a), (c), (p), (d)) if (!(d)) { continue; } else + +extern int dmar_table_init(void); +extern int dmar_dev_scope_init(void); +extern int dmar_parse_dev_scope(void *start, void *end, int *cnt, + struct dmar_dev_scope **devices, u16 segment); +extern void *dmar_alloc_dev_scope(void *start, void *end, int *cnt); +extern void dmar_free_dev_scope(struct dmar_dev_scope **devices, int *cnt); +extern int dmar_insert_dev_scope(struct dmar_pci_notify_info *info, + void *start, void*end, u16 segment, + struct dmar_dev_scope *devices, + int devices_cnt); +extern int dmar_remove_dev_scope(struct dmar_pci_notify_info *info, + u16 segment, struct dmar_dev_scope *devices, + int count); +/* Intel IOMMU detection */ +extern int detect_intel_iommu(void); +extern int enable_drhd_fault_handling(void); #else -static inline void detect_intel_iommu(void) +struct dmar_pci_notify_info; +static inline int detect_intel_iommu(void) { - return; + return -ENODEV; } -static inline int intel_iommu_init(void) + +static inline int dmar_table_init(void) { return -ENODEV; } +static inline int enable_drhd_fault_handling(void) +{ + return -1; +} +#endif /* !CONFIG_DMAR_TABLE */ + +struct irte { + union { + struct { + __u64 present : 1, + fpd : 1, + dst_mode : 1, + redir_hint : 1, + trigger_mode : 1, + dlvry_mode : 3, + avail : 4, + __reserved_1 : 4, + vector : 8, + __reserved_2 : 8, + dest_id : 32; + }; + __u64 low; + }; + + union { + struct { + __u64 sid : 16, + sq : 2, + svt : 2, + __reserved_3 : 44; + }; + __u64 high; + }; +}; + +enum { + IRQ_REMAP_XAPIC_MODE, + IRQ_REMAP_X2APIC_MODE, +}; + +/* Can't use the common MSI interrupt functions + * since DMAR is not a pci device + */ +struct irq_data; +extern void dmar_msi_unmask(struct irq_data *data); +extern void dmar_msi_mask(struct irq_data *data); +extern void dmar_msi_read(int irq, struct msi_msg *msg); +extern void dmar_msi_write(int irq, struct msi_msg *msg); +extern int dmar_set_interrupt(struct intel_iommu *iommu); +extern irqreturn_t dmar_fault(int irq, void *dev_id); +extern int arch_setup_dmar_msi(unsigned int irq); + +#ifdef CONFIG_INTEL_IOMMU +extern int iommu_detected, no_iommu; +extern int dmar_parse_one_rmrr(struct acpi_dmar_header *header); +extern int dmar_parse_one_atsr(struct acpi_dmar_header *header); +extern int dmar_iommu_notify_scope_dev(struct dmar_pci_notify_info *info); +extern int intel_iommu_init(void); +#else /* !CONFIG_INTEL_IOMMU: */ +static inline int intel_iommu_init(void) { return -ENODEV; } +static inline int dmar_parse_one_rmrr(struct acpi_dmar_header *header) +{ + return 0; +} +static inline int dmar_parse_one_atsr(struct acpi_dmar_header *header) +{ + return 0; +} +static inline int dmar_iommu_notify_scope_dev(struct dmar_pci_notify_info *info) +{ + return 0; +} +#endif /* CONFIG_INTEL_IOMMU */ -#endif /* !CONFIG_DMAR */ #endif /* __DMAR_H__ */ |
