From: Antonios Motakis <[email protected]> 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 <[email protected]> Signed-off-by: Dmitry Voytik <[email protected]> --- hypervisor/arch/arm64/include/asm/traps.h | 2 + hypervisor/arch/arm64/mmio.c | 84 ++++++++++++++++++++++++++++++- hypervisor/arch/arm64/traps.c | 10 +++- 3 files changed, 93 insertions(+), 3 deletions(-) diff --git a/hypervisor/arch/arm64/include/asm/traps.h b/hypervisor/arch/arm64/include/asm/traps.h index 3a60e30..2f2e0f6 100644 --- a/hypervisor/arch/arm64/include/asm/traps.h +++ b/hypervisor/arch/arm64/include/asm/traps.h @@ -31,5 +31,7 @@ struct trap_context { void arch_skip_instruction(struct trap_context *ctx); +int arch_handle_dabt(struct trap_context *ctx); + #endif /* !__ASSEMBLY__ */ #endif /* !_JAILHOUSE_ASM_TRAPS_H */ diff --git a/hypervisor/arch/arm64/mmio.c b/hypervisor/arch/arm64/mmio.c index 37745d7..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 <[email protected]> * + * 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,6 +17,12 @@ #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) { @@ -20,8 +30,80 @@ unsigned int arch_mmio_count_regions(struct cell *cell) return 0; } -void arm_mmio_perform_access(unsigned long base, struct mmio_access *mmio) +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 199b497..cc6fe6c 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_common.h> +#include <asm/mmio.h> #include <asm/platform.h> #include <asm/psci.h> #include <asm/sysregs.h> @@ -23,8 +24,9 @@ void arch_skip_instruction(struct trap_context *ctx) { - trace_error(-EINVAL); - while(1); + u32 instruction_length = ESR_IL(ctx->esr); + + ctx->pc += (instruction_length ? 4 : 2); } static void dump_regs(struct trap_context *ctx) @@ -105,6 +107,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.8.0.rc3 -- 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 [email protected]. For more options, visit https://groups.google.com/d/optout.
