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