diff options
author | Sergio Andres Gomez Del Real <sergio.g.delreal@gmail.com> | 2017-09-13 04:05:20 -0500 |
---|---|---|
committer | Paolo Bonzini <pbonzini@redhat.com> | 2017-12-22 15:01:48 +0100 |
commit | babfa20ca4721e950d8096f32b1dc091763a8837 (patch) | |
tree | 6df0ae5cc0b791f31a01e2fa480c92cf9067c920 /target/i386 | |
parent | d6dcc5583e7a3f04a76de72424ee63c760dffd0f (diff) | |
download | qemu-babfa20ca4721e950d8096f32b1dc091763a8837.zip qemu-babfa20ca4721e950d8096f32b1dc091763a8837.tar.gz qemu-babfa20ca4721e950d8096f32b1dc091763a8837.tar.bz2 |
i386: hvf: implement vga dirty page tracking
This patch implements setting the tracking of dirty vga 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 <Sergio.G.DelReal@gmail.com>
Message-Id: <20170913090522.4022-13-Sergio.G.DelReal@gmail.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Diffstat (limited to 'target/i386')
-rw-r--r-- | target/i386/hvf-all.c | 73 |
1 files changed, 66 insertions, 7 deletions
diff --git a/target/i386/hvf-all.c b/target/i386/hvf-all.c index ddeadac..b63dd55 100644 --- a/target/i386/hvf-all.c +++ b/target/i386/hvf-all.c @@ -193,6 +193,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"); @@ -289,8 +290,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; @@ -306,6 +306,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 @@ -316,7 +324,58 @@ 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) +{ + 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, @@ -335,6 +394,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 hvf_reset_vcpu(CPUState *cpu) { @@ -607,7 +669,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); @@ -618,9 +680,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: |