]> rtime.felk.cvut.cz Git - jailhouse.git/blobdiff - hypervisor/arch/arm/mmio.c
Merge remote-tracking branch 'kiszka/master'
[jailhouse.git] / hypervisor / arch / arm / mmio.c
index 5d7fdf51a726e063bb053c3055491456fffe4d00..1098e8df57dbbca53ccad00de15ac4c4922652b8 100644 (file)
  */
 
 #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)
 {
@@ -55,49 +61,12 @@ static void arch_inject_dabt(struct trap_context *ctx, unsigned long addr)
        arm_write_sysreg(DFAR, addr);
 }
 
-int arch_mmio_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);
-                       break;
-               case 2:
-                       mmio_write16(addr, access->val);
-                       break;
-               case 4:
-                       mmio_write32(addr, access->val);
-                       break;
-               default:
-                       return -EINVAL;
-               }
-       } else {
-               switch (access->size) {
-               case 1:
-                       access->val = mmio_read8(addr);
-                       break;
-               case 2:
-                       access->val = mmio_read16(addr);
-                       break;
-               case 4:
-                       access->val = mmio_read32(addr);
-                       break;
-               default:
-                       return -EINVAL;
-               }
-       }
-
-       return 0;
-}
-
-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;
@@ -112,10 +81,10 @@ int arch_handle_dabt(struct per_cpu *cpu_data, struct trap_context *ctx)
 
        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
@@ -132,36 +101,34 @@ int arch_handle_dabt(struct per_cpu *cpu_data, struct trap_context *ctx)
 
        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;
 }