[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] [xen stable-4.6] arm32: handle async aborts delivered while at HYP



commit 0ba95621b8988ad5ceb76b43e76be404fd798f7b
Author:     Wei Chen <Wei.Chen@xxxxxxx>
AuthorDate: Tue Nov 29 16:12:39 2016 +0100
Commit:     Jan Beulich <jbeulich@xxxxxxxx>
CommitDate: Tue Nov 29 16:12:39 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 6789cd0..04a3e37 100644
--- a/xen/include/asm-arm/processor.h
+++ b/xen/include/asm-arm/processor.h
@@ -642,6 +642,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.6

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxx
https://lists.xenproject.org/xen-changelog

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.