qemu with hax to log dma reads & writes jcs.org/2018/11/12/vfio

target/xtensa: move WINDOW_BASE SR update to postprocessing

Opcodes that modify WINDOW_BASE SR don't have dependency on opcodes that
use windowed registers. If such opcodes are combined in a single
instruction they may not be correctly ordered. Instead of adding said
dependency use temporary register to store changed WINDOW_BASE value and
do actual register window rotation as a postprocessing step.
Not all opcodes that change WINDOW_BASE need this: retw, rfwo and rfwu
are also jump opcodes, so they are guaranteed to be translated last and
thus will not affect other opcodes in the same instruction.

Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>

+28 -20
+1
target/xtensa/cpu.h
··· 486 486 float64 f64; 487 487 } fregs[16]; 488 488 float_status fp_status; 489 + uint32_t windowbase_next; 489 490 490 491 #ifndef CONFIG_USER_ONLY 491 492 xtensa_tlb_entry itlb[7][MAX_TLB_WAY_SIZE];
+1 -2
target/xtensa/helper.h
··· 3 3 DEF_HELPER_4(exception_cause_vaddr, noreturn, env, i32, i32, i32) 4 4 DEF_HELPER_3(debug_exception, noreturn, env, i32, i32) 5 5 6 - DEF_HELPER_2(wsr_windowbase, void, env, i32) 6 + DEF_HELPER_1(sync_windowbase, void, env) 7 7 DEF_HELPER_4(entry, void, env, i32, i32, i32) 8 8 DEF_HELPER_2(test_ill_retw, void, env, i32) 9 9 DEF_HELPER_2(test_underflow_retw, void, env, i32) 10 10 DEF_HELPER_2(retw, i32, env, i32) 11 - DEF_HELPER_2(rotw, void, env, i32) 12 11 DEF_HELPER_3(window_check, noreturn, env, i32, i32) 13 12 DEF_HELPER_1(restore_owb, void, env) 14 13 DEF_HELPER_2(movsp, void, env, i32)
+22 -8
target/xtensa/translate.c
··· 82 82 static TCGv_i32 cpu_FR[16]; 83 83 static TCGv_i32 cpu_SR[256]; 84 84 static TCGv_i32 cpu_UR[256]; 85 + static TCGv_i32 cpu_windowbase_next; 85 86 86 87 #include "exec/gen-icount.h" 87 88 ··· 253 254 uregnames[i].name); 254 255 } 255 256 } 257 + 258 + cpu_windowbase_next = 259 + tcg_global_mem_new_i32(cpu_env, 260 + offsetof(CPUXtensaState, windowbase_next), 261 + "windowbase_next"); 256 262 } 257 263 258 264 static inline bool option_enabled(DisasContext *dc, int opt) ··· 557 563 #ifndef CONFIG_USER_ONLY 558 564 static void gen_wsr_windowbase(DisasContext *dc, uint32_t sr, TCGv_i32 v) 559 565 { 560 - gen_helper_wsr_windowbase(cpu_env, v); 566 + tcg_gen_mov_i32(cpu_windowbase_next, v); 561 567 } 562 568 563 569 static void gen_wsr_windowstart(DisasContext *dc, uint32_t sr, TCGv_i32 v) ··· 858 864 859 865 if (op_flags & XTENSA_OP_CHECK_INTERRUPTS) { 860 866 gen_check_interrupts(dc); 867 + } 868 + if (op_flags & XTENSA_OP_SYNC_REGISTER_WINDOW) { 869 + gen_helper_sync_windowbase(cpu_env); 861 870 } 862 871 if (op_flags & XTENSA_OP_EXIT_TB_M1) { 863 872 slot = -1; ··· 2268 2277 static void translate_rotw(DisasContext *dc, const uint32_t arg[], 2269 2278 const uint32_t par[]) 2270 2279 { 2271 - TCGv_i32 tmp = tcg_const_i32(arg[0]); 2272 - gen_helper_rotw(cpu_env, tmp); 2273 - tcg_temp_free(tmp); 2280 + tcg_gen_addi_i32(cpu_windowbase_next, cpu_SR[WINDOW_BASE], arg[0]); 2274 2281 } 2275 2282 2276 2283 static void translate_rsil(DisasContext *dc, const uint32_t arg[], ··· 2972 2979 .translate = translate_entry, 2973 2980 .test_ill = test_ill_entry, 2974 2981 .test_overflow = test_overflow_entry, 2975 - .op_flags = XTENSA_OP_EXIT_TB_M1, 2982 + .op_flags = XTENSA_OP_EXIT_TB_M1 | 2983 + XTENSA_OP_SYNC_REGISTER_WINDOW, 2976 2984 }, { 2977 2985 .name = "esync", 2978 2986 .translate = translate_nop, ··· 3554 3562 }, { 3555 3563 .name = "rotw", 3556 3564 .translate = translate_rotw, 3557 - .op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_M1, 3565 + .op_flags = XTENSA_OP_PRIVILEGED | 3566 + XTENSA_OP_EXIT_TB_M1 | 3567 + XTENSA_OP_SYNC_REGISTER_WINDOW, 3558 3568 }, { 3559 3569 .name = "rsil", 3560 3570 .translate = translate_rsil, ··· 4622 4632 .translate = translate_wsr, 4623 4633 .test_ill = test_ill_wsr, 4624 4634 .par = (const uint32_t[]){WINDOW_BASE}, 4625 - .op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_M1, 4635 + .op_flags = XTENSA_OP_PRIVILEGED | 4636 + XTENSA_OP_EXIT_TB_M1 | 4637 + XTENSA_OP_SYNC_REGISTER_WINDOW, 4626 4638 }, { 4627 4639 .name = "wsr.windowstart", 4628 4640 .translate = translate_wsr, ··· 5108 5120 .translate = translate_xsr, 5109 5121 .test_ill = test_ill_xsr, 5110 5122 .par = (const uint32_t[]){WINDOW_BASE}, 5111 - .op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_M1, 5123 + .op_flags = XTENSA_OP_PRIVILEGED | 5124 + XTENSA_OP_EXIT_TB_M1 | 5125 + XTENSA_OP_SYNC_REGISTER_WINDOW, 5112 5126 }, { 5113 5127 .name = "xsr.windowstart", 5114 5128 .translate = translate_xsr,
+4 -10
target/xtensa/win_helper.c
··· 96 96 xtensa_rotate_window_abs(env, env->sregs[WINDOW_BASE] + delta); 97 97 } 98 98 99 - void HELPER(wsr_windowbase)(CPUXtensaState *env, uint32_t v) 99 + void HELPER(sync_windowbase)(CPUXtensaState *env) 100 100 { 101 - xtensa_rotate_window_abs(env, v); 101 + xtensa_rotate_window_abs(env, env->windowbase_next); 102 102 } 103 103 104 104 void HELPER(entry)(CPUXtensaState *env, uint32_t pc, uint32_t s, uint32_t imm) ··· 106 106 int callinc = (env->sregs[PS] & PS_CALLINC) >> PS_CALLINC_SHIFT; 107 107 108 108 env->regs[(callinc << 2) | (s & 3)] = env->regs[s] - imm; 109 - xtensa_rotate_window(env, callinc); 110 - env->sregs[WINDOW_START] |= 111 - windowstart_bit(env->sregs[WINDOW_BASE], env); 109 + env->windowbase_next = env->sregs[WINDOW_BASE] + callinc; 110 + env->sregs[WINDOW_START] |= windowstart_bit(env->windowbase_next, env); 112 111 } 113 112 114 113 void HELPER(window_check)(CPUXtensaState *env, uint32_t pc, uint32_t w) ··· 194 193 xtensa_rotate_window(env, -n); 195 194 env->sregs[WINDOW_START] &= ~windowstart_bit(windowbase, env); 196 195 return ret_pc; 197 - } 198 - 199 - void HELPER(rotw)(CPUXtensaState *env, uint32_t imm4) 200 - { 201 - xtensa_rotate_window(env, imm4); 202 196 } 203 197 204 198 void xtensa_restore_owb(CPUXtensaState *env)