*/
#include <jailhouse/mmio.h>
+#include <asm/bitops.h>
#include <asm/irqchip.h>
#include <asm/processor.h>
#include <asm/smp.h>
#include <asm/traps.h>
+unsigned int arch_mmio_count_regions(struct cell *cell)
+{
+ return irqchip_mmio_count_regions(cell) + smp_mmio_regions;
+}
+
/* Taken from the ARM ARM pseudocode for taking a data abort */
static void arch_inject_dabt(struct trap_context *ctx, unsigned long addr)
{
arm_write_sysreg(DFAR, addr);
}
-void arm_mmio_perform_access(struct mmio_access *mmio)
-{
- void *addr = (void *)mmio->address;
-
- if (mmio->is_write)
- switch (mmio->size) {
- case 1:
- mmio_write8(addr, mmio->value);
- return;
- case 2:
- mmio_write16(addr, mmio->value);
- return;
- case 4:
- mmio_write32(addr, mmio->value);
- return;
- }
- else
- switch (mmio->size) {
- case 1:
- mmio->value = mmio_read8(addr);
- return;
- case 2:
- mmio->value = mmio_read16(addr);
- return;
- case 4:
- mmio->value = mmio_read32(addr);
- return;
- }
-
- printk("WARNING: Ignoring unsupported MMIO access size %d\n",
- mmio->size);
-}
-
-int arch_handle_dabt(struct per_cpu *cpu_data, struct trap_context *ctx)
+int arch_handle_dabt(struct trap_context *ctx)
{
+ enum mmio_result mmio_result;
struct mmio_access mmio;
unsigned long hpfar;
unsigned long hdfar;
- int ret = TRAP_UNHANDLED;
/* Decode the syndrome fields */
u32 icc = ESR_ICC(ctx->esr);
u32 isv = icc >> 24;
mmio.address = hpfar << 8;
mmio.address |= hdfar & 0xfff;
- cpu_data->stats[JAILHOUSE_CPU_STAT_VMEXITS_MMIO]++;
+ this_cpu_data()->stats[JAILHOUSE_CPU_STAT_VMEXITS_MMIO]++;
/*
* Invalid instruction syndrome means multiple access or writeback, there
mmio.is_write = is_write;
mmio.size = size;
- ret = irqchip_mmio_access(cpu_data, &mmio);
- if (ret == TRAP_UNHANDLED)
- ret = arch_smp_mmio_access(cpu_data, &mmio);
-
- if (ret == TRAP_HANDLED) {
- /* Put the read value into the dest register */
- if (!is_write) {
- if (sse)
- mmio.value = sign_extend(mmio.value, 8 * size);
- access_cell_reg(ctx, srt, &mmio.value, false);
- }
+ mmio_result = mmio_handle_access(&mmio);
+ if (mmio_result == MMIO_ERROR)
+ return TRAP_FORBIDDEN;
+ if (mmio_result == MMIO_UNHANDLED)
+ goto error_unhandled;
- arch_skip_instruction(ctx);
+ /* Put the read value into the dest register */
+ if (!is_write) {
+ if (sse)
+ mmio.value = sign_extend(mmio.value, 8 * size);
+ access_cell_reg(ctx, srt, &mmio.value, false);
}
- if (ret != TRAP_UNHANDLED)
- return ret;
+ arch_skip_instruction(ctx);
+ return TRAP_HANDLED;
error_unhandled:
panic_printk("Unhandled data %s at 0x%x(%d)\n",
(is_write ? "write" : "read"), mmio.address, size);
- return ret;
+ return TRAP_UNHANDLED;
}