Skip to content

Commit e2faabe

Browse files
jrtc27rth7680
authored andcommitted
accel/tcg: Forward probe size on to notdirty_write
Without this, we just dirty a single byte, and so if the caller writes more than one byte to the host memory then we won't have invalidated any translation blocks that start after the first byte and overlap those writes. In particular, AArch64's DC ZVA implementation uses probe_access (via probe_write), and so we don't invalidate the entire block, only the TB overlapping the first byte (and, in the unusual case an unaligned VA is given to the instruction, we also probe that specific address in order to get the right VA reported on an exception, so will invalidate a TB overlapping that address too). Since our IC IVAU implementation is a no-op for system emulation that relies on the softmmu already having detected self-modifying code via this mechanism, this means we have observably wrong behaviour when jumping to code that has been DC ZVA'ed. In practice this is an unusual thing for software to do, as in reality the OS will DC ZVA the page and the application will go and write actual instructions to it that aren't UDF #0, but you can write a test that clearly shows the faulty behaviour. For functions other than probe_access it's not clear what size to use when 0 is passed in. Arguably a size of 0 shouldn't dirty at all, since if you want to actually write then you should pass in a real size, but I have conservatively kept the implementation as dirtying the first byte in that case so as to avoid breaking any assumptions about that behaviour. Signed-off-by: Jessica Clarke <jrtc27@jrtc27.com> Message-Id: <20231104031232.3246614-1-jrtc27@jrtc27.com> [rth: Move the dirtysize computation next to notdirty_write.] Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
1 parent cf9b579 commit e2faabe

File tree

1 file changed

+7
-4
lines changed

1 file changed

+7
-4
lines changed

accel/tcg/cputlb.c

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1479,7 +1479,8 @@ int probe_access_full(CPUArchState *env, vaddr addr, int size,
14791479

14801480
/* Handle clean RAM pages. */
14811481
if (unlikely(flags & TLB_NOTDIRTY)) {
1482-
notdirty_write(env_cpu(env), addr, 1, *pfull, retaddr);
1482+
int dirtysize = size == 0 ? 1 : size;
1483+
notdirty_write(env_cpu(env), addr, dirtysize, *pfull, retaddr);
14831484
flags &= ~TLB_NOTDIRTY;
14841485
}
14851486

@@ -1502,7 +1503,8 @@ int probe_access_full_mmu(CPUArchState *env, vaddr addr, int size,
15021503

15031504
/* Handle clean RAM pages. */
15041505
if (unlikely(flags & TLB_NOTDIRTY)) {
1505-
notdirty_write(env_cpu(env), addr, 1, *pfull, 0);
1506+
int dirtysize = size == 0 ? 1 : size;
1507+
notdirty_write(env_cpu(env), addr, dirtysize, *pfull, 0);
15061508
flags &= ~TLB_NOTDIRTY;
15071509
}
15081510

@@ -1524,7 +1526,8 @@ int probe_access_flags(CPUArchState *env, vaddr addr, int size,
15241526

15251527
/* Handle clean RAM pages. */
15261528
if (unlikely(flags & TLB_NOTDIRTY)) {
1527-
notdirty_write(env_cpu(env), addr, 1, full, retaddr);
1529+
int dirtysize = size == 0 ? 1 : size;
1530+
notdirty_write(env_cpu(env), addr, dirtysize, full, retaddr);
15281531
flags &= ~TLB_NOTDIRTY;
15291532
}
15301533

@@ -1560,7 +1563,7 @@ void *probe_access(CPUArchState *env, vaddr addr, int size,
15601563

15611564
/* Handle clean RAM pages. */
15621565
if (flags & TLB_NOTDIRTY) {
1563-
notdirty_write(env_cpu(env), addr, 1, full, retaddr);
1566+
notdirty_write(env_cpu(env), addr, size, full, retaddr);
15641567
}
15651568
}
15661569

0 commit comments

Comments
 (0)