summaryrefslogtreecommitdiffstats
path: root/qemu/hw/i386/intel_iommu_internal.h
blob: e5f514c6e360d16c7d1e4ce445e58d9500d47173 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
/*
 * QEMU emulation of an Intel IOMMU (VT-d)
 *   (DMA Remapping device)
 *
 * Copyright (C) 2013 Knut Omang, Oracle <knut.omang@oracle.com>
 * Copyright (C) 2014 Le Tan, <tamlokveer@gmail.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.

 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.

 * You should have received a copy of the GNU General Public License along
 * with this program; if not, see <http://www.gnu.org/licenses/>.
 *
 * Lots of defines copied from kernel/include/linux/intel-iommu.h:
 *   Copyright (C) 2006-2008 Intel Corporation
 *   Author: Ashok Raj <ashok.raj@intel.com>
 *   Author: Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com>
 *
 */

#ifndef HW_I386_INTEL_IOMMU_INTERNAL_H
#define HW_I386_INTEL_IOMMU_INTERNAL_H
#include "hw/i386/intel_iommu.h"

/*
 * Intel IOMMU register specification
 */
#define DMAR_VER_REG            0x0  /* Arch version supported by this IOMMU */
#define DMAR_CAP_REG            0x8  /* Hardware supported capabilities */
#define DMAR_CAP_REG_HI         0xc  /* High 32-bit of DMAR_CAP_REG */
#define DMAR_ECAP_REG           0x10 /* Extended capabilities supported */
#define DMAR_ECAP_REG_HI        0X14
#define DMAR_GCMD_REG           0x18 /* Global command */
#define DMAR_GSTS_REG           0x1c /* Global status */
#define DMAR_RTADDR_REG         0x20 /* Root entry table */
#define DMAR_RTADDR_REG_HI      0X24
#define DMAR_CCMD_REG           0x28 /* Context command */
#define DMAR_CCMD_REG_HI        0x2c
#define DMAR_FSTS_REG           0x34 /* Fault status */
#define DMAR_FECTL_REG          0x38 /* Fault control */
#define DMAR_FEDATA_REG         0x3c /* Fault event interrupt data */
#define DMAR_FEADDR_REG         0x40 /* Fault event interrupt addr */
#define DMAR_FEUADDR_REG        0x44 /* Upper address */
#define DMAR_AFLOG_REG          0x58 /* Advanced fault control */
#define DMAR_AFLOG_REG_HI       0X5c
#define DMAR_PMEN_REG           0x64 /* Enable protected memory region */
#define DMAR_PLMBASE_REG        0x68 /* PMRR low addr */
#define DMAR_PLMLIMIT_REG       0x6c /* PMRR low limit */
#define DMAR_PHMBASE_REG        0x70 /* PMRR high base addr */
#define DMAR_PHMBASE_REG_HI     0X74
#define DMAR_PHMLIMIT_REG       0x78 /* PMRR high limit */
#define DMAR_PHMLIMIT_REG_HI    0x7c
#define DMAR_IQH_REG            0x80 /* Invalidation queue head */
#define DMAR_IQH_REG_HI         0X84
#define DMAR_IQT_REG            0x88 /* Invalidation queue tail */
#define DMAR_IQT_REG_HI         0X8c
#define DMAR_IQA_REG            0x90 /* Invalidation queue addr */
#define DMAR_IQA_REG_HI         0x94
#define DMAR_ICS_REG            0x9c /* Invalidation complete status */
#define DMAR_IRTA_REG           0xb8 /* Interrupt remapping table addr */
#define DMAR_IRTA_REG_HI        0xbc
#define DMAR_IECTL_REG          0xa0 /* Invalidation event control */
#define DMAR_IEDATA_REG         0xa4 /* Invalidation event data */
#define DMAR_IEADDR_REG         0xa8 /* Invalidation event address */
#define DMAR_IEUADDR_REG        0xac /* Invalidation event address */
#define DMAR_PQH_REG            0xc0 /* Page request queue head */
#define DMAR_PQH_REG_HI         0xc4
#define DMAR_PQT_REG            0xc8 /* Page request queue tail*/
#define DMAR_PQT_REG_HI         0xcc
#define DMAR_PQA_REG            0xd0 /* Page request queue address */
#define DMAR_PQA_REG_HI         0xd4
#define DMAR_PRS_REG            0xdc /* Page request status */
#define DMAR_PECTL_REG          0xe0 /* Page request event control */
#define DMAR_PEDATA_REG         0xe4 /* Page request event data */
#define DMAR_PEADDR_REG         0xe8 /* Page request event address */
#define DMAR_PEUADDR_REG        0xec /* Page event upper address */
#define DMAR_MTRRCAP_REG        0x100 /* MTRR capability */
#define DMAR_MTRRCAP_REG_HI     0x104
#define DMAR_MTRRDEF_REG        0x108 /* MTRR default type */
#define DMAR_MTRRDEF_REG_HI     0x10c

/* IOTLB registers */
#define DMAR_IOTLB_REG_OFFSET   0xf0 /* Offset to the IOTLB registers */
#define DMAR_IVA_REG            DMAR_IOTLB_REG_OFFSET /* Invalidate address */
#define DMAR_IVA_REG_HI         (DMAR_IVA_REG + 4)
/* IOTLB invalidate register */
#define DMAR_IOTLB_REG          (DMAR_IOTLB_REG_OFFSET + 0x8)
#define DMAR_IOTLB_REG_HI       (DMAR_IOTLB_REG + 4)

/* FRCD */
#define DMAR_FRCD_REG_OFFSET    0x220 /* Offset to the fault recording regs */
/* NOTICE: If you change the DMAR_FRCD_REG_NR, please remember to change the
 * DMAR_REG_SIZE in include/hw/i386/intel_iommu.h.
 * #define DMAR_REG_SIZE   (DMAR_FRCD_REG_OFFSET + 16 * DMAR_FRCD_REG_NR)
 */
#define DMAR_FRCD_REG_NR        1ULL /* Num of fault recording regs */

#define DMAR_FRCD_REG_0_0       0x220 /* The 0th fault recording regs */
#define DMAR_FRCD_REG_0_1       0x224
#define DMAR_FRCD_REG_0_2       0x228
#define DMAR_FRCD_REG_0_3       0x22c

/* Interrupt Address Range */
#define VTD_INTERRUPT_ADDR_FIRST    0xfee00000ULL
#define VTD_INTERRUPT_ADDR_LAST     0xfeefffffULL

/* The shift of source_id in the key of IOTLB hash table */
#define VTD_IOTLB_SID_SHIFT         36
#define VTD_IOTLB_LVL_SHIFT         44
#define VTD_IOTLB_MAX_SIZE          1024    /* Max size of the hash table */

/* IOTLB_REG */
#define VTD_TLB_GLOBAL_FLUSH        (1ULL << 60) /* Global invalidation */
#define VTD_TLB_DSI_FLUSH           (2ULL << 60) /* Domain-selective */
#define VTD_TLB_PSI_FLUSH           (3ULL << 60) /* Page-selective */
#define VTD_TLB_FLUSH_GRANU_MASK    (3ULL << 60)
#define VTD_TLB_GLOBAL_FLUSH_A      (1ULL << 57)
#define VTD_TLB_DSI_FLUSH_A         (2ULL << 57)
#define VTD_TLB_PSI_FLUSH_A         (3ULL << 57)
#define VTD_TLB_FLUSH_GRANU_MASK_A  (3ULL << 57)
#define VTD_TLB_IVT                 (1ULL << 63)
#define VTD_TLB_DID(val)            (((val) >> 32) & VTD_DOMAIN_ID_MASK)

/* IVA_REG */
#define VTD_IVA_ADDR(val)       ((val) & ~0xfffULL & ((1ULL << VTD_MGAW) - 1))
#define VTD_IVA_AM(val)         ((val) & 0x3fULL)

/* GCMD_REG */
#define VTD_GCMD_TE                 (1UL << 31)
#define VTD_GCMD_SRTP               (1UL << 30)
#define VTD_GCMD_SFL                (1UL << 29)
#define VTD_GCMD_EAFL               (1UL << 28)
#define VTD_GCMD_WBF                (1UL << 27)
#define VTD_GCMD_QIE                (1UL << 26)
#define VTD_GCMD_IRE                (1UL << 25)
#define VTD_GCMD_SIRTP              (1UL << 24)
#define VTD_GCMD_CFI                (1UL << 23)

/* GSTS_REG */
#define VTD_GSTS_TES                (1UL << 31)
#define VTD_GSTS_RTPS               (1UL << 30)
#define VTD_GSTS_FLS                (1UL << 29)
#define VTD_GSTS_AFLS               (1UL << 28)
#define VTD_GSTS_WBFS               (1UL << 27)
#define VTD_GSTS_QIES               (1UL << 26)
#define VTD_GSTS_IRES               (1UL << 25)
#define VTD_GSTS_IRTPS              (1UL << 24)
#define VTD_GSTS_CFIS               (1UL << 23)

/* CCMD_REG */
#define VTD_CCMD_ICC                (1ULL << 63)
#define VTD_CCMD_GLOBAL_INVL        (1ULL << 61)
#define VTD_CCMD_DOMAIN_INVL        (2ULL << 61)
#define VTD_CCMD_DEVICE_INVL        (3ULL << 61)
#define VTD_CCMD_CIRG_MASK          (3ULL << 61)
#define VTD_CCMD_GLOBAL_INVL_A      (1ULL << 59)
#define VTD_CCMD_DOMAIN_INVL_A      (2ULL << 59)
#define VTD_CCMD_DEVICE_INVL_A      (3ULL << 59)
#define VTD_CCMD_CAIG_MASK          (3ULL << 59)
#define VTD_CCMD_DID(val)           ((val) & VTD_DOMAIN_ID_MASK)
#define VTD_CCMD_SID(val)           (((val) >> 16) & 0xffffULL)
#define VTD_CCMD_FM(val)            (((val) >> 32) & 3ULL)

/* RTADDR_REG */
#define VTD_RTADDR_RTT              (1ULL << 11)
#define VTD_RTADDR_ADDR_MASK        (VTD_HAW_MASK ^ 0xfffULL)

/* ECAP_REG */
/* (offset >> 4) << 8 */
#define VTD_ECAP_IRO                (DMAR_IOTLB_REG_OFFSET << 4)
#define VTD_ECAP_QI                 (1ULL << 1)

/* CAP_REG */
/* (offset >> 4) << 24 */
#define VTD_CAP_FRO                 (DMAR_FRCD_REG_OFFSET << 20)
#define VTD_CAP_NFR                 ((DMAR_FRCD_REG_NR - 1) << 40)
#define VTD_DOMAIN_ID_SHIFT         16  /* 16-bit domain id for 64K domains */
#define VTD_DOMAIN_ID_MASK          ((1UL << VTD_DOMAIN_ID_SHIFT) - 1)
#define VTD_CAP_ND                  (((VTD_DOMAIN_ID_SHIFT - 4) / 2) & 7ULL)
#define VTD_MGAW                    39  /* Maximum Guest Address Width */
#define VTD_CAP_MGAW                (((VTD_MGAW - 1) & 0x3fULL) << 16)
#define VTD_MAMV                    18ULL
#define VTD_CAP_MAMV                (VTD_MAMV << 48)
#define VTD_CAP_PSI                 (1ULL << 39)
#define VTD_CAP_SLLPS               ((1ULL << 34) | (1ULL << 35))

/* Supported Adjusted Guest Address Widths */
#define VTD_CAP_SAGAW_SHIFT         8
#define VTD_CAP_SAGAW_MASK          (0x1fULL << VTD_CAP_SAGAW_SHIFT)
 /* 39-bit AGAW, 3-level page-table */
#define VTD_CAP_SAGAW_39bit         (0x2ULL << VTD_CAP_SAGAW_SHIFT)
 /* 48-bit AGAW, 4-level page-table */
#define VTD_CAP_SAGAW_48bit         (0x4ULL << VTD_CAP_SAGAW_SHIFT)
#define VTD_CAP_SAGAW               VTD_CAP_SAGAW_39bit

/* IQT_REG */
#define VTD_IQT_QT(val)             (((val) >> 4) & 0x7fffULL)

/* IQA_REG */
#define VTD_IQA_IQA_MASK            (VTD_HAW_MASK ^ 0xfffULL)
#define VTD_IQA_QS                  0x7ULL

/* IQH_REG */
#define VTD_IQH_QH_SHIFT            4
#define VTD_IQH_QH_MASK             0x7fff0ULL

/* ICS_REG */
#define VTD_ICS_IWC                 1UL

/* IECTL_REG */
#define VTD_IECTL_IM                (1UL << 31)
#define VTD_IECTL_IP                (1UL << 30)

/* FSTS_REG */
#define VTD_FSTS_FRI_MASK       0xff00UL
#define VTD_FSTS_FRI(val)       ((((uint32_t)(val)) << 8) & VTD_FSTS_FRI_MASK)
#define VTD_FSTS_IQE            (1UL << 4)
#define VTD_FSTS_PPF            (1UL << 1)
#define VTD_FSTS_PFO            1UL

/* FECTL_REG */
#define VTD_FECTL_IM            (1UL << 31)
#define VTD_FECTL_IP            (1UL << 30)

/* Fault Recording Register */
/* For the high 64-bit of 128-bit */
#define VTD_FRCD_F              (1ULL << 63)
#define VTD_FRCD_T              (1ULL << 62)
#define VTD_FRCD_FR(val)        (((val) & 0xffULL) << 32)
#define VTD_FRCD_SID_MASK       0xffffULL
#define VTD_FRCD_SID(val)       ((val) & VTD_FRCD_SID_MASK)
/* For the low 64-bit of 128-bit */
#define VTD_FRCD_FI(val)        ((val) & (((1ULL << VTD_MGAW) - 1) ^ 0xfffULL))

/* DMA Remapping Fault Conditions */
typedef enum VTDFaultReason {
    VTD_FR_RESERVED = 0,        /* Reserved for Advanced Fault logging */
    VTD_FR_ROOT_ENTRY_P = 1,    /* The Present(P) field of root-entry is 0 */
    VTD_FR_CONTEXT_ENTRY_P,     /* The Present(P) field of context-entry is 0 */
    VTD_FR_CONTEXT_ENTRY_INV,   /* Invalid programming of a context-entry */
    VTD_FR_ADDR_BEYOND_MGAW,    /* Input-address above (2^x-1) */
    VTD_FR_WRITE,               /* No write permission */
    VTD_FR_READ,                /* No read permission */
    /* Fail to access a second-level paging entry (not SL_PML4E) */
    VTD_FR_PAGING_ENTRY_INV,
    VTD_FR_ROOT_TABLE_INV,      /* Fail to access a root-entry */
    VTD_FR_CONTEXT_TABLE_INV,   /* Fail to access a context-entry */
    /* Non-zero reserved field in a present root-entry */
    VTD_FR_ROOT_ENTRY_RSVD,
    /* Non-zero reserved field in a present context-entry */
    VTD_FR_CONTEXT_ENTRY_RSVD,
    /* Non-zero reserved field in a second-level paging entry with at lease one
     * Read(R) and Write(W) or Execute(E) field is Set.
     */
    VTD_FR_PAGING_ENTRY_RSVD,
    /* Translation request or translated request explicitly blocked dut to the
     * programming of the Translation Type (T) field in the present
     * context-entry.
     */
    VTD_FR_CONTEXT_ENTRY_TT,
    /* This is not a normal fault reason. We use this to indicate some faults
     * that are not referenced by the VT-d specification.
     * Fault event with such reason should not be recorded.
     */
    VTD_FR_RESERVED_ERR,
    VTD_FR_MAX,                 /* Guard */
} VTDFaultReason;

#define VTD_CONTEXT_CACHE_GEN_MAX       0xffffffffUL

/* Queued Invalidation Descriptor */
struct VTDInvDesc {
    uint64_t lo;
    uint64_t hi;
};
typedef struct VTDInvDesc VTDInvDesc;

/* Masks for struct VTDInvDesc */
#define VTD_INV_DESC_TYPE               0xf
#define VTD_INV_DESC_CC                 0x1 /* Context-cache Invalidate Desc */
#define VTD_INV_DESC_IOTLB              0x2
#define VTD_INV_DESC_WAIT               0x5 /* Invalidation Wait Descriptor */
#define VTD_INV_DESC_NONE               0   /* Not an Invalidate Descriptor */

/* Masks for Invalidation Wait Descriptor*/
#define VTD_INV_DESC_WAIT_SW            (1ULL << 5)
#define VTD_INV_DESC_WAIT_IF            (1ULL << 4)
#define VTD_INV_DESC_WAIT_FN            (1ULL << 6)
#define VTD_INV_DESC_WAIT_DATA_SHIFT    32
#define VTD_INV_DESC_WAIT_RSVD_LO       0Xffffff80ULL
#define VTD_INV_DESC_WAIT_RSVD_HI       3ULL

/* Masks for Context-cache Invalidation Descriptor */
#define VTD_INV_DESC_CC_G               (3ULL << 4)
#define VTD_INV_DESC_CC_GLOBAL          (1ULL << 4)
#define VTD_INV_DESC_CC_DOMAIN          (2ULL << 4)
#define VTD_INV_DESC_CC_DEVICE          (3ULL << 4)
#define VTD_INV_DESC_CC_DID(val)        (((val) >> 16) & VTD_DOMAIN_ID_MASK)
#define VTD_INV_DESC_CC_SID(val)        (((val) >> 32) & 0xffffUL)
#define VTD_INV_DESC_CC_FM(val)         (((val) >> 48) & 3UL)
#define VTD_INV_DESC_CC_RSVD            0xfffc00000000ffc0ULL

/* Masks for IOTLB Invalidate Descriptor */
#define VTD_INV_DESC_IOTLB_G            (3ULL << 4)
#define VTD_INV_DESC_IOTLB_GLOBAL       (1ULL << 4)
#define VTD_INV_DESC_IOTLB_DOMAIN       (2ULL << 4)
#define VTD_INV_DESC_IOTLB_PAGE         (3ULL << 4)
#define VTD_INV_DESC_IOTLB_DID(val)     (((val) >> 16) & VTD_DOMAIN_ID_MASK)
#define VTD_INV_DESC_IOTLB_ADDR(val)    ((val) & ~0xfffULL & \
                                         ((1ULL << VTD_MGAW) - 1))
#define VTD_INV_DESC_IOTLB_AM(val)      ((val) & 0x3fULL)
#define VTD_INV_DESC_IOTLB_RSVD_LO      0xffffffff0000ff00ULL
#define VTD_INV_DESC_IOTLB_RSVD_HI      0xf80ULL

/* Information about page-selective IOTLB invalidate */
struct VTDIOTLBPageInvInfo {
    uint16_t domain_id;
    uint64_t addr;
    uint8_t mask;
};
typedef struct VTDIOTLBPageInvInfo VTDIOTLBPageInvInfo;

/* Pagesize of VTD paging structures, including root and context tables */
#define VTD_PAGE_SHIFT              12
#define VTD_PAGE_SIZE               (1ULL << VTD_PAGE_SHIFT)

#define VTD_PAGE_SHIFT_4K           12
#define VTD_PAGE_MASK_4K            (~((1ULL << VTD_PAGE_SHIFT_4K) - 1))
#define VTD_PAGE_SHIFT_2M           21
#define VTD_PAGE_MASK_2M            (~((1ULL << VTD_PAGE_SHIFT_2M) - 1))
#define VTD_PAGE_SHIFT_1G           30
#define VTD_PAGE_MASK_1G            (~((1ULL << VTD_PAGE_SHIFT_1G) - 1))

struct VTDRootEntry {
    uint64_t val;
    uint64_t rsvd;
};
typedef struct VTDRootEntry VTDRootEntry;

/* Masks for struct VTDRootEntry */
#define VTD_ROOT_ENTRY_P            1ULL
#define VTD_ROOT_ENTRY_CTP          (~0xfffULL)

#define VTD_ROOT_ENTRY_NR           (VTD_PAGE_SIZE / sizeof(VTDRootEntry))
#define VTD_ROOT_ENTRY_RSVD         (0xffeULL | ~VTD_HAW_MASK)

/* Masks for struct VTDContextEntry */
/* lo */
#define VTD_CONTEXT_ENTRY_P         (1ULL << 0)
#define VTD_CONTEXT_ENTRY_FPD       (1ULL << 1) /* Fault Processing Disable */
#define VTD_CONTEXT_ENTRY_TT        (3ULL << 2) /* Translation Type */
#define VTD_CONTEXT_TT_MULTI_LEVEL  0
#define VTD_CONTEXT_TT_DEV_IOTLB    1
#define VTD_CONTEXT_TT_PASS_THROUGH 2
/* Second Level Page Translation Pointer*/
#define VTD_CONTEXT_ENTRY_SLPTPTR   (~0xfffULL)
#define VTD_CONTEXT_ENTRY_RSVD_LO   (0xff0ULL | ~VTD_HAW_MASK)
/* hi */
#define VTD_CONTEXT_ENTRY_AW        7ULL /* Adjusted guest-address-width */
#define VTD_CONTEXT_ENTRY_DID(val)  (((val) >> 8) & VTD_DOMAIN_ID_MASK)
#define VTD_CONTEXT_ENTRY_RSVD_HI   0xffffffffff000080ULL

#define VTD_CONTEXT_ENTRY_NR        (VTD_PAGE_SIZE / sizeof(VTDContextEntry))

/* Paging Structure common */
#define VTD_SL_PT_PAGE_SIZE_MASK    (1ULL << 7)
/* Bits to decide the offset for each level */
#define VTD_SL_LEVEL_BITS           9

/* Second Level Paging Structure */
#define VTD_SL_PML4_LEVEL           4
#define VTD_SL_PDP_LEVEL            3
#define VTD_SL_PD_LEVEL             2
#define VTD_SL_PT_LEVEL             1
#define VTD_SL_PT_ENTRY_NR          512

/* Masks for Second Level Paging Entry */
#define VTD_SL_RW_MASK              3ULL
#define VTD_SL_R                    1ULL
#define VTD_SL_W                    (1ULL << 1)
#define VTD_SL_PT_BASE_ADDR_MASK    (~(VTD_PAGE_SIZE - 1) & VTD_HAW_MASK)
#define VTD_SL_IGN_COM              0xbff0000000000000ULL

#endif