2 * Jailhouse, a Linux-based partitioning hypervisor
4 * Copyright (c) ARM Limited, 2014
7 * Jean-Philippe Brucker <jean-philippe.brucker@arm.com>
9 * This work is licensed under the terms of the GNU GPL, version 2. See
10 * the COPYING file in the top-level directory.
13 #include <jailhouse/entry.h>
14 #include <jailhouse/mmio.h>
15 #include <jailhouse/paging.h>
16 #include <jailhouse/printk.h>
17 #include <jailhouse/string.h>
18 #include <asm/gic_common.h>
19 #include <asm/irqchip.h>
20 #include <asm/platform.h>
21 #include <asm/setup.h>
22 #include <asm/sysregs.h>
25 #define AMBA_DEVICE 0xb105f00d
28 unsigned long gicd_size;
31 * The init function must be called after the MMU setup, and whilst in the
32 * per-cpu setup, which means that a bool must be set by the master CPU
34 static bool irqchip_is_init;
35 static struct irqchip_ops irqchip;
37 bool spi_in_cell(struct cell *cell, unsigned int spi)
39 /* FIXME: Change the configuration to a bitmask range */
45 spi_mask = cell->arch.spis >> 32;
47 spi_mask = cell->arch.spis;
49 return spi_mask & (1 << (spi & 31));
52 static int irqchip_init_pending(struct per_cpu *cpu_data)
54 struct pending_irq *pend_array;
56 if (cpu_data->pending_irqs == NULL) {
57 cpu_data->pending_irqs = pend_array = page_alloc(&mem_pool, 1);
58 if (pend_array == NULL)
61 pend_array = cpu_data->pending_irqs;
64 memset(pend_array, 0, PAGE_SIZE);
66 cpu_data->pending_irqs = pend_array;
67 cpu_data->first_pending = NULL;
73 * Find the first available pending struct for insertion. The `prev' pointer is
74 * set to the previous pending interrupt, if any, to help inserting the new one
76 * Returns NULL when no slot is available
78 static struct pending_irq* get_pending_slot(struct per_cpu *cpu_data,
79 struct pending_irq **prev)
82 struct pending_irq *pending = cpu_data->first_pending;
86 for (i = 0; i < MAX_PENDING_IRQS; i++) {
87 pending_idx = pending - cpu_data->pending_irqs;
88 if (pending == NULL || i < pending_idx)
89 return cpu_data->pending_irqs + i;
92 pending = pending->next;
98 int irqchip_insert_pending(struct per_cpu *cpu_data, struct pending_irq *irq)
100 struct pending_irq *prev = NULL;
101 struct pending_irq *slot;
103 spin_lock(&cpu_data->gic_lock);
105 slot = get_pending_slot(cpu_data, &prev);
107 spin_unlock(&cpu_data->gic_lock);
112 * Don't override the pointers yet, they may be read by the injection
113 * loop. Odds are astronomically low, but hey.
115 memcpy(slot, irq, sizeof(struct pending_irq) - 2 * sizeof(void *));
118 slot->next = prev->next;
121 slot->next = cpu_data->first_pending;
122 cpu_data->first_pending = slot;
125 slot->next->prev = slot;
127 spin_unlock(&cpu_data->gic_lock);
132 int irqchip_set_pending(struct per_cpu *cpu_data, u32 irq_id, bool try_inject)
134 struct pending_irq pending;
136 pending.virt_id = irq_id;
138 if (is_sgi(irq_id)) {
140 pending.type.sgi.cpuid = 0;
143 pending.type.irq = irq_id;
146 if (try_inject && irqchip.inject_irq(cpu_data, &pending) == 0)
149 return irqchip_insert_pending(cpu_data, &pending);
153 * Only executed by `irqchip_inject_pending' on a CPU to inject its own stuff.
155 int irqchip_remove_pending(struct per_cpu *cpu_data, struct pending_irq *irq)
157 spin_lock(&cpu_data->gic_lock);
159 if (cpu_data->first_pending == irq)
160 cpu_data->first_pending = irq->next;
162 irq->prev->next = irq->next;
164 irq->next->prev = irq->prev;
166 spin_unlock(&cpu_data->gic_lock);
171 int irqchip_inject_pending(struct per_cpu *cpu_data)
174 struct pending_irq *pending = cpu_data->first_pending;
176 while (pending != NULL) {
177 err = irqchip.inject_irq(cpu_data, pending);
179 /* The list registers are full. */
183 * Removal only changes the pointers, but does not
184 * deallocate anything.
185 * Concurrent accesses are avoided with the spinlock,
186 * but the `next' pointer of the current pending object
187 * may be rewritten by an external insert before or
188 * after this removal, which isn't an issue.
190 irqchip_remove_pending(cpu_data, pending);
192 pending = pending->next;
198 void irqchip_handle_irq(struct per_cpu *cpu_data)
200 irqchip.handle_irq(cpu_data);
203 void irqchip_eoi_irq(u32 irqn, bool deactivate)
205 irqchip.eoi_irq(irqn, deactivate);
208 int irqchip_send_sgi(struct sgi *sgi)
210 return irqchip.send_sgi(sgi);
213 int irqchip_cpu_init(struct per_cpu *cpu_data)
217 err = irqchip_init_pending(cpu_data);
221 if (irqchip.cpu_init)
222 return irqchip.cpu_init(cpu_data);
227 int irqchip_cpu_reset(struct per_cpu *cpu_data)
231 err = irqchip_init_pending(cpu_data);
235 if (irqchip.cpu_reset)
236 return irqchip.cpu_reset(cpu_data, false);
241 void irqchip_cpu_shutdown(struct per_cpu *cpu_data)
244 * The GIC backend must take care of only resetting the hyp interface if
245 * it has been initialised: this function may be executed during the
248 if (irqchip.cpu_reset)
249 irqchip.cpu_reset(cpu_data, true);
252 static const struct jailhouse_irqchip *
253 irqchip_find_config(struct jailhouse_cell_desc *config)
255 const struct jailhouse_irqchip *irq_config =
256 jailhouse_cell_irqchips(config);
258 if (config->num_irqchips)
264 int irqchip_cell_init(struct cell *cell)
266 const struct jailhouse_irqchip *pins = irqchip_find_config(cell->config);
268 cell->arch.spis = (pins ? pins->pin_bitmap : 0);
270 return irqchip.cell_init(cell);
273 void irqchip_cell_exit(struct cell *cell)
275 const struct jailhouse_irqchip *root_pins =
276 irqchip_find_config(root_cell.config);
278 /* might be called by arch_shutdown while rolling back
280 if (!irqchip_is_init)
284 root_cell.arch.spis |= cell->arch.spis & root_pins->pin_bitmap;
286 irqchip.cell_exit(cell);
289 void irqchip_root_cell_shrink(struct cell *cell)
291 root_cell.arch.spis &= ~(cell->arch.spis);
294 /* Only the GIC is implemented */
295 extern struct irqchip_ops gic_irqchip;
297 int irqchip_init(void)
303 /* Only executed on master CPU */
307 /* FIXME: parse device tree */
308 gicd_base = GICD_BASE;
309 gicd_size = GICD_SIZE;
311 if ((err = arch_map_device(gicd_base, gicd_base, gicd_size)) != 0)
314 for (i = 3; i >= 0; i--) {
315 cidr = mmio_read32(gicd_base + GICD_CIDR0 + i * 4);
316 dev_id |= cidr << i * 8;
318 if (dev_id != AMBA_DEVICE)
319 goto err_no_distributor;
321 /* Probe the GIC version */
322 pidr2 = mmio_read32(gicd_base + GICD_PIDR2);
323 switch (GICD_PIDR2_ARCH(pidr2)) {
327 memcpy(&irqchip, &gic_irqchip, sizeof(struct irqchip_ops));
332 err = irqchip.init();
333 irqchip_is_init = true;
339 printk("GIC: no distributor found\n");
340 arch_unmap_device(gicd_base, gicd_size);