]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/amd64/vmm/amd/amdvi_priv.h
Merge bmake-20170510
[FreeBSD/FreeBSD.git] / sys / amd64 / vmm / amd / amdvi_priv.h
1 /*-
2  * Copyright (c) 2016 Anish Gupta (anish@freebsd.org)
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice unmodified, this list of conditions, and the following
10  *    disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  *
26  * $FreeBSD$
27  */
28
29 #ifndef _AMDVI_PRIV_H_
30 #define _AMDVI_PRIV_H_
31
32 #define BIT(n)                  (1ULL << (n))
33 /* Return value of bits[n:m] where n and (n >= ) m are bit positions. */
34 #define REG_BITS(x, n, m)       (((x) >> (m)) &                 \
35                                 ((1 << (((n) - (m)) + 1)) - 1))
36
37 /*
38  * IOMMU PCI capability.
39  */
40 #define AMDVI_PCI_CAP_IOTLB     BIT(0)  /* IOTLB is supported. */
41 #define AMDVI_PCI_CAP_HT        BIT(1)  /* HyperTransport tunnel support. */
42 #define AMDVI_PCI_CAP_NPCACHE   BIT(2)  /* Not present page cached. */
43 #define AMDVI_PCI_CAP_EFR       BIT(3)  /* Extended features. */
44 #define AMDVI_PCI_CAP_EXT       BIT(4)  /* Miscellaneous information reg. */
45
46 /*
47  * IOMMU extended features.
48  */
49 #define AMDVI_EX_FEA_PREFSUP    BIT(0)  /* Prefetch command support. */
50 #define AMDVI_EX_FEA_PPRSUP     BIT(1)  /* PPR support */
51 #define AMDVI_EX_FEA_XTSUP      BIT(2)  /* Reserved */
52 #define AMDVI_EX_FEA_NXSUP      BIT(3)  /* No-execute. */
53 #define AMDVI_EX_FEA_GTSUP      BIT(4)  /* Guest translation support. */
54 #define AMDVI_EX_FEA_EFRW       BIT(5)  /* Reserved */
55 #define AMDVI_EX_FEA_IASUP      BIT(6)  /* Invalidate all command supp. */
56 #define AMDVI_EX_FEA_GASUP      BIT(7)  /* Guest APIC or AVIC support. */
57 #define AMDVI_EX_FEA_HESUP      BIT(8)  /* Hardware Error. */
58 #define AMDVI_EX_FEA_PCSUP      BIT(9)  /* Performance counters support. */
59 /* XXX: add more EFER bits. */
60
61 /*
62  * Device table entry or DTE
63  * NOTE: Must be 256-bits/32 bytes aligned.
64  */
65 struct amdvi_dte {
66         uint32_t dt_valid:1;            /* Device Table valid. */
67         uint32_t pt_valid:1;            /* Page translation valid. */
68         uint8_t  :7;                    /* Reserved[8:2] */
69         uint8_t  pt_level:3;            /* Paging level, 0 to disable. */
70         uint64_t pt_base:40;            /* Page table root pointer. */
71         uint8_t  :3;                    /* Reserved[54:52] */
72         uint8_t  gv_valid:1;            /* Revision 2, GVA to SPA. */
73         uint8_t  gv_level:2;            /* Revision 2, GLX level. */
74         uint8_t  gv_cr3_lsb:3;          /* Revision 2, GCR3[14:12] */
75         uint8_t  read_allow:1;          /* I/O read enabled. */
76         uint8_t  write_allow:1;         /* I/O write enabled. */
77         uint8_t  :1;                    /* Reserved[63] */
78         uint16_t domain_id:16;          /* Domain ID */
79         uint16_t gv_cr3_lsb2:16;        /* Revision 2, GCR3[30:15] */
80         uint8_t  iotlb_enable:1;        /* Device support IOTLB */
81         uint8_t  sup_second_io_fault:1; /* Suppress subsequent I/O faults. */
82         uint8_t  sup_all_io_fault:1;    /* Suppress all I/O page faults. */
83         uint8_t  IOctl:2;               /* Port I/O control. */
84         uint8_t  iotlb_cache_disable:1; /* IOTLB cache hints. */
85         uint8_t  snoop_disable:1;       /* Snoop disable. */
86         uint8_t  allow_ex:1;            /* Allow exclusion. */
87         uint8_t  sysmgmt:2;             /* System management message.*/
88         uint8_t  :1;                    /* Reserved[106] */
89         uint32_t gv_cr3_msb:21;         /* Revision 2, GCR3[51:31] */
90         uint8_t  intmap_valid:1;        /* Interrupt map valid. */
91         uint8_t  intmap_len:4;          /* Interrupt map table length. */
92         uint8_t  intmap_ign:1;          /* Ignore unmapped interrupts. */
93         uint64_t intmap_base:46;        /* IntMap base. */
94         uint8_t  :4;                    /* Reserved[183:180] */
95         uint8_t  init_pass:1;           /* INIT pass through or PT */
96         uint8_t  extintr_pass:1;        /* External Interrupt PT */
97         uint8_t  nmi_pass:1;            /* NMI PT */
98         uint8_t  :1;                    /* Reserved[187] */
99         uint8_t  intr_ctrl:2;           /* Interrupt control */
100         uint8_t  lint0_pass:1;          /* LINT0 PT */
101         uint8_t  lint1_pass:1;          /* LINT1 PT */
102         uint64_t :64;                   /* Reserved[255:192] */
103 } __attribute__((__packed__));
104 CTASSERT(sizeof(struct amdvi_dte) == 32);
105
106 /*
107  * IOMMU command entry.
108  */
109 struct amdvi_cmd {
110         uint32_t        word0;
111         uint32_t        word1:28;
112         uint8_t         opcode:4;
113         uint64_t        addr;
114 } __attribute__((__packed__));
115
116 /* Command opcodes. */
117 #define AMDVI_CMP_WAIT_OPCODE   0x1     /* Completion wait. */
118 #define AMDVI_INVD_DTE_OPCODE   0x2     /* Invalidate device table entry. */
119 #define AMDVI_INVD_PAGE_OPCODE  0x3     /* Invalidate pages. */
120 #define AMDVI_INVD_IOTLB_OPCODE 0x4     /* Invalidate IOTLB pages. */
121 #define AMDVI_INVD_INTR_OPCODE  0x5     /* Invalidate Interrupt table. */
122 #define AMDVI_PREFETCH_PAGES_OPCODE     0x6     /* Prefetch IOMMU pages. */
123 #define AMDVI_COMP_PPR_OPCODE   0x7     /* Complete PPR request. */
124 #define AMDVI_INV_ALL_OPCODE    0x8     /* Invalidate all. */
125
126 /* Completion wait attributes. */
127 #define AMDVI_CMP_WAIT_STORE    BIT(0)  /* Write back data. */
128 #define AMDVI_CMP_WAIT_INTR     BIT(1)  /* Completion wait interrupt. */
129 #define AMDVI_CMP_WAIT_FLUSH    BIT(2)  /* Flush queue. */
130
131 /* Invalidate page. */
132 #define AMDVI_INVD_PAGE_S       BIT(0)  /* Invalidation size. */
133 #define AMDVI_INVD_PAGE_PDE     BIT(1)  /* Invalidate PDE. */
134 #define AMDVI_INVD_PAGE_GN_GVA  BIT(2)  /* GPA or GVA. */
135
136 #define AMDVI_INVD_PAGE_ALL_ADDR        (0x7FFFFFFFFFFFFULL << 12)
137
138 /* Invalidate IOTLB. */
139 #define AMDVI_INVD_IOTLB_S      BIT(0)  /* Invalidation size 4k or addr */
140 #define AMDVI_INVD_IOTLB_GN_GVA BIT(2)  /* GPA or GVA. */
141
142 #define AMDVI_INVD_IOTLB_ALL_ADDR       (0x7FFFFFFFFFFFFULL << 12)
143 /* XXX: add more command entries. */
144
145 /*
146  * IOMMU event entry.
147  */
148 struct amdvi_event {
149         uint16_t        devid;
150         uint16_t        pasid_hi;
151         uint16_t        pasid_domid;    /* PASID low or DomainID */
152         uint16_t        flag:12;
153         uint8_t         opcode:4;
154         uint64_t        addr;
155 } __attribute__((__packed__));
156 CTASSERT(sizeof(struct amdvi_event) == 16);
157
158 /* Various event types. */
159 #define AMDVI_EVENT_INVALID_DTE         0x1
160 #define AMDVI_EVENT_PFAULT              0x2
161 #define AMDVI_EVENT_DTE_HW_ERROR        0x3
162 #define AMDVI_EVENT_PAGE_HW_ERROR       0x4
163 #define AMDVI_EVENT_ILLEGAL_CMD         0x5
164 #define AMDVI_EVENT_CMD_HW_ERROR        0x6
165 #define AMDVI_EVENT_IOTLB_TIMEOUT       0x7
166 #define AMDVI_EVENT_INVALID_DTE_REQ     0x8
167 #define AMDVI_EVENT_INVALID_PPR_REQ     0x9
168 #define AMDVI_EVENT_COUNTER_ZERO        0xA
169
170 #define AMDVI_EVENT_FLAG_MASK           0x1FF   /* Mask for event flags. */
171 #define AMDVI_EVENT_FLAG_TYPE(x)        (((x) >> 9) & 0x3)
172
173 /*
174  * IOMMU control block.
175  */
176 struct amdvi_ctrl {
177         struct {
178                 uint16_t size:9;
179                 uint16_t :3;
180                 uint64_t base:40;       /* Devtable register base. */
181                 uint16_t :12;
182         } dte;
183         struct {
184                 uint16_t :12;
185                 uint64_t base:40;
186                 uint8_t  :4;
187                 uint8_t  len:4;
188                 uint8_t  :4;
189         } cmd;
190         struct {
191                 uint16_t :12;
192                 uint64_t base:40;
193                 uint8_t  :4;
194                 uint8_t  len:4;
195                 uint8_t  :4;
196         } event;
197         uint16_t control :13;
198         uint64_t         :51;
199         struct {
200                 uint8_t  enable:1;
201                 uint8_t  allow:1;
202                 uint16_t :10;
203                 uint64_t base:40;
204                 uint16_t :12;
205                 uint16_t :12;
206                 uint64_t limit:40;
207                 uint16_t :12;
208         } excl;
209         /* 
210          * Revision 2 only. 
211          */
212         uint64_t ex_feature;
213         struct {
214                 uint16_t :12;
215                 uint64_t base:40;
216                 uint8_t  :4;
217                 uint8_t  len:4;
218                 uint8_t  :4;
219         } ppr;
220         uint64_t first_event;
221         uint64_t second_event;
222         uint64_t event_status;
223         /* Revision 2 only, end. */
224         uint8_t  pad1[0x1FA8];          /* Padding. */
225         uint32_t cmd_head:19;
226         uint64_t :45;
227         uint32_t cmd_tail:19;
228         uint64_t :45;
229         uint32_t evt_head:19;
230         uint64_t :45;
231         uint32_t evt_tail:19;
232         uint64_t :45;
233         uint64_t :56;
234         uint8_t  status:8;
235         uint64_t pad2;
236         uint8_t  :4;
237         uint16_t ppr_head:15;
238         uint64_t :45;
239         uint8_t  :4;
240         uint16_t ppr_tail:15;
241         uint64_t :45;
242         uint8_t  pad3[0x1FC0];          /* Padding. */
243
244         /* XXX: More for rev2. */
245 } __attribute__((__packed__));
246 CTASSERT(offsetof(struct amdvi_ctrl, pad1)== 0x58);
247 CTASSERT(offsetof(struct amdvi_ctrl, pad2)== 0x2028);
248 CTASSERT(offsetof(struct amdvi_ctrl, pad3)== 0x2040);
249
250 #define AMDVI_MMIO_V1_SIZE      (4 * PAGE_SIZE) /* v1 size */
251 /* 
252  * AMF IOMMU v2 size including event counters 
253  */
254 #define AMDVI_MMIO_V2_SIZE      (8 * PAGE_SIZE)
255
256 CTASSERT(sizeof(struct amdvi_ctrl) == 0x4000);
257 CTASSERT(sizeof(struct amdvi_ctrl) == AMDVI_MMIO_V1_SIZE);
258
259 /* IVHD flag */
260 #define IVHD_FLAG_HTT           BIT(0)  /* Hypertransport Tunnel. */
261 #define IVHD_FLAG_PPW           BIT(1)  /* Pass posted write. */
262 #define IVHD_FLAG_RPPW          BIT(2)  /* Response pass posted write. */
263 #define IVHD_FLAG_ISOC          BIT(3)  /* Isoc support. */
264 #define IVHD_FLAG_IOTLB         BIT(4)  /* IOTLB support. */
265 #define IVHD_FLAG_COH           BIT(5)  /* Coherent control, default 1 */
266 #define IVHD_FLAG_PFS           BIT(6)  /* Prefetch IOMMU pages. */
267 #define IVHD_FLAG_PPRS          BIT(7)  /* Peripheral page support. */
268
269 /* IVHD device entry data setting. */
270 #define IVHD_DEV_LINT0_PASS     BIT(6)  /* LINT0 interrupts. */
271 #define IVHD_DEV_LINT1_PASS     BIT(7)  /* LINT1 interrupts. */
272
273 /* Bit[5:4] for System Mgmt. Bit3 is reserved. */
274 #define IVHD_DEV_INIT_PASS      BIT(0)  /* INIT */
275 #define IVHD_DEV_EXTINTR_PASS   BIT(1)  /* ExtInt */
276 #define IVHD_DEV_NMI_PASS       BIT(2)  /* NMI */
277
278 /* IVHD 8-byte extended data settings. */
279 #define IVHD_DEV_EXT_ATS_DISABLE        BIT(31) /* Disable ATS */
280
281 /* IOMMU control register. */
282 #define AMDVI_CTRL_EN           BIT(0)  /* IOMMU enable. */
283 #define AMDVI_CTRL_HTT          BIT(1)  /* Hypertransport tunnel enable. */
284 #define AMDVI_CTRL_ELOG         BIT(2)  /* Event log enable. */
285 #define AMDVI_CTRL_ELOGINT      BIT(3)  /* Event log interrupt. */
286 #define AMDVI_CTRL_COMINT       BIT(4)  /* Completion wait interrupt. */
287 #define AMDVI_CTRL_PPW          BIT(8)
288 #define AMDVI_CTRL_RPPW         BIT(9)
289 #define AMDVI_CTRL_COH          BIT(10)
290 #define AMDVI_CTRL_ISOC         BIT(11)
291 #define AMDVI_CTRL_CMD          BIT(12) /* Command buffer enable. */
292 #define AMDVI_CTRL_PPRLOG       BIT(13)
293 #define AMDVI_CTRL_PPRINT       BIT(14)
294 #define AMDVI_CTRL_PPREN        BIT(15)
295 #define AMDVI_CTRL_GTE          BIT(16) /* Guest translation enable. */
296 #define AMDVI_CTRL_GAE          BIT(17) /* Guest APIC enable. */
297
298 /* Invalidation timeout. */
299 #define AMDVI_CTRL_INV_NO_TO    0       /* No timeout. */
300 #define AMDVI_CTRL_INV_TO_1ms   1       /* 1 ms */
301 #define AMDVI_CTRL_INV_TO_10ms  2       /* 10 ms */
302 #define AMDVI_CTRL_INV_TO_100ms 3       /* 100 ms */
303 #define AMDVI_CTRL_INV_TO_1S    4       /* 1 second */
304 #define AMDVI_CTRL_INV_TO_10S   5       /* 10 second */
305 #define AMDVI_CTRL_INV_TO_100S  6       /* 100 second */
306
307 /*
308  * Max number of PCI devices.
309  * 256 bus x 32 slot/devices x 8 functions.
310  */
311 #define PCI_NUM_DEV_MAX         0x10000
312
313 /* Maximum number of domains supported by IOMMU. */
314 #define AMDVI_MAX_DOMAIN        (BIT(16) - 1)
315
316 /*
317  * IOMMU Page Table attributes.
318  */
319 #define AMDVI_PT_PRESENT        BIT(0)
320 #define AMDVI_PT_COHERENT       BIT(60)
321 #define AMDVI_PT_READ           BIT(61)
322 #define AMDVI_PT_WRITE          BIT(62)
323
324 #define AMDVI_PT_RW             (AMDVI_PT_READ | AMDVI_PT_WRITE)
325 #define AMDVI_PT_MASK           0xFFFFFFFFFF000UL /* Only [51:12] for PA */
326
327 #define AMDVI_PD_LEVEL_SHIFT    9
328 #define AMDVI_PD_SUPER(x)       (((x) >> AMDVI_PD_LEVEL_SHIFT) == 7)
329 /*
330  * IOMMU Status, offset 0x2020
331  */
332 #define AMDVI_STATUS_EV_OF              BIT(0)  /* Event overflow. */
333 #define AMDVI_STATUS_EV_INTR            BIT(1)  /* Event interrupt. */
334 /* Completion wait command completed. */
335 #define AMDVI_STATUS_CMP                BIT(2)
336
337 #define IVRS_CTRL_RID                   1       /* MMIO RID */
338
339 /* ACPI IVHD */
340 struct ivhd_dev_cfg {
341         uint32_t start_id;
342         uint32_t end_id;
343         uint8_t  data;                  /* Device configuration. */
344         bool     enable_ats;            /* ATS enabled for the device. */
345         int      ats_qlen;              /* ATS invalidation queue depth. */
346 };
347
348 struct amdvi_domain {
349         uint64_t *ptp;                  /* Highest level page table */
350         int     ptp_level;              /* Level of page tables */
351         u_int   id;                     /* Domain id */
352         SLIST_ENTRY (amdvi_domain) next;
353 };
354
355 /*
356  * AMD IOMMU softc.
357  */
358 struct amdvi_softc {
359         struct amdvi_ctrl *ctrl;        /* Control area. */
360         device_t        dev;            /* IOMMU device. */
361         bool            iotlb;          /* IOTLB supported by IOMMU */
362         struct amdvi_cmd *cmd;          /* Command descriptor area. */
363         int             cmd_max;        /* Max number of commands. */
364         uint64_t        cmp_data;       /* Command completion write back. */
365         struct amdvi_event *event;      /* Event descriptor area. */
366         struct resource *event_res;     /* Event interrupt resource. */
367         void            *event_tag;     /* Event interrupt tag. */
368         int             event_max;      /* Max number of events. */
369         int             event_irq;
370         int             event_rid;
371         /* ACPI various flags. */
372         uint32_t        ivhd_flag;      /* ACPI IVHD flag. */
373         uint32_t        ivhd_efr;       /* ACPI v1 Reserved or v2 EFR . */
374         /* PCI related. */
375         uint16_t        cap_off;        /* PCI Capability offset. */
376         uint8_t         pci_cap;        /* PCI capability. */
377         uint64_t        pci_efr;        /* PCI EFR for rev2.0 */
378         uint16_t        pci_seg;        /* IOMMU PCI domain/segment. */
379         uint16_t        pci_rid;        /* PCI BDF of IOMMU */
380         /* Device range under this IOMMU. */
381         uint16_t        start_dev_rid;  /* First device under this IOMMU. */
382         uint16_t        end_dev_rid;    /* Last device under this IOMMU. */
383
384         /* BIOS provided device configuration for end points. */
385         struct          ivhd_dev_cfg dev_cfg[10];
386         int             dev_cfg_cnt;
387
388         /* Software statistics. */
389         uint64_t        event_intr_cnt; /* Total event INTR count. */
390         uint64_t        total_cmd;      /* Total number of commands. */
391 };
392
393 int     amdvi_setup_hw(struct amdvi_softc *softc);
394 int     amdvi_teardown_hw(struct amdvi_softc *softc);
395 #endif /* _AMDVI_PRIV_H_ */