]> Git Repo - qemu.git/commitdiff
target-arm: Implement WFE as a yield operation
authorPeter Maydell <[email protected]>
Mon, 10 Mar 2014 14:56:30 +0000 (14:56 +0000)
committerPeter Maydell <[email protected]>
Mon, 10 Mar 2014 14:56:30 +0000 (14:56 +0000)
Implement WFE to yield our timeslice to the next CPU.
This avoids slowdowns in multicore configurations caused
by one core busy-waiting on a spinlock which can't possibly
be unlocked until the other core has an opportunity to run.
This speeds up my test case A15 dual-core boot by a factor
of three (though it is still four or five times slower than
a single-core boot).

Signed-off-by: Peter Maydell <[email protected]>
Message-id: 1393339545[email protected]
Reviewed-by: Richard Henderson <[email protected]>
Tested-by: Rob Herring <[email protected]>
include/exec/cpu-defs.h
target-arm/helper.h
target-arm/op_helper.c
target-arm/translate.c
target-arm/translate.h

index 01cd8c7a2b065e14e652d96cf9b1801f4893fe37..66a3d469382a16b852831df9dede0c711a74a648 100644 (file)
@@ -59,6 +59,7 @@ typedef uint64_t target_ulong;
 #define EXCP_HLT        0x10001 /* hlt instruction reached */
 #define EXCP_DEBUG      0x10002 /* cpu stopped after a breakpoint or singlestep */
 #define EXCP_HALTED     0x10003 /* cpu is halted (waiting for external event) */
+#define EXCP_YIELD      0x10004 /* cpu wants to yield timeslice to another */
 
 #define TB_JMP_CACHE_BITS 12
 #define TB_JMP_CACHE_SIZE (1 << TB_JMP_CACHE_BITS)
index 276f3a9149a65aab1623eb9e0c09fb4ee03eb14b..8923f8ae71f616433d3c94ba09f9ac4cccfbbaf0 100644 (file)
@@ -50,6 +50,7 @@ DEF_HELPER_FLAGS_3(sel_flags, TCG_CALL_NO_RWG_SE,
                    i32, i32, i32, i32)
 DEF_HELPER_2(exception, void, env, i32)
 DEF_HELPER_1(wfi, void, env)
+DEF_HELPER_1(wfe, void, env)
 
 DEF_HELPER_3(cpsr_write, void, env, i32, i32)
 DEF_HELPER_1(cpsr_read, i32, env)
index 7d06d2f9a56118d3a0b3f38a1b22cd0fcbd0dc76..5851e041a05a6616fb777b40b0458efbd73379ec 100644 (file)
@@ -225,6 +225,15 @@ void HELPER(wfi)(CPUARMState *env)
     cpu_loop_exit(env);
 }
 
+void HELPER(wfe)(CPUARMState *env)
+{
+    /* Don't actually halt the CPU, just yield back to top
+     * level loop
+     */
+    env->exception_index = EXCP_YIELD;
+    cpu_loop_exit(env);
+}
+
 void HELPER(exception)(CPUARMState *env, uint32_t excp)
 {
     env->exception_index = excp;
index 253d2a13eb28cac82adcedafc5d751f246f4af36..df259debcc75acd061c3ad11bfa3f747902dcc48 100644 (file)
@@ -3939,6 +3939,9 @@ static void gen_nop_hint(DisasContext *s, int val)
         s->is_jmp = DISAS_WFI;
         break;
     case 2: /* wfe */
+        gen_set_pc_im(s, s->pc);
+        s->is_jmp = DISAS_WFE;
+        break;
     case 4: /* sev */
     case 5: /* sevl */
         /* TODO: Implement SEV, SEVL and WFE.  May help SMP performance.  */
@@ -10857,6 +10860,9 @@ static inline void gen_intermediate_code_internal(ARMCPU *cpu,
         case DISAS_WFI:
             gen_helper_wfi(cpu_env);
             break;
+        case DISAS_WFE:
+            gen_helper_wfe(cpu_env);
+            break;
         case DISAS_SWI:
             gen_exception(EXCP_SWI);
             break;
index 67da6996c969d9a146c12ef00e3a0e8ce82ebfe8..2f491f9ff6626655987dd7aaa30bf18388159d7e 100644 (file)
@@ -44,6 +44,8 @@ extern TCGv_ptr cpu_env;
  * emitting unreachable code at the end of the TB in the A64 decoder
  */
 #define DISAS_EXC 6
+/* WFE */
+#define DISAS_WFE 7
 
 #ifdef TARGET_AARCH64
 void a64_translate_init(void);
This page took 0.046909 seconds and 4 git commands to generate.