[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH v3 12/14] hvf: implement vga dirty page tracking
From: |
Sergio Andres Gomez Del Real |
Subject: |
[Qemu-devel] [PATCH v3 12/14] hvf: implement vga dirty page tracking |
Date: |
Mon, 4 Sep 2017 22:54:55 -0500 |
This commit implements setting the tracking of dirty pages, using hvf's
interface to protect guest memory. It uses the MemoryListener callback
mechanism through .log_start/stop/sync
Signed-off-by: Sergio Andres Gomez Del Real <address@hidden>
---
include/sysemu/hvf.h | 5 ++++
target/i386/hvf-all.c | 74 ++++++++++++++++++++++++++++++++++++++++++++++-----
2 files changed, 72 insertions(+), 7 deletions(-)
diff --git a/include/sysemu/hvf.h b/include/sysemu/hvf.h
index 944b014596..43b02be63c 100644
--- a/include/sysemu/hvf.h
+++ b/include/sysemu/hvf.h
@@ -34,11 +34,16 @@ uint32_t hvf_get_supported_cpuid(uint32_t func, uint32_t
idx,
#define hvf_get_supported_cpuid(func, idx, reg) 0
#endif
+/* hvf_slot flags */
+#define HVF_SLOT_LOG (1 << 0)
+
typedef struct hvf_slot {
uint64_t start;
uint64_t size;
uint8_t *mem;
int slot_id;
+ uint32_t flags;
+ MemoryRegion *region;
} hvf_slot;
struct hvf_vcpu_caps {
diff --git a/target/i386/hvf-all.c b/target/i386/hvf-all.c
index be68c71ea0..5644fa8ae0 100644
--- a/target/i386/hvf-all.c
+++ b/target/i386/hvf-all.c
@@ -195,6 +195,7 @@ void hvf_set_phys_mem(MemoryRegionSection *section, bool
add)
mem->size = int128_get64(section->size);
mem->mem = memory_region_get_ram_ptr(area) + section->offset_within_region;
mem->start = section->offset_within_address_space;
+ mem->region = area;
if (do_hvf_set_memory(mem)) {
error_report("Error registering new memory slot\n");
@@ -291,8 +292,7 @@ void hvf_cpu_synchronize_post_init(CPUState *cpu_state)
run_on_cpu(cpu_state, _hvf_cpu_synchronize_post_init, RUN_ON_CPU_NULL);
}
-/* TODO: ept fault handlig */
-static bool ept_emulation_fault(uint64_t ept_qual)
+static bool ept_emulation_fault(hvf_slot *slot, addr_t gpa, uint64_t ept_qual)
{
int read, write;
@@ -308,6 +308,14 @@ static bool ept_emulation_fault(uint64_t ept_qual)
return false;
}
+ if (write && slot) {
+ if (slot->flags & HVF_SLOT_LOG) {
+ memory_region_set_dirty(slot->region, gpa - slot->start, 1);
+ hv_vm_protect((hv_gpaddr_t)slot->start, (size_t)slot->size,
+ HV_MEMORY_READ | HV_MEMORY_WRITE);
+ }
+ }
+
/*
* The EPT violation must have been caused by accessing a
* guest-physical address that is a translation of a guest-linear
@@ -318,7 +326,59 @@ static bool ept_emulation_fault(uint64_t ept_qual)
return false;
}
- return true;
+ return !slot;
+}
+
+static void hvf_set_dirty_tracking(MemoryRegionSection *section, bool on)
+{
+ struct mac_slot *macslot;
+ hvf_slot *slot;
+
+ slot = hvf_find_overlap_slot(
+ section->offset_within_address_space,
+ section->offset_within_address_space +
int128_get64(section->size));
+
+ /* protect region against writes; begin tracking it */
+ if (on) {
+ slot->flags |= HVF_SLOT_LOG;
+ hv_vm_protect((hv_gpaddr_t)slot->start, (size_t)slot->size,
+ HV_MEMORY_READ);
+ /* stop tracking region*/
+ } else {
+ slot->flags &= ~HVF_SLOT_LOG;
+ hv_vm_protect((hv_gpaddr_t)slot->start, (size_t)slot->size,
+ HV_MEMORY_READ | HV_MEMORY_WRITE);
+ }
+}
+
+static void hvf_log_start(MemoryListener *listener,
+ MemoryRegionSection *section, int old, int new)
+{
+ if (old != 0) {
+ return;
+ }
+
+ hvf_set_dirty_tracking(section, 1);
+}
+
+static void hvf_log_stop(MemoryListener *listener,
+ MemoryRegionSection *section, int old, int new)
+{
+ if (new != 0) {
+ return;
+ }
+
+ hvf_set_dirty_tracking(section, 0);
+}
+
+static void hvf_log_sync(MemoryListener *listener,
+ MemoryRegionSection *section)
+{
+ /*
+ * sync of dirty pages is handled elsewhere; just make sure we keep
+ * tracking the region.
+ */
+ hvf_set_dirty_tracking(section, 1);
}
static void hvf_region_add(MemoryListener *listener,
@@ -337,6 +397,9 @@ static MemoryListener hvf_memory_listener = {
.priority = 10,
.region_add = hvf_region_add,
.region_del = hvf_region_del,
+ .log_start = hvf_log_start,
+ .log_stop = hvf_log_stop,
+ .log_sync = hvf_log_sync,
};
void vmx_reset_vcpu(CPUState *cpu) {
@@ -609,7 +672,7 @@ int hvf_vcpu_exec(CPUState *cpu)
slot = hvf_find_overlap_slot(gpa, gpa);
/* mmio */
- if (ept_emulation_fault(exit_qual) && !slot) {
+ if (ept_emulation_fault(slot, gpa, exit_qual)) {
struct x86_decode decode;
load_regs(cpu);
@@ -620,9 +683,6 @@ int hvf_vcpu_exec(CPUState *cpu)
store_regs(cpu);
break;
}
-#ifdef DIRTY_VGA_TRACKING
- /* TODO: handle dirty page tracking */
-#endif
break;
}
case EXIT_REASON_INOUT:
--
2.14.1
- [Qemu-devel] [PATCH v3 03/14] hvf: fix licensing issues; isolate task handling code (GPL v2-only), (continued)
- [Qemu-devel] [PATCH v3 09/14] hvf: use new helper functions for put/get xsave, Sergio Andres Gomez Del Real, 2017/09/04
- [Qemu-devel] [PATCH v3 10/14] hvf: implement hvf_get_supported_cpuid, Sergio Andres Gomez Del Real, 2017/09/04
- [Qemu-devel] [PATCH v3 11/14] hvf: refactor cpuid code, Sergio Andres Gomez Del Real, 2017/09/04
- [Qemu-devel] [PATCH v3 12/14] hvf: implement vga dirty page tracking,
Sergio Andres Gomez Del Real <=
- [Qemu-devel] [PATCH v3 13/14] hvf: refactor event injection code for hvf, Sergio Andres Gomez Del Real, 2017/09/04
- [Qemu-devel] [PATCH v3 14/14] hvf: inject General Protection Fault when vmexit through vmcall, Sergio Andres Gomez Del Real, 2017/09/04
- [Qemu-devel] [PATCH v3 06/14] hvf: handle fields from CPUState and CPUX86State, Sergio Andres Gomez Del Real, 2017/09/04
- Re: [Qemu-devel] [PATCH v3 00/14] add support for Hypervisor.framework in QEMU, Sergio Andrés Gómez del Real, 2017/09/04
- [Qemu-devel] [PATCH v3 02/14] hvf: add code base from Google's QEMU repository, Sergio Andres Gomez Del Real, 2017/09/05
- [Qemu-devel] [PATCH v3 04/14] hvf: run hvf code through checkpatch.pl and fix style issues, Sergio Andres Gomez Del Real, 2017/09/05