target/i386: emulate, hvf, mshv: rework MMU code

target/i386/emulate doesn't currently properly emulate instructions
which might cause a page fault during their execution. Notably, REP STOS/MOVS
from MMIO to an address which is unmapped until a page fault exception is raised
causes an abort() in vmx_write_mem.

Change the interface between the HW accel backend and target/i386/emulate as a first step towards addressing that.

Adapt the page table walker code to give actionable errors,
while leaving a possibility for backends to provide their own walker.

This removes the usage of the Hyper-V page walker in the mshv backend.

Signed-off-by: Mohamed Mediouni <mohamed@unpredictable.fr>
Link: https://lore.kernel.org/r/20260223233950.96076-20-mohamed@unpredictable.fr
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
Mohamed Mediouni
2026-02-24 00:39:41 +01:00
committed by Paolo Bonzini
parent d1d985a34d
commit 1c85a4a3d7
11 changed files with 146 additions and 184 deletions

View File

@@ -80,7 +80,7 @@ static inline uint64_t decode_bytes(CPUX86State *env, struct x86_decode *decode,
if (emul_ops->fetch_instruction) {
emul_ops->fetch_instruction(env_cpu(env), &val, va, size);
} else {
emul_ops->read_mem(env_cpu(env), &val, va, size);
x86_read_mem(env_cpu(env), &val, va, size);
}
}
decode->len += size;

View File

@@ -166,7 +166,7 @@ void write_val_to_reg(void *reg_ptr, target_ulong val, int size)
static void write_val_to_mem(CPUX86State *env, target_ulong ptr, target_ulong val, int size)
{
emul_ops->write_mem(env_cpu(env), &val, ptr, size);
x86_write_mem(env_cpu(env), &val, ptr, size);
}
void write_val_ext(CPUX86State *env, struct x86_decode_op *decode, target_ulong val, int size)
@@ -180,7 +180,7 @@ void write_val_ext(CPUX86State *env, struct x86_decode_op *decode, target_ulong
uint8_t *read_mmio(CPUX86State *env, target_ulong ptr, int bytes)
{
emul_ops->read_mem(env_cpu(env), env->emu_mmio_buf, ptr, bytes);
x86_read_mem(env_cpu(env), env->emu_mmio_buf, ptr, bytes);
return env->emu_mmio_buf;
}
@@ -497,7 +497,7 @@ static void exec_ins_single(CPUX86State *env, struct x86_decode *decode)
emul_ops->handle_io(env_cpu(env), DX(env), env->emu_mmio_buf, 0,
decode->operand_size, 1);
emul_ops->write_mem(env_cpu(env), env->emu_mmio_buf, addr,
x86_write_mem(env_cpu(env), env->emu_mmio_buf, addr,
decode->operand_size);
string_increment_reg(env, R_EDI, decode);
@@ -518,7 +518,7 @@ static void exec_outs_single(CPUX86State *env, struct x86_decode *decode)
{
target_ulong addr = decode_linear_addr(env, decode, RSI(env), R_DS);
emul_ops->read_mem(env_cpu(env), env->emu_mmio_buf, addr,
x86_read_mem(env_cpu(env), env->emu_mmio_buf, addr,
decode->operand_size);
emul_ops->handle_io(env_cpu(env), DX(env), env->emu_mmio_buf, 1,
decode->operand_size, 1);
@@ -604,7 +604,7 @@ static void exec_stos_single(CPUX86State *env, struct x86_decode *decode)
addr = linear_addr_size(env_cpu(env), RDI(env),
decode->addressing_size, R_ES);
val = read_reg(env, R_EAX, decode->operand_size);
emul_ops->write_mem(env_cpu(env), &val, addr, decode->operand_size);
x86_write_mem(env_cpu(env), &val, addr, decode->operand_size);
string_increment_reg(env, R_EDI, decode);
}
@@ -628,7 +628,7 @@ static void exec_scas_single(CPUX86State *env, struct x86_decode *decode)
addr = linear_addr_size(env_cpu(env), RDI(env),
decode->addressing_size, R_ES);
decode->op[1].type = X86_VAR_IMMEDIATE;
emul_ops->read_mem(env_cpu(env), &decode->op[1].val, addr, decode->operand_size);
x86_read_mem(env_cpu(env), &decode->op[1].val, addr, decode->operand_size);
EXEC_2OP_FLAGS_CMD(env, decode, -, SET_FLAGS_OSZAPC_SUB, false);
string_increment_reg(env, R_EDI, decode);
@@ -653,7 +653,7 @@ static void exec_lods_single(CPUX86State *env, struct x86_decode *decode)
target_ulong val = 0;
addr = decode_linear_addr(env, decode, RSI(env), R_DS);
emul_ops->read_mem(env_cpu(env), &val, addr, decode->operand_size);
x86_read_mem(env_cpu(env), &val, addr, decode->operand_size);
write_reg(env, R_EAX, val, decode->operand_size);
string_increment_reg(env, R_ESI, decode);

View File

@@ -21,13 +21,13 @@
#include "x86.h"
#include "x86_decode.h"
#include "x86_mmu.h"
#include "cpu.h"
struct x86_emul_ops {
void (*fetch_instruction)(CPUState *cpu, void *data, target_ulong addr,
int bytes);
void (*read_mem)(CPUState *cpu, void *data, target_ulong addr, int bytes);
void (*write_mem)(CPUState *cpu, void *data, target_ulong addr, int bytes);
MMUTranslateResult (*mmu_gva_to_gpa) (CPUState *cpu, target_ulong gva, uint64_t *gpa, MMUTranslateFlags flags);
void (*read_segment_descriptor)(CPUState *cpu, struct x86_segment_descriptor *desc,
enum X86Seg seg);
void (*handle_io)(CPUState *cpu, uint16_t port, void *data, int direction,

View File

@@ -13,6 +13,7 @@
#include "cpu.h"
#include "emulate/x86_decode.h"
#include "emulate/x86_emu.h"
#include "emulate/x86_mmu.h"
#include "qemu/error-report.h"
#include "system/mshv.h"
@@ -176,7 +177,7 @@ bool x86_read_segment_descriptor(CPUState *cpu,
}
gva = base + sel.index * 8;
emul_ops->read_mem(cpu, desc, gva, sizeof(*desc));
x86_read_mem_priv(cpu, desc, gva, sizeof(*desc));
return true;
}
@@ -200,7 +201,7 @@ bool x86_read_call_gate(CPUState *cpu, struct x86_call_gate *idt_desc,
}
gva = base + gate * 8;
emul_ops->read_mem(cpu, idt_desc, gva, sizeof(*idt_desc));
x86_read_mem_priv(cpu, idt_desc, gva, sizeof(*idt_desc));
return true;
}

View File

@@ -21,7 +21,9 @@
#include "cpu.h"
#include "system/address-spaces.h"
#include "system/memory.h"
#include "qemu/error-report.h"
#include "emulate/x86.h"
#include "emulate/x86_emu.h"
#include "emulate/x86_mmu.h"
#define pte_present(pte) (pte & PT_PRESENT)
@@ -32,6 +34,11 @@
#define pte_large_page(pte) (pte & PT_PS)
#define pte_global_access(pte) (pte & PT_GLOBAL)
#define mmu_validate_write(flags) (flags & MMU_TRANSLATE_VALIDATE_WRITE)
#define mmu_validate_execute(flags) (flags & MMU_TRANSLATE_VALIDATE_EXECUTE)
#define mmu_priv_checks_exempt(flags) (flags & MMU_TRANSLATE_PRIV_CHECKS_EXEMPT)
#define PAE_CR3_MASK (~0x1fllu)
#define LEGACY_CR3_MASK (0xffffffff)
@@ -40,14 +47,16 @@
#define PAE_PTE_LARGE_PAGE_MASK ((-1llu << (21)) & ((1llu << 52) - 1))
#define PAE_PTE_SUPER_PAGE_MASK ((-1llu << (30)) & ((1llu << 52) - 1))
static bool is_user(CPUState *cpu)
{
return false;
}
struct gpt_translation {
target_ulong gva;
uint64_t gpa;
int err_code;
uint64_t pte[5];
bool write_access;
bool user_access;
bool exec_access;
};
static int gpt_top_level(CPUState *cpu, bool pae)
@@ -99,25 +108,15 @@ static bool get_pt_entry(CPUState *cpu, struct gpt_translation *pt,
}
/* test page table entry */
static bool test_pt_entry(CPUState *cpu, struct gpt_translation *pt,
int level, int *largeness, bool pae)
static MMUTranslateResult test_pt_entry(CPUState *cpu, struct gpt_translation *pt,
int level, int *largeness, bool pae, MMUTranslateFlags flags)
{
X86CPU *x86_cpu = X86_CPU(cpu);
CPUX86State *env = &x86_cpu->env;
uint64_t pte = pt->pte[level];
if (pt->write_access) {
pt->err_code |= MMU_PAGE_WT;
}
if (pt->user_access) {
pt->err_code |= MMU_PAGE_US;
}
if (pt->exec_access) {
pt->err_code |= MMU_PAGE_NX;
}
if (!pte_present(pte)) {
return false;
return MMU_TRANSLATE_PAGE_NOT_MAPPED;
}
if (pae && !x86_is_long_mode(cpu) && 2 == level) {
@@ -125,32 +124,30 @@ static bool test_pt_entry(CPUState *cpu, struct gpt_translation *pt,
}
if (level && pte_large_page(pte)) {
pt->err_code |= MMU_PAGE_PT;
*largeness = level;
}
if (!level) {
pt->err_code |= MMU_PAGE_PT;
}
uint32_t cr0 = env->cr[0];
/* check protection */
if (cr0 & CR0_WP_MASK) {
if (pt->write_access && !pte_write_access(pte)) {
return false;
if (mmu_validate_write(flags) && !pte_write_access(pte)) {
return MMU_TRANSLATE_PRIV_VIOLATION;
}
}
if (pt->user_access && !pte_user_access(pte)) {
return false;
if (!mmu_priv_checks_exempt(flags)) {
if (is_user(cpu) && !pte_user_access(pte)) {
return MMU_TRANSLATE_PRIV_VIOLATION;
}
}
if (pae && pt->exec_access && !pte_exec_access(pte)) {
return false;
if (pae && mmu_validate_execute(flags) && !pte_exec_access(pte)) {
return MMU_TRANSLATE_PRIV_VIOLATION;
}
exit:
/* TODO: check reserved bits */
return true;
return MMU_TRANSLATE_SUCCESS;
}
static inline uint64_t pse_pte_to_page(uint64_t pte)
@@ -181,7 +178,7 @@ static inline uint64_t large_page_gpa(struct gpt_translation *pt, bool pae,
static bool walk_gpt(CPUState *cpu, target_ulong addr, int err_code,
static MMUTranslateResult walk_gpt(CPUState *cpu, target_ulong addr, MMUTranslateFlags flags,
struct gpt_translation *pt, bool pae)
{
X86CPU *x86_cpu = X86_CPU(cpu);
@@ -190,21 +187,20 @@ static bool walk_gpt(CPUState *cpu, target_ulong addr, int err_code,
int largeness = 0;
target_ulong cr3 = env->cr[3];
uint64_t page_mask = pae ? PAE_PTE_PAGE_MASK : LEGACY_PTE_PAGE_MASK;
MMUTranslateResult res;
memset(pt, 0, sizeof(*pt));
top_level = gpt_top_level(cpu, pae);
pt->pte[top_level] = pae ? (cr3 & PAE_CR3_MASK) : (cr3 & LEGACY_CR3_MASK);
pt->gva = addr;
pt->user_access = (err_code & MMU_PAGE_US);
pt->write_access = (err_code & MMU_PAGE_WT);
pt->exec_access = (err_code & MMU_PAGE_NX);
for (level = top_level; level > 0; level--) {
get_pt_entry(cpu, pt, level, pae);
res = test_pt_entry(cpu, pt, level - 1, &largeness, pae, flags);
if (!test_pt_entry(cpu, pt, level - 1, &largeness, pae)) {
return false;
if (res) {
return res;
}
if (largeness) {
@@ -218,69 +214,111 @@ static bool walk_gpt(CPUState *cpu, target_ulong addr, int err_code,
pt->gpa = large_page_gpa(pt, pae, largeness);
}
return true;
return res;
}
bool mmu_gva_to_gpa(CPUState *cpu, target_ulong gva, uint64_t *gpa)
MMUTranslateResult mmu_gva_to_gpa(CPUState *cpu, target_ulong gva, uint64_t *gpa, MMUTranslateFlags flags)
{
if (emul_ops->mmu_gva_to_gpa) {
return emul_ops->mmu_gva_to_gpa(cpu, gva, gpa, flags);
}
bool res;
struct gpt_translation pt;
int err_code = 0;
if (!x86_is_paging_mode(cpu)) {
*gpa = gva;
return true;
return MMU_TRANSLATE_SUCCESS;
}
res = walk_gpt(cpu, gva, err_code, &pt, x86_is_pae_enabled(cpu));
if (res) {
res = walk_gpt(cpu, gva, flags, &pt, x86_is_pae_enabled(cpu));
if (res == MMU_TRANSLATE_SUCCESS) {
*gpa = pt.gpa;
return true;
}
return false;
return res;
}
void vmx_write_mem(CPUState *cpu, target_ulong gva, void *data, int bytes)
static MMUTranslateResult x86_write_mem_ex(CPUState *cpu, void *data, target_ulong gva, int bytes, bool priv_check_exempt)
{
MMUTranslateResult translate_res = MMU_TRANSLATE_SUCCESS;
MemTxResult mem_tx_res;
uint64_t gpa;
while (bytes > 0) {
/* copy page */
int copy = MIN(bytes, 0x1000 - (gva & 0xfff));
if (!mmu_gva_to_gpa(cpu, gva, &gpa)) {
VM_PANIC_EX("%s: mmu_gva_to_gpa " TARGET_FMT_lx " failed\n",
__func__, gva);
} else {
address_space_write(&address_space_memory, gpa,
MEMTXATTRS_UNSPECIFIED, data, copy);
translate_res = mmu_gva_to_gpa(cpu, gva, &gpa, MMU_TRANSLATE_VALIDATE_WRITE);
if (translate_res) {
return translate_res;
}
mem_tx_res = address_space_write(&address_space_memory, gpa,
MEMTXATTRS_UNSPECIFIED, data, copy);
if (mem_tx_res == MEMTX_DECODE_ERROR) {
warn_report("write to unmapped mmio region gpa=0x%" PRIx64 " size=%i", gpa, bytes);
return MMU_TRANSLATE_GPA_UNMAPPED;
} else if (mem_tx_res == MEMTX_ACCESS_ERROR) {
return MMU_TRANSLATE_GPA_NO_WRITE_ACCESS;
}
bytes -= copy;
gva += copy;
data += copy;
}
return translate_res;
}
void vmx_read_mem(CPUState *cpu, void *data, target_ulong gva, int bytes)
MMUTranslateResult x86_write_mem(CPUState *cpu, void *data, target_ulong gva, int bytes)
{
return x86_write_mem_ex(cpu, data, gva, bytes, false);
}
MMUTranslateResult x86_write_mem_priv(CPUState *cpu, void *data, target_ulong gva, int bytes)
{
return x86_write_mem_ex(cpu, data, gva, bytes, true);
}
static MMUTranslateResult x86_read_mem_ex(CPUState *cpu, void *data, target_ulong gva, int bytes, bool priv_check_exempt)
{
MMUTranslateResult translate_res = MMU_TRANSLATE_SUCCESS;
MemTxResult mem_tx_res;
uint64_t gpa;
while (bytes > 0) {
/* copy page */
int copy = MIN(bytes, 0x1000 - (gva & 0xfff));
if (!mmu_gva_to_gpa(cpu, gva, &gpa)) {
VM_PANIC_EX("%s: mmu_gva_to_gpa " TARGET_FMT_lx " failed\n",
__func__, gva);
translate_res = mmu_gva_to_gpa(cpu, gva, &gpa, 0);
if (translate_res) {
return translate_res;
}
address_space_read(&address_space_memory, gpa, MEMTXATTRS_UNSPECIFIED,
mem_tx_res = address_space_read(&address_space_memory, gpa, MEMTXATTRS_UNSPECIFIED,
data, copy);
if (mem_tx_res == MEMTX_DECODE_ERROR) {
warn_report("read from unmapped mmio region gpa=0x%" PRIx64 " size=%i", gpa, bytes);
return MMU_TRANSLATE_GPA_UNMAPPED;
} else if (mem_tx_res == MEMTX_ACCESS_ERROR) {
return MMU_TRANSLATE_GPA_NO_READ_ACCESS;
}
bytes -= copy;
gva += copy;
data += copy;
}
return translate_res;
}
MMUTranslateResult x86_read_mem(CPUState *cpu, void *data, target_ulong gva, int bytes)
{
return x86_read_mem_ex(cpu, data, gva, bytes, false);
}
MMUTranslateResult x86_read_mem_priv(CPUState *cpu, void *data, target_ulong gva, int bytes)
{
return x86_read_mem_ex(cpu, data, gva, bytes, true);
}

View File

@@ -30,15 +30,30 @@
#define PT_GLOBAL (1 << 8)
#define PT_NX (1llu << 63)
/* error codes */
#define MMU_PAGE_PT (1 << 0)
#define MMU_PAGE_WT (1 << 1)
#define MMU_PAGE_US (1 << 2)
#define MMU_PAGE_NX (1 << 3)
typedef enum MMUTranslateFlags {
MMU_TRANSLATE_VALIDATE_WRITE = BIT(1),
MMU_TRANSLATE_VALIDATE_EXECUTE = BIT(2),
MMU_TRANSLATE_PRIV_CHECKS_EXEMPT = BIT(3)
} MMUTranslateFlags;
bool mmu_gva_to_gpa(CPUState *cpu, target_ulong gva, uint64_t *gpa);
typedef enum MMUTranslateResult {
MMU_TRANSLATE_SUCCESS = 0,
MMU_TRANSLATE_PAGE_NOT_MAPPED = 1,
MMU_TRANSLATE_PRIV_VIOLATION = 2,
MMU_TRANSLATE_INVALID_PT_FLAGS = 3,
MMU_TRANSLATE_GPA_UNMAPPED = 4,
MMU_TRANSLATE_GPA_NO_READ_ACCESS = 5,
MMU_TRANSLATE_GPA_NO_WRITE_ACCESS = 6
} MMUTranslateResult;
MMUTranslateResult mmu_gva_to_gpa(CPUState *cpu, target_ulong gva, uint64_t *gpa, MMUTranslateFlags flags);
/* Thin wrappers x86_write_mem_ex/x86_read_mem_ex for code readability */
MMUTranslateResult x86_write_mem(CPUState *cpu, void *data, target_ulong gva, int bytes);
MMUTranslateResult x86_read_mem(CPUState *cpu, void *data, target_ulong gva, int bytes);
MMUTranslateResult x86_write_mem_priv(CPUState *cpu, void *data, target_ulong gva, int bytes);
MMUTranslateResult x86_read_mem_priv(CPUState *cpu, void *data, target_ulong gva, int bytes);
void vmx_write_mem(CPUState *cpu, target_ulong gva, void *data, int bytes);
void vmx_read_mem(CPUState *cpu, void *data, target_ulong gva, int bytes);
#endif /* X86_MMU_H */

View File

@@ -252,27 +252,7 @@ static void hvf_read_segment_descriptor(CPUState *s, struct x86_segment_descript
vmx_segment_to_x86_descriptor(s, &vmx_segment, desc);
}
static void hvf_read_mem(CPUState *cpu, void *data, target_ulong gva, int bytes)
{
X86CPU *x86_cpu = X86_CPU(cpu);
CPUX86State *env = &x86_cpu->env;
env->cr[0] = rvmcs(cpu->accel->fd, VMCS_GUEST_CR0);
env->cr[3] = rvmcs(cpu->accel->fd, VMCS_GUEST_CR3);
vmx_read_mem(cpu, data, gva, bytes);
}
static void hvf_write_mem(CPUState *cpu, void *data, target_ulong gva, int bytes)
{
X86CPU *x86_cpu = X86_CPU(cpu);
CPUX86State *env = &x86_cpu->env;
env->cr[0] = rvmcs(cpu->accel->fd, VMCS_GUEST_CR0);
env->cr[3] = rvmcs(cpu->accel->fd, VMCS_GUEST_CR3);
vmx_write_mem(cpu, gva, data, bytes);
}
static const struct x86_emul_ops hvf_x86_emul_ops = {
.read_mem = hvf_read_mem,
.write_mem = hvf_write_mem,
.read_segment_descriptor = hvf_read_segment_descriptor,
.handle_io = hvf_handle_io,
.simulate_rdmsr = hvf_simulate_rdmsr,
@@ -490,6 +470,14 @@ static void hvf_cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
}
}
static void hvf_load_crs(CPUState *cs)
{
X86CPU *x86_cpu = X86_CPU(cpu);
CPUX86State *env = &x86_cpu->env;
env->cr[0] = rvmcs(cpu->accel->fd, VMCS_GUEST_CR0);
env->cr[3] = rvmcs(cpu->accel->fd, VMCS_GUEST_CR3);
}
void hvf_load_regs(CPUState *cs)
{
X86CPU *cpu = X86_CPU(cs);
@@ -802,6 +790,7 @@ static int hvf_handle_vmexit(CPUState *cpu)
struct x86_decode decode;
hvf_load_regs(cpu);
hvf_load_crs(cpu);
decode_instruction(env, &decode);
exec_instruction(env, &decode);
hvf_store_regs(cpu);
@@ -843,6 +832,7 @@ static int hvf_handle_vmexit(CPUState *cpu)
}
hvf_load_regs(cpu);
hvf_load_crs(cpu);
decode_instruction(env, &decode);
assert(ins_len == decode.len);
exec_instruction(env, &decode);
@@ -948,6 +938,7 @@ static int hvf_handle_vmexit(CPUState *cpu)
struct x86_decode decode;
hvf_load_regs(cpu);
hvf_load_crs(cpu);
decode_instruction(env, &decode);
exec_instruction(env, &decode);
hvf_store_regs(cpu);

View File

@@ -72,7 +72,7 @@ bool x86_read_segment_descriptor(CPUState *cpu,
return false;
}
vmx_read_mem(cpu, desc, base + sel.index * 8, sizeof(*desc));
x86_read_mem_priv(cpu, desc, base + sel.index * 8, sizeof(*desc));
return true;
}
@@ -95,7 +95,7 @@ bool x86_write_segment_descriptor(CPUState *cpu,
printf("%s: gdt limit\n", __func__);
return false;
}
vmx_write_mem(cpu, base + sel.index * 8, desc, sizeof(*desc));
x86_write_mem_priv(cpu, desc, base + sel.index * 8, sizeof(*desc));
return true;
}
@@ -111,7 +111,7 @@ bool x86_read_call_gate(CPUState *cpu, struct x86_call_gate *idt_desc,
return false;
}
vmx_read_mem(cpu, idt_desc, base + gate * 8, sizeof(*idt_desc));
x86_read_mem_priv(cpu, idt_desc, base + gate * 8, sizeof(*idt_desc));
return true;
}

View File

@@ -93,16 +93,16 @@ static int task_switch_32(CPUState *cpu, x86_segment_selector tss_sel, x86_segme
uint32_t eip_offset = offsetof(struct x86_tss_segment32, eip);
uint32_t ldt_sel_offset = offsetof(struct x86_tss_segment32, ldt);
vmx_read_mem(cpu, &tss_seg, old_tss_base, sizeof(tss_seg));
x86_read_mem_priv(cpu, &tss_seg, old_tss_base, sizeof(tss_seg));
save_state_to_tss32(cpu, &tss_seg);
vmx_write_mem(cpu, old_tss_base + eip_offset, &tss_seg.eip, ldt_sel_offset - eip_offset);
vmx_read_mem(cpu, &tss_seg, new_tss_base, sizeof(tss_seg));
x86_write_mem_priv(cpu, &tss_seg.eip, old_tss_base + eip_offset, ldt_sel_offset - eip_offset);
x86_read_mem_priv(cpu, &tss_seg, new_tss_base, sizeof(tss_seg));
if (old_tss_sel.sel != 0xffff) {
tss_seg.prev_tss = old_tss_sel.sel;
vmx_write_mem(cpu, new_tss_base, &tss_seg.prev_tss, sizeof(tss_seg.prev_tss));
x86_write_mem_priv(cpu, &tss_seg.prev_tss, new_tss_base, sizeof(tss_seg.prev_tss));
}
load_state_from_tss32(cpu, &tss_seg);
return 0;

View File

@@ -1548,74 +1548,6 @@ int mshv_create_vcpu(int vm_fd, uint8_t vp_index, int *cpu_fd)
return 0;
}
static int guest_mem_read_with_gva(const CPUState *cpu, uint64_t gva,
uint8_t *data, uintptr_t size,
bool fetch_instruction)
{
int ret;
uint64_t gpa, flags;
flags = HV_TRANSLATE_GVA_VALIDATE_READ;
ret = translate_gva(cpu, gva, &gpa, flags);
if (ret < 0) {
error_report("failed to translate gva to gpa");
return -1;
}
ret = mshv_guest_mem_read(gpa, data, size, false, fetch_instruction);
if (ret < 0) {
error_report("failed to read from guest memory");
return -1;
}
return 0;
}
static int guest_mem_write_with_gva(const CPUState *cpu, uint64_t gva,
const uint8_t *data, uintptr_t size)
{
int ret;
uint64_t gpa, flags;
flags = HV_TRANSLATE_GVA_VALIDATE_WRITE;
ret = translate_gva(cpu, gva, &gpa, flags);
if (ret < 0) {
error_report("failed to translate gva to gpa");
return -1;
}
ret = mshv_guest_mem_write(gpa, data, size, false);
if (ret < 0) {
error_report("failed to write to guest memory");
return -1;
}
return 0;
}
static void write_mem(CPUState *cpu, void *data, target_ulong addr, int bytes)
{
if (guest_mem_write_with_gva(cpu, addr, data, bytes) < 0) {
error_report("failed to write memory");
abort();
}
}
static void fetch_instruction(CPUState *cpu, void *data,
target_ulong addr, int bytes)
{
if (guest_mem_read_with_gva(cpu, addr, data, bytes, true) < 0) {
error_report("failed to fetch instruction");
abort();
}
}
static void read_mem(CPUState *cpu, void *data, target_ulong addr, int bytes)
{
if (guest_mem_read_with_gva(cpu, addr, data, bytes, false) < 0) {
error_report("failed to read memory");
abort();
}
}
static void read_segment_descriptor(CPUState *cpu,
struct x86_segment_descriptor *desc,
enum X86Seg seg_idx)
@@ -1634,9 +1566,6 @@ static void read_segment_descriptor(CPUState *cpu,
}
static const struct x86_emul_ops mshv_x86_emul_ops = {
.fetch_instruction = fetch_instruction,
.read_mem = read_mem,
.write_mem = write_mem,
.read_segment_descriptor = read_segment_descriptor,
};

View File

@@ -862,16 +862,6 @@ static int whpx_handle_portio(CPUState *cpu,
return 0;
}
static void write_mem(CPUState *cpu, void *data, target_ulong addr, int bytes)
{
vmx_write_mem(cpu, addr, data, bytes);
}
static void read_mem(CPUState *cpu, void *data, target_ulong addr, int bytes)
{
vmx_read_mem(cpu, data, addr, bytes);
}
static void read_segment_descriptor(CPUState *cpu,
struct x86_segment_descriptor *desc,
enum X86Seg seg_idx)
@@ -891,8 +881,6 @@ static void read_segment_descriptor(CPUState *cpu,
static const struct x86_emul_ops whpx_x86_emul_ops = {
.read_mem = read_mem,
.write_mem = write_mem,
.read_segment_descriptor = read_segment_descriptor,
.handle_io = handle_io
};