mirror of
https://github.com/yuzu-emu/unicorn.git
synced 2025-01-11 08:15:40 +00:00
target-arm: Break the TB after ISB to execute self-modified code correctly
If any store instruction writes the code inside the same TB after this store insn, the execution of the TB must be stopped to execute new code correctly. As described in ARMv8 manual D3.4.6 self-modifying code must do an IC invalidation to be valid, and an ISB after it. So it's enough to end the TB after ISB instruction on the code translation. Also this TB break is necessary to take any pending interrupts immediately after an ISB (as required by ARMv8 ARM D1.14.4). Backports commit 6df99dec9e81838423d723996e96236693fa31fe from qemu
This commit is contained in:
parent
d1bba24d86
commit
04992f0fb3
|
@ -545,8 +545,13 @@ static const ARMCPRegInfo v6_cp_reginfo[] = {
|
|||
/* prefetch by MVA in v6, NOP in v7 */
|
||||
{ "MVA_prefetch", 15,7,13, 0,0,1, 0,
|
||||
ARM_CP_NOP, PL1_W, },
|
||||
{ "ISB", 15,7,5, 0,0,4, 0,
|
||||
ARM_CP_NOP, PL0_W, },
|
||||
/* We need to break the TB after ISB to execute self-modifying code
|
||||
* correctly and also to take any pending interrupts immediately.
|
||||
* So use arm_cp_write_ignore() function instead of ARM_CP_NOP flag.
|
||||
*/
|
||||
{ "ISB", 15,7,5, 0,0,4, 0, ARM_CP_NO_RAW,
|
||||
PL0_W, 0, NULL, 0, 0, {0, 0},
|
||||
NULL, NULL, arm_cp_write_ignore },
|
||||
{ "DSB", 15,7,10, 0,0,4, 0,
|
||||
ARM_CP_NOP, PL0_W, },
|
||||
{ "DMB", 15,7,10, 0,0,5, 0,
|
||||
|
|
|
@ -1270,9 +1270,15 @@ static void handle_sync(DisasContext *s, uint32_t insn,
|
|||
return;
|
||||
case 4: /* DSB */
|
||||
case 5: /* DMB */
|
||||
case 6: /* ISB */
|
||||
/* We don't emulate caches so barriers are no-ops */
|
||||
return;
|
||||
case 6: /* ISB */
|
||||
/* We need to break the TB after this insn to execute
|
||||
* a self-modified code correctly and also to take
|
||||
* any pending interrupts immediately.
|
||||
*/
|
||||
s->is_jmp = DISAS_UPDATE;
|
||||
return;
|
||||
default:
|
||||
unallocated_encoding(s);
|
||||
return;
|
||||
|
|
|
@ -7860,10 +7860,16 @@ static void disas_arm_insn(DisasContext *s, unsigned int insn) // qq
|
|||
return;
|
||||
case 4: /* dsb */
|
||||
case 5: /* dmb */
|
||||
case 6: /* isb */
|
||||
ARCH(7);
|
||||
/* We don't emulate caches so these are a no-op. */
|
||||
return;
|
||||
case 6: /* isb */
|
||||
/* We need to break the TB after this insn to execute
|
||||
* self-modifying code correctly and also to take
|
||||
* any pending interrupts immediately.
|
||||
*/
|
||||
gen_lookup_tb(s);
|
||||
return;
|
||||
default:
|
||||
goto illegal_op;
|
||||
}
|
||||
|
@ -10172,9 +10178,16 @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw
|
|||
break;
|
||||
case 4: /* dsb */
|
||||
case 5: /* dmb */
|
||||
case 6: /* isb */
|
||||
/* These execute as NOPs. */
|
||||
break;
|
||||
case 6: /* isb */
|
||||
/* We need to break the TB after this insn
|
||||
* to execute self-modifying code correctly
|
||||
* and also to take any pending interrupts
|
||||
* immediately.
|
||||
*/
|
||||
gen_lookup_tb(s);
|
||||
break;
|
||||
default:
|
||||
goto illegal_op;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue