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

[Xen-devel] [PATCH 02/18] xen/arm: Restore HCR_EL2 register



Different domains may have different HCR_EL2 flags. For example, the
64-bit domain needs HCR_RW flag but the 32-bit does not need it. So
we give each domain a default HCR_EL2 value and save it in the VCPU's
context.

HCR_EL2 register has only one bit can be updated automatically without
explicit write (HCR_VSE). But we haven't used this bit currently, so
we can consider that the HCR_EL2 register will not be modified while
the guest is running. So save the HCR_EL2 while guest exiting to
hypervisor is not neccessary. We just have to restore this register for
each VCPU while leaving hypervisor.

We prefer to restore HCR_EL2 in leave_hypervisor_tail rather than in
ctxt_switch_to. Because the leave_hypervisor_tail is the closest place
to the exception return. In this case, we don't need to warrant the
HCR_EL2 will not be changed between ctxt_switch_to and exception return.

Even though we have restored HCR_EL2 in leave_hypervisor_tail, we still
have to keep the write to HCR_EL2 in p2m_restore_state. That because
p2m_restore_state could be used to switch between two p2m and possibly
to do address translation using hardware. For instance when building
the hardware domain, we are using the instruction to before copying
data. During the translation, some bits of base register (such as SCTLR
and HCR) could be cached in TLB and used for the translation.

We had some issues in the past (see commit b3cbe129d "xen: arm: Ensure
HCR_EL2.RW is set correctly when building dom0"), so we should probably
keep the write to HCR_EL2 in p2m_restore_state.

Signed-off-by: wei chen <Wei.Chen@xxxxxxx>
---
 xen/arch/arm/domain.c        |  2 ++
 xen/arch/arm/p2m.c           | 15 +++++++++------
 xen/arch/arm/traps.c         |  1 +
 xen/include/asm-arm/domain.h |  3 +++
 4 files changed, 15 insertions(+), 6 deletions(-)

diff --git a/xen/arch/arm/domain.c b/xen/arch/arm/domain.c
index bb327da..5d18bb0 100644
--- a/xen/arch/arm/domain.c
+++ b/xen/arch/arm/domain.c
@@ -513,6 +513,8 @@ int vcpu_initialise(struct vcpu *v)
 
     v->arch.actlr = READ_SYSREG32(ACTLR_EL1);
 
+    v->arch.hcr_el2 = get_default_hcr_flags();
+
     processor_vcpu_initialise(v);
 
     if ( (rc = vcpu_vgic_init(v)) != 0 )
diff --git a/xen/arch/arm/p2m.c b/xen/arch/arm/p2m.c
index 1fc6ca3..c49bfa6 100644
--- a/xen/arch/arm/p2m.c
+++ b/xen/arch/arm/p2m.c
@@ -128,26 +128,29 @@ void p2m_save_state(struct vcpu *p)
 
 void p2m_restore_state(struct vcpu *n)
 {
-    register_t hcr;
     struct p2m_domain *p2m = &n->domain->arch.p2m;
 
     if ( is_idle_vcpu(n) )
         return;
 
-    hcr = READ_SYSREG(HCR_EL2);
-
     WRITE_SYSREG64(p2m->vttbr, VTTBR_EL2);
     isb();
 
     if ( is_32bit_domain(n->domain) )
-        hcr &= ~HCR_RW;
+        n->arch.hcr_el2 &= ~HCR_RW;
     else
-        hcr |= HCR_RW;
+        n->arch.hcr_el2 |= HCR_RW;
 
     WRITE_SYSREG(n->arch.sctlr, SCTLR_EL1);
     isb();
 
-    WRITE_SYSREG(hcr, HCR_EL2);
+    /*
+     * p2m_restore_state could be used to switch between two p2m and possibly
+     * to do address translation using hardware. And these operations may
+     * happen during the interval between enter/leave hypervior, so we should
+     * probably keep the write to HCR_EL2 here.
+     */
+    WRITE_SYSREG(n->arch.hcr_el2, HCR_EL2);
     isb();
 }
 
diff --git a/xen/arch/arm/traps.c b/xen/arch/arm/traps.c
index d343c66..9792d02 100644
--- a/xen/arch/arm/traps.c
+++ b/xen/arch/arm/traps.c
@@ -2811,6 +2811,7 @@ asmlinkage void leave_hypervisor_tail(void)
         local_irq_disable();
         if (!softirq_pending(smp_processor_id())) {
             gic_inject();
+            WRITE_SYSREG(current->arch.hcr_el2, HCR_EL2);
             return;
         }
         local_irq_enable();
diff --git a/xen/include/asm-arm/domain.h b/xen/include/asm-arm/domain.h
index 09fe502..7b1dacc 100644
--- a/xen/include/asm-arm/domain.h
+++ b/xen/include/asm-arm/domain.h
@@ -204,6 +204,9 @@ struct arch_vcpu
     register_t tpidr_el1;
     register_t tpidrro_el0;
 
+    /* HYP configuration */
+    register_t hcr_el2;
+
     uint32_t teecr, teehbr; /* ThumbEE, 32-bit guests only */
 #ifdef CONFIG_ARM_32
     /*
-- 
2.7.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®.