From 8840d8370daa6a7594c3917131d679d2e1eb979e Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Tue, 13 Feb 2018 22:46:56 -0500 Subject: [PATCH] target-arm: Split DISAS_YIELD from DISAS_WFE Currently we use DISAS_WFE for both WFE and YIELD instructions. This is functionally correct because at the moment both of them are implemented as "yield this CPU back to the top level loop so another CPU has a chance to run". However it's rather confusing that YIELD ends up calling HELPER(wfe), and if we ever want to implement real behaviour for WFE and SEV it's likely to trip us up. Split out the yield codepath to use DISAS_YIELD and a new HELPER(yield) function, and have HELPER(wfe) call HELPER(yield). Backports commit 049e24a191c212d9468db84169197887f2c91586 from qemu --- qemu/aarch64.h | 2 ++ qemu/aarch64eb.h | 2 ++ qemu/arm.h | 2 ++ qemu/armeb.h | 2 ++ qemu/header_gen.py | 2 ++ qemu/m68k.h | 2 ++ qemu/mips.h | 2 ++ qemu/mips64.h | 2 ++ qemu/mips64el.h | 2 ++ qemu/mipsel.h | 2 ++ qemu/powerpc.h | 2 ++ qemu/sparc.h | 2 ++ qemu/sparc64.h | 2 ++ qemu/target-arm/helper.h | 1 + qemu/target-arm/op_helper.c | 18 +++++++++++++++--- qemu/target-arm/translate-a64.c | 6 ++++++ qemu/target-arm/translate.h | 1 + qemu/x86_64.h | 2 ++ 18 files changed, 51 insertions(+), 3 deletions(-) diff --git a/qemu/aarch64.h b/qemu/aarch64.h index eb91e405..a8b26eb7 100644 --- a/qemu/aarch64.h +++ b/qemu/aarch64.h @@ -1137,6 +1137,7 @@ #define gen_helper_vfp_ultos gen_helper_vfp_ultos_aarch64 #define gen_helper_wfe gen_helper_wfe_aarch64 #define gen_helper_wfi gen_helper_wfi_aarch64 +#define gen_helper_yield gen_helper_yield_aarch64 #define gen_hvc gen_hvc_aarch64 #define gen_intermediate_code_internal gen_intermediate_code_internal_aarch64 #define gen_intermediate_code_internal_a64 gen_intermediate_code_internal_a64_aarch64 @@ -1923,6 +1924,7 @@ #define helper_vfp_uqtos helper_vfp_uqtos_aarch64 #define helper_wfe helper_wfe_aarch64 #define helper_wfi helper_wfi_aarch64 +#define helper_yield helper_yield_aarch64 #define hex2decimal hex2decimal_aarch64 #define hw_breakpoint_update hw_breakpoint_update_aarch64 #define hw_breakpoint_update_all hw_breakpoint_update_all_aarch64 diff --git a/qemu/aarch64eb.h b/qemu/aarch64eb.h index f8edd23b..9e25ad19 100644 --- a/qemu/aarch64eb.h +++ b/qemu/aarch64eb.h @@ -1137,6 +1137,7 @@ #define gen_helper_vfp_ultos gen_helper_vfp_ultos_aarch64eb #define gen_helper_wfe gen_helper_wfe_aarch64eb #define gen_helper_wfi gen_helper_wfi_aarch64eb +#define gen_helper_yield gen_helper_yield_aarch64eb #define gen_hvc gen_hvc_aarch64eb #define gen_intermediate_code_internal gen_intermediate_code_internal_aarch64eb #define gen_intermediate_code_internal_a64 gen_intermediate_code_internal_a64_aarch64eb @@ -1923,6 +1924,7 @@ #define helper_vfp_uqtos helper_vfp_uqtos_aarch64eb #define helper_wfe helper_wfe_aarch64eb #define helper_wfi helper_wfi_aarch64eb +#define helper_yield helper_yield_aarch64eb #define hex2decimal hex2decimal_aarch64eb #define hw_breakpoint_update hw_breakpoint_update_aarch64eb #define hw_breakpoint_update_all hw_breakpoint_update_all_aarch64eb diff --git a/qemu/arm.h b/qemu/arm.h index 8b442ff9..70c7eff9 100644 --- a/qemu/arm.h +++ b/qemu/arm.h @@ -1137,6 +1137,7 @@ #define gen_helper_vfp_ultos gen_helper_vfp_ultos_arm #define gen_helper_wfe gen_helper_wfe_arm #define gen_helper_wfi gen_helper_wfi_arm +#define gen_helper_yield gen_helper_yield_arm #define gen_hvc gen_hvc_arm #define gen_intermediate_code_internal gen_intermediate_code_internal_arm #define gen_intermediate_code_internal_a64 gen_intermediate_code_internal_a64_arm @@ -1923,6 +1924,7 @@ #define helper_vfp_uqtos helper_vfp_uqtos_arm #define helper_wfe helper_wfe_arm #define helper_wfi helper_wfi_arm +#define helper_yield helper_yield_arm #define hex2decimal hex2decimal_arm #define hw_breakpoint_update hw_breakpoint_update_arm #define hw_breakpoint_update_all hw_breakpoint_update_all_arm diff --git a/qemu/armeb.h b/qemu/armeb.h index e8c306bb..10a72b31 100644 --- a/qemu/armeb.h +++ b/qemu/armeb.h @@ -1137,6 +1137,7 @@ #define gen_helper_vfp_ultos gen_helper_vfp_ultos_armeb #define gen_helper_wfe gen_helper_wfe_armeb #define gen_helper_wfi gen_helper_wfi_armeb +#define gen_helper_yield gen_helper_yield_armeb #define gen_hvc gen_hvc_armeb #define gen_intermediate_code_internal gen_intermediate_code_internal_armeb #define gen_intermediate_code_internal_a64 gen_intermediate_code_internal_a64_armeb @@ -1923,6 +1924,7 @@ #define helper_vfp_uqtos helper_vfp_uqtos_armeb #define helper_wfe helper_wfe_armeb #define helper_wfi helper_wfi_armeb +#define helper_yield helper_yield_armeb #define hex2decimal hex2decimal_armeb #define hw_breakpoint_update hw_breakpoint_update_armeb #define hw_breakpoint_update_all hw_breakpoint_update_all_armeb diff --git a/qemu/header_gen.py b/qemu/header_gen.py index 20ae68d8..add19b32 100644 --- a/qemu/header_gen.py +++ b/qemu/header_gen.py @@ -1143,6 +1143,7 @@ symbols = ( 'gen_helper_vfp_ultos', 'gen_helper_wfe', 'gen_helper_wfi', + 'gen_helper_yield', 'gen_hvc', 'gen_intermediate_code_internal', 'gen_intermediate_code_internal_a64', @@ -1929,6 +1930,7 @@ symbols = ( 'helper_vfp_uqtos', 'helper_wfe', 'helper_wfi', + 'helper_yield', 'hex2decimal', 'hw_breakpoint_update', 'hw_breakpoint_update_all', diff --git a/qemu/m68k.h b/qemu/m68k.h index 96e1254b..dc4f2711 100644 --- a/qemu/m68k.h +++ b/qemu/m68k.h @@ -1137,6 +1137,7 @@ #define gen_helper_vfp_ultos gen_helper_vfp_ultos_m68k #define gen_helper_wfe gen_helper_wfe_m68k #define gen_helper_wfi gen_helper_wfi_m68k +#define gen_helper_yield gen_helper_yield_m68k #define gen_hvc gen_hvc_m68k #define gen_intermediate_code_internal gen_intermediate_code_internal_m68k #define gen_intermediate_code_internal_a64 gen_intermediate_code_internal_a64_m68k @@ -1923,6 +1924,7 @@ #define helper_vfp_uqtos helper_vfp_uqtos_m68k #define helper_wfe helper_wfe_m68k #define helper_wfi helper_wfi_m68k +#define helper_yield helper_yield_m68k #define hex2decimal hex2decimal_m68k #define hw_breakpoint_update hw_breakpoint_update_m68k #define hw_breakpoint_update_all hw_breakpoint_update_all_m68k diff --git a/qemu/mips.h b/qemu/mips.h index 9d61af1b..177078e0 100644 --- a/qemu/mips.h +++ b/qemu/mips.h @@ -1137,6 +1137,7 @@ #define gen_helper_vfp_ultos gen_helper_vfp_ultos_mips #define gen_helper_wfe gen_helper_wfe_mips #define gen_helper_wfi gen_helper_wfi_mips +#define gen_helper_yield gen_helper_yield_mips #define gen_hvc gen_hvc_mips #define gen_intermediate_code_internal gen_intermediate_code_internal_mips #define gen_intermediate_code_internal_a64 gen_intermediate_code_internal_a64_mips @@ -1923,6 +1924,7 @@ #define helper_vfp_uqtos helper_vfp_uqtos_mips #define helper_wfe helper_wfe_mips #define helper_wfi helper_wfi_mips +#define helper_yield helper_yield_mips #define hex2decimal hex2decimal_mips #define hw_breakpoint_update hw_breakpoint_update_mips #define hw_breakpoint_update_all hw_breakpoint_update_all_mips diff --git a/qemu/mips64.h b/qemu/mips64.h index 06302324..6036a496 100644 --- a/qemu/mips64.h +++ b/qemu/mips64.h @@ -1137,6 +1137,7 @@ #define gen_helper_vfp_ultos gen_helper_vfp_ultos_mips64 #define gen_helper_wfe gen_helper_wfe_mips64 #define gen_helper_wfi gen_helper_wfi_mips64 +#define gen_helper_yield gen_helper_yield_mips64 #define gen_hvc gen_hvc_mips64 #define gen_intermediate_code_internal gen_intermediate_code_internal_mips64 #define gen_intermediate_code_internal_a64 gen_intermediate_code_internal_a64_mips64 @@ -1923,6 +1924,7 @@ #define helper_vfp_uqtos helper_vfp_uqtos_mips64 #define helper_wfe helper_wfe_mips64 #define helper_wfi helper_wfi_mips64 +#define helper_yield helper_yield_mips64 #define hex2decimal hex2decimal_mips64 #define hw_breakpoint_update hw_breakpoint_update_mips64 #define hw_breakpoint_update_all hw_breakpoint_update_all_mips64 diff --git a/qemu/mips64el.h b/qemu/mips64el.h index ce53005c..10e26bec 100644 --- a/qemu/mips64el.h +++ b/qemu/mips64el.h @@ -1137,6 +1137,7 @@ #define gen_helper_vfp_ultos gen_helper_vfp_ultos_mips64el #define gen_helper_wfe gen_helper_wfe_mips64el #define gen_helper_wfi gen_helper_wfi_mips64el +#define gen_helper_yield gen_helper_yield_mips64el #define gen_hvc gen_hvc_mips64el #define gen_intermediate_code_internal gen_intermediate_code_internal_mips64el #define gen_intermediate_code_internal_a64 gen_intermediate_code_internal_a64_mips64el @@ -1923,6 +1924,7 @@ #define helper_vfp_uqtos helper_vfp_uqtos_mips64el #define helper_wfe helper_wfe_mips64el #define helper_wfi helper_wfi_mips64el +#define helper_yield helper_yield_mips64el #define hex2decimal hex2decimal_mips64el #define hw_breakpoint_update hw_breakpoint_update_mips64el #define hw_breakpoint_update_all hw_breakpoint_update_all_mips64el diff --git a/qemu/mipsel.h b/qemu/mipsel.h index 0b9dac0c..e7ca951d 100644 --- a/qemu/mipsel.h +++ b/qemu/mipsel.h @@ -1137,6 +1137,7 @@ #define gen_helper_vfp_ultos gen_helper_vfp_ultos_mipsel #define gen_helper_wfe gen_helper_wfe_mipsel #define gen_helper_wfi gen_helper_wfi_mipsel +#define gen_helper_yield gen_helper_yield_mipsel #define gen_hvc gen_hvc_mipsel #define gen_intermediate_code_internal gen_intermediate_code_internal_mipsel #define gen_intermediate_code_internal_a64 gen_intermediate_code_internal_a64_mipsel @@ -1923,6 +1924,7 @@ #define helper_vfp_uqtos helper_vfp_uqtos_mipsel #define helper_wfe helper_wfe_mipsel #define helper_wfi helper_wfi_mipsel +#define helper_yield helper_yield_mipsel #define hex2decimal hex2decimal_mipsel #define hw_breakpoint_update hw_breakpoint_update_mipsel #define hw_breakpoint_update_all hw_breakpoint_update_all_mipsel diff --git a/qemu/powerpc.h b/qemu/powerpc.h index fdb9d019..5c76755d 100644 --- a/qemu/powerpc.h +++ b/qemu/powerpc.h @@ -1137,6 +1137,7 @@ #define gen_helper_vfp_ultos gen_helper_vfp_ultos_powerpc #define gen_helper_wfe gen_helper_wfe_powerpc #define gen_helper_wfi gen_helper_wfi_powerpc +#define gen_helper_yield gen_helper_yield_powerpc #define gen_hvc gen_hvc_powerpc #define gen_intermediate_code_internal gen_intermediate_code_internal_powerpc #define gen_intermediate_code_internal_a64 gen_intermediate_code_internal_a64_powerpc @@ -1923,6 +1924,7 @@ #define helper_vfp_uqtos helper_vfp_uqtos_powerpc #define helper_wfe helper_wfe_powerpc #define helper_wfi helper_wfi_powerpc +#define helper_yield helper_yield_powerpc #define hex2decimal hex2decimal_powerpc #define hw_breakpoint_update hw_breakpoint_update_powerpc #define hw_breakpoint_update_all hw_breakpoint_update_all_powerpc diff --git a/qemu/sparc.h b/qemu/sparc.h index 45702778..28ad32b1 100644 --- a/qemu/sparc.h +++ b/qemu/sparc.h @@ -1137,6 +1137,7 @@ #define gen_helper_vfp_ultos gen_helper_vfp_ultos_sparc #define gen_helper_wfe gen_helper_wfe_sparc #define gen_helper_wfi gen_helper_wfi_sparc +#define gen_helper_yield gen_helper_yield_sparc #define gen_hvc gen_hvc_sparc #define gen_intermediate_code_internal gen_intermediate_code_internal_sparc #define gen_intermediate_code_internal_a64 gen_intermediate_code_internal_a64_sparc @@ -1923,6 +1924,7 @@ #define helper_vfp_uqtos helper_vfp_uqtos_sparc #define helper_wfe helper_wfe_sparc #define helper_wfi helper_wfi_sparc +#define helper_yield helper_yield_sparc #define hex2decimal hex2decimal_sparc #define hw_breakpoint_update hw_breakpoint_update_sparc #define hw_breakpoint_update_all hw_breakpoint_update_all_sparc diff --git a/qemu/sparc64.h b/qemu/sparc64.h index daeeab71..913c63b8 100644 --- a/qemu/sparc64.h +++ b/qemu/sparc64.h @@ -1137,6 +1137,7 @@ #define gen_helper_vfp_ultos gen_helper_vfp_ultos_sparc64 #define gen_helper_wfe gen_helper_wfe_sparc64 #define gen_helper_wfi gen_helper_wfi_sparc64 +#define gen_helper_yield gen_helper_yield_sparc64 #define gen_hvc gen_hvc_sparc64 #define gen_intermediate_code_internal gen_intermediate_code_internal_sparc64 #define gen_intermediate_code_internal_a64 gen_intermediate_code_internal_a64_sparc64 @@ -1923,6 +1924,7 @@ #define helper_vfp_uqtos helper_vfp_uqtos_sparc64 #define helper_wfe helper_wfe_sparc64 #define helper_wfi helper_wfi_sparc64 +#define helper_yield helper_yield_sparc64 #define hex2decimal hex2decimal_sparc64 #define hw_breakpoint_update hw_breakpoint_update_sparc64 #define hw_breakpoint_update_all hw_breakpoint_update_all_sparc64 diff --git a/qemu/target-arm/helper.h b/qemu/target-arm/helper.h index 7c1644ec..082bf980 100644 --- a/qemu/target-arm/helper.h +++ b/qemu/target-arm/helper.h @@ -53,6 +53,7 @@ DEF_HELPER_2(exception_internal, void, env, i32) DEF_HELPER_4(exception_with_syndrome, void, env, i32, i32, i32) DEF_HELPER_1(wfi, void, env) DEF_HELPER_1(wfe, void, env) +DEF_HELPER_1(yield, void, env) DEF_HELPER_1(pre_hvc, void, env) DEF_HELPER_2(pre_smc, void, env, i32) diff --git a/qemu/target-arm/op_helper.c b/qemu/target-arm/op_helper.c index e9556203..95538866 100644 --- a/qemu/target-arm/op_helper.c +++ b/qemu/target-arm/op_helper.c @@ -323,13 +323,25 @@ void HELPER(wfi)(CPUARMState *env) void HELPER(wfe)(CPUARMState *env) { - CPUState *cs = CPU(arm_env_get_cpu(env)); - - /* Don't actually halt the CPU, just yield back to top + /* This is a hint instruction that is semantically different + * from YIELD even though we currently implement it identically. + * Don't actually halt the CPU, just yield back to top * level loop. This is not going into a "low power state" * (ie halting until some event occurs), so we never take * a configurable trap to a different exception level. */ + HELPER(yield)(env); +} + +void HELPER(yield)(CPUARMState *env) +{ + ARMCPU *cpu = arm_env_get_cpu(env); + CPUState *cs = CPU(cpu); + + /* This is a non-trappable hint instruction that generally indicates + * that the guest is currently busy-looping. Yield control back to the + * top level loop so that a more deserving VCPU has a chance to run. + */ cs->exception_index = EXCP_YIELD; cpu_loop_exit(cs); } diff --git a/qemu/target-arm/translate-a64.c b/qemu/target-arm/translate-a64.c index 79cd761c..6d7f0fcd 100644 --- a/qemu/target-arm/translate-a64.c +++ b/qemu/target-arm/translate-a64.c @@ -1234,6 +1234,8 @@ static void handle_hint(DisasContext *s, uint32_t insn, s->is_jmp = DISAS_WFI; return; case 1: /* YIELD */ + s->is_jmp = DISAS_YIELD; + return; case 2: /* WFE */ s->is_jmp = DISAS_WFE; return; @@ -11400,6 +11402,10 @@ tb_end: gen_a64_set_pc_im(dc, dc->pc); gen_helper_wfe(tcg_ctx, tcg_ctx->cpu_env); break; + case DISAS_YIELD: + gen_a64_set_pc_im(dc, dc->pc); + gen_helper_yield(tcg_ctx, tcg_ctx->cpu_env); + break; case DISAS_WFI: /* This is a special case because we don't want to just halt the CPU * if trying to debug across a WFI. diff --git a/qemu/target-arm/translate.h b/qemu/target-arm/translate.h index 5a77471f..d0abef50 100644 --- a/qemu/target-arm/translate.h +++ b/qemu/target-arm/translate.h @@ -110,6 +110,7 @@ static inline int default_exception_el(DisasContext *s) #define DISAS_WFE 7 #define DISAS_HVC 8 #define DISAS_SMC 9 +#define DISAS_YIELD 10 #ifdef TARGET_AARCH64 void a64_translate_init(struct uc_struct *uc); diff --git a/qemu/x86_64.h b/qemu/x86_64.h index 133617ce..5e7de80d 100644 --- a/qemu/x86_64.h +++ b/qemu/x86_64.h @@ -1137,6 +1137,7 @@ #define gen_helper_vfp_ultos gen_helper_vfp_ultos_x86_64 #define gen_helper_wfe gen_helper_wfe_x86_64 #define gen_helper_wfi gen_helper_wfi_x86_64 +#define gen_helper_yield gen_helper_yield_x86_64 #define gen_hvc gen_hvc_x86_64 #define gen_intermediate_code_internal gen_intermediate_code_internal_x86_64 #define gen_intermediate_code_internal_a64 gen_intermediate_code_internal_a64_x86_64 @@ -1923,6 +1924,7 @@ #define helper_vfp_uqtos helper_vfp_uqtos_x86_64 #define helper_wfe helper_wfe_x86_64 #define helper_wfi helper_wfi_x86_64 +#define helper_yield helper_yield_x86_64 #define hex2decimal hex2decimal_x86_64 #define hw_breakpoint_update hw_breakpoint_update_x86_64 #define hw_breakpoint_update_all hw_breakpoint_update_all_x86_64