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

[Xen-devel] [PATCH] arm/hypercall: Use the common hcall_preempted boolean



With hcall_preempted having just been made common, ARM can use use it to
simplify its hypercall handling.

This simplifies the continuation logic and removes the risk of accidentally
skipping multiple instructions.

Signed-off-by: Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
---
CC: Stefano Stabellini <sstabellini@xxxxxxxxxx>
CC: Julien Grall <julien.grall@xxxxxxx>

NB: Only compile tested, not functionally tested.  However, it is basically an
identical transformation as done to x86 PV guests in the previous patch, which
I have tested thoroughly.
---
 xen/arch/arm/domain.c | 10 ++--------
 xen/arch/arm/traps.c  | 16 ++++++++--------
 2 files changed, 10 insertions(+), 16 deletions(-)

diff --git a/xen/arch/arm/domain.c b/xen/arch/arm/domain.c
index 7e43691..fb1d8a5 100644
--- a/xen/arch/arm/domain.c
+++ b/xen/arch/arm/domain.c
@@ -349,17 +349,12 @@ void sync_vcpu_execstate(struct vcpu *v)
 
 void hypercall_cancel_continuation(void)
 {
-    struct cpu_user_regs *regs = guest_cpu_user_regs();
     struct mc_state *mcs = &current->mc_state;
 
     if ( mcs->flags & MCSF_in_multicall )
-    {
         __clear_bit(_MCSF_call_preempted, &mcs->flags);
-    }
     else
-    {
-        regs->pc += 4; /* undo re-execute 'hvc #XEN_HYPERCALL_TAG' */
-    }
+        current->hcall_preempted = false;
 }
 
 unsigned long hypercall_create_continuation(
@@ -391,8 +386,7 @@ unsigned long hypercall_create_continuation(
     {
         regs = guest_cpu_user_regs();
 
-        /* Ensure the hypercall trap instruction is re-executed. */
-        regs->pc -= 4;  /* re-execute 'hvc #XEN_HYPERCALL_TAG' */
+        current->hcall_preempted = true;
 
 #ifdef CONFIG_ARM_64
         if ( !is_32bit_domain(current->domain) )
diff --git a/xen/arch/arm/traps.c b/xen/arch/arm/traps.c
index 92b1d80..7c99dc2 100644
--- a/xen/arch/arm/traps.c
+++ b/xen/arch/arm/traps.c
@@ -1454,9 +1454,6 @@ static void do_trap_hypercall(struct cpu_user_regs *regs, 
register_t *nr,
                               unsigned long iss)
 {
     arm_hypercall_fn_t call = NULL;
-#ifndef NDEBUG
-    register_t orig_pc = regs->pc;
-#endif
 
     BUILD_BUG_ON(NR_hypercalls < ARRAY_SIZE(arm_hypercall_table) );
 
@@ -1470,6 +1467,8 @@ static void do_trap_hypercall(struct cpu_user_regs *regs, 
register_t *nr,
         return;
     }
 
+    current->hcall_preempted = false;
+
     perfc_incra(hypercalls, *nr);
     call = arm_hypercall_table[*nr].fn;
     if ( call == NULL )
@@ -1481,12 +1480,9 @@ static void do_trap_hypercall(struct cpu_user_regs 
*regs, register_t *nr,
     HYPERCALL_RESULT_REG(regs) = call(HYPERCALL_ARGS(regs));
 
 #ifndef NDEBUG
-    /*
-     * Clobber argument registers only if pc is unchanged, otherwise
-     * this is a hypercall continuation.
-     */
-    if ( orig_pc == regs->pc )
+    if ( !current->hcall_preempted )
     {
+        /* Deliberately corrupt parameter regs used by this hypercall. */
         switch ( arm_hypercall_table[*nr].nr_args ) {
         case 5: HYPERCALL_ARG5(regs) = 0xDEADBEEF;
         case 4: HYPERCALL_ARG4(regs) = 0xDEADBEEF;
@@ -1499,6 +1495,10 @@ static void do_trap_hypercall(struct cpu_user_regs 
*regs, register_t *nr,
         *nr = 0xDEADBEEF;
     }
 #endif
+
+    /* Ensure the hypercall trap instruction is re-executed. */
+    if ( current->hcall_preempted )
+        regs->pc -= 4;  /* re-execute 'hvc #XEN_HYPERCALL_TAG' */
 }
 
 static bool check_multicall_32bit_clean(struct multicall_entry *multi)
-- 
2.1.4


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

 


Rackspace

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