]> xenbits.xensource.com Git - xen.git/commitdiff
xen/arm: Trap and yield on WFE instructions
authorAnup Patel <anup.patel@linaro.org>
Wed, 16 Jul 2014 10:32:15 +0000 (16:02 +0530)
committerIan Campbell <ian.campbell@citrix.com>
Wed, 16 Jul 2014 14:30:08 +0000 (15:30 +0100)
If we have a Guest/DomU with two or more of its VCPUs running
on same host CPU then it can quite likely happen that these
VCPUs fight for same spinlock and one of them will waste CPU
cycles in WFE instruction. This patch makes WFE instruction
trap for VCPU and forces VCPU to yield its timeslice.

The KVM ARM/ARM64 also does similar thing for handling WFE
instructions. (Please refer,
https://lists.cs.columbia.edu/pipermail/kvmarm/2013-November/006259.html)

In general, this patch is more of an optimization for an
oversubscribed system having number of VCPUs more than
underlying host CPUs.

Signed-off-by: Anup Patel <anup.patel@linaro.org>
Signed-off-by: Pranavkumar Sawargaonkar <pranavkumar@linaro.org>
Tested-by: Pranavkumar Sawargaonkar <pranavkumar@linaro.org>
Acked-by: Ian Campbell <ian.campbell@citrix.com>
[ ijc -- resolved conflict with "Adding helper function for WFI",
         nuked stray hard tab ]

xen/arch/arm/traps.c
xen/include/asm-arm/processor.h

index 5e4c837ca4667327cfe76bf48116a54263ee1799..3dfabd066f115d00d2a379781adb2174e6c20051 100644 (file)
@@ -90,7 +90,7 @@ void __cpuinit init_traps(void)
 
     /* Setup hypervisor traps */
     WRITE_SYSREG(HCR_PTW|HCR_BSU_INNER|HCR_AMO|HCR_IMO|HCR_FMO|HCR_VM|
-                 HCR_TWI|HCR_TSC|HCR_TAC|HCR_SWIO|HCR_TIDCP, HCR_EL2);
+                 HCR_TWE|HCR_TWI|HCR_TSC|HCR_TAC|HCR_SWIO|HCR_TIDCP, HCR_EL2);
     isb();
 }
 
@@ -1803,8 +1803,13 @@ asmlinkage void do_trap_hypervisor(struct cpu_user_regs *regs)
             advance_pc(regs, hsr);
             return;
         }
-        /* at the moment we only trap WFI */
-        vcpu_block_unless_event_pending(current);
+        if ( hsr.wfi_wfe.ti ) {
+            /* Yield the VCPU for WFE */
+            vcpu_force_reschedule(current);
+        } else {
+            /* Block the VCPU for WFI */
+            vcpu_block_unless_event_pending(current);
+        }
         advance_pc(regs, hsr);
         break;
     case HSR_EC_CP15_32:
index bdfff4e95de22a4a3b6af31b69874d41ecdbc669..9d230f32e837c439c9106f5d114847a42afed1ea 100644 (file)
@@ -276,6 +276,15 @@ union hsr {
         unsigned long ec:6;    /* Exception Class */
     } cond;
 
+    struct hsr_wfi_wfe {
+        unsigned long ti:1;    /* Trapped instruction */
+        unsigned long sbzp:19;
+        unsigned long cc:4;    /* Condition Code */
+        unsigned long ccvalid:1;/* CC Valid */
+        unsigned long len:1;   /* Instruction length */
+        unsigned long ec:6;    /* Exception Class */
+    } wfi_wfe;
+
     /* reg, reg0, reg1 are 4 bits on AArch32, the fifth bit is sbzp. */
     struct hsr_cp32 {
         unsigned long read:1;  /* Direction */