]> rtime.felk.cvut.cz Git - jailhouse.git/commitdiff
arm: dispatch hypercalls
authorJean-Philippe Brucker <jean-philippe.brucker@arm.com>
Thu, 26 Jun 2014 12:49:35 +0000 (13:49 +0100)
committerJan Kiszka <jan.kiszka@siemens.com>
Fri, 19 Dec 2014 10:04:07 +0000 (11:04 +0100)
Initial code for handling hypervisor traps. Only the non-banked registers
need to be saved in the low-level handler, the rest of the context won't
be overwritten.
The per-cpu datas are loaded from TPIDR_EL2 and the general-purpose
registers are saved directly on the stack and supplied as 'struct
registers' to the dispatcher.
The latter then inspects the ESR value and calls the core accordingly.
The return value and the general-purpose registers are passed back to the
driver by retrieving 'struct registers' from the stack, before doing the
final ERET.
This patch allows to handle all status querying hypercalls.

Signed-off-by: Jean-Philippe Brucker <jean-philippe.brucker@arm.com>
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
hypervisor/arch/arm/Makefile
hypervisor/arch/arm/exception.S
hypervisor/arch/arm/include/asm/control.h
hypervisor/arch/arm/include/asm/processor.h
hypervisor/arch/arm/include/asm/sysregs.h
hypervisor/arch/arm/include/asm/traps.h [new file with mode: 0644]
hypervisor/arch/arm/traps.c [new file with mode: 0644]

index 1957436fb37e5e95208052fb044d311bcee79736..c92f93f35f1705e1c99eddb4dd2ce923a0f529d5 100644 (file)
@@ -16,6 +16,6 @@ KBUILD_AFLAGS := $(filter-out -include asm/unified.h,$(KBUILD_AFLAGS))
 
 always := built-in.o
 
-obj-y := entry.o dbg-write.o exception.o setup.o lib.o
+obj-y := entry.o dbg-write.o exception.o setup.o lib.o traps.o
 obj-y += paging.o mmu_hyp.o mmu_cell.o
 obj-$(CONFIG_SERIAL_AMBA_PL011) += dbg-write-pl011.o
index 8c483aaeb7bafce0fad0832b228fadfec9f9e1c5..075172b1b200c772926907ab8b175c8e14e4b6e6 100644 (file)
@@ -11,6 +11,7 @@
  */
 
 #include <asm/head.h>
+#include <asm/sysregs.h>
 
        .text
        .globl hyp_vectors
@@ -21,6 +22,18 @@ hyp_vectors:
        b       .
        b       .
        b       .
+       b       hyp_trap
        b       .
        b       .
-       b       .
+
+hyp_trap:
+       /* Fill the struct registers. Should comply with NUM_USR_REGS */
+       push    {r0-r12, lr}
+
+       arm_read_sysreg(TPIDR_EL2, r0)
+       mov     r1, sp
+       bl      arch_handle_trap
+
+       /* Restore usr regs */
+       pop     {r0-r12, lr}
+       eret
index b569cbae2674a0098d55a8e7dd2854282a3f0ed3..4903d872cba8916bb7bbd749ca3284120bc8f092 100644 (file)
@@ -20,6 +20,7 @@
 
 int arch_mmu_cell_init(struct cell *cell);
 int arch_mmu_cpu_cell_init(struct per_cpu *cpu_data);
+void arch_handle_trap(struct per_cpu *cpu_data, struct registers *guest_regs);
 
 #endif /* !__ASSEMBLY__ */
 
index d50ba08eb199626a2004df38094dd2d49fc12572..b928a17402b4e05e027939321c293678df79c4eb 100644 (file)
 #define PAR_ATTR_SHIFT 56
 #define PAR_ATTR_MASK  0xff
 
+/* exception class */
+#define ESR_EC_SHIFT           26
+#define ESR_EC(hsr)            ((hsr) >> ESR_EC_SHIFT & 0x3f)
+/* instruction length */
+#define ESR_IL_SHIFT           25
+#define ESR_IL(hsr)            ((hsr) >> ESR_IL_SHIFT & 0x1)
+/* Instruction specific */
+#define ESR_ICC_MASK           0x1ffffff
+#define ESR_ICC(hsr)           ((hsr) & ESR_ICC_MASK)
+/* Exception classes values */
+#define ESR_EC_UNK             0x00
+#define ESR_EC_WFI             0x01
+#define ESR_EC_CP15_32         0x03
+#define ESR_EC_CP15_64         0x04
+#define ESR_EC_CP14_32         0x05
+#define ESR_EC_CP14_LC         0x06
+#define ESR_EC_HCPTR           0x07
+#define ESR_EC_CP10            0x08
+#define ESR_EC_CP14_64         0x0c
+#define ESR_EC_SVC_HYP         0x11
+#define ESR_EC_HVC             0x12
+#define ESR_EC_SMC             0x13
+#define ESR_EC_IABT            0x20
+#define ESR_EC_IABT_HYP                0x21
+#define ESR_EC_PCALIGN         0x22
+#define ESR_EC_DABT            0x24
+#define ESR_EC_DABT_HYP                0x25
+
+#define NUM_USR_REGS           14
+
 #ifndef __ASSEMBLY__
 
 struct registers {
+       /* r0 - r12 and lr. The other registers are banked. */
+       unsigned long usr[NUM_USR_REGS];
 };
 
 #define dmb(domain)    asm volatile("dmb " #domain "\n" ::: "memory")
index 1679734304ea721d1993450bc5101b93e6ab5429..b2aaf0634fefe31ab8641083462374f1d6009c74 100644 (file)
@@ -33,6 +33,7 @@
 #define ID_PFR0_EL1    SYSREG_32(0, c0, c1, 0)
 #define ID_PFR1_EL1    SYSREG_32(0, c0, c1, 1)
 #define SCTLR_EL2      SYSREG_32(4, c1, c0, 0)
+#define ESR_EL2                SYSREG_32(4, c5, c2, 0)
 #define TPIDR_EL2      SYSREG_32(4, c13, c0, 2)
 #define TTBR0_EL2      SYSREG_64(4, c2)
 #define TCR_EL2                SYSREG_32(4, c2, c0, 2)
diff --git a/hypervisor/arch/arm/include/asm/traps.h b/hypervisor/arch/arm/include/asm/traps.h
new file mode 100644 (file)
index 0000000..6dcc712
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Jailhouse, a Linux-based partitioning hypervisor
+ *
+ * Copyright (c) ARM Limited, 2014
+ *
+ * Authors:
+ *  Jean-Philippe Brucker <jean-philippe.brucker@arm.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.  See
+ * the COPYING file in the top-level directory.
+ */
+
+#ifndef _JAILHOUSE_ASM_TRAPS_H
+#define _JAILHOUSE_ASM_TRAPS_H
+
+#include <jailhouse/types.h>
+#include <asm/head.h>
+#include <asm/percpu.h>
+
+#ifndef __ASSEMBLY__
+
+enum trap_return {
+       TRAP_HANDLED            = 1,
+       TRAP_UNHANDLED          = 0,
+};
+
+struct trap_context {
+       unsigned long *regs;
+       u32 esr;
+       u32 cpsr;
+};
+
+typedef int (*trap_handler)(struct per_cpu *cpu_data,
+                            struct trap_context *ctx);
+
+#define arm_read_banked_reg(reg, val)                                  \
+       asm volatile ("mrs %0, " #reg "\n" : "=r" (val))
+
+#define arm_write_banked_reg(reg, val)                                 \
+       asm volatile ("msr " #reg ", %0\n" : : "r" (val))
+
+#endif /* !__ASSEMBLY__ */
+#endif /* !_JAILHOUSE_ASM_TRAPS_H */
diff --git a/hypervisor/arch/arm/traps.c b/hypervisor/arch/arm/traps.c
new file mode 100644 (file)
index 0000000..4587522
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * Jailhouse, a Linux-based partitioning hypervisor
+ *
+ * Copyright (c) ARM Limited, 2014
+ *
+ * Authors:
+ *  Jean-Philippe Brucker <jean-philippe.brucker@arm.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.  See
+ * the COPYING file in the top-level directory.
+ */
+
+#include <asm/control.h>
+#include <asm/traps.h>
+#include <asm/sysregs.h>
+#include <jailhouse/printk.h>
+#include <jailhouse/control.h>
+
+static int arch_handle_hvc(struct per_cpu *cpu_data, struct trap_context *ctx)
+{
+       unsigned long *regs = ctx->regs;
+
+       regs[0] = hypercall(regs[0], regs[1], regs[2]);
+
+       return TRAP_HANDLED;
+}
+
+static const trap_handler trap_handlers[38] =
+{
+       [ESR_EC_HVC]            = arch_handle_hvc,
+};
+
+void arch_handle_trap(struct per_cpu *cpu_data, struct registers *guest_regs)
+{
+       struct trap_context ctx;
+       u32 exception_class;
+       int ret = TRAP_UNHANDLED;
+
+       arm_read_banked_reg(SPSR_hyp, ctx.cpsr);
+       arm_read_sysreg(ESR_EL2, ctx.esr);
+       exception_class = ESR_EC(ctx.esr);
+       ctx.regs = guest_regs->usr;
+
+       if (trap_handlers[exception_class])
+               ret = trap_handlers[exception_class](cpu_data, &ctx);
+
+       if (ret != TRAP_HANDLED) {
+               panic_printk("CPU%d: Unhandled HYP trap, syndrome 0x%x\n",
+                               cpu_data->cpu_id, ctx.esr);
+               while(1);
+       }
+}