*/
#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 *access)
+int arch_handle_dabt(struct trap_context *ctx)
{
- void *addr = (void *)access->addr;
-
- if (access->is_write)
- switch (access->size) {
- case 1:
- mmio_write8(addr, access->val);
- return;
- case 2:
- mmio_write16(addr, access->val);
- return;
- case 4:
- mmio_write32(addr, access->val);
- return;
- }
- else
- switch (access->size) {
- case 1:
- access->val = mmio_read8(addr);
- return;
- case 2:
- access->val = mmio_read16(addr);
- return;
- case 4:
- access->val = mmio_read32(addr);
- return;
- }
-
- printk("WARNING: Ignoring unsupported MMIO access size %d\n",
- access->size);
-}
-
-int arch_handle_dabt(struct per_cpu *cpu_data, struct trap_context *ctx)
-{
- struct mmio_access access;
+ 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;
arm_read_sysreg(HPFAR, hpfar);
arm_read_sysreg(HDFAR, hdfar);
- access.addr = hpfar << 8;
- access.addr |= hdfar & 0xfff;
+ 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
if (is_write) {
/* Load the value to write from the src register */
- access_cell_reg(ctx, srt, &access.val, true);
+ access_cell_reg(ctx, srt, &mmio.value, true);
if (sse)
- access.val = sign_extend(access.val, 8 * size);
+ mmio.value = sign_extend(mmio.value, 8 * size);
} else {
- access.val = 0;
+ mmio.value = 0;
}
- access.is_write = is_write;
- access.size = size;
-
- ret = irqchip_mmio_access(cpu_data, &access);
- if (ret == TRAP_UNHANDLED)
- ret = arch_smp_mmio_access(cpu_data, &access);
-
- if (ret == TRAP_HANDLED) {
- /* Put the read value into the dest register */
- if (!is_write) {
- if (sse)
- access.val = sign_extend(access.val, 8 * size);
- access_cell_reg(ctx, srt, &access.val, false);
- }
-
- arch_skip_instruction(ctx);
+ mmio.is_write = is_write;
+ mmio.size = size;
+
+ mmio_result = mmio_handle_access(&mmio);
+ if (mmio_result == MMIO_ERROR)
+ return TRAP_FORBIDDEN;
+ if (mmio_result == MMIO_UNHANDLED)
+ goto error_unhandled;
+
+ /* 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"), access.addr, size);
+ (is_write ? "write" : "read"), mmio.address, size);
- return ret;
+ return TRAP_UNHANDLED;
}