xen/arm: Don't save/restore context for idle VCPU
authorJulien Grall <julien.grall@linaro.org>
Mon, 7 Jul 2014 15:29:15 +0000 (16:29 +0100)
committerIan Campbell <ian.campbell@citrix.com>
Thu, 10 Jul 2014 10:20:08 +0000 (11:20 +0100)
When an idle VCPU is running, Xen will never exit the hypervisor mode.
Futhermore, some part of the VCPU/domain initialization is already skipped for
them to avoid memory consumption.

Actually each save/restore functions are checking themself if the vcpu is
an idle one or not. We can safely skipped the context switch in one place
and gain a bit of time when we {,un}schedule idle VCPU. This is because
the saving part will take care of disabling anything related to guest (such
as GICv).

Also replace every check of and idle VCPU in save/restore functions by an
ASSERT, to know if someone is calling them with an idle VCPU in argument.

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/gic.c
xen/arch/arm/vtimer.c

index bb5c8107565cb870e1be713bcb729af2b3fd163f..0c16f23e4d23c0d037ef22fdaa53ee9a62312253 100644 (file)
@@ -60,6 +60,12 @@ void idle_loop(void)
 
 static void ctxt_switch_from(struct vcpu *p)
 {
+    /* When the idle VCPU is running, Xen will always stay in hypervisor
+     * mode. Therefore we don't need to save the context of an idle VCPU.
+     */
+    if ( is_idle_vcpu(p) )
+        goto end_context;
+
     p2m_save_state(p);
 
     /* CP 15 */
@@ -132,11 +138,19 @@ static void ctxt_switch_from(struct vcpu *p)
     gic_save_state(p);
 
     isb();
+
+end_context:
     context_saved(p);
 }
 
 static void ctxt_switch_to(struct vcpu *n)
 {
+    /* When the idle VCPU is running, Xen will always stay in hypervisor
+     * mode. Therefore we don't need to restore the context of an idle VCPU.
+     */
+    if ( is_idle_vcpu(n) )
+        return;
+
     p2m_restore_state(n);
 
     WRITE_SYSREG32(n->domain->arch.vpidr, VPIDR_EL2);
index e1e27b359d3db6e0fe8718ae7a0e0244c62df98c..83b004c4eacfb193f8868c0c07538d915fda7c69 100644 (file)
@@ -69,6 +69,7 @@ unsigned int gic_number_lines(void)
 void gic_save_state(struct vcpu *v)
 {
     ASSERT(!local_irq_is_enabled());
+    ASSERT(!is_idle_vcpu(v));
 
     /* No need for spinlocks here because interrupts are disabled around
      * this call and it only accesses struct vcpu fields that cannot be
@@ -82,9 +83,7 @@ void gic_save_state(struct vcpu *v)
 void gic_restore_state(struct vcpu *v)
 {
     ASSERT(!local_irq_is_enabled());
-
-    if ( is_idle_vcpu(v) )
-        return;
+    ASSERT(!is_idle_vcpu(v));
 
     this_cpu(lr_mask) = v->arch.lr_mask;
     gic_hw_ops->restore_state(v);
index 690657b9c7135c6ad5ade2a5606eb9bb2b099d25..2e95cebac13bb351cf084219c2b42c3f0cf1fac1 100644 (file)
@@ -94,8 +94,7 @@ void vcpu_timer_destroy(struct vcpu *v)
 
 int virt_timer_save(struct vcpu *v)
 {
-    if ( is_idle_domain(v->domain) )
-        return 0;
+    ASSERT(!is_idle_vcpu(v));
 
     v->arch.virt_timer.ctl = READ_SYSREG32(CNTV_CTL_EL0);
     WRITE_SYSREG32(v->arch.virt_timer.ctl & ~CNTx_CTL_ENABLE, CNTV_CTL_EL0);
@@ -111,8 +110,7 @@ int virt_timer_save(struct vcpu *v)
 
 int virt_timer_restore(struct vcpu *v)
 {
-    if ( is_idle_domain(v->domain) )
-        return 0;
+    ASSERT(!is_idle_vcpu(v));
 
     stop_timer(&v->arch.virt_timer.timer);
     migrate_timer(&v->arch.virt_timer.timer, v->processor);