From: Antonios Motakis <antonios.mota...@huawei.com>

Catch accesses to the mmio regions that we want to handle from the
hypervisor. These are used also by the GIC code.

Signed-off-by: Antonios Motakis <antonios.mota...@huawei.com>
Signed-off-by: Dmitry Voytik <dmitry.voy...@huawei.com>
[Jan: rebase, adjust arch_skip_instruction to update ELR_EL2 itself]
Signed-off-by: Jan Kiszka <jan.kis...@siemens.com>
---
 hypervisor/arch/arm64/include/asm/traps.h |  2 +
 hypervisor/arch/arm64/mmio.c              | 88 +++++++++++++++++++++++++++++++
 hypervisor/arch/arm64/traps.c             | 12 ++++-
 3 files changed, 100 insertions(+), 2 deletions(-)

diff --git a/hypervisor/arch/arm64/include/asm/traps.h 
b/hypervisor/arch/arm64/include/asm/traps.h
index 1ce21d9..78f9f47 100644
--- a/hypervisor/arch/arm64/include/asm/traps.h
+++ b/hypervisor/arch/arm64/include/asm/traps.h
@@ -30,4 +30,6 @@ struct trap_context {
 
 void arch_skip_instruction(struct trap_context *ctx);
 
+int arch_handle_dabt(struct trap_context *ctx);
+
 #endif /* !_JAILHOUSE_ASM_TRAPS_H */
diff --git a/hypervisor/arch/arm64/mmio.c b/hypervisor/arch/arm64/mmio.c
index 56f71b2..0c43365 100644
--- a/hypervisor/arch/arm64/mmio.c
+++ b/hypervisor/arch/arm64/mmio.c
@@ -2,10 +2,14 @@
  * Jailhouse AArch64 support
  *
  * Copyright (C) 2015 Huawei Technologies Duesseldorf GmbH
+ * Copyright (C) 2014 ARM Limited
  *
  * Authors:
  *  Antonios Motakis <antonios.mota...@huawei.com>
  *
+ * Part of the fuctionality is derived from the AArch32 implementation, under
+ * hypervisor/arch/arm/mmio.c by Jean-Philippe Brucker.
+ *
  * This work is licensed under the terms of the GNU GPL, version 2.  See
  * the COPYING file in the top-level directory.
  */
@@ -13,9 +17,93 @@
 #include <jailhouse/entry.h>
 #include <jailhouse/mmio.h>
 #include <jailhouse/printk.h>
+#include <asm/bitops.h>
+#include <asm/percpu.h>
+#include <asm/sysregs.h>
+#include <asm/traps.h>
+
+/* AARCH64_TODO: consider merging this with the AArch32 version */
 
 unsigned int arch_mmio_count_regions(struct cell *cell)
 {
        /* not entirely a lie :) */
        return 0;
 }
+
+static void arch_inject_dabt(struct trap_context *ctx, unsigned long addr)
+{
+       trace_error(-EINVAL);
+       while (1);
+}
+
+int arch_handle_dabt(struct trap_context *ctx)
+{
+       enum mmio_result mmio_result;
+       struct mmio_access mmio;
+       unsigned long hpfar;
+       unsigned long hdfar;
+       /* Decode the syndrome fields */
+       u32 iss         = ESR_ISS(ctx->esr);
+       u32 isv         = iss >> 24;
+       u32 sas         = iss >> 22 & 0x3;
+       u32 sse         = iss >> 21 & 0x1;
+       u32 srt         = iss >> 16 & 0x1f;
+       u32 ea          = iss >> 9 & 0x1;
+       u32 cm          = iss >> 8 & 0x1;
+       u32 s1ptw       = iss >> 7 & 0x1;
+       u32 is_write    = iss >> 6 & 0x1;
+       u32 size        = 1 << sas;
+
+       arm_read_sysreg(HPFAR_EL2, hpfar);
+       arm_read_sysreg(FAR_EL2, hdfar);
+       mmio.address = hpfar << 8;
+       mmio.address |= hdfar & 0xfff;
+
+       this_cpu_data()->stats[JAILHOUSE_CPU_STAT_VMEXITS_MMIO]++;
+
+       /*
+        * Invalid instruction syndrome means multiple access or writeback,
+        * there is nothing we can do.
+        */
+       if (!isv)
+               goto error_unhandled;
+
+       /* Re-inject abort during page walk, cache maintenance or external */
+       if (s1ptw || ea || cm) {
+               arch_inject_dabt(ctx, hdfar);
+               return TRAP_HANDLED;
+       }
+
+       if (is_write) {
+               /* Load the value to write from the src register */
+               mmio.value = (srt == 31) ? 0 : ctx->regs[srt];
+               if (sse)
+                       mmio.value = sign_extend(mmio.value, 8 * size);
+       } else {
+               mmio.value = 0;
+       }
+       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 && (srt != 31)) {
+               if (sse)
+                       mmio.value = sign_extend(mmio.value, 8 * size);
+               ctx->regs[srt] = mmio.value;
+       }
+
+       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 TRAP_UNHANDLED;
+}
diff --git a/hypervisor/arch/arm64/traps.c b/hypervisor/arch/arm64/traps.c
index de48f01..9830209 100644
--- a/hypervisor/arch/arm64/traps.c
+++ b/hypervisor/arch/arm64/traps.c
@@ -15,6 +15,7 @@
 #include <jailhouse/printk.h>
 #include <asm/control.h>
 #include <asm/gic.h>
+#include <asm/mmio.h>
 #include <asm/psci.h>
 #include <asm/sysregs.h>
 #include <asm/traps.h>
@@ -22,8 +23,11 @@
 
 void arch_skip_instruction(struct trap_context *ctx)
 {
-       trace_error(-EINVAL);
-       while(1);
+       u64 pc;
+
+       arm_read_sysreg(ELR_EL2, pc);
+       pc += ESR_IL(ctx->esr) ? 4 : 2;
+       arm_write_sysreg(ELR_EL2, pc);
 }
 
 static void dump_regs(struct trap_context *ctx)
@@ -105,6 +109,10 @@ static void arch_handle_trap(struct per_cpu *cpu_data,
 
        /* exception class */
        switch (ESR_EC(ctx.esr)) {
+       case ESR_EC_DABT_LOW:
+               ret = arch_handle_dabt(&ctx);
+               break;
+
        default:
                ret = TRAP_UNHANDLED;
        }
-- 
2.1.4

-- 
You received this message because you are subscribed to the Google Groups 
"Jailhouse" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to jailhouse-dev+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to