[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen stable-4.7] arm32: handle async aborts delivered while at HYP
commit 0726cb5f06dda6276fcf999d472b15c958d49a8d Author: Wei Chen <Wei.Chen@xxxxxxx> AuthorDate: Tue Nov 29 16:10:09 2016 +0100 Commit: Jan Beulich <jbeulich@xxxxxxxx> CommitDate: Tue Nov 29 16:10:09 2016 +0100 arm32: handle async aborts delivered while at HYP If guest generates an asynchronous abort and then traps into HYP (by HVC or IRQ) before the abort has been delivered, the hypervisor could not catch it, because the PSTATE.A bit is masked all the time in hypervisor. So this asynchronous abort may be slipped to next running guest with PSTATE.A bit unmasked. In order to avoid this, it is necessary to take the abort at HYP, by clearing the PSTATE.A bit. In this patch, we unmask the PSTATE.A bit to open a window to catch guest-generated asynchronous abort in all Guest -> HYP switch paths. If we caught such asynchronous abort in checking window, the HYP data abort exception will be triggered and the abort source guest will be crashed. This is part of XSA-201. Signed-off-by: Wei Chen <Wei.Chen@xxxxxxx> Reviewed-by: Julien Grall <julien.grall@xxxxxxx> Acked-by: Stefano Stabellini <sstabellini@xxxxxxxxxx> master commit: 6aaff7b407ca76dcfc4fe81f2afe9d1594cb0d6b master date: 2016-11-29 15:59:55 +0100 --- xen/arch/arm/arm32/entry.S | 55 +++++++++++++++++++++++++++++++++++ xen/arch/arm/arm32/traps.c | 5 +++- xen/include/asm-arm/arm32/processor.h | 11 +++++++ xen/include/asm-arm/processor.h | 2 ++ 4 files changed, 72 insertions(+), 1 deletion(-) diff --git a/xen/arch/arm/arm32/entry.S b/xen/arch/arm/arm32/entry.S index 774e7c6..4b47f9b 100644 --- a/xen/arch/arm/arm32/entry.S +++ b/xen/arch/arm/arm32/entry.S @@ -42,6 +42,61 @@ save_guest_regs: SAVE_BANKED(fiq) SAVE_ONE_BANKED(R8_fiq); SAVE_ONE_BANKED(R9_fiq); SAVE_ONE_BANKED(R10_fiq) SAVE_ONE_BANKED(R11_fiq); SAVE_ONE_BANKED(R12_fiq); + /* + * Start to check pending virtual abort in the gap of Guest -> HYP + * world switch. + * + * Save ELR_hyp to check whether the pending virtual abort exception + * takes place while we are doing this trap exception. + */ + mrs r1, ELR_hyp + + /* + * Force loads and stores to complete before unmasking asynchronous + * aborts and forcing the delivery of the exception. + */ + dsb sy + + /* + * Unmask asynchronous abort bit. If there is a pending asynchronous + * abort, the data_abort exception will happen after A bit is cleared. + */ + cpsie a + + /* + * This is our single instruction exception window. A pending + * asynchronous abort is guaranteed to occur at the earliest when we + * unmask it, and at the latest just after the ISB. + * + * If a pending abort occurs, the program will jump to data_abort + * exception handler, and the ELR_hyp will be set to + * abort_guest_exit_start or abort_guest_exit_end. + */ + .global abort_guest_exit_start +abort_guest_exit_start: + + isb + + .global abort_guest_exit_end +abort_guest_exit_end: + /* Mask CPSR asynchronous abort bit, close the checking window. */ + cpsid a + + /* + * Compare ELR_hyp and the saved value to check whether we are + * returning from a valid exception caused by pending virtual + * abort. + */ + mrs r2, ELR_hyp + cmp r1, r2 + + /* + * Not equal, the pending virtual abort exception took place, the + * initial exception does not have any significance to be handled. + * Exit ASAP. + */ + bne return_from_trap + mov pc, lr #define DEFINE_TRAP_ENTRY(trap) \ diff --git a/xen/arch/arm/arm32/traps.c b/xen/arch/arm/arm32/traps.c index f8cf864..7bfc5ff 100644 --- a/xen/arch/arm/arm32/traps.c +++ b/xen/arch/arm/arm32/traps.c @@ -63,7 +63,10 @@ asmlinkage void do_trap_prefetch_abort(struct cpu_user_regs *regs) asmlinkage void do_trap_data_abort(struct cpu_user_regs *regs) { - do_unexpected_trap("Data Abort", regs); + if ( VABORT_GEN_BY_GUEST(regs) ) + do_trap_guest_error(regs); + else + do_unexpected_trap("Data Abort", regs); } /* diff --git a/xen/include/asm-arm/arm32/processor.h b/xen/include/asm-arm/arm32/processor.h index f41644d..e3bd004 100644 --- a/xen/include/asm-arm/arm32/processor.h +++ b/xen/include/asm-arm/arm32/processor.h @@ -55,6 +55,17 @@ struct cpu_user_regs uint32_t pad1; /* Doubleword-align the user half of the frame */ }; + +/* Functions for pending virtual abort checking window. */ +void abort_guest_exit_start(void); +void abort_guest_exit_end(void); + +#define VABORT_GEN_BY_GUEST(r) \ +( \ + ( (unsigned long)abort_guest_exit_start == (r)->pc ) || \ + ( (unsigned long)abort_guest_exit_end == (r)->pc ) \ +) + #endif /* Layout as used in assembly, with src/dest registers mixed in */ diff --git a/xen/include/asm-arm/processor.h b/xen/include/asm-arm/processor.h index 284ad6a..00fd3c8 100644 --- a/xen/include/asm-arm/processor.h +++ b/xen/include/asm-arm/processor.h @@ -647,6 +647,8 @@ void vcpu_regs_user_to_hyp(struct vcpu *vcpu, int call_smc(register_t function_id, register_t arg0, register_t arg1, register_t arg2); +void do_trap_guest_error(struct cpu_user_regs *regs); + #endif /* __ASSEMBLY__ */ #endif /* __ASM_ARM_PROCESSOR_H */ /* -- generated by git-patchbot for /home/xen/git/xen.git#stable-4.7 _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxx https://lists.xenproject.org/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |