xref: /freebsd/sys/amd64/vmm/amd/amdvi_priv.h (revision d6b92ffa)
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 	uint16_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_ */
396