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