1 /*
2 * ARM GICv3 ITS support
3 *
4 * Andre Przywara <andre.przywara@arm.com>
5 * Copyright (c) 2016,2017 ARM Ltd.
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; under version 2 of the License.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #ifndef __ASM_ARM_ITS_H__
21 #define __ASM_ARM_ITS_H__
22
23 #define GITS_CTLR 0x000
24 #define GITS_IIDR 0x004
25 #define GITS_TYPER 0x008
26 #define GITS_CBASER 0x080
27 #define GITS_CWRITER 0x088
28 #define GITS_CREADR 0x090
29 #define GITS_BASER_NR_REGS 8
30 #define GITS_BASER0 0x100
31 #define GITS_BASER1 0x108
32 #define GITS_BASER2 0x110
33 #define GITS_BASER3 0x118
34 #define GITS_BASER4 0x120
35 #define GITS_BASER5 0x128
36 #define GITS_BASER6 0x130
37 #define GITS_BASER7 0x138
38 #define GITS_PIDR2 GICR_PIDR2
39
40 /* Register bits */
41 #define GITS_VALID_BIT BIT(63)
42
43 #define GITS_CTLR_QUIESCENT BIT(31)
44 #define GITS_CTLR_ENABLE BIT(0)
45
46 #define GITS_TYPER_PTA BIT(19)
47 #define GITS_TYPER_DEVIDS_SHIFT 13
48 #define GITS_TYPER_DEVIDS_MASK (0x1fUL << GITS_TYPER_DEVIDS_SHIFT)
49 #define GITS_TYPER_DEVICE_ID_BITS(r) (((r & GITS_TYPER_DEVIDS_MASK) >> \
50 GITS_TYPER_DEVIDS_SHIFT) + 1)
51
52 #define GITS_TYPER_IDBITS_SHIFT 8
53 #define GITS_TYPER_IDBITS_MASK (0x1fUL << GITS_TYPER_IDBITS_SHIFT)
54 #define GITS_TYPER_EVENT_ID_BITS(r) (((r & GITS_TYPER_IDBITS_MASK) >> \
55 GITS_TYPER_IDBITS_SHIFT) + 1)
56
57 #define GITS_TYPER_ITT_SIZE_SHIFT 4
58 #define GITS_TYPER_ITT_SIZE_MASK (0xfUL << GITS_TYPER_ITT_SIZE_SHIFT)
59 #define GITS_TYPER_ITT_SIZE(r) ((((r) & GITS_TYPER_ITT_SIZE_MASK) >> \
60 GITS_TYPER_ITT_SIZE_SHIFT) + 1)
61 #define GITS_TYPER_PHYSICAL (1U << 0)
62
63 #define GITS_BASER_INDIRECT BIT(62)
64 #define GITS_BASER_INNER_CACHEABILITY_SHIFT 59
65 #define GITS_BASER_TYPE_SHIFT 56
66 #define GITS_BASER_TYPE_MASK (7ULL << GITS_BASER_TYPE_SHIFT)
67 #define GITS_BASER_OUTER_CACHEABILITY_SHIFT 53
68 #define GITS_BASER_TYPE_NONE 0UL
69 #define GITS_BASER_TYPE_DEVICE 1UL
70 #define GITS_BASER_TYPE_VCPU 2UL
71 #define GITS_BASER_TYPE_CPU 3UL
72 #define GITS_BASER_TYPE_COLLECTION 4UL
73 #define GITS_BASER_TYPE_RESERVED5 5UL
74 #define GITS_BASER_TYPE_RESERVED6 6UL
75 #define GITS_BASER_TYPE_RESERVED7 7UL
76 #define GITS_BASER_ENTRY_SIZE_SHIFT 48
77 #define GITS_BASER_ENTRY_SIZE(reg) \
78 (((reg >> GITS_BASER_ENTRY_SIZE_SHIFT) & 0x1f) + 1)
79 #define GITS_BASER_SHAREABILITY_SHIFT 10
80 #define GITS_BASER_PAGE_SIZE_SHIFT 8
81 #define GITS_BASER_SIZE_MASK 0xff
82 #define GITS_BASER_SHAREABILITY_MASK (0x3ULL << GITS_BASER_SHAREABILITY_SHIFT)
83 #define GITS_BASER_OUTER_CACHEABILITY_MASK (0x7ULL << GITS_BASER_OUTER_CACHEABILITY_SHIFT)
84 #define GITS_BASER_INNER_CACHEABILITY_MASK (0x7ULL << GITS_BASER_INNER_CACHEABILITY_SHIFT)
85
86 #define GITS_CBASER_SIZE_MASK 0xff
87
88 /* ITS command definitions */
89 #define ITS_CMD_SIZE 32
90
91 #define GITS_CMD_MOVI 0x01
92 #define GITS_CMD_INT 0x03
93 #define GITS_CMD_CLEAR 0x04
94 #define GITS_CMD_SYNC 0x05
95 #define GITS_CMD_MAPD 0x08
96 #define GITS_CMD_MAPC 0x09
97 #define GITS_CMD_MAPTI 0x0a
98 #define GITS_CMD_MAPI 0x0b
99 #define GITS_CMD_INV 0x0c
100 #define GITS_CMD_INVALL 0x0d
101 #define GITS_CMD_MOVALL 0x0e
102 #define GITS_CMD_DISCARD 0x0f
103
104 #define ITS_DOORBELL_OFFSET 0x10040
105 #define GICV3_ITS_SIZE SZ_128K
106
107 #include <xen/device_tree.h>
108 #include <xen/rbtree.h>
109
110 #define HOST_ITS_FLUSH_CMD_QUEUE (1U << 0)
111 #define HOST_ITS_USES_PTA (1U << 1)
112
113 /* We allocate LPIs on the hosts in chunks of 32 to reduce handling overhead. */
114 #define LPI_BLOCK 32U
115
116 /* data structure for each hardware ITS */
117 struct host_its {
118 struct list_head entry;
119 const struct dt_device_node *dt_node;
120 paddr_t addr;
121 paddr_t size;
122 void __iomem *its_base;
123 unsigned int devid_bits;
124 unsigned int evid_bits;
125 unsigned int itte_size;
126 spinlock_t cmd_lock;
127 void *cmd_buf;
128 unsigned int flags;
129 };
130
131
132 #ifdef CONFIG_HAS_ITS
133
134 extern struct list_head host_its_list;
135
136 /* Parse the host DT and pick up all host ITSes. */
137 void gicv3_its_dt_init(const struct dt_device_node *node);
138
139 #ifdef CONFIG_ACPI
140 void gicv3_its_acpi_init(void);
141 unsigned long gicv3_its_make_hwdom_madt(const struct domain *d,
142 void *base_ptr);
143 #endif
144
145 /* Deny iomem access for its */
146 int gicv3_its_deny_access(const struct domain *d);
147
148 bool gicv3_its_host_has_its(void);
149
150 unsigned int vgic_v3_its_count(const struct domain *d);
151
152 void gicv3_do_LPI(unsigned int lpi);
153
154 int gicv3_lpi_init_rdist(void __iomem * rdist_base);
155
156 /* Initialize the host structures for LPIs and the host ITSes. */
157 int gicv3_lpi_init_host_lpis(unsigned int host_lpi_bits);
158 int gicv3_its_init(void);
159
160 /* Store the physical address and ID for each redistributor as read from DT. */
161 void gicv3_set_redist_address(paddr_t address, unsigned int redist_id);
162 uint64_t gicv3_get_redist_address(unsigned int cpu, bool use_pta);
163
164 /* Map a collection for this host CPU to each host ITS. */
165 int gicv3_its_setup_collection(unsigned int cpu);
166
167 /* Initialize and destroy the per-domain parts of the virtual ITS support. */
168 int vgic_v3_its_init_domain(struct domain *d);
169 void vgic_v3_its_free_domain(struct domain *d);
170
171 /* Create the appropriate DT nodes for a hardware domain. */
172 int gicv3_its_make_hwdom_dt_nodes(const struct domain *d,
173 const struct dt_device_node *gic,
174 void *fdt);
175
176 /*
177 * Map a device on the host by allocating an ITT on the host (ITS).
178 * "nr_event" specifies how many events (interrupts) this device will need.
179 * Setting "valid" to false deallocates the device.
180 */
181 int gicv3_its_map_guest_device(struct domain *d,
182 paddr_t host_doorbell, uint32_t host_devid,
183 paddr_t guest_doorbell, uint32_t guest_devid,
184 uint64_t nr_events, bool valid);
185
186 int gicv3_allocate_host_lpi_block(struct domain *d, uint32_t *first_lpi);
187 void gicv3_free_host_lpi_block(uint32_t first_lpi);
188
189 void vgic_vcpu_inject_lpi(struct domain *d, unsigned int virq);
190
191 struct pending_irq *gicv3_its_get_event_pending_irq(struct domain *d,
192 paddr_t vdoorbell_address,
193 uint32_t vdevid,
194 uint32_t eventid);
195 int gicv3_remove_guest_event(struct domain *d, paddr_t vdoorbell_address,
196 uint32_t vdevid, uint32_t eventid);
197 struct pending_irq *gicv3_assign_guest_event(struct domain *d, paddr_t doorbell,
198 uint32_t devid, uint32_t eventid,
199 uint32_t virt_lpi);
200 void gicv3_lpi_update_host_entry(uint32_t host_lpi, int domain_id,
201 uint32_t virt_lpi);
202
203 #else
204
gicv3_its_dt_init(const struct dt_device_node * node)205 static inline void gicv3_its_dt_init(const struct dt_device_node *node)
206 {
207 }
208
209 #ifdef CONFIG_ACPI
gicv3_its_acpi_init(void)210 static inline void gicv3_its_acpi_init(void)
211 {
212 }
213
gicv3_its_make_hwdom_madt(const struct domain * d,void * base_ptr)214 static inline unsigned long gicv3_its_make_hwdom_madt(const struct domain *d,
215 void *base_ptr)
216 {
217 return 0;
218 }
219 #endif
220
gicv3_its_deny_access(const struct domain * d)221 static inline int gicv3_its_deny_access(const struct domain *d)
222 {
223 return 0;
224 }
225
gicv3_its_host_has_its(void)226 static inline bool gicv3_its_host_has_its(void)
227 {
228 return false;
229 }
230
vgic_v3_its_count(const struct domain * d)231 static inline unsigned int vgic_v3_its_count(const struct domain *d)
232 {
233 return 0;
234 }
235
gicv3_do_LPI(unsigned int lpi)236 static inline void gicv3_do_LPI(unsigned int lpi)
237 {
238 /* We don't enable LPIs without an ITS. */
239 BUG();
240 }
241
gicv3_lpi_init_rdist(void __iomem * rdist_base)242 static inline int gicv3_lpi_init_rdist(void __iomem * rdist_base)
243 {
244 return -ENODEV;
245 }
246
gicv3_lpi_init_host_lpis(unsigned int host_lpi_bits)247 static inline int gicv3_lpi_init_host_lpis(unsigned int host_lpi_bits)
248 {
249 return 0;
250 }
251
gicv3_its_init(void)252 static inline int gicv3_its_init(void)
253 {
254 return 0;
255 }
256
gicv3_set_redist_address(paddr_t address,unsigned int redist_id)257 static inline void gicv3_set_redist_address(paddr_t address,
258 unsigned int redist_id)
259 {
260 }
261
gicv3_its_setup_collection(unsigned int cpu)262 static inline int gicv3_its_setup_collection(unsigned int cpu)
263 {
264 /* We should never get here without an ITS. */
265 BUG();
266 }
267
vgic_v3_its_init_domain(struct domain * d)268 static inline int vgic_v3_its_init_domain(struct domain *d)
269 {
270 return 0;
271 }
272
vgic_v3_its_free_domain(struct domain * d)273 static inline void vgic_v3_its_free_domain(struct domain *d)
274 {
275 }
276
gicv3_its_make_hwdom_dt_nodes(const struct domain * d,const struct dt_device_node * gic,void * fdt)277 static inline int gicv3_its_make_hwdom_dt_nodes(const struct domain *d,
278 const struct dt_device_node *gic,
279 void *fdt)
280 {
281 return 0;
282 }
283
284 #endif /* CONFIG_HAS_ITS */
285
286 #endif
287
288 /*
289 * Local variables:
290 * mode: C
291 * c-file-style: "BSD"
292 * c-basic-offset: 4
293 * indent-tabs-mode: nil
294 * End:
295 */
296