[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH 63/88] exec: Handle multipage ranges in invalidate_a
From: |
Michael Roth |
Subject: |
[Qemu-devel] [PATCH 63/88] exec: Handle multipage ranges in invalidate_and_set_dirty() |
Date: |
Thu, 8 Jan 2015 11:34:07 -0600 |
From: Peter Maydell <address@hidden>
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.
Cc: address@hidden
Signed-off-by: Peter Maydell <address@hidden>
Reviewed-by: Paolo Bonzini <address@hidden>
Message-id: address@hidden
(cherry picked from commit f874bf905ff2f8dcc17acbfc61e49a92a6f4d04b)
Signed-off-by: Michael Roth <address@hidden>
---
exec.c | 6 ++----
include/exec/ram_addr.h | 25 +++++++++++++++++++++++++
2 files changed, 27 insertions(+), 4 deletions(-)
diff --git a/exec.c b/exec.c
index a7d7daa..bfee04a 100644
--- a/exec.c
+++ b/exec.c
@@ -2009,10 +2009,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);
diff --git a/include/exec/ram_addr.h b/include/exec/ram_addr.h
index 6593be1..e50e71c 100644
--- a/include/exec/ram_addr.h
+++ b/include/exec/ram_addr.h
@@ -49,6 +49,21 @@ static inline bool cpu_physical_memory_get_dirty(ram_addr_t
start,
return next < end;
}
+static inline bool cpu_physical_memory_get_clean(ram_addr_t start,
+ ram_addr_t length,
+ unsigned client)
+{
+ unsigned long end, page, next;
+
+ assert(client < DIRTY_MEMORY_NUM);
+
+ end = TARGET_PAGE_ALIGN(start + length) >> TARGET_PAGE_BITS;
+ page = start >> TARGET_PAGE_BITS;
+ next = find_next_zero_bit(ram_list.dirty_memory[client], end, page);
+
+ return next < end;
+}
+
static inline bool cpu_physical_memory_get_dirty_flag(ram_addr_t addr,
unsigned client)
{
@@ -64,6 +79,16 @@ static inline bool cpu_physical_memory_is_clean(ram_addr_t
addr)
return !(vga && code && migration);
}
+static inline bool cpu_physical_memory_range_includes_clean(ram_addr_t start,
+ ram_addr_t length)
+{
+ bool vga = cpu_physical_memory_get_clean(start, length, DIRTY_MEMORY_VGA);
+ bool code = cpu_physical_memory_get_clean(start, length,
DIRTY_MEMORY_CODE);
+ bool migration =
+ cpu_physical_memory_get_clean(start, length, DIRTY_MEMORY_MIGRATION);
+ return vga || code || migration;
+}
+
static inline void cpu_physical_memory_set_dirty_flag(ram_addr_t addr,
unsigned client)
{
--
1.9.1
- [Qemu-devel] [PATCH 58/88] target-xtensa: add missing window check for entry, (continued)
- [Qemu-devel] [PATCH 58/88] target-xtensa: add missing window check for entry, Michael Roth, 2015/01/08
- [Qemu-devel] [PATCH 21/88] ivshmem: Check ivshmem_read() size argument, Michael Roth, 2015/01/08
- [Qemu-devel] [PATCH 23/88] ivshmem: Fix potential OOB r/w access, Michael Roth, 2015/01/08
- [Qemu-devel] [PATCH 55/88] snapshot: add bdrv_drain_all() to bdrv_snapshot_delete() to avoid concurrency problem, Michael Roth, 2015/01/08
- [Qemu-devel] [PATCH 61/88] libcacard: fix resource leak, Michael Roth, 2015/01/08
- [Qemu-devel] [PATCH 59/88] kvm: Fix memory slot page alignment logic, Michael Roth, 2015/01/08
- [Qemu-devel] [PATCH 62/88] l2tpv3: fix possible double free, Michael Roth, 2015/01/08
- [Qemu-devel] [PATCH 60/88] virtio-scsi: work around bug in old BIOSes, Michael Roth, 2015/01/08
- [Qemu-devel] [PATCH 64/88] hw/ide/core.c: Prevent SIGSEGV during migration, Michael Roth, 2015/01/08
- [Qemu-devel] [PATCH 66/88] block: Make essential BlockDriver objects public, Michael Roth, 2015/01/08
- [Qemu-devel] [PATCH 63/88] exec: Handle multipage ranges in invalidate_and_set_dirty(),
Michael Roth <=
- [Qemu-devel] [PATCH 67/88] block: Omit bdrv_find_format for essential drivers, Michael Roth, 2015/01/08
- [Qemu-devel] [PATCH 65/88] virtio-net: fix unmap leak, Michael Roth, 2015/01/08
- [Qemu-devel] [PATCH 68/88] block/vvfat: qcow driver may not be found, Michael Roth, 2015/01/08
- [Qemu-devel] [PATCH 70/88] block: Check create_opts before image creation, Michael Roth, 2015/01/08
- [Qemu-devel] [PATCH 73/88] iotests: Only kill NBD server if it runs, Michael Roth, 2015/01/08
- [Qemu-devel] [PATCH 69/88] block/nfs: Add create_opts, Michael Roth, 2015/01/08
- [Qemu-devel] [PATCH 79/88] block migration: fix return value, Michael Roth, 2015/01/08
- [Qemu-devel] [PATCH 71/88] qemu-img: Check create_opts before image creation, Michael Roth, 2015/01/08
- [Qemu-devel] [PATCH 72/88] qemu-img: Check create_opts before image amendment, Michael Roth, 2015/01/08
- [Qemu-devel] [PATCH 74/88] iotests: Add test for unsupported image creation, Michael Roth, 2015/01/08