1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22#ifndef INTEL_IOMMU_H
23#define INTEL_IOMMU_H
24
25#include "hw/i386/x86-iommu.h"
26#include "qemu/iova-tree.h"
27#include "qom/object.h"
28
29#define TYPE_INTEL_IOMMU_DEVICE "intel-iommu"
30OBJECT_DECLARE_SIMPLE_TYPE(IntelIOMMUState, INTEL_IOMMU_DEVICE)
31
32#define TYPE_INTEL_IOMMU_MEMORY_REGION "intel-iommu-iommu-memory-region"
33
34
35#define Q35_HOST_BRIDGE_IOMMU_ADDR 0xfed90000ULL
36
37#define VTD_PCI_BUS_MAX 256
38#define VTD_PCI_SLOT_MAX 32
39#define VTD_PCI_FUNC_MAX 8
40#define VTD_PCI_SLOT(devfn) (((devfn) >> 3) & 0x1f)
41#define VTD_PCI_FUNC(devfn) ((devfn) & 0x07)
42#define VTD_SID_TO_BUS(sid) (((sid) >> 8) & 0xff)
43#define VTD_SID_TO_DEVFN(sid) ((sid) & 0xff)
44
45#define DMAR_REG_SIZE 0x230
46#define VTD_HOST_AW_39BIT 39
47#define VTD_HOST_AW_48BIT 48
48#define VTD_HOST_ADDRESS_WIDTH VTD_HOST_AW_39BIT
49#define VTD_HAW_MASK(aw) ((1ULL << (aw)) - 1)
50
51#define DMAR_REPORT_F_INTR (1)
52
53#define VTD_MSI_ADDR_HI_MASK (0xffffffff00000000ULL)
54#define VTD_MSI_ADDR_HI_SHIFT (32)
55#define VTD_MSI_ADDR_LO_MASK (0x00000000ffffffffULL)
56
57typedef struct VTDContextEntry VTDContextEntry;
58typedef struct VTDContextCacheEntry VTDContextCacheEntry;
59typedef struct VTDAddressSpace VTDAddressSpace;
60typedef struct VTDIOTLBEntry VTDIOTLBEntry;
61typedef struct VTDBus VTDBus;
62typedef union VTD_IR_TableEntry VTD_IR_TableEntry;
63typedef union VTD_IR_MSIAddress VTD_IR_MSIAddress;
64typedef struct VTDPASIDDirEntry VTDPASIDDirEntry;
65typedef struct VTDPASIDEntry VTDPASIDEntry;
66
67
68struct VTDContextEntry {
69 union {
70 struct {
71 uint64_t lo;
72 uint64_t hi;
73 };
74 struct {
75 uint64_t val[4];
76 };
77 };
78};
79
80struct VTDContextCacheEntry {
81
82
83
84 uint32_t context_cache_gen;
85 struct VTDContextEntry context_entry;
86};
87
88
89struct VTDPASIDDirEntry {
90 uint64_t val;
91};
92
93
94struct VTDPASIDEntry {
95 uint64_t val[8];
96};
97
98struct VTDAddressSpace {
99 PCIBus *bus;
100 uint8_t devfn;
101 AddressSpace as;
102 IOMMUMemoryRegion iommu;
103 MemoryRegion root;
104 MemoryRegion nodmar;
105 MemoryRegion iommu_ir;
106 IntelIOMMUState *iommu_state;
107 VTDContextCacheEntry context_cache_entry;
108 QLIST_ENTRY(VTDAddressSpace) next;
109
110 IOMMUNotifierFlag notifier_flags;
111 IOVATree *iova_tree;
112};
113
114struct VTDBus {
115 PCIBus* bus;
116
117 VTDAddressSpace *dev_as[];
118};
119
120struct VTDIOTLBEntry {
121 uint64_t gfn;
122 uint16_t domain_id;
123 uint64_t slpte;
124 uint64_t mask;
125 uint8_t access_flags;
126};
127
128
129enum {
130 VTD_SQ_FULL = 0x00,
131 VTD_SQ_IGN_3 = 0x01,
132 VTD_SQ_IGN_2_3 = 0x02,
133 VTD_SQ_IGN_1_3 = 0x03,
134 VTD_SQ_MAX,
135};
136
137
138enum {
139 VTD_SVT_NONE = 0x00,
140 VTD_SVT_ALL = 0x01,
141 VTD_SVT_BUS = 0x02,
142 VTD_SVT_MAX,
143};
144
145
146union VTD_IR_TableEntry {
147 struct {
148#ifdef HOST_WORDS_BIGENDIAN
149 uint32_t __reserved_1:8;
150 uint32_t vector:8;
151 uint32_t irte_mode:1;
152 uint32_t __reserved_0:3;
153 uint32_t __avail:4;
154 uint32_t delivery_mode:3;
155 uint32_t trigger_mode:1;
156 uint32_t redir_hint:1;
157 uint32_t dest_mode:1;
158 uint32_t fault_disable:1;
159 uint32_t present:1;
160#else
161 uint32_t present:1;
162 uint32_t fault_disable:1;
163 uint32_t dest_mode:1;
164 uint32_t redir_hint:1;
165 uint32_t trigger_mode:1;
166 uint32_t delivery_mode:3;
167 uint32_t __avail:4;
168 uint32_t __reserved_0:3;
169 uint32_t irte_mode:1;
170 uint32_t vector:8;
171 uint32_t __reserved_1:8;
172#endif
173 uint32_t dest_id;
174 uint16_t source_id;
175#ifdef HOST_WORDS_BIGENDIAN
176 uint64_t __reserved_2:44;
177 uint64_t sid_vtype:2;
178 uint64_t sid_q:2;
179#else
180 uint64_t sid_q:2;
181 uint64_t sid_vtype:2;
182 uint64_t __reserved_2:44;
183#endif
184 } QEMU_PACKED irte;
185 uint64_t data[2];
186};
187
188#define VTD_IR_INT_FORMAT_COMPAT (0)
189#define VTD_IR_INT_FORMAT_REMAP (1)
190
191
192union VTD_IR_MSIAddress {
193 struct {
194#ifdef HOST_WORDS_BIGENDIAN
195 uint32_t __head:12;
196 uint32_t index_l:15;
197 uint32_t int_mode:1;
198 uint32_t sub_valid:1;
199 uint32_t index_h:1;
200 uint32_t __not_care:2;
201#else
202 uint32_t __not_care:2;
203 uint32_t index_h:1;
204 uint32_t sub_valid:1;
205 uint32_t int_mode:1;
206 uint32_t index_l:15;
207 uint32_t __head:12;
208#endif
209 } QEMU_PACKED addr;
210 uint32_t data;
211};
212
213
214#define VTD_IR_MSI_DATA (0)
215
216
217struct IntelIOMMUState {
218 X86IOMMUState x86_iommu;
219 MemoryRegion csrmem;
220 MemoryRegion mr_nodmar;
221 MemoryRegion mr_ir;
222 MemoryRegion mr_sys_alias;
223 uint8_t csr[DMAR_REG_SIZE];
224 uint8_t wmask[DMAR_REG_SIZE];
225 uint8_t w1cmask[DMAR_REG_SIZE];
226 uint8_t womask[DMAR_REG_SIZE];
227 uint32_t version;
228
229 bool caching_mode;
230 bool scalable_mode;
231
232 dma_addr_t root;
233 bool root_scalable;
234 bool dmar_enabled;
235
236 uint16_t iq_head;
237 uint16_t iq_tail;
238 dma_addr_t iq;
239 uint16_t iq_size;
240 bool iq_dw;
241 bool qi_enabled;
242 uint8_t iq_last_desc_type;
243
244
245
246
247 uint16_t next_frcd_reg;
248
249 uint64_t cap;
250 uint64_t ecap;
251
252 uint32_t context_cache_gen;
253 GHashTable *iotlb;
254
255 GHashTable *vtd_as_by_busptr;
256 VTDBus *vtd_as_by_bus_num[VTD_PCI_BUS_MAX];
257
258 QLIST_HEAD(, VTDAddressSpace) vtd_as_with_notifiers;
259
260
261 bool intr_enabled;
262 dma_addr_t intr_root;
263 uint32_t intr_size;
264 bool intr_eime;
265 OnOffAuto intr_eim;
266 bool buggy_eim;
267 uint8_t aw_bits;
268 bool dma_drain;
269
270
271
272
273
274 QemuMutex iommu_lock;
275};
276
277
278
279
280VTDAddressSpace *vtd_find_add_as(IntelIOMMUState *s, PCIBus *bus, int devfn);
281
282#endif
283