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/control.h>
14 #include <jailhouse/mmio.h>
16 #include <asm/gic_common.h>
17 #include <asm/irqchip.h>
18 #include <asm/percpu.h>
19 #include <asm/platform.h>
20 #include <asm/spinlock.h>
21 #include <asm/traps.h>
23 #define REG_RANGE(base, n, size) \
24 (base) ... ((base) + (n - 1) * (size))
26 extern void *gicd_base;
27 extern unsigned int gicd_size;
29 static DEFINE_SPINLOCK(dist_lock);
32 * Most of the GIC distributor writes only reconfigure the IRQs corresponding to
33 * the bits of the written value, by using separate `set' and `clear' registers.
34 * Such registers can be handled by setting the `is_poke' boolean, which allows
35 * to simply restrict the access->val with the cell configuration mask.
36 * Others, such as the priority registers, will need to be read and written back
37 * with a restricted value, by using the distributor lock.
39 static int restrict_bitmask_access(struct per_cpu *cpu_data,
40 struct mmio_access *access,
41 unsigned int reg_index,
42 unsigned int bits_per_irq,
46 unsigned long access_mask = 0;
48 * In order to avoid division, the number of bits per irq is limited
49 * to powers of 2 for the moment.
51 unsigned long irqs_per_reg = 32 >> ffsl(bits_per_irq);
52 unsigned long spi_bits = (1 << bits_per_irq) - 1;
53 /* First, extract the first interrupt affected by this access */
54 unsigned int first_irq = reg_index * irqs_per_reg;
56 /* For SGIs or PPIs, let the caller do the mmio access */
57 if (!is_spi(first_irq))
58 return TRAP_UNHANDLED;
60 /* For SPIs, compare against the cell config mask */
62 for (spi = first_irq; spi < first_irq + irqs_per_reg; spi++) {
63 unsigned int bit_nr = (spi - first_irq) * bits_per_irq;
64 if (spi_in_cell(cpu_data->cell, spi))
65 access_mask |= spi_bits << bit_nr;
68 if (!access->is_write) {
69 /* Restrict the read value */
70 arch_mmio_access(access);
71 access->val &= access_mask;
77 * Modify the existing value of this register by first reading
79 * Relies on a spinlock since we need two mmio accesses.
81 unsigned long access_val = access->val;
83 spin_lock(&dist_lock);
85 access->is_write = false;
86 arch_mmio_access(access);
87 access->is_write = true;
90 access->val &= ~(access_mask & ~access_val);
91 access->val |= access_val;
92 arch_mmio_access(access);
94 spin_unlock(&dist_lock);
98 access->val &= access_mask;
100 return TRAP_UNHANDLED;
105 * GICv3 uses a 64bit register IROUTER for each IRQ
107 static int handle_irq_route(struct per_cpu *cpu_data,
108 struct mmio_access *access, unsigned int irq)
110 struct cell *cell = cpu_data->cell;
113 /* Ignore aff3 on AArch32 (return 0) */
114 if (access->size == 4 && (access->addr % 8))
117 /* SGIs and PPIs are res0 */
122 * Ignore accesses to SPIs that do not belong to the cell. This isn't
123 * forbidden, because the guest driver may simply iterate over all
124 * registers at initialisation
126 if (!spi_in_cell(cell, irq - 32))
129 /* Translate the virtual cpu id into the physical one */
130 if (access->is_write) {
131 access->val = arm_cpu_virt2phys(cell, access->val);
132 if (access->val == -1) {
133 printk("Attempt to route IRQ%d outside of cell\n", irq);
134 return TRAP_FORBIDDEN;
136 /* And do the access */
137 return TRAP_UNHANDLED;
139 cpu = mmio_read32(gicd_base + GICD_IROUTER + 8 * irq);
140 access->val = arm_cpu_phys2virt(cpu);
145 int gic_handle_dist_access(struct per_cpu *cpu_data,
146 struct mmio_access *access)
149 unsigned long reg = access->addr - (unsigned long)gicd_base;
152 case REG_RANGE(GICD_IROUTER, 1024, 8):
153 ret = handle_irq_route(cpu_data, access,
154 (reg - GICD_IROUTER) / 8);
157 case REG_RANGE(GICD_ICENABLER, 32, 4):
158 case REG_RANGE(GICD_ISENABLER, 32, 4):
159 case REG_RANGE(GICD_ICPENDR, 32, 4):
160 case REG_RANGE(GICD_ISPENDR, 32, 4):
161 case REG_RANGE(GICD_ICACTIVER, 32, 4):
162 case REG_RANGE(GICD_ISACTIVER, 32, 4):
163 ret = restrict_bitmask_access(cpu_data, access,
164 (reg & 0x7f) / 4, 1, true);
167 case REG_RANGE(GICD_IGROUPR, 32, 4):
168 ret = restrict_bitmask_access(cpu_data, access,
169 (reg & 0x7f) / 4, 1, false);
172 case REG_RANGE(GICD_ICFGR, 64, 4):
173 ret = restrict_bitmask_access(cpu_data, access,
174 (reg & 0xff) / 4, 2, false);
177 case REG_RANGE(GICD_IPRIORITYR, 255, 4):
178 ret = restrict_bitmask_access(cpu_data, access,
179 (reg & 0x3ff) / 4, 8, false);
185 case REG_RANGE(GICD_PIDR0, 4, 4):
186 case REG_RANGE(GICD_PIDR4, 4, 4):
187 case REG_RANGE(GICD_CIDR0, 4, 4):
188 /* Allow read access, ignore write */
189 ret = (access->is_write ? TRAP_HANDLED : TRAP_UNHANDLED);
197 /* The sub-handlers return TRAP_UNHANDLED to allow the access */
198 if (ret == TRAP_UNHANDLED) {
199 arch_mmio_access(access);