1f363d039SEric Auger /* SPDX-License-Identifier: BSD-3-Clause */
2f363d039SEric Auger /*
3f363d039SEric Auger  * Virtio-iommu definition v0.12
4f363d039SEric Auger  *
5f363d039SEric Auger  * Copyright (C) 2019 Arm Ltd.
6f363d039SEric Auger  */
7f363d039SEric Auger #ifndef _LINUX_VIRTIO_IOMMU_H
8f363d039SEric Auger #define _LINUX_VIRTIO_IOMMU_H
9f363d039SEric Auger 
10f363d039SEric Auger #include "standard-headers/linux/types.h"
11f363d039SEric Auger 
12f363d039SEric Auger /* Feature bits */
13f363d039SEric Auger #define VIRTIO_IOMMU_F_INPUT_RANGE		0
14f363d039SEric Auger #define VIRTIO_IOMMU_F_DOMAIN_RANGE		1
15f363d039SEric Auger #define VIRTIO_IOMMU_F_MAP_UNMAP		2
16f363d039SEric Auger #define VIRTIO_IOMMU_F_BYPASS			3
17f363d039SEric Auger #define VIRTIO_IOMMU_F_PROBE			4
18f363d039SEric Auger #define VIRTIO_IOMMU_F_MMIO			5
19*ef17dd6aSVivek Goyal #define VIRTIO_IOMMU_F_BYPASS_CONFIG		6
20f363d039SEric Auger 
21f363d039SEric Auger struct virtio_iommu_range_64 {
22f363d039SEric Auger 	uint64_t					start;
23f363d039SEric Auger 	uint64_t					end;
24f363d039SEric Auger };
25f363d039SEric Auger 
26f363d039SEric Auger struct virtio_iommu_range_32 {
27f363d039SEric Auger 	uint32_t					start;
28f363d039SEric Auger 	uint32_t					end;
29f363d039SEric Auger };
30f363d039SEric Auger 
31f363d039SEric Auger struct virtio_iommu_config {
32f363d039SEric Auger 	/* Supported page sizes */
33f363d039SEric Auger 	uint64_t					page_size_mask;
34f363d039SEric Auger 	/* Supported IOVA range */
35f363d039SEric Auger 	struct virtio_iommu_range_64		input_range;
36f363d039SEric Auger 	/* Max domain ID size */
37f363d039SEric Auger 	struct virtio_iommu_range_32		domain_range;
38f363d039SEric Auger 	/* Probe buffer size */
39f363d039SEric Auger 	uint32_t					probe_size;
40*ef17dd6aSVivek Goyal 	uint8_t					bypass;
41*ef17dd6aSVivek Goyal 	uint8_t					reserved[3];
42f363d039SEric Auger };
43f363d039SEric Auger 
44f363d039SEric Auger /* Request types */
45f363d039SEric Auger #define VIRTIO_IOMMU_T_ATTACH			0x01
46f363d039SEric Auger #define VIRTIO_IOMMU_T_DETACH			0x02
47f363d039SEric Auger #define VIRTIO_IOMMU_T_MAP			0x03
48f363d039SEric Auger #define VIRTIO_IOMMU_T_UNMAP			0x04
49f363d039SEric Auger #define VIRTIO_IOMMU_T_PROBE			0x05
50f363d039SEric Auger 
51f363d039SEric Auger /* Status types */
52f363d039SEric Auger #define VIRTIO_IOMMU_S_OK			0x00
53f363d039SEric Auger #define VIRTIO_IOMMU_S_IOERR			0x01
54f363d039SEric Auger #define VIRTIO_IOMMU_S_UNSUPP			0x02
55f363d039SEric Auger #define VIRTIO_IOMMU_S_DEVERR			0x03
56f363d039SEric Auger #define VIRTIO_IOMMU_S_INVAL			0x04
57f363d039SEric Auger #define VIRTIO_IOMMU_S_RANGE			0x05
58f363d039SEric Auger #define VIRTIO_IOMMU_S_NOENT			0x06
59f363d039SEric Auger #define VIRTIO_IOMMU_S_FAULT			0x07
60f363d039SEric Auger #define VIRTIO_IOMMU_S_NOMEM			0x08
61f363d039SEric Auger 
62f363d039SEric Auger struct virtio_iommu_req_head {
63f363d039SEric Auger 	uint8_t					type;
64f363d039SEric Auger 	uint8_t					reserved[3];
65f363d039SEric Auger };
66f363d039SEric Auger 
67f363d039SEric Auger struct virtio_iommu_req_tail {
68f363d039SEric Auger 	uint8_t					status;
69f363d039SEric Auger 	uint8_t					reserved[3];
70f363d039SEric Auger };
71f363d039SEric Auger 
72*ef17dd6aSVivek Goyal #define VIRTIO_IOMMU_ATTACH_F_BYPASS		(1 << 0)
73*ef17dd6aSVivek Goyal 
74f363d039SEric Auger struct virtio_iommu_req_attach {
75f363d039SEric Auger 	struct virtio_iommu_req_head		head;
76f363d039SEric Auger 	uint32_t					domain;
77f363d039SEric Auger 	uint32_t					endpoint;
78*ef17dd6aSVivek Goyal 	uint32_t					flags;
79*ef17dd6aSVivek Goyal 	uint8_t					reserved[4];
80f363d039SEric Auger 	struct virtio_iommu_req_tail		tail;
81f363d039SEric Auger };
82f363d039SEric Auger 
83f363d039SEric Auger struct virtio_iommu_req_detach {
84f363d039SEric Auger 	struct virtio_iommu_req_head		head;
85f363d039SEric Auger 	uint32_t					domain;
86f363d039SEric Auger 	uint32_t					endpoint;
87f363d039SEric Auger 	uint8_t					reserved[8];
88f363d039SEric Auger 	struct virtio_iommu_req_tail		tail;
89f363d039SEric Auger };
90f363d039SEric Auger 
91f363d039SEric Auger #define VIRTIO_IOMMU_MAP_F_READ			(1 << 0)
92f363d039SEric Auger #define VIRTIO_IOMMU_MAP_F_WRITE		(1 << 1)
93f363d039SEric Auger #define VIRTIO_IOMMU_MAP_F_MMIO			(1 << 2)
94f363d039SEric Auger 
95f363d039SEric Auger #define VIRTIO_IOMMU_MAP_F_MASK			(VIRTIO_IOMMU_MAP_F_READ |	\
96f363d039SEric Auger 						 VIRTIO_IOMMU_MAP_F_WRITE |	\
97f363d039SEric Auger 						 VIRTIO_IOMMU_MAP_F_MMIO)
98f363d039SEric Auger 
99f363d039SEric Auger struct virtio_iommu_req_map {
100f363d039SEric Auger 	struct virtio_iommu_req_head		head;
101f363d039SEric Auger 	uint32_t					domain;
102f363d039SEric Auger 	uint64_t					virt_start;
103f363d039SEric Auger 	uint64_t					virt_end;
104f363d039SEric Auger 	uint64_t					phys_start;
105f363d039SEric Auger 	uint32_t					flags;
106f363d039SEric Auger 	struct virtio_iommu_req_tail		tail;
107f363d039SEric Auger };
108f363d039SEric Auger 
109f363d039SEric Auger struct virtio_iommu_req_unmap {
110f363d039SEric Auger 	struct virtio_iommu_req_head		head;
111f363d039SEric Auger 	uint32_t					domain;
112f363d039SEric Auger 	uint64_t					virt_start;
113f363d039SEric Auger 	uint64_t					virt_end;
114f363d039SEric Auger 	uint8_t					reserved[4];
115f363d039SEric Auger 	struct virtio_iommu_req_tail		tail;
116f363d039SEric Auger };
117f363d039SEric Auger 
118f363d039SEric Auger #define VIRTIO_IOMMU_PROBE_T_NONE		0
119f363d039SEric Auger #define VIRTIO_IOMMU_PROBE_T_RESV_MEM		1
120f363d039SEric Auger 
121f363d039SEric Auger #define VIRTIO_IOMMU_PROBE_T_MASK		0xfff
122f363d039SEric Auger 
123f363d039SEric Auger struct virtio_iommu_probe_property {
124f363d039SEric Auger 	uint16_t					type;
125f363d039SEric Auger 	uint16_t					length;
126f363d039SEric Auger };
127f363d039SEric Auger 
128f363d039SEric Auger #define VIRTIO_IOMMU_RESV_MEM_T_RESERVED	0
129f363d039SEric Auger #define VIRTIO_IOMMU_RESV_MEM_T_MSI		1
130f363d039SEric Auger 
131f363d039SEric Auger struct virtio_iommu_probe_resv_mem {
132f363d039SEric Auger 	struct virtio_iommu_probe_property	head;
133f363d039SEric Auger 	uint8_t					subtype;
134f363d039SEric Auger 	uint8_t					reserved[3];
135f363d039SEric Auger 	uint64_t					start;
136f363d039SEric Auger 	uint64_t					end;
137f363d039SEric Auger };
138f363d039SEric Auger 
139f363d039SEric Auger struct virtio_iommu_req_probe {
140f363d039SEric Auger 	struct virtio_iommu_req_head		head;
141f363d039SEric Auger 	uint32_t					endpoint;
142f363d039SEric Auger 	uint8_t					reserved[64];
143f363d039SEric Auger 
144f363d039SEric Auger 	uint8_t					properties[];
145f363d039SEric Auger 
146f363d039SEric Auger 	/*
147f363d039SEric Auger 	 * Tail follows the variable-length properties array. No padding,
148f363d039SEric Auger 	 * property lengths are all aligned on 8 bytes.
149f363d039SEric Auger 	 */
150f363d039SEric Auger };
151f363d039SEric Auger 
152f363d039SEric Auger /* Fault types */
153f363d039SEric Auger #define VIRTIO_IOMMU_FAULT_R_UNKNOWN		0
154f363d039SEric Auger #define VIRTIO_IOMMU_FAULT_R_DOMAIN		1
155f363d039SEric Auger #define VIRTIO_IOMMU_FAULT_R_MAPPING		2
156f363d039SEric Auger 
157f363d039SEric Auger #define VIRTIO_IOMMU_FAULT_F_READ		(1 << 0)
158f363d039SEric Auger #define VIRTIO_IOMMU_FAULT_F_WRITE		(1 << 1)
159f363d039SEric Auger #define VIRTIO_IOMMU_FAULT_F_EXEC		(1 << 2)
160f363d039SEric Auger #define VIRTIO_IOMMU_FAULT_F_ADDRESS		(1 << 8)
161f363d039SEric Auger 
162f363d039SEric Auger struct virtio_iommu_fault {
163f363d039SEric Auger 	uint8_t					reason;
164f363d039SEric Auger 	uint8_t					reserved[3];
165f363d039SEric Auger 	uint32_t					flags;
166f363d039SEric Auger 	uint32_t					endpoint;
167f363d039SEric Auger 	uint8_t					reserved2[4];
168f363d039SEric Auger 	uint64_t					address;
169f363d039SEric Auger };
170f363d039SEric Auger 
171f363d039SEric Auger #endif
172