Browse Source

target/i386/hvf: Use address_space_translate in ept_emulation_fault

The hvf_slot structure is a poor replacement for properly
looking up a memory region in the address space.
Use memory_region_get_dirty_log_mask instead of HVF_SLOT_LOG.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Reviewed-by: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>
Message-ID: <20251103101034.59039-6-philmd@linaro.org>
pull/316/head
Richard Henderson 6 months ago
committed by Philippe Mathieu-Daudé
parent
commit
ef878343e8
  1. 41
      target/i386/hvf/hvf.c

41
target/i386/hvf/hvf.c

@ -119,9 +119,12 @@ void hvf_handle_io(CPUState *env, uint16_t port, void *buffer,
}
}
static bool ept_emulation_fault(hvf_slot *slot, uint64_t gpa, uint64_t ept_qual)
static bool ept_emulation_fault(CPUState *cs, uint64_t gpa, uint64_t ept_qual)
{
int read, write;
bool read, write;
MemoryRegion *mr;
hwaddr gpa_page = gpa & qemu_real_host_page_mask();
hwaddr xlat;
/* EPT fault on an instruction fetch doesn't make sense here */
if (ept_qual & EPT_VIOLATION_INST_FETCH) {
@ -129,21 +132,22 @@ static bool ept_emulation_fault(hvf_slot *slot, uint64_t gpa, uint64_t ept_qual)
}
/* EPT fault must be a read fault or a write fault */
read = ept_qual & EPT_VIOLATION_DATA_READ ? 1 : 0;
write = ept_qual & EPT_VIOLATION_DATA_WRITE ? 1 : 0;
if ((read | write) == 0) {
read = ept_qual & EPT_VIOLATION_DATA_READ;
write = ept_qual & EPT_VIOLATION_DATA_WRITE;
if (!read && !write) {
return false;
}
if (write && slot) {
if (slot->flags & HVF_SLOT_LOG) {
uintptr_t page_size = qemu_real_host_page_size();
intptr_t page_mask = -(intptr_t)page_size;
uint64_t dirty_page_start = gpa & page_mask;
mr = address_space_translate(cpu_get_address_space(cs, X86ASIdx_MEM),
gpa_page, &xlat, NULL, write,
MEMTXATTRS_UNSPECIFIED);
memory_region_set_dirty(slot->region, gpa - slot->start, 1);
hvf_unprotect_dirty_range(dirty_page_start, page_size);
}
/* Handle dirty page logging for ram. */
if (write && memory_region_get_dirty_log_mask(mr)) {
uintptr_t page_size = qemu_real_host_page_size();
memory_region_set_dirty(mr, gpa_page + xlat, page_size);
hvf_unprotect_dirty_range(gpa_page, page_size);
}
/*
@ -156,11 +160,8 @@ static bool ept_emulation_fault(hvf_slot *slot, uint64_t gpa, uint64_t ept_qual)
return false;
}
if (!slot) {
return true;
}
if (!memory_region_is_ram(slot->region) &&
!(read && memory_region_is_romd(slot->region))) {
if (!memory_region_is_ram(mr) &&
!(read && memory_region_is_romd(mr))) {
return true;
}
return false;
@ -765,7 +766,6 @@ static int hvf_handle_vmexit(CPUState *cpu)
/* Need to check if MMIO or unmapped fault */
case EXIT_REASON_EPT_FAULT:
{
hvf_slot *slot;
uint64_t gpa = rvmcs(cpu->accel->fd, VMCS_GUEST_PHYSICAL_ADDRESS);
if (((idtvec_info & VMCS_IDT_VEC_VALID) == 0) &&
@ -773,9 +773,8 @@ static int hvf_handle_vmexit(CPUState *cpu)
vmx_set_nmi_blocking(cpu);
}
slot = hvf_find_overlap_slot(gpa, 1);
/* mmio */
if (ept_emulation_fault(slot, gpa, exit_qual)) {
if (ept_emulation_fault(cpu, gpa, exit_qual)) {
struct x86_decode decode;
hvf_load_regs(cpu);

Loading…
Cancel
Save