diff --git a/qemu/target-arm/helper.c b/qemu/target-arm/helper.c index 1b8df6ee..d2c4cebb 100644 --- a/qemu/target-arm/helper.c +++ b/qemu/target-arm/helper.c @@ -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, diff --git a/qemu/target-arm/translate-a64.c b/qemu/target-arm/translate-a64.c index 27b07a89..11adefa2 100644 --- a/qemu/target-arm/translate-a64.c +++ b/qemu/target-arm/translate-a64.c @@ -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; diff --git a/qemu/target-arm/translate.c b/qemu/target-arm/translate.c index ffc77272..f64d81fe 100644 --- a/qemu/target-arm/translate.c +++ b/qemu/target-arm/translate.c @@ -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; }