| 1 | |
| 2 | * Copyright (c) 2006, Intel Corporation.
|
| 3 | *
|
| 4 | * This program is free software; you can redistribute it and/or modify it
|
| 5 | * under the terms and conditions of the GNU General Public License,
|
| 6 | * version 2, as published by the Free Software Foundation.
|
| 7 | *
|
| 8 | * This program is distributed in the hope it will be useful, but WITHOUT
|
| 9 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
| 10 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
| 11 | * more details.
|
| 12 | *
|
| 13 | * You should have received a copy of the GNU General Public License along with
|
| 14 | * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
|
| 15 | * Place - Suite 330, Boston, MA 02111-1307 USA.
|
| 16 | *
|
| 17 | * Copyright (C) Ashok Raj <[email protected]>
|
| 18 | * Copyright (C) Shaohua Li <[email protected]>
|
| 19 |
|
| 20 |
|
| 21 | #ifndef __DMAR_H__
|
| 22 | #define __DMAR_H__
|
| 23 |
|
| 24 | #include <linux/acpi.h>
|
| 25 | #include <linux/types.h>
|
| 26 | #include <linux/msi.h>
|
| 27 | #include <linux/irqreturn.h>
|
| 28 | #include <linux/rwsem.h>
|
| 29 | #include <linux/rcupdate.h>
|
| 30 |
|
| 31 | struct acpi_dmar_header;
|
| 32 |
|
| 33 |
|
| 34 | #define DMAR_INTR_REMAP 0x1
|
| 35 | #define DMAR_X2APIC_OPT_OUT 0x2
|
| 36 |
|
| 37 | struct intel_iommu;
|
| 38 |
|
| 39 | struct dmar_dev_scope {
|
| 40 | struct device __rcu *dev;
|
| 41 | u8 bus;
|
| 42 | u8 devfn;
|
| 43 | };
|
| 44 |
|
| 45 | #ifdef CONFIG_DMAR_TABLE
|
| 46 | extern struct acpi_table_header *dmar_tbl;
|
| 47 | struct dmar_drhd_unit {
|
| 48 | struct list_head list;
|
| 49 | struct acpi_dmar_header *hdr;
|
| 50 | u64 reg_base_addr;
|
| 51 | struct dmar_dev_scope *devices;
|
| 52 | int devices_cnt;
|
| 53 | u16 segment;
|
| 54 | u8 ignored:1;
|
| 55 | u8 include_all:1;
|
| 56 | struct intel_iommu *iommu;
|
| 57 | };
|
| 58 |
|
| 59 | struct dmar_pci_notify_info {
|
| 60 | struct pci_dev *dev;
|
| 61 | unsigned long event;
|
| 62 | int bus;
|
| 63 | u16 seg;
|
| 64 | u16 level;
|
| 65 | struct acpi_dmar_pci_path path[];
|
| 66 | } __attribute__((packed));
|
| 67 |
|
| 68 | extern struct rw_semaphore dmar_global_lock;
|
| 69 | extern struct list_head dmar_drhd_units;
|
| 70 |
|
| 71 | #define for_each_drhd_unit(drhd) \
|
| 72 | list_for_each_entry_rcu(drhd, &dmar_drhd_units, list)
|
| 73 |
|
| 74 | #define for_each_active_drhd_unit(drhd) \
|
| 75 | list_for_each_entry_rcu(drhd, &dmar_drhd_units, list) \
|
| 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 | if (i=drhd->iommu, drhd->ignored) {} else
|
| 81 |
|
| 82 | #define for_each_iommu(i, drhd) \
|
| 83 | list_for_each_entry_rcu(drhd, &dmar_drhd_units, list) \
|
| 84 | if (i=drhd->iommu, 0) {} else
|
| 85 |
|
| 86 | static inline bool dmar_rcu_check(void)
|
| 87 | {
|
| 88 | return rwsem_is_locked(&dmar_global_lock) ||
|
| 89 | system_state == SYSTEM_BOOTING;
|
| 90 | }
|
| 91 |
|
| 92 | #define dmar_rcu_dereference(p) rcu_dereference_check((p), dmar_rcu_check())
|
| 93 |
|
| 94 | #define for_each_dev_scope(a, c, p, d) \
|
| 95 | for ((p) = 0; ((d) = (p) < (c) ? dmar_rcu_dereference((a)[(p)].dev) : \
|
| 96 | NULL, (p) < (c)); (p)++)
|
| 97 |
|
| 98 | #define for_each_active_dev_scope(a, c, p, d) \
|
| 99 | for_each_dev_scope((a), (c), (p), (d)) if (!(d)) { continue; } else
|
| 100 |
|
| 101 | extern int dmar_table_init(void);
|
| 102 | extern int dmar_dev_scope_init(void);
|
| 103 | extern int dmar_parse_dev_scope(void *start, void *end, int *cnt,
|
| 104 | struct dmar_dev_scope **devices, u16 segment);
|
| 105 | extern void *dmar_alloc_dev_scope(void *start, void *end, int *cnt);
|
| 106 | extern void dmar_free_dev_scope(struct dmar_dev_scope **devices, int *cnt);
|
| 107 | extern int dmar_insert_dev_scope(struct dmar_pci_notify_info *info,
|
| 108 | void *start, void*end, u16 segment,
|
| 109 | struct dmar_dev_scope *devices,
|
| 110 | int devices_cnt);
|
| 111 | extern int dmar_remove_dev_scope(struct dmar_pci_notify_info *info,
|
| 112 | u16 segment, struct dmar_dev_scope *devices,
|
| 113 | int count);
|
| 114 |
|
| 115 | extern int detect_intel_iommu(void);
|
| 116 | extern int enable_drhd_fault_handling(void);
|
| 117 | #else
|
| 118 | struct dmar_pci_notify_info;
|
| 119 | static inline int detect_intel_iommu(void)
|
| 120 | {
|
| 121 | return -ENODEV;
|
| 122 | }
|
| 123 |
|
| 124 | static inline int dmar_table_init(void)
|
| 125 | {
|
| 126 | return -ENODEV;
|
| 127 | }
|
| 128 | static inline int enable_drhd_fault_handling(void)
|
| 129 | {
|
| 130 | return -1;
|
| 131 | }
|
| 132 | #endif
|
| 133 |
|
| 134 | struct irte {
|
| 135 | union {
|
| 136 | struct {
|
| 137 | __u64 present : 1,
|
| 138 | fpd : 1,
|
| 139 | dst_mode : 1,
|
| 140 | redir_hint : 1,
|
| 141 | trigger_mode : 1,
|
| 142 | dlvry_mode : 3,
|
| 143 | avail : 4,
|
| 144 | __reserved_1 : 4,
|
| 145 | vector : 8,
|
| 146 | __reserved_2 : 8,
|
| 147 | dest_id : 32;
|
| 148 | };
|
| 149 | __u64 low;
|
| 150 | };
|
| 151 |
|
| 152 | union {
|
| 153 | struct {
|
| 154 | __u64 sid : 16,
|
| 155 | sq : 2,
|
| 156 | svt : 2,
|
| 157 | __reserved_3 : 44;
|
| 158 | };
|
| 159 | __u64 high;
|
| 160 | };
|
| 161 | };
|
| 162 |
|
| 163 | enum {
|
| 164 | IRQ_REMAP_XAPIC_MODE,
|
| 165 | IRQ_REMAP_X2APIC_MODE,
|
| 166 | };
|
| 167 |
|
| 168 | |
| 169 | * since DMAR is not a pci device
|
| 170 |
|
| 171 | struct irq_data;
|
| 172 | extern void dmar_msi_unmask(struct irq_data *data);
|
| 173 | extern void dmar_msi_mask(struct irq_data *data);
|
| 174 | extern void dmar_msi_read(int irq, struct msi_msg *msg);
|
| 175 | extern void dmar_msi_write(int irq, struct msi_msg *msg);
|
| 176 | extern int dmar_set_interrupt(struct intel_iommu *iommu);
|
| 177 | extern irqreturn_t dmar_fault(int irq, void *dev_id);
|
| 178 | extern int arch_setup_dmar_msi(unsigned int irq);
|
| 179 |
|
| 180 | #ifdef CONFIG_INTEL_IOMMU
|
| 181 | extern int iommu_detected, no_iommu;
|
| 182 | extern int dmar_parse_one_rmrr(struct acpi_dmar_header *header);
|
| 183 | extern int dmar_parse_one_atsr(struct acpi_dmar_header *header);
|
| 184 | extern int dmar_iommu_notify_scope_dev(struct dmar_pci_notify_info *info);
|
| 185 | extern int intel_iommu_init(void);
|
| 186 | #else
|
| 187 | static inline int intel_iommu_init(void) { return -ENODEV; }
|
| 188 | static inline int dmar_parse_one_rmrr(struct acpi_dmar_header *header)
|
| 189 | {
|
| 190 | return 0;
|
| 191 | }
|
| 192 | static inline int dmar_parse_one_atsr(struct acpi_dmar_header *header)
|
| 193 | {
|
| 194 | return 0;
|
| 195 | }
|
| 196 | static inline int dmar_iommu_notify_scope_dev(struct dmar_pci_notify_info *info)
|
| 197 | {
|
| 198 | return 0;
|
| 199 | }
|
| 200 | #endif
|
| 201 |
|
| 202 | #endif
|