xen/arm: Trap the ACTLR register
authorJulien Grall <julien.grall@linaro.org>
Thu, 4 Jul 2013 15:01:06 +0000 (16:01 +0100)
committerIan Campbell <ian.campbell@citrix.com>
Wed, 17 Jul 2013 15:55:24 +0000 (16:55 +0100)
On Cortex-A15 ACTLR is used to set the SMP bit. If the guest has the control on
this register, it can disable SMP support and so TLB broadcast.

Implement the access to ACTRL as read-only register with SMP bit set to one
if the guest has multiple VCPUs.

Signed-off-by: Julien Grall <julien.grall@linaro.org>
Acked-by: Ian Campbell <ian.campbell@citrix.com>
xen/arch/arm/domain.c
xen/arch/arm/traps.c

index f465ab7586351d670ae5e830a878b163f2b7756f..6937abf6af60b81e069f25e4bf098a31643abde2 100644 (file)
@@ -28,6 +28,7 @@
 #include <asm/irq.h>
 #include <asm/cpufeature.h>
 #include <asm/vfp.h>
+#include <asm/processor-ca15.h>
 
 #include <asm/gic.h>
 #include "vtimer.h"
@@ -61,7 +62,6 @@ static void ctxt_switch_from(struct vcpu *p)
     p->arch.csselr = READ_SYSREG(CSSELR_EL1);
 
     /* Control Registers */
-    p->arch.actlr = READ_SYSREG(ACTLR_EL1);
     p->arch.sctlr = READ_SYSREG(SCTLR_EL1);
     p->arch.cpacr = READ_SYSREG(CPACR_EL1);
 
@@ -182,7 +182,6 @@ static void ctxt_switch_to(struct vcpu *n)
     isb();
 
     /* Control Registers */
-    WRITE_SYSREG(n->arch.actlr, ACTLR_EL1);
     WRITE_SYSREG(n->arch.sctlr, SCTLR_EL1);
     WRITE_SYSREG(n->arch.cpacr, CPACR_EL1);
 
@@ -452,6 +451,12 @@ int vcpu_initialise(struct vcpu *v)
         return rc;
 
     v->arch.sctlr = SCTLR_BASE;
+    v->arch.actlr = READ_SYSREG32(ACTLR_EL1);
+    /* XXX: Handle other than CA15 cpus */
+    if ( v->domain->max_vcpus > 1 )
+        v->arch.actlr |= ACTLR_CA15_SMP;
+    else
+        v->arch.actlr &= ~ACTLR_CA15_SMP;
 
     if ( (rc = vcpu_vgic_init(v)) != 0 )
         return rc;
index 398d20932357668faac4c73130faf7fdde8c42a6..bbd60aa0f83750521dbef3a7f5c8f0fa3cb99523 100644 (file)
@@ -62,7 +62,8 @@ void __cpuinit init_traps(void)
     WRITE_SYSREG((vaddr_t)hyp_traps_vector, VBAR_EL2);
 
     /* Setup hypervisor traps */
-    WRITE_SYSREG(HCR_PTW|HCR_BSU_OUTER|HCR_AMO|HCR_IMO|HCR_VM|HCR_TWI|HCR_TSC, HCR_EL2);
+    WRITE_SYSREG(HCR_PTW|HCR_BSU_OUTER|HCR_AMO|HCR_IMO|HCR_VM|HCR_TWI|HCR_TSC|
+                 HCR_TAC, HCR_EL2);
     isb();
 }
 
@@ -836,6 +837,7 @@ static void do_cp15_32(struct cpu_user_regs *regs,
 {
     struct hsr_cp32 cp32 = hsr.cp32;
     uint32_t *r = (uint32_t*)select_user_reg(regs, cp32.reg);
+    struct vcpu *v = current;
 
     if ( !cp32.ccvalid ) {
         dprintk(XENLOG_ERR, "cp_15(32): need to handle invalid condition codes\n");
@@ -889,6 +891,10 @@ static void do_cp15_32(struct cpu_user_regs *regs,
             domain_crash_synchronous();
         }
         break;
+    case HSR_CPREG32(ACTLR):
+        if ( cp32.read )
+           *r = v->arch.actlr;
+        break;
     default:
         printk("%s p15, %d, r%d, cr%d, cr%d, %d @ 0x%"PRIregister"\n",
                cp32.read ? "mrc" : "mcr",