From: Richard Henderson <[email protected]> Notice writes to pages which are being monitored. Mark the page dirty, re-enable writes, and retry the instruction without emulation.
Assert the fault is not from a stage1 page table walk. Signed-off-by: Richard Henderson <[email protected]> Signed-off-by: Philippe Mathieu-Daudé <[email protected]> --- target/arm/hvf/hvf.c | 52 ++++++++++++++++++++++++++++++++++++-------- 1 file changed, 43 insertions(+), 9 deletions(-) diff --git a/target/arm/hvf/hvf.c b/target/arm/hvf/hvf.c index 77998ab90a6..cf4746c344a 100644 --- a/target/arm/hvf/hvf.c +++ b/target/arm/hvf/hvf.c @@ -37,6 +37,7 @@ #include "target/arm/trace.h" #include "trace.h" #include "migration/vmstate.h" +#include "exec/target_page.h" #include "gdbstub/enums.h" @@ -1880,9 +1881,10 @@ static int hvf_handle_exception(CPUState *cpu, hv_vcpu_exit_exception_t *excp) uint32_t srt = (syndrome >> 16) & 0x1f; uint32_t cm = (syndrome >> 8) & 0x1; uint64_t val = 0; + uint64_t ipa = excp->physical_address; + AddressSpace *as = cpu_get_address_space(cpu, ARMASIdx_NS); - trace_hvf_data_abort(excp->virtual_address, - excp->physical_address, isv, + trace_hvf_data_abort(excp->virtual_address, ipa, isv, iswrite, s1ptw, len, srt); if (cm) { @@ -1891,23 +1893,55 @@ static int hvf_handle_exception(CPUState *cpu, hv_vcpu_exit_exception_t *excp) break; } + /* Handle dirty page logging for ram. */ + if (iswrite) { + hwaddr xlat; + MemoryRegion *mr = address_space_translate(as, ipa, &xlat, + NULL, true, + MEMTXATTRS_UNSPECIFIED); + if (memory_region_is_ram(mr)) { + uint64_t ipa_page = ipa & TARGET_PAGE_MASK; + + /* TODO: Inject exception to the guest. */ + assert(!mr->readonly); + + if (memory_region_get_dirty_log_mask(mr)) { + memory_region_set_dirty(mr, ipa_page + xlat, + TARGET_PAGE_SIZE); + hvf_unprotect_dirty_range(ipa_page, TARGET_PAGE_SIZE); + } + + /* Retry with page writes enabled. */ + break; + } + } + + /* + * TODO: If s1ptw, this is an error in the guest os page tables. + * Inject the exception into the guest. + */ + assert(!s1ptw); + + /* + * TODO: ISV will be 0 for SIMD or SVE accesses. + * Inject the exception into the guest. + */ assert(isv); + /* + * Emulate MMIO. + * TODO: Inject faults for errors. + */ if (iswrite) { val = hvf_get_reg(cpu, srt); - address_space_write(&address_space_memory, - excp->physical_address, - MEMTXATTRS_UNSPECIFIED, &val, len); + address_space_write(as, ipa, MEMTXATTRS_UNSPECIFIED, &val, len); } else { - address_space_read(&address_space_memory, - excp->physical_address, - MEMTXATTRS_UNSPECIFIED, &val, len); + address_space_read(as, ipa, MEMTXATTRS_UNSPECIFIED, &val, len); if (sse) { val = sextract64(val, 0, len * 8); } hvf_set_reg(cpu, srt, val); } - advance_pc = true; break; } -- 2.51.0
