xref: /freebsd/sys/amd64/vmm/amd/amdvi_priv.h (revision f3754afd5901857787271e73f9c34d3b9069a03f)
107ff474aSAnish Gupta /*-
2*4d846d26SWarner Losh  * SPDX-License-Identifier: BSD-2-Clause
3ebc3c37cSMarcelo Araujo  *
407ff474aSAnish Gupta  * Copyright (c) 2016 Anish Gupta (anish@freebsd.org)
5b5c74dfdSKa Ho Ng  * Copyright (c) 2021 The FreeBSD Foundation
6b5c74dfdSKa Ho Ng  *
7b5c74dfdSKa Ho Ng  * Portions of this software were developed by Ka Ho Ng
8b5c74dfdSKa Ho Ng  * under sponsorship from the FreeBSD Foundation.
907ff474aSAnish Gupta  *
1007ff474aSAnish Gupta  * Redistribution and use in source and binary forms, with or without
1107ff474aSAnish Gupta  * modification, are permitted provided that the following conditions
1207ff474aSAnish Gupta  * are met:
1307ff474aSAnish Gupta  * 1. Redistributions of source code must retain the above copyright
1407ff474aSAnish Gupta  *    notice unmodified, this list of conditions, and the following
1507ff474aSAnish Gupta  *    disclaimer.
1607ff474aSAnish Gupta  * 2. Redistributions in binary form must reproduce the above copyright
1707ff474aSAnish Gupta  *    notice, this list of conditions and the following disclaimer in the
1807ff474aSAnish Gupta  *    documentation and/or other materials provided with the distribution.
1907ff474aSAnish Gupta  *
2007ff474aSAnish Gupta  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
2107ff474aSAnish Gupta  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
2207ff474aSAnish Gupta  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
2307ff474aSAnish Gupta  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
2407ff474aSAnish Gupta  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
2507ff474aSAnish Gupta  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2607ff474aSAnish Gupta  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2707ff474aSAnish Gupta  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2807ff474aSAnish Gupta  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
2907ff474aSAnish Gupta  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3007ff474aSAnish Gupta  */
3107ff474aSAnish Gupta 
3207ff474aSAnish Gupta #ifndef _AMDVI_PRIV_H_
3307ff474aSAnish Gupta #define _AMDVI_PRIV_H_
3407ff474aSAnish Gupta 
350b37d3d9SAnish Gupta #include <contrib/dev/acpica/include/acpi.h>
360b37d3d9SAnish Gupta 
3707ff474aSAnish Gupta #define	BIT(n)			(1ULL << (n))
3807ff474aSAnish Gupta /* Return value of bits[n:m] where n and (n >= ) m are bit positions. */
3907ff474aSAnish Gupta #define REG_BITS(x, n, m)	(((x) >> (m)) & 		\
4007ff474aSAnish Gupta 				((1 << (((n) - (m)) + 1)) - 1))
4107ff474aSAnish Gupta 
4207ff474aSAnish Gupta /*
4307ff474aSAnish Gupta  * IOMMU PCI capability.
4407ff474aSAnish Gupta  */
4507ff474aSAnish Gupta #define AMDVI_PCI_CAP_IOTLB	BIT(0)	/* IOTLB is supported. */
4607ff474aSAnish Gupta #define AMDVI_PCI_CAP_HT	BIT(1)	/* HyperTransport tunnel support. */
4707ff474aSAnish Gupta #define AMDVI_PCI_CAP_NPCACHE	BIT(2)	/* Not present page cached. */
4807ff474aSAnish Gupta #define AMDVI_PCI_CAP_EFR	BIT(3)	/* Extended features. */
4907ff474aSAnish Gupta #define AMDVI_PCI_CAP_EXT	BIT(4)	/* Miscellaneous information reg. */
5007ff474aSAnish Gupta 
5107ff474aSAnish Gupta /*
5207ff474aSAnish Gupta  * IOMMU extended features.
5307ff474aSAnish Gupta  */
5407ff474aSAnish Gupta #define AMDVI_EX_FEA_PREFSUP	BIT(0)	/* Prefetch command support. */
5507ff474aSAnish Gupta #define AMDVI_EX_FEA_PPRSUP	BIT(1)	/* PPR support */
5607ff474aSAnish Gupta #define AMDVI_EX_FEA_XTSUP	BIT(2)	/* Reserved */
5707ff474aSAnish Gupta #define AMDVI_EX_FEA_NXSUP	BIT(3)	/* No-execute. */
5807ff474aSAnish Gupta #define AMDVI_EX_FEA_GTSUP	BIT(4)	/* Guest translation support. */
5907ff474aSAnish Gupta #define AMDVI_EX_FEA_EFRW	BIT(5)	/* Reserved */
6007ff474aSAnish Gupta #define AMDVI_EX_FEA_IASUP	BIT(6)	/* Invalidate all command supp. */
6107ff474aSAnish Gupta #define AMDVI_EX_FEA_GASUP	BIT(7)	/* Guest APIC or AVIC support. */
6207ff474aSAnish Gupta #define AMDVI_EX_FEA_HESUP	BIT(8)	/* Hardware Error. */
6307ff474aSAnish Gupta #define AMDVI_EX_FEA_PCSUP	BIT(9)	/* Performance counters support. */
6407ff474aSAnish Gupta /* XXX: add more EFER bits. */
6507ff474aSAnish Gupta 
6607ff474aSAnish Gupta /*
6707ff474aSAnish Gupta  * Device table entry or DTE
6807ff474aSAnish Gupta  * NOTE: Must be 256-bits/32 bytes aligned.
6907ff474aSAnish Gupta  */
7007ff474aSAnish Gupta struct amdvi_dte {
7107ff474aSAnish Gupta 	uint32_t dt_valid:1;		/* Device Table valid. */
7207ff474aSAnish Gupta 	uint32_t pt_valid:1;		/* Page translation valid. */
735228ad10SRyan Libby 	uint16_t :7;			/* Reserved[8:2] */
7407ff474aSAnish Gupta 	uint8_t	 pt_level:3;		/* Paging level, 0 to disable. */
7507ff474aSAnish Gupta 	uint64_t pt_base:40;		/* Page table root pointer. */
7607ff474aSAnish Gupta 	uint8_t  :3;			/* Reserved[54:52] */
7707ff474aSAnish Gupta 	uint8_t	 gv_valid:1;		/* Revision 2, GVA to SPA. */
7807ff474aSAnish Gupta 	uint8_t	 gv_level:2;		/* Revision 2, GLX level. */
7907ff474aSAnish Gupta 	uint8_t	 gv_cr3_lsb:3;		/* Revision 2, GCR3[14:12] */
8007ff474aSAnish Gupta 	uint8_t	 read_allow:1;		/* I/O read enabled. */
8107ff474aSAnish Gupta 	uint8_t	 write_allow:1;		/* I/O write enabled. */
8207ff474aSAnish Gupta 	uint8_t  :1;			/* Reserved[63] */
8307ff474aSAnish Gupta 	uint16_t domain_id:16;		/* Domain ID */
8407ff474aSAnish Gupta 	uint16_t gv_cr3_lsb2:16;	/* Revision 2, GCR3[30:15] */
8507ff474aSAnish Gupta 	uint8_t	 iotlb_enable:1;	/* Device support IOTLB */
8607ff474aSAnish Gupta 	uint8_t	 sup_second_io_fault:1;	/* Suppress subsequent I/O faults. */
8707ff474aSAnish Gupta 	uint8_t	 sup_all_io_fault:1;	/* Suppress all I/O page faults. */
8807ff474aSAnish Gupta 	uint8_t	 IOctl:2;		/* Port I/O control. */
8907ff474aSAnish Gupta 	uint8_t	 iotlb_cache_disable:1;	/* IOTLB cache hints. */
9007ff474aSAnish Gupta 	uint8_t	 snoop_disable:1;	/* Snoop disable. */
9107ff474aSAnish Gupta 	uint8_t	 allow_ex:1;		/* Allow exclusion. */
9207ff474aSAnish Gupta 	uint8_t	 sysmgmt:2;		/* System management message.*/
9307ff474aSAnish Gupta 	uint8_t  :1;			/* Reserved[106] */
9407ff474aSAnish Gupta 	uint32_t gv_cr3_msb:21;		/* Revision 2, GCR3[51:31] */
9507ff474aSAnish Gupta 	uint8_t	 intmap_valid:1;	/* Interrupt map valid. */
9607ff474aSAnish Gupta 	uint8_t	 intmap_len:4;		/* Interrupt map table length. */
9707ff474aSAnish Gupta 	uint8_t	 intmap_ign:1;		/* Ignore unmapped interrupts. */
9807ff474aSAnish Gupta 	uint64_t intmap_base:46;	/* IntMap base. */
9907ff474aSAnish Gupta 	uint8_t  :4;			/* Reserved[183:180] */
10007ff474aSAnish Gupta 	uint8_t	 init_pass:1;		/* INIT pass through or PT */
10107ff474aSAnish Gupta 	uint8_t	 extintr_pass:1;	/* External Interrupt PT */
10207ff474aSAnish Gupta 	uint8_t	 nmi_pass:1;		/* NMI PT */
10307ff474aSAnish Gupta 	uint8_t  :1;			/* Reserved[187] */
10407ff474aSAnish Gupta 	uint8_t	 intr_ctrl:2;		/* Interrupt control */
10507ff474aSAnish Gupta 	uint8_t	 lint0_pass:1;		/* LINT0 PT */
10607ff474aSAnish Gupta 	uint8_t	 lint1_pass:1;		/* LINT1 PT */
10707ff474aSAnish Gupta 	uint64_t :64;			/* Reserved[255:192] */
10807ff474aSAnish Gupta } __attribute__((__packed__));
10907ff474aSAnish Gupta CTASSERT(sizeof(struct amdvi_dte) == 32);
11007ff474aSAnish Gupta 
11107ff474aSAnish Gupta /*
11207ff474aSAnish Gupta  * IOMMU command entry.
11307ff474aSAnish Gupta  */
11407ff474aSAnish Gupta struct amdvi_cmd {
11507ff474aSAnish Gupta 	uint32_t 	word0;
11607ff474aSAnish Gupta 	uint32_t 	word1:28;
11707ff474aSAnish Gupta 	uint8_t		opcode:4;
11807ff474aSAnish Gupta 	uint64_t 	addr;
11907ff474aSAnish Gupta } __attribute__((__packed__));
12007ff474aSAnish Gupta 
12107ff474aSAnish Gupta /* Command opcodes. */
12207ff474aSAnish Gupta #define AMDVI_CMP_WAIT_OPCODE	0x1	/* Completion wait. */
12307ff474aSAnish Gupta #define AMDVI_INVD_DTE_OPCODE	0x2	/* Invalidate device table entry. */
12407ff474aSAnish Gupta #define AMDVI_INVD_PAGE_OPCODE	0x3	/* Invalidate pages. */
12507ff474aSAnish Gupta #define AMDVI_INVD_IOTLB_OPCODE	0x4	/* Invalidate IOTLB pages. */
12607ff474aSAnish Gupta #define AMDVI_INVD_INTR_OPCODE	0x5	/* Invalidate Interrupt table. */
12707ff474aSAnish Gupta #define AMDVI_PREFETCH_PAGES_OPCODE	0x6	/* Prefetch IOMMU pages. */
12807ff474aSAnish Gupta #define AMDVI_COMP_PPR_OPCODE	0x7	/* Complete PPR request. */
12907ff474aSAnish Gupta #define AMDVI_INV_ALL_OPCODE	0x8	/* Invalidate all. */
13007ff474aSAnish Gupta 
13107ff474aSAnish Gupta /* Completion wait attributes. */
13207ff474aSAnish Gupta #define AMDVI_CMP_WAIT_STORE	BIT(0)	/* Write back data. */
13307ff474aSAnish Gupta #define AMDVI_CMP_WAIT_INTR	BIT(1)	/* Completion wait interrupt. */
13407ff474aSAnish Gupta #define AMDVI_CMP_WAIT_FLUSH	BIT(2)	/* Flush queue. */
13507ff474aSAnish Gupta 
13607ff474aSAnish Gupta /* Invalidate page. */
13707ff474aSAnish Gupta #define AMDVI_INVD_PAGE_S	BIT(0)	/* Invalidation size. */
13807ff474aSAnish Gupta #define AMDVI_INVD_PAGE_PDE	BIT(1)	/* Invalidate PDE. */
13907ff474aSAnish Gupta #define AMDVI_INVD_PAGE_GN_GVA	BIT(2)	/* GPA or GVA. */
14007ff474aSAnish Gupta 
14107ff474aSAnish Gupta #define AMDVI_INVD_PAGE_ALL_ADDR	(0x7FFFFFFFFFFFFULL << 12)
14207ff474aSAnish Gupta 
14307ff474aSAnish Gupta /* Invalidate IOTLB. */
14407ff474aSAnish Gupta #define AMDVI_INVD_IOTLB_S	BIT(0)	/* Invalidation size 4k or addr */
14507ff474aSAnish Gupta #define AMDVI_INVD_IOTLB_GN_GVA	BIT(2)	/* GPA or GVA. */
14607ff474aSAnish Gupta 
14707ff474aSAnish Gupta #define AMDVI_INVD_IOTLB_ALL_ADDR	(0x7FFFFFFFFFFFFULL << 12)
14807ff474aSAnish Gupta /* XXX: add more command entries. */
14907ff474aSAnish Gupta 
15007ff474aSAnish Gupta /*
15107ff474aSAnish Gupta  * IOMMU event entry.
15207ff474aSAnish Gupta  */
15307ff474aSAnish Gupta struct amdvi_event {
15407ff474aSAnish Gupta 	uint16_t 	devid;
15507ff474aSAnish Gupta 	uint16_t 	pasid_hi;
15607ff474aSAnish Gupta 	uint16_t 	pasid_domid;	/* PASID low or DomainID */
15707ff474aSAnish Gupta 	uint16_t 	flag:12;
15807ff474aSAnish Gupta 	uint8_t		opcode:4;
15907ff474aSAnish Gupta 	uint64_t 	addr;
16007ff474aSAnish Gupta } __attribute__((__packed__));
16107ff474aSAnish Gupta CTASSERT(sizeof(struct amdvi_event) == 16);
16207ff474aSAnish Gupta 
16307ff474aSAnish Gupta /* Various event types. */
16407ff474aSAnish Gupta #define AMDVI_EVENT_INVALID_DTE		0x1
16507ff474aSAnish Gupta #define AMDVI_EVENT_PFAULT		0x2
16607ff474aSAnish Gupta #define AMDVI_EVENT_DTE_HW_ERROR	0x3
16707ff474aSAnish Gupta #define AMDVI_EVENT_PAGE_HW_ERROR	0x4
16807ff474aSAnish Gupta #define AMDVI_EVENT_ILLEGAL_CMD		0x5
16907ff474aSAnish Gupta #define AMDVI_EVENT_CMD_HW_ERROR	0x6
17007ff474aSAnish Gupta #define AMDVI_EVENT_IOTLB_TIMEOUT	0x7
17107ff474aSAnish Gupta #define AMDVI_EVENT_INVALID_DTE_REQ	0x8
17207ff474aSAnish Gupta #define AMDVI_EVENT_INVALID_PPR_REQ	0x9
17307ff474aSAnish Gupta #define AMDVI_EVENT_COUNTER_ZERO	0xA
17407ff474aSAnish Gupta 
17507ff474aSAnish Gupta #define AMDVI_EVENT_FLAG_MASK           0x1FF	/* Mask for event flags. */
17607ff474aSAnish Gupta #define AMDVI_EVENT_FLAG_TYPE(x)        (((x) >> 9) & 0x3)
17707ff474aSAnish Gupta 
17807ff474aSAnish Gupta /*
17907ff474aSAnish Gupta  * IOMMU control block.
18007ff474aSAnish Gupta  */
18107ff474aSAnish Gupta struct amdvi_ctrl {
18207ff474aSAnish Gupta 	struct {
18307ff474aSAnish Gupta 		uint16_t size:9;
18407ff474aSAnish Gupta 		uint16_t :3;
18507ff474aSAnish Gupta 		uint64_t base:40;	/* Devtable register base. */
18607ff474aSAnish Gupta 		uint16_t :12;
18707ff474aSAnish Gupta 	} dte;
18807ff474aSAnish Gupta 	struct {
18907ff474aSAnish Gupta 		uint16_t :12;
19007ff474aSAnish Gupta 		uint64_t base:40;
19107ff474aSAnish Gupta 		uint8_t  :4;
19207ff474aSAnish Gupta 		uint8_t	 len:4;
19307ff474aSAnish Gupta 		uint8_t  :4;
19407ff474aSAnish Gupta 	} cmd;
19507ff474aSAnish Gupta 	struct {
19607ff474aSAnish Gupta 		uint16_t :12;
19707ff474aSAnish Gupta 		uint64_t base:40;
19807ff474aSAnish Gupta 		uint8_t  :4;
19907ff474aSAnish Gupta 		uint8_t	 len:4;
20007ff474aSAnish Gupta 		uint8_t  :4;
20107ff474aSAnish Gupta 	} event;
20207ff474aSAnish Gupta 	uint16_t control :13;
20307ff474aSAnish Gupta 	uint64_t	 :51;
20407ff474aSAnish Gupta 	struct {
20507ff474aSAnish Gupta 		uint8_t	 enable:1;
20607ff474aSAnish Gupta 		uint8_t	 allow:1;
20707ff474aSAnish Gupta 		uint16_t :10;
20807ff474aSAnish Gupta 		uint64_t base:40;
20907ff474aSAnish Gupta 		uint16_t :12;
21007ff474aSAnish Gupta 		uint16_t :12;
21107ff474aSAnish Gupta 		uint64_t limit:40;
21207ff474aSAnish Gupta 		uint16_t :12;
21307ff474aSAnish Gupta 	} excl;
21407ff474aSAnish Gupta 	/*
21507ff474aSAnish Gupta 	 * Revision 2 only.
21607ff474aSAnish Gupta 	 */
21707ff474aSAnish Gupta 	uint64_t ex_feature;
21807ff474aSAnish Gupta 	struct {
21907ff474aSAnish Gupta 		uint16_t :12;
22007ff474aSAnish Gupta 		uint64_t base:40;
22107ff474aSAnish Gupta 		uint8_t  :4;
22207ff474aSAnish Gupta 		uint8_t	 len:4;
22307ff474aSAnish Gupta 		uint8_t  :4;
22407ff474aSAnish Gupta 	} ppr;
22507ff474aSAnish Gupta 	uint64_t first_event;
22607ff474aSAnish Gupta 	uint64_t second_event;
22707ff474aSAnish Gupta 	uint64_t event_status;
22807ff474aSAnish Gupta 	/* Revision 2 only, end. */
22907ff474aSAnish Gupta 	uint8_t	 pad1[0x1FA8];		/* Padding. */
23007ff474aSAnish Gupta 	uint32_t cmd_head:19;
23107ff474aSAnish Gupta 	uint64_t :45;
23207ff474aSAnish Gupta 	uint32_t cmd_tail:19;
23307ff474aSAnish Gupta 	uint64_t :45;
23407ff474aSAnish Gupta 	uint32_t evt_head:19;
23507ff474aSAnish Gupta 	uint64_t :45;
23607ff474aSAnish Gupta 	uint32_t evt_tail:19;
23707ff474aSAnish Gupta 	uint64_t :45;
23853d580f9SAndriy Gapon 	uint32_t status:19;
2395a041f21SAndriy Gapon 	uint64_t :45;
24007ff474aSAnish Gupta 	uint64_t pad2;
24107ff474aSAnish Gupta 	uint8_t  :4;
24207ff474aSAnish Gupta 	uint16_t ppr_head:15;
24307ff474aSAnish Gupta 	uint64_t :45;
24407ff474aSAnish Gupta 	uint8_t  :4;
24507ff474aSAnish Gupta 	uint16_t ppr_tail:15;
24607ff474aSAnish Gupta 	uint64_t :45;
24707ff474aSAnish Gupta 	uint8_t	 pad3[0x1FC0];		/* Padding. */
24807ff474aSAnish Gupta 
24907ff474aSAnish Gupta 	/* XXX: More for rev2. */
25007ff474aSAnish Gupta } __attribute__((__packed__));
25107ff474aSAnish Gupta CTASSERT(offsetof(struct amdvi_ctrl, pad1)== 0x58);
25207ff474aSAnish Gupta CTASSERT(offsetof(struct amdvi_ctrl, pad2)== 0x2028);
25307ff474aSAnish Gupta CTASSERT(offsetof(struct amdvi_ctrl, pad3)== 0x2040);
25407ff474aSAnish Gupta 
25507ff474aSAnish Gupta #define AMDVI_MMIO_V1_SIZE	(4 * PAGE_SIZE)	/* v1 size */
25607ff474aSAnish Gupta /*
25707ff474aSAnish Gupta  * AMF IOMMU v2 size including event counters
25807ff474aSAnish Gupta  */
25907ff474aSAnish Gupta #define AMDVI_MMIO_V2_SIZE	(8 * PAGE_SIZE)
26007ff474aSAnish Gupta 
26107ff474aSAnish Gupta CTASSERT(sizeof(struct amdvi_ctrl) == 0x4000);
26207ff474aSAnish Gupta CTASSERT(sizeof(struct amdvi_ctrl) == AMDVI_MMIO_V1_SIZE);
26307ff474aSAnish Gupta 
26407ff474aSAnish Gupta /* IVHD flag */
26507ff474aSAnish Gupta #define IVHD_FLAG_HTT		BIT(0)	/* Hypertransport Tunnel. */
26607ff474aSAnish Gupta #define IVHD_FLAG_PPW		BIT(1)	/* Pass posted write. */
26707ff474aSAnish Gupta #define IVHD_FLAG_RPPW		BIT(2)	/* Response pass posted write. */
26807ff474aSAnish Gupta #define IVHD_FLAG_ISOC		BIT(3)	/* Isoc support. */
26907ff474aSAnish Gupta #define IVHD_FLAG_IOTLB		BIT(4)	/* IOTLB support. */
27007ff474aSAnish Gupta #define IVHD_FLAG_COH		BIT(5)	/* Coherent control, default 1 */
27107ff474aSAnish Gupta #define IVHD_FLAG_PFS		BIT(6)	/* Prefetch IOMMU pages. */
27207ff474aSAnish Gupta #define IVHD_FLAG_PPRS		BIT(7)	/* Peripheral page support. */
27307ff474aSAnish Gupta 
27407ff474aSAnish Gupta /* IVHD device entry data setting. */
27507ff474aSAnish Gupta #define IVHD_DEV_LINT0_PASS	BIT(6)	/* LINT0 interrupts. */
27607ff474aSAnish Gupta #define IVHD_DEV_LINT1_PASS	BIT(7)	/* LINT1 interrupts. */
27707ff474aSAnish Gupta 
27807ff474aSAnish Gupta /* Bit[5:4] for System Mgmt. Bit3 is reserved. */
27907ff474aSAnish Gupta #define IVHD_DEV_INIT_PASS	BIT(0)	/* INIT */
28007ff474aSAnish Gupta #define IVHD_DEV_EXTINTR_PASS	BIT(1)	/* ExtInt */
28107ff474aSAnish Gupta #define IVHD_DEV_NMI_PASS	BIT(2)	/* NMI */
28207ff474aSAnish Gupta 
28307ff474aSAnish Gupta /* IVHD 8-byte extended data settings. */
28407ff474aSAnish Gupta #define IVHD_DEV_EXT_ATS_DISABLE	BIT(31)	/* Disable ATS */
28507ff474aSAnish Gupta 
28607ff474aSAnish Gupta /* IOMMU control register. */
28707ff474aSAnish Gupta #define AMDVI_CTRL_EN		BIT(0)	/* IOMMU enable. */
28807ff474aSAnish Gupta #define AMDVI_CTRL_HTT		BIT(1)	/* Hypertransport tunnel enable. */
28907ff474aSAnish Gupta #define AMDVI_CTRL_ELOG		BIT(2)	/* Event log enable. */
29007ff474aSAnish Gupta #define AMDVI_CTRL_ELOGINT	BIT(3)	/* Event log interrupt. */
29107ff474aSAnish Gupta #define AMDVI_CTRL_COMINT	BIT(4)	/* Completion wait interrupt. */
29207ff474aSAnish Gupta #define AMDVI_CTRL_PPW		BIT(8)
29307ff474aSAnish Gupta #define AMDVI_CTRL_RPPW		BIT(9)
29407ff474aSAnish Gupta #define AMDVI_CTRL_COH		BIT(10)
29507ff474aSAnish Gupta #define AMDVI_CTRL_ISOC		BIT(11)
29607ff474aSAnish Gupta #define AMDVI_CTRL_CMD		BIT(12)	/* Command buffer enable. */
29707ff474aSAnish Gupta #define AMDVI_CTRL_PPRLOG	BIT(13)
29807ff474aSAnish Gupta #define AMDVI_CTRL_PPRINT	BIT(14)
29907ff474aSAnish Gupta #define AMDVI_CTRL_PPREN	BIT(15)
30007ff474aSAnish Gupta #define AMDVI_CTRL_GTE		BIT(16)	/* Guest translation enable. */
30107ff474aSAnish Gupta #define AMDVI_CTRL_GAE		BIT(17)	/* Guest APIC enable. */
30207ff474aSAnish Gupta 
30307ff474aSAnish Gupta /* Invalidation timeout. */
30407ff474aSAnish Gupta #define AMDVI_CTRL_INV_NO_TO	0	/* No timeout. */
30507ff474aSAnish Gupta #define AMDVI_CTRL_INV_TO_1ms	1	/* 1 ms */
30607ff474aSAnish Gupta #define AMDVI_CTRL_INV_TO_10ms	2	/* 10 ms */
30707ff474aSAnish Gupta #define AMDVI_CTRL_INV_TO_100ms	3	/* 100 ms */
30807ff474aSAnish Gupta #define AMDVI_CTRL_INV_TO_1S	4	/* 1 second */
30907ff474aSAnish Gupta #define AMDVI_CTRL_INV_TO_10S	5	/* 10 second */
31007ff474aSAnish Gupta #define AMDVI_CTRL_INV_TO_100S	6	/* 100 second */
31107ff474aSAnish Gupta 
31207ff474aSAnish Gupta /*
31307ff474aSAnish Gupta  * Max number of PCI devices.
31407ff474aSAnish Gupta  * 256 bus x 32 slot/devices x 8 functions.
31507ff474aSAnish Gupta  */
31607ff474aSAnish Gupta #define PCI_NUM_DEV_MAX		0x10000
31707ff474aSAnish Gupta 
31807ff474aSAnish Gupta /* Maximum number of domains supported by IOMMU. */
31907ff474aSAnish Gupta #define AMDVI_MAX_DOMAIN	(BIT(16) - 1)
32007ff474aSAnish Gupta 
32107ff474aSAnish Gupta /*
32207ff474aSAnish Gupta  * IOMMU Page Table attributes.
32307ff474aSAnish Gupta  */
32407ff474aSAnish Gupta #define AMDVI_PT_PRESENT	BIT(0)
32507ff474aSAnish Gupta #define AMDVI_PT_COHERENT	BIT(60)
32607ff474aSAnish Gupta #define AMDVI_PT_READ		BIT(61)
32707ff474aSAnish Gupta #define AMDVI_PT_WRITE		BIT(62)
32807ff474aSAnish Gupta 
32907ff474aSAnish Gupta #define AMDVI_PT_RW		(AMDVI_PT_READ | AMDVI_PT_WRITE)
33007ff474aSAnish Gupta #define AMDVI_PT_MASK		0xFFFFFFFFFF000UL /* Only [51:12] for PA */
33107ff474aSAnish Gupta 
33207ff474aSAnish Gupta #define AMDVI_PD_LEVEL_SHIFT	9
33307ff474aSAnish Gupta #define AMDVI_PD_SUPER(x)	(((x) >> AMDVI_PD_LEVEL_SHIFT) == 7)
33407ff474aSAnish Gupta /*
33507ff474aSAnish Gupta  * IOMMU Status, offset 0x2020
33607ff474aSAnish Gupta  */
33707ff474aSAnish Gupta #define AMDVI_STATUS_EV_OF		BIT(0)	/* Event overflow. */
33807ff474aSAnish Gupta #define AMDVI_STATUS_EV_INTR		BIT(1)	/* Event interrupt. */
33907ff474aSAnish Gupta /* Completion wait command completed. */
34007ff474aSAnish Gupta #define AMDVI_STATUS_CMP		BIT(2)
34107ff474aSAnish Gupta 
34207ff474aSAnish Gupta #define	IVRS_CTRL_RID			1	/* MMIO RID */
34307ff474aSAnish Gupta 
34407ff474aSAnish Gupta /* ACPI IVHD */
34507ff474aSAnish Gupta struct ivhd_dev_cfg {
34607ff474aSAnish Gupta 	uint32_t start_id;
34707ff474aSAnish Gupta 	uint32_t end_id;
34807ff474aSAnish Gupta 	uint8_t	 data;			/* Device configuration. */
34907ff474aSAnish Gupta 	bool	 enable_ats;		/* ATS enabled for the device. */
35007ff474aSAnish Gupta 	int	 ats_qlen;		/* ATS invalidation queue depth. */
35107ff474aSAnish Gupta };
35207ff474aSAnish Gupta 
35307ff474aSAnish Gupta struct amdvi_domain {
35407ff474aSAnish Gupta 	uint64_t *ptp;			/* Highest level page table */
35507ff474aSAnish Gupta 	int	ptp_level;		/* Level of page tables */
35607ff474aSAnish Gupta 	u_int	id;			/* Domain id */
35707ff474aSAnish Gupta 	SLIST_ENTRY (amdvi_domain) next;
35807ff474aSAnish Gupta };
35907ff474aSAnish Gupta 
36007ff474aSAnish Gupta /*
3619363000dSAnish Gupta  * Different type of IVHD.
3629363000dSAnish Gupta  * XXX: Use AcpiIvrsType once new IVHD types are available.
3639363000dSAnish Gupta */
3649363000dSAnish Gupta enum IvrsType
3659363000dSAnish Gupta {
3663ee58df5SJung-uk Kim 	IVRS_TYPE_HARDWARE_LEGACY = ACPI_IVRS_TYPE_HARDWARE1,
3673ee58df5SJung-uk Kim 					/* Legacy without EFRi support. */
3683ee58df5SJung-uk Kim 	IVRS_TYPE_HARDWARE_EFR	  = ACPI_IVRS_TYPE_HARDWARE2,
3693ee58df5SJung-uk Kim 						/* With EFR support. */
3709363000dSAnish Gupta 	IVRS_TYPE_HARDWARE_MIXED  = 0x40, /* Mixed with EFR support. */
3719363000dSAnish Gupta };
3729363000dSAnish Gupta 
3739363000dSAnish Gupta /*
37407ff474aSAnish Gupta  * AMD IOMMU softc.
37507ff474aSAnish Gupta  */
37607ff474aSAnish Gupta struct amdvi_softc {
37707ff474aSAnish Gupta 	struct amdvi_ctrl *ctrl;	/* Control area. */
37807ff474aSAnish Gupta 	device_t 	dev;		/* IOMMU device. */
37974ada297SKa Ho Ng 	device_t 	pci_dev;	/* IOMMU PCI function device. */
3809363000dSAnish Gupta 	enum IvrsType   ivhd_type;	/* IOMMU IVHD type. */
38107ff474aSAnish Gupta 	bool		iotlb;		/* IOTLB supported by IOMMU */
38207ff474aSAnish Gupta 	struct amdvi_cmd *cmd;		/* Command descriptor area. */
38307ff474aSAnish Gupta 	int 		cmd_max;	/* Max number of commands. */
38407ff474aSAnish Gupta 	uint64_t	cmp_data;	/* Command completion write back. */
38507ff474aSAnish Gupta 	struct amdvi_event *event;	/* Event descriptor area. */
38607ff474aSAnish Gupta 	int		event_max;	/* Max number of events. */
38707ff474aSAnish Gupta 	/* ACPI various flags. */
38807ff474aSAnish Gupta 	uint32_t 	ivhd_flag;	/* ACPI IVHD flag. */
3890b37d3d9SAnish Gupta 	uint32_t 	ivhd_feature;	/* ACPI v1 Reserved or v2 attribute. */
3900b37d3d9SAnish Gupta 	uint64_t 	ext_feature;	/* IVHD EFR */
39107ff474aSAnish Gupta 	/* PCI related. */
39207ff474aSAnish Gupta 	uint16_t 	cap_off;	/* PCI Capability offset. */
39307ff474aSAnish Gupta 	uint8_t		pci_cap;	/* PCI capability. */
39407ff474aSAnish Gupta 	uint16_t 	pci_seg;	/* IOMMU PCI domain/segment. */
39507ff474aSAnish Gupta 	uint16_t 	pci_rid;	/* PCI BDF of IOMMU */
39607ff474aSAnish Gupta 
397b5c74dfdSKa Ho Ng 	/* ACPI device configuration for end points. */
398b5c74dfdSKa Ho Ng 	struct 		ivhd_dev_cfg *dev_cfg;
39907ff474aSAnish Gupta 	int		dev_cfg_cnt;
400b5c74dfdSKa Ho Ng 	int		dev_cfg_cap;
40107ff474aSAnish Gupta 
40207ff474aSAnish Gupta 	/* Software statistics. */
40307ff474aSAnish Gupta 	uint64_t 	event_intr_cnt;	/* Total event INTR count. */
40407ff474aSAnish Gupta 	uint64_t 	total_cmd;	/* Total number of commands. */
40507ff474aSAnish Gupta };
40607ff474aSAnish Gupta 
40707ff474aSAnish Gupta int	amdvi_setup_hw(struct amdvi_softc *softc);
40807ff474aSAnish Gupta int	amdvi_teardown_hw(struct amdvi_softc *softc);
40907ff474aSAnish Gupta #endif /* _AMDVI_PRIV_H_ */
410