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 void irqchip_set_pending(struct per_cpu *cpu_data, u16 irq_id)
54 bool local_injection = (this_cpu_data() == cpu_data);
55 unsigned int new_tail;
57 if (local_injection && irqchip.inject_irq(cpu_data, irq_id) != -EBUSY)
60 spin_lock(&cpu_data->pending_irqs_lock);
62 new_tail = (cpu_data->pending_irqs_tail + 1) % MAX_PENDING_IRQS;
64 /* Queue space available? */
65 if (new_tail != cpu_data->pending_irqs_head) {
66 cpu_data->pending_irqs[cpu_data->pending_irqs_tail] = irq_id;
67 cpu_data->pending_irqs_tail = new_tail;
69 * Make the change to pending_irqs_tail visible before the
70 * caller sends SGI_INJECT.
75 spin_unlock(&cpu_data->pending_irqs_lock);
78 * The list registers are full, trigger maintenance interrupt if we are
79 * on the target CPU. In the other case, the caller will send a
80 * SGI_INJECT, and irqchip_inject_pending will take care.
83 irqchip.enable_maint_irq(true);
86 void irqchip_inject_pending(struct per_cpu *cpu_data)
90 while (cpu_data->pending_irqs_head != cpu_data->pending_irqs_tail) {
91 irq_id = cpu_data->pending_irqs[cpu_data->pending_irqs_head];
93 if (irqchip.inject_irq(cpu_data, irq_id) == -EBUSY) {
95 * The list registers are full, trigger maintenance
96 * interrupt and leave.
98 irqchip.enable_maint_irq(true);
102 cpu_data->pending_irqs_head =
103 (cpu_data->pending_irqs_head + 1) % MAX_PENDING_IRQS;
107 * The software interrupt queue is empty - turn off the maintenance
110 irqchip.enable_maint_irq(false);
113 void irqchip_handle_irq(struct per_cpu *cpu_data)
115 irqchip.handle_irq(cpu_data);
118 void irqchip_eoi_irq(u32 irqn, bool deactivate)
120 irqchip.eoi_irq(irqn, deactivate);
123 int irqchip_send_sgi(struct sgi *sgi)
125 return irqchip.send_sgi(sgi);
128 int irqchip_cpu_init(struct per_cpu *cpu_data)
130 return irqchip.cpu_init(cpu_data);
133 int irqchip_cpu_reset(struct per_cpu *cpu_data)
135 cpu_data->pending_irqs_head = cpu_data->pending_irqs_tail = 0;
137 return irqchip.cpu_reset(cpu_data, false);
140 void irqchip_cpu_shutdown(struct per_cpu *cpu_data)
143 * The GIC backend must take care of only resetting the hyp interface if
144 * it has been initialised: this function may be executed during the
147 irqchip.cpu_reset(cpu_data, true);
150 static const struct jailhouse_irqchip *
151 irqchip_find_config(struct jailhouse_cell_desc *config)
153 const struct jailhouse_irqchip *irq_config =
154 jailhouse_cell_irqchips(config);
156 if (config->num_irqchips)
162 int irqchip_cell_init(struct cell *cell)
164 const struct jailhouse_irqchip *pins = irqchip_find_config(cell->config);
166 cell->arch.spis = (pins ? pins->pin_bitmap : 0);
168 return irqchip.cell_init(cell);
171 void irqchip_cell_exit(struct cell *cell)
173 const struct jailhouse_irqchip *root_pins =
174 irqchip_find_config(root_cell.config);
176 /* might be called by arch_shutdown while rolling back
178 if (!irqchip_is_init)
182 root_cell.arch.spis |= cell->arch.spis & root_pins->pin_bitmap;
184 irqchip.cell_exit(cell);
187 void irqchip_root_cell_shrink(struct cell *cell)
189 root_cell.arch.spis &= ~(cell->arch.spis);
192 /* Only the GIC is implemented */
193 extern struct irqchip_ops gic_irqchip;
195 int irqchip_init(void)
201 /* Only executed on master CPU */
205 /* FIXME: parse device tree */
206 gicd_base = GICD_BASE;
207 gicd_size = GICD_SIZE;
209 if ((err = arch_map_device(gicd_base, gicd_base, gicd_size)) != 0)
212 for (i = 3; i >= 0; i--) {
213 cidr = mmio_read32(gicd_base + GICD_CIDR0 + i * 4);
214 dev_id |= cidr << i * 8;
216 if (dev_id != AMBA_DEVICE)
217 goto err_no_distributor;
219 /* Probe the GIC version */
220 pidr2 = mmio_read32(gicd_base + GICD_PIDR2);
221 switch (GICD_PIDR2_ARCH(pidr2)) {
225 memcpy(&irqchip, &gic_irqchip, sizeof(struct irqchip_ops));
228 goto err_no_distributor;
232 err = irqchip.init();
233 irqchip_is_init = true;
239 printk("GIC: no supported distributor found\n");
240 arch_unmap_device(gicd_base, gicd_size);