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

[Xen-devel] [PATCH v2 04/19] xen: arm: provide and use a handle_raz_wi helper



Reduces the use of goto in the trap handlers to none.

Some explicitly 32-bit types become register_t here, but that's OK, on
32-bit they are 32-bit already and on 64-bit it is fine/harmless to
set the larger register, a 32-bit guest won't see the top half in any
case.

Per section B1.2.1 (ARMv8 DDI0487 A.d) writes to wN registers are zero
extended, so there is no risk of leaking the top half here.

Unlike the previous code the advancing of PC is handled within the
helper, rather than after the end of the switch as before. So return
as the handler is called.

Signed-off-by: Ian Campbell <ian.campbell@xxxxxxxxxx>
---
v2: Added reference to B1.2.1
---
 xen/arch/arm/traps.c |   51 +++++++++++++++++++++++++-------------------------
 1 file changed, 26 insertions(+), 25 deletions(-)

diff --git a/xen/arch/arm/traps.c b/xen/arch/arm/traps.c
index 7270116..8b1846a 100644
--- a/xen/arch/arm/traps.c
+++ b/xen/arch/arm/traps.c
@@ -1574,11 +1574,24 @@ static void advance_pc(struct cpu_user_regs *regs, 
const union hsr hsr)
     regs->pc += hsr.len ? 4 : 2;
 }
 
+/* Read as zero + write ignore */
+static void handle_raz_wi(struct cpu_user_regs *regs,
+                          register_t *reg,
+                          bool_t read,
+                          const union hsr hsr)
+{
+    if ( read )
+        *reg = 0;
+    /* else: write ignored */
+
+    advance_pc(regs, hsr);
+}
+
 static void do_cp15_32(struct cpu_user_regs *regs,
                        const union hsr hsr)
 {
     const struct hsr_cp32 cp32 = hsr.cp32;
-    uint32_t *r = (uint32_t*)select_user_reg(regs, cp32.reg);
+    register_t *r = select_user_reg(regs, cp32.reg);
     struct vcpu *v = current;
 
     if ( !check_conditional_instr(regs, hsr) )
@@ -1613,14 +1626,14 @@ static void do_cp15_32(struct cpu_user_regs *regs,
         /* RO at EL0. RAZ/WI at EL1 */
         if ( psr_mode_is_user(regs) && !hsr.cp32.read )
             return inject_undef_exception(regs, hsr);
-        goto cp15_32_raz_wi;
+        return handle_raz_wi(regs, r, cp32.read, hsr);
 
     case HSR_CPREG32(PMINTENSET):
     case HSR_CPREG32(PMINTENCLR):
         /* EL1 only, however MDCR_EL2.TPM==1 means EL0 may trap here also. */
         if ( psr_mode_is_user(regs) )
             return inject_undef_exception(regs, hsr);
-        goto cp15_32_raz_wi;
+        return handle_raz_wi(regs, r, cp32.read, hsr);
     case HSR_CPREG32(PMCR):
     case HSR_CPREG32(PMCNTENSET):
     case HSR_CPREG32(PMCNTENCLR):
@@ -1639,11 +1652,7 @@ static void do_cp15_32(struct cpu_user_regs *regs,
          */
         if ( psr_mode_is_user(regs) )
             return inject_undef_exception(regs, hsr);
- cp15_32_raz_wi:
-        if ( cp32.read )
-            *r = 0;
-        /* else: write ignored */
-        break;
+        return handle_raz_wi(regs, r, cp32.read, hsr);
 
     default:
         gdprintk(XENLOG_ERR,
@@ -1694,7 +1703,7 @@ static void do_cp15_64(struct cpu_user_regs *regs,
 static void do_cp14_32(struct cpu_user_regs *regs, const union hsr hsr)
 {
     const struct hsr_cp32 cp32 = hsr.cp32;
-    uint32_t *r = (uint32_t *)select_user_reg(regs, cp32.reg);
+    register_t *r = select_user_reg(regs, cp32.reg);
     struct domain *d = current->domain;
 
     if ( !check_conditional_instr(regs, hsr) )
@@ -1738,12 +1747,11 @@ static void do_cp14_32(struct cpu_user_regs *regs, 
const union hsr hsr)
         if ( usr_mode(regs) )
             return inject_undef_exception(regs, hsr);
 
-        /* Implement debug status and control register as RAZ/WI.
-         * The OS won't use Hardware debug if MDBGen not set
+        /*
+         * Implement debug status and control register as RAZ/WI.
+         * The OS won't use Hardware debug if MDBGen not set.
          */
-        if ( cp32.read )
-           *r = 0;
-        break;
+        return handle_raz_wi(regs, r, cp32.read, hsr);
 
     case HSR_CPREG32(DBGVCR):
     case HSR_CPREG32(DBGBVR0):
@@ -1755,10 +1763,7 @@ static void do_cp14_32(struct cpu_user_regs *regs, const 
union hsr hsr)
     case HSR_CPREG32(DBGOSDLR):
         if ( usr_mode(regs) )
             return inject_undef_exception(regs, hsr);
-        /* RAZ/WI */
-        if ( cp32.read )
-            *r = 0;
-        break;
+        return handle_raz_wi(regs, r, cp32.read, hsr);
 
     case HSR_CPREG32(DBGOSLAR):
         if ( usr_mode(regs) )
@@ -1845,7 +1850,7 @@ static void do_sysreg(struct cpu_user_regs *regs,
          */
         if ( psr_mode_is_user(regs) )
             return inject_undef_exception(regs, hsr);
-        goto sysreg_raz_wi;
+        return handle_raz_wi(regs, x, hsr.sysreg.read, hsr);
 
     case HSR_SYSREG_MDCCSR_EL0:
         /*
@@ -1863,7 +1868,7 @@ static void do_sysreg(struct cpu_user_regs *regs,
         /* RO at EL0. RAZ/WI at EL1 */
         if ( psr_mode_is_user(regs) && !hsr.sysreg.read )
             return inject_undef_exception(regs, hsr);
-        goto sysreg_raz_wi;
+        return handle_raz_wi(regs, x, hsr.sysreg.read, hsr);
     case HSR_SYSREG_PMCR_EL0:
     case HSR_SYSREG_PMCNTENSET_EL0:
     case HSR_SYSREG_PMCNTENCLR_EL0:
@@ -1882,11 +1887,7 @@ static void do_sysreg(struct cpu_user_regs *regs,
          */
         if ( psr_mode_is_user(regs) )
             return inject_undef_exception(regs, hsr);
- sysreg_raz_wi:
-        if ( hsr.sysreg.read )
-            *x = 0;
-        /* else: write ignored */
-        break;
+        return handle_raz_wi(regs, x, hsr.sysreg.read, hsr);
 
     /* Write only, Write ignore registers: */
     case HSR_SYSREG_OSLAR_EL1:
-- 
1.7.10.4


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


 


Rackspace

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