diff mbox

[v3] target-arm: Break the TB after ISB to execute self-modified code correctly

Message ID 1441814517-16041-1-git-send-email-afarallax@yandex.ru
State New
Headers show

Commit Message

Sergey Sorokin Sept. 9, 2015, 4:01 p.m. UTC
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 a self-modified code need to do
IC invalidation to be valid, and 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
according to ARMv8 ARM D1.14.4.

Signed-off-by: Sergey Sorokin <afarallax@yandex.ru>
---
Changes since previous version:
* ARMv6 ISB was also fixed.
* Second reason for TB breaking was mentioned in comments
and the commit message.

 target-arm/helper.c        |  6 +++++-
 target-arm/translate-a64.c |  8 +++++++-
 target-arm/translate.c     | 17 +++++++++++++++--
 3 files changed, 27 insertions(+), 4 deletions(-)

Comments

Peter Maydell Sept. 11, 2015, 3:44 p.m. UTC | #1
On 9 September 2015 at 17:01, Sergey Sorokin <afarallax@yandex.ru> wrote:
> 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 a self-modified code need to do
> IC invalidation to be valid, and 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
> according to ARMv8 ARM D1.14.4.
>
> Signed-off-by: Sergey Sorokin <afarallax@yandex.ru>

This doesn't compile...

/home/petmay01/linaro/qemu-from-laptop/qemu/target-arm/translate.c: In
function ‘disas_thumb2_insn’:
/home/petmay01/linaro/qemu-from-laptop/qemu/target-arm/translate.c:10017:29:
error: ‘return’ with no value, in function returning non-void
[-Werror=return-type]
                             return;
                             ^

thanks
-- PMM
Sergey Sorokin Sept. 11, 2015, 3:55 p.m. UTC | #2
11.09.2015, 18:44, "Peter Maydell" <peter.maydell@linaro.org>:
> On 9 September 2015 at 17:01, Sergey Sorokin <afarallax@yandex.ru> wrote:
>>  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 a self-modified code need to do
>>  IC invalidation to be valid, and 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
>>  according to ARMv8 ARM D1.14.4.
>>
>>  Signed-off-by: Sergey Sorokin <afarallax@yandex.ru>
>
> This doesn't compile...
>
> /home/petmay01/linaro/qemu-from-laptop/qemu/target-arm/translate.c: In
> function ‘disas_thumb2_insn’:
> /home/petmay01/linaro/qemu-from-laptop/qemu/target-arm/translate.c:10017:29:
> error: ‘return’ with no value, in function returning non-void
> [-Werror=return-type]
>                              return;
>                              ^
>
> thanks
> -- PMM

Oh, sorry. I'll fix it next week.
Peter Maydell Oct. 1, 2015, 12:12 p.m. UTC | #3
On 11 September 2015 at 16:55, Sergey Sorokin <afarallax@yandex.ru> wrote:
>
>
> 11.09.2015, 18:44, "Peter Maydell" <peter.maydell@linaro.org>:
>> On 9 September 2015 at 17:01, Sergey Sorokin <afarallax@yandex.ru> wrote:
>>>  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 a self-modified code need to do
>>>  IC invalidation to be valid, and 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
>>>  according to ARMv8 ARM D1.14.4.
>>>
>>>  Signed-off-by: Sergey Sorokin <afarallax@yandex.ru>
>>
>> This doesn't compile...
>>
>> /home/petmay01/linaro/qemu-from-laptop/qemu/target-arm/translate.c: In
>> function ‘disas_thumb2_insn’:
>> /home/petmay01/linaro/qemu-from-laptop/qemu/target-arm/translate.c:10017:29:
>> error: ‘return’ with no value, in function returning non-void
>> [-Werror=return-type]
>>                              return;
>>                              ^

> Oh, sorry. I'll fix it next week.

Just a nudge that I think I'm still waiting for the next round of
this patchset from you?

thanks
-- PMM
Sergey Sorokin Oct. 2, 2015, 12:11 p.m. UTC | #4
Oh, sorry, I forgot about this. A lot of work now.
I'll send the patch.

01.10.2015, 15:12, "Peter Maydell" <peter.maydell@linaro.org>:
> On 11 September 2015 at 16:55, Sergey Sorokin <afarallax@yandex.ru> wrote:
>>  11.09.2015, 18:44, "Peter Maydell" <peter.maydell@linaro.org>:
>>>  On 9 September 2015 at 17:01, Sergey Sorokin <afarallax@yandex.ru> wrote:
>>>>   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 a self-modified code need to do
>>>>   IC invalidation to be valid, and 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
>>>>   according to ARMv8 ARM D1.14.4.
>>>>
>>>>   Signed-off-by: Sergey Sorokin <afarallax@yandex.ru>
>>>
>>>  This doesn't compile...
>>>
>>>  /home/petmay01/linaro/qemu-from-laptop/qemu/target-arm/translate.c: In
>>>  function ‘disas_thumb2_insn’:
>>>  /home/petmay01/linaro/qemu-from-laptop/qemu/target-arm/translate.c:10017:29:
>>>  error: ‘return’ with no value, in function returning non-void
>>>  [-Werror=return-type]
>>>                               return;
>>>                               ^
>
>>  Oh, sorry. I'll fix it next week.
>
> Just a nudge that I think I'm still waiting for the next round of
> this patchset from you?
>
> thanks
> -- PMM
diff mbox

Patch

diff --git a/target-arm/helper.c b/target-arm/helper.c
index fc4b65f..a12841f 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -627,8 +627,12 @@  static const ARMCPRegInfo v6_cp_reginfo[] = {
     { .name = "MVA_prefetch",
       .cp = 15, .crn = 7, .crm = 13, .opc1 = 0, .opc2 = 1,
       .access = PL1_W, .type = ARM_CP_NOP },
+    /* We need to break the TB after ISB to execute a self-modified code
+     * correctly and also to take any pending interrupts immediately.
+     * So use arm_cp_write_ignore() function instead of ARM_CP_NOP flag.
+     */
     { .name = "ISB", .cp = 15, .crn = 7, .crm = 5, .opc1 = 0, .opc2 = 4,
-      .access = PL0_W, .type = ARM_CP_NOP },
+      .access = PL0_W, .type = ARM_CP_NO_RAW, .writefn = arm_cp_write_ignore },
     { .name = "DSB", .cp = 15, .crn = 7, .crm = 10, .opc1 = 0, .opc2 = 4,
       .access = PL0_W, .type = ARM_CP_NOP },
     { .name = "DMB", .cp = 15, .crn = 7, .crm = 10, .opc1 = 0, .opc2 = 5,
diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c
index faece2c..11dfd4b 100644
--- a/target-arm/translate-a64.c
+++ b/target-arm/translate-a64.c
@@ -1235,9 +1235,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/target-arm/translate.c b/target-arm/translate.c
index 0bd3d05..00e0e4d 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -7689,10 +7689,16 @@  static void disas_arm_insn(DisasContext *s, unsigned int insn)
                 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
+                 * a self-modified code correctly and also to take
+                 * any pending interrupts immediately.
+                 */
+                gen_lookup_tb(s);
+                return;
             default:
                 goto illegal_op;
             }
@@ -9999,9 +10005,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 a self-modified code correctly
+                             * and also to take any pending interrupts
+                             * immediately.
+                             */
+                            gen_lookup_tb(s);
+                            return;
                         default:
                             goto illegal_op;
                         }