aboutsummaryrefslogtreecommitdiff
path: root/exec.c
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2014-11-16 19:44:21 +0000
committerPeter Maydell <peter.maydell@linaro.org>2014-11-17 15:49:57 +0000
commite10b20e9edc73ef4d3871a0fd30e842383110959 (patch)
treecaeb0d61de8d685e804ba96bd95e95e0ff09bc61 /exec.c
parentc500b62a84f4c34330eccf9783c507b490202cc1 (diff)
exec: Handle multipage ranges in invalidate_and_set_dirty()ranchu-virtserial-rebasedranchu-linaro-beta2
The code in invalidate_and_set_dirty() needs to handle addr/length combinations which cross guest physical page boundaries. This can happen, for example, when disk I/O reads large blocks into guest RAM which previously held code that we have cached translations for. Unfortunately we were only checking the clean/dirty status of the first page in the range, and then were calling a tb_invalidate function which only handles ranges that don't cross page boundaries. Fix the function to deal with multipage ranges. The symptoms of this bug were that guest code would misbehave (eg segfault), in particular after a guest reboot but potentially any time the guest reused a page of its physical RAM for new code. [This is a cherry pick of upstream commit f874bf90] Cc: qemu-stable@nongnu.org Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Paolo Bonzini <pbonzini@redhat.com> Message-id: 1416167061-13203-1-git-send-email-peter.maydell@linaro.org
Diffstat (limited to 'exec.c')
-rw-r--r--exec.c6
1 files changed, 2 insertions, 4 deletions
diff --git a/exec.c b/exec.c
index 759055d0e3..f0e2bd32b6 100644
--- a/exec.c
+++ b/exec.c
@@ -2066,10 +2066,8 @@ int cpu_memory_rw_debug(CPUState *cpu, target_ulong addr,
static void invalidate_and_set_dirty(hwaddr addr,
hwaddr length)
{
- if (cpu_physical_memory_is_clean(addr)) {
- /* invalidate code */
- tb_invalidate_phys_page_range(addr, addr + length, 0);
- /* set dirty bit */
+ if (cpu_physical_memory_range_includes_clean(addr, length)) {
+ tb_invalidate_phys_range(addr, addr + length, 0);
cpu_physical_memory_set_dirty_range_nocode(addr, length);
}
xen_modified_memory(addr, length);