@samitouri / QOSamiQemu / commits / 1c85a4a3d7

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>

Mohamed Mediouni committed Feb 24, 2026 at 00:39 UTC 1c85a4a3d7a5eca63f3f05c4a4c99223d044b4ce
11 files changed +146 -184
target/i386/emulate/x86_decode.c
+1 -1
@@ -80,7 +80,7 @@ static inline uint64_t decode_bytes(CPUX86State *env, struct x86_decode *decode,
80 if (emul_ops->fetch_instruction) {
81 emul_ops->fetch_instruction(env_cpu(env), &val, va, size);
82 } else {
83 - emul_ops->read_mem(env_cpu(env), &val, va, size);
83 + x86_read_mem(env_cpu(env), &val, va, size);
84 }
85 }
86 decode->len += size;
target/i386/emulate/x86_emu.c
+7 -7
@@ -166,7 +166,7 @@ void write_val_to_reg(void *reg_ptr, target_ulong val, int size)
166
167 static void write_val_to_mem(CPUX86State *env, target_ulong ptr, target_ulong val, int size)
168 {
169 - emul_ops->write_mem(env_cpu(env), &val, ptr, size);
169 + x86_write_mem(env_cpu(env), &val, ptr, size);
170 }
171
172 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
180
181 uint8_t *read_mmio(CPUX86State *env, target_ulong ptr, int bytes)
182 {
183 - emul_ops->read_mem(env_cpu(env), env->emu_mmio_buf, ptr, bytes);
183 + x86_read_mem(env_cpu(env), env->emu_mmio_buf, ptr, bytes);
184 return env->emu_mmio_buf;
185 }
186
@@ -497,7 +497,7 @@ static void exec_ins_single(CPUX86State *env, struct x86_decode *decode)
497
498 emul_ops->handle_io(env_cpu(env), DX(env), env->emu_mmio_buf, 0,
499 decode->operand_size, 1);
500 - emul_ops->write_mem(env_cpu(env), env->emu_mmio_buf, addr,
500 + x86_write_mem(env_cpu(env), env->emu_mmio_buf, addr,
501 decode->operand_size);
502
503 string_increment_reg(env, R_EDI, decode);
@@ -518,7 +518,7 @@ static void exec_outs_single(CPUX86State *env, struct x86_decode *decode)
518 {
519 target_ulong addr = decode_linear_addr(env, decode, RSI(env), R_DS);
520
521 - emul_ops->read_mem(env_cpu(env), env->emu_mmio_buf, addr,
521 + x86_read_mem(env_cpu(env), env->emu_mmio_buf, addr,
522 decode->operand_size);
523 emul_ops->handle_io(env_cpu(env), DX(env), env->emu_mmio_buf, 1,
524 decode->operand_size, 1);
@@ -604,7 +604,7 @@ static void exec_stos_single(CPUX86State *env, struct x86_decode *decode)
604 addr = linear_addr_size(env_cpu(env), RDI(env),
605 decode->addressing_size, R_ES);
606 val = read_reg(env, R_EAX, decode->operand_size);
607 - emul_ops->write_mem(env_cpu(env), &val, addr, decode->operand_size);
607 + x86_write_mem(env_cpu(env), &val, addr, decode->operand_size);
608
609 string_increment_reg(env, R_EDI, decode);
610 }
@@ -628,7 +628,7 @@ static void exec_scas_single(CPUX86State *env, struct x86_decode *decode)
628 addr = linear_addr_size(env_cpu(env), RDI(env),
629 decode->addressing_size, R_ES);
630 decode->op[1].type = X86_VAR_IMMEDIATE;
631 - emul_ops->read_mem(env_cpu(env), &decode->op[1].val, addr, decode->operand_size);
631 + x86_read_mem(env_cpu(env), &decode->op[1].val, addr, decode->operand_size);
632
633 EXEC_2OP_FLAGS_CMD(env, decode, -, SET_FLAGS_OSZAPC_SUB, false);
634 string_increment_reg(env, R_EDI, decode);
@@ -653,7 +653,7 @@ static void exec_lods_single(CPUX86State *env, struct x86_decode *decode)
653 target_ulong val = 0;
654
655 addr = decode_linear_addr(env, decode, RSI(env), R_DS);
656 - emul_ops->read_mem(env_cpu(env), &val, addr, decode->operand_size);
656 + x86_read_mem(env_cpu(env), &val, addr, decode->operand_size);
657 write_reg(env, R_EAX, val, decode->operand_size);
658
659 string_increment_reg(env, R_ESI, decode);
target/i386/emulate/x86_emu.h
+2 -2
@@ -21,13 +21,13 @@
21
22 #include "x86.h"
23 #include "x86_decode.h"
24 +#include "x86_mmu.h"
25 #include "cpu.h"
26
27 struct x86_emul_ops {
28 void (*fetch_instruction)(CPUState *cpu, void *data, target_ulong addr,
29 int bytes);
29 - void (*read_mem)(CPUState *cpu, void *data, target_ulong addr, int bytes);
30 - void (*write_mem)(CPUState *cpu, void *data, target_ulong addr, int bytes);
30 + MMUTranslateResult (*mmu_gva_to_gpa) (CPUState *cpu, target_ulong gva, uint64_t *gpa, MMUTranslateFlags flags);
31 void (*read_segment_descriptor)(CPUState *cpu, struct x86_segment_descriptor *desc,
32 enum X86Seg seg);
33 void (*handle_io)(CPUState *cpu, uint16_t port, void *data, int direction,
target/i386/emulate/x86_helpers.c
+3 -2
@@ -13,6 +13,7 @@
13 #include "cpu.h"
14 #include "emulate/x86_decode.h"
15 #include "emulate/x86_emu.h"
16 +#include "emulate/x86_mmu.h"
17 #include "qemu/error-report.h"
18 #include "system/mshv.h"
19
@@ -176,7 +177,7 @@ bool x86_read_segment_descriptor(CPUState *cpu,
177 }
178
179 gva = base + sel.index * 8;
179 - emul_ops->read_mem(cpu, desc, gva, sizeof(*desc));
180 + x86_read_mem_priv(cpu, desc, gva, sizeof(*desc));
181
182 return true;
183 }
@@ -200,7 +201,7 @@ bool x86_read_call_gate(CPUState *cpu, struct x86_call_gate *idt_desc,
201 }
202
203 gva = base + gate * 8;
203 - emul_ops->read_mem(cpu, idt_desc, gva, sizeof(*idt_desc));
204 + x86_read_mem_priv(cpu, idt_desc, gva, sizeof(*idt_desc));
205
206 return true;
207 }
target/i386/emulate/x86_mmu.c
+92 -54
@@ -21,7 +21,9 @@
21 #include "cpu.h"
22 #include "system/address-spaces.h"
23 #include "system/memory.h"
24 +#include "qemu/error-report.h"
25 #include "emulate/x86.h"
26 +#include "emulate/x86_emu.h"
27 #include "emulate/x86_mmu.h"
28
29 #define pte_present(pte) (pte & PT_PRESENT)
@@ -32,6 +34,11 @@
34 #define pte_large_page(pte) (pte & PT_PS)
35 #define pte_global_access(pte) (pte & PT_GLOBAL)
36
37 +#define mmu_validate_write(flags) (flags & MMU_TRANSLATE_VALIDATE_WRITE)
38 +#define mmu_validate_execute(flags) (flags & MMU_TRANSLATE_VALIDATE_EXECUTE)
39 +#define mmu_priv_checks_exempt(flags) (flags & MMU_TRANSLATE_PRIV_CHECKS_EXEMPT)
40 +
41 +
42 #define PAE_CR3_MASK (~0x1fllu)
43 #define LEGACY_CR3_MASK (0xffffffff)
44
@@ -40,14 +47,16 @@
47 #define PAE_PTE_LARGE_PAGE_MASK ((-1llu << (21)) & ((1llu << 52) - 1))
48 #define PAE_PTE_SUPER_PAGE_MASK ((-1llu << (30)) & ((1llu << 52) - 1))
49
50 +static bool is_user(CPUState *cpu)
51 +{
52 + return false;
53 +}
54 +
55 +
56 struct gpt_translation {
57 target_ulong gva;
58 uint64_t gpa;
46 - int err_code;
59 uint64_t pte[5];
48 - bool write_access;
49 - bool user_access;
50 - bool exec_access;
60 };
61
62 static int gpt_top_level(CPUState *cpu, bool pae)
@@ -99,25 +108,15 @@ static bool get_pt_entry(CPUState *cpu, struct gpt_translation *pt,
108 }
109
110 /* test page table entry */
102 -static bool test_pt_entry(CPUState *cpu, struct gpt_translation *pt,
103 - int level, int *largeness, bool pae)
111 +static MMUTranslateResult test_pt_entry(CPUState *cpu, struct gpt_translation *pt,
112 + int level, int *largeness, bool pae, MMUTranslateFlags flags)
113 {
114 X86CPU *x86_cpu = X86_CPU(cpu);
115 CPUX86State *env = &x86_cpu->env;
116 uint64_t pte = pt->pte[level];
117
109 - if (pt->write_access) {
110 - pt->err_code |= MMU_PAGE_WT;
111 - }
112 - if (pt->user_access) {
113 - pt->err_code |= MMU_PAGE_US;
114 - }
115 - if (pt->exec_access) {
116 - pt->err_code |= MMU_PAGE_NX;
117 - }
118 -
118 if (!pte_present(pte)) {
120 - return false;
119 + return MMU_TRANSLATE_PAGE_NOT_MAPPED;
120 }
121
122 if (pae && !x86_is_long_mode(cpu) && 2 == level) {
@@ -125,32 +124,30 @@ static bool test_pt_entry(CPUState *cpu, struct gpt_translation *pt,
124 }
125
126 if (level && pte_large_page(pte)) {
128 - pt->err_code |= MMU_PAGE_PT;
127 *largeness = level;
128 }
131 - if (!level) {
132 - pt->err_code |= MMU_PAGE_PT;
133 - }
129
130 uint32_t cr0 = env->cr[0];
131 /* check protection */
132 if (cr0 & CR0_WP_MASK) {
138 - if (pt->write_access && !pte_write_access(pte)) {
139 - return false;
133 + if (mmu_validate_write(flags) && !pte_write_access(pte)) {
134 + return MMU_TRANSLATE_PRIV_VIOLATION;
135 }
136 }
137
143 - if (pt->user_access && !pte_user_access(pte)) {
144 - return false;
138 + if (!mmu_priv_checks_exempt(flags)) {
139 + if (is_user(cpu) && !pte_user_access(pte)) {
140 + return MMU_TRANSLATE_PRIV_VIOLATION;
141 + }
142 }
143
147 - if (pae && pt->exec_access && !pte_exec_access(pte)) {
148 - return false;
144 + if (pae && mmu_validate_execute(flags) && !pte_exec_access(pte)) {
145 + return MMU_TRANSLATE_PRIV_VIOLATION;
146 }
147
148 exit:
149 /* TODO: check reserved bits */
153 - return true;
150 + return MMU_TRANSLATE_SUCCESS;
151 }
152
153 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,
178
179
180
184 -static bool walk_gpt(CPUState *cpu, target_ulong addr, int err_code,
181 +static MMUTranslateResult walk_gpt(CPUState *cpu, target_ulong addr, MMUTranslateFlags flags,
182 struct gpt_translation *pt, bool pae)
183 {
184 X86CPU *x86_cpu = X86_CPU(cpu);
@@ -190,21 +187,20 @@ static bool walk_gpt(CPUState *cpu, target_ulong addr, int err_code,
187 int largeness = 0;
188 target_ulong cr3 = env->cr[3];
189 uint64_t page_mask = pae ? PAE_PTE_PAGE_MASK : LEGACY_PTE_PAGE_MASK;
190 + MMUTranslateResult res;
191
192 memset(pt, 0, sizeof(*pt));
193 top_level = gpt_top_level(cpu, pae);
194
195 pt->pte[top_level] = pae ? (cr3 & PAE_CR3_MASK) : (cr3 & LEGACY_CR3_MASK);
196 pt->gva = addr;
199 - pt->user_access = (err_code & MMU_PAGE_US);
200 - pt->write_access = (err_code & MMU_PAGE_WT);
201 - pt->exec_access = (err_code & MMU_PAGE_NX);
197
198 for (level = top_level; level > 0; level--) {
199 get_pt_entry(cpu, pt, level, pae);
200 + res = test_pt_entry(cpu, pt, level - 1, &largeness, pae, flags);
201
206 - if (!test_pt_entry(cpu, pt, level - 1, &largeness, pae)) {
207 - return false;
202 + if (res) {
203 + return res;
204 }
205
206 if (largeness) {
@@ -218,69 +214,111 @@ static bool walk_gpt(CPUState *cpu, target_ulong addr, int err_code,
214 pt->gpa = large_page_gpa(pt, pae, largeness);
215 }
216
221 - return true;
217 + return res;
218 }
219
220
225 -bool mmu_gva_to_gpa(CPUState *cpu, target_ulong gva, uint64_t *gpa)
221 +MMUTranslateResult mmu_gva_to_gpa(CPUState *cpu, target_ulong gva, uint64_t *gpa, MMUTranslateFlags flags)
222 {
223 + if (emul_ops->mmu_gva_to_gpa) {
224 + return emul_ops->mmu_gva_to_gpa(cpu, gva, gpa, flags);
225 + }
226 +
227 bool res;
228 struct gpt_translation pt;
229 - int err_code = 0;
229
230 if (!x86_is_paging_mode(cpu)) {
231 *gpa = gva;
233 - return true;
232 + return MMU_TRANSLATE_SUCCESS;
233 }
234
236 - res = walk_gpt(cpu, gva, err_code, &pt, x86_is_pae_enabled(cpu));
237 - if (res) {
235 + res = walk_gpt(cpu, gva, flags, &pt, x86_is_pae_enabled(cpu));
236 + if (res == MMU_TRANSLATE_SUCCESS) {
237 *gpa = pt.gpa;
239 - return true;
238 }
239
242 - return false;
240 + return res;
241 }
242
245 -void vmx_write_mem(CPUState *cpu, target_ulong gva, void *data, int bytes)
243 +static MMUTranslateResult x86_write_mem_ex(CPUState *cpu, void *data, target_ulong gva, int bytes, bool priv_check_exempt)
244 {
245 + MMUTranslateResult translate_res = MMU_TRANSLATE_SUCCESS;
246 + MemTxResult mem_tx_res;
247 uint64_t gpa;
248
249 while (bytes > 0) {
250 /* copy page */
251 int copy = MIN(bytes, 0x1000 - (gva & 0xfff));
252
253 - if (!mmu_gva_to_gpa(cpu, gva, &gpa)) {
254 - VM_PANIC_EX("%s: mmu_gva_to_gpa " TARGET_FMT_lx " failed\n",
255 - __func__, gva);
256 - } else {
257 - address_space_write(&address_space_memory, gpa,
258 - MEMTXATTRS_UNSPECIFIED, data, copy);
253 + translate_res = mmu_gva_to_gpa(cpu, gva, &gpa, MMU_TRANSLATE_VALIDATE_WRITE);
254 + if (translate_res) {
255 + return translate_res;
256 + }
257 +
258 + mem_tx_res = address_space_write(&address_space_memory, gpa,
259 + MEMTXATTRS_UNSPECIFIED, data, copy);
260 +
261 + if (mem_tx_res == MEMTX_DECODE_ERROR) {
262 + warn_report("write to unmapped mmio region gpa=0x%" PRIx64 " size=%i", gpa, bytes);
263 + return MMU_TRANSLATE_GPA_UNMAPPED;
264 + } else if (mem_tx_res == MEMTX_ACCESS_ERROR) {
265 + return MMU_TRANSLATE_GPA_NO_WRITE_ACCESS;
266 }
267
268 bytes -= copy;
269 gva += copy;
270 data += copy;
271 }
272 + return translate_res;
273 +}
274 +
275 +MMUTranslateResult x86_write_mem(CPUState *cpu, void *data, target_ulong gva, int bytes)
276 +{
277 + return x86_write_mem_ex(cpu, data, gva, bytes, false);
278 +}
279 +
280 +MMUTranslateResult x86_write_mem_priv(CPUState *cpu, void *data, target_ulong gva, int bytes)
281 +{
282 + return x86_write_mem_ex(cpu, data, gva, bytes, true);
283 }
284
267 -void vmx_read_mem(CPUState *cpu, void *data, target_ulong gva, int bytes)
285 +static MMUTranslateResult x86_read_mem_ex(CPUState *cpu, void *data, target_ulong gva, int bytes, bool priv_check_exempt)
286 {
287 + MMUTranslateResult translate_res = MMU_TRANSLATE_SUCCESS;
288 + MemTxResult mem_tx_res;
289 uint64_t gpa;
290
291 while (bytes > 0) {
292 /* copy page */
293 int copy = MIN(bytes, 0x1000 - (gva & 0xfff));
294
275 - if (!mmu_gva_to_gpa(cpu, gva, &gpa)) {
276 - VM_PANIC_EX("%s: mmu_gva_to_gpa " TARGET_FMT_lx " failed\n",
277 - __func__, gva);
295 + translate_res = mmu_gva_to_gpa(cpu, gva, &gpa, 0);
296 + if (translate_res) {
297 + return translate_res;
298 }
279 - address_space_read(&address_space_memory, gpa, MEMTXATTRS_UNSPECIFIED,
299 + mem_tx_res = address_space_read(&address_space_memory, gpa, MEMTXATTRS_UNSPECIFIED,
300 data, copy);
301
302 + if (mem_tx_res == MEMTX_DECODE_ERROR) {
303 + warn_report("read from unmapped mmio region gpa=0x%" PRIx64 " size=%i", gpa, bytes);
304 + return MMU_TRANSLATE_GPA_UNMAPPED;
305 + } else if (mem_tx_res == MEMTX_ACCESS_ERROR) {
306 + return MMU_TRANSLATE_GPA_NO_READ_ACCESS;
307 + }
308 +
309 bytes -= copy;
310 gva += copy;
311 data += copy;
312 }
313 + return translate_res;
314 +}
315 +
316 +MMUTranslateResult x86_read_mem(CPUState *cpu, void *data, target_ulong gva, int bytes)
317 +{
318 + return x86_read_mem_ex(cpu, data, gva, bytes, false);
319 +}
320 +
321 +MMUTranslateResult x86_read_mem_priv(CPUState *cpu, void *data, target_ulong gva, int bytes)
322 +{
323 + return x86_read_mem_ex(cpu, data, gva, bytes, true);
324 }
target/i386/emulate/x86_mmu.h
+23 -8
@@ -30,15 +30,30 @@
30 #define PT_GLOBAL (1 << 8)
31 #define PT_NX (1llu << 63)
32
33 -/* error codes */
34 -#define MMU_PAGE_PT (1 << 0)
35 -#define MMU_PAGE_WT (1 << 1)
36 -#define MMU_PAGE_US (1 << 2)
37 -#define MMU_PAGE_NX (1 << 3)
33 +typedef enum MMUTranslateFlags {
34 + MMU_TRANSLATE_VALIDATE_WRITE = BIT(1),
35 + MMU_TRANSLATE_VALIDATE_EXECUTE = BIT(2),
36 + MMU_TRANSLATE_PRIV_CHECKS_EXEMPT = BIT(3)
37 +} MMUTranslateFlags;
38
39 -bool mmu_gva_to_gpa(CPUState *cpu, target_ulong gva, uint64_t *gpa);
39 +typedef enum MMUTranslateResult {
40 + MMU_TRANSLATE_SUCCESS = 0,
41 + MMU_TRANSLATE_PAGE_NOT_MAPPED = 1,
42 + MMU_TRANSLATE_PRIV_VIOLATION = 2,
43 + MMU_TRANSLATE_INVALID_PT_FLAGS = 3,
44 + MMU_TRANSLATE_GPA_UNMAPPED = 4,
45 + MMU_TRANSLATE_GPA_NO_READ_ACCESS = 5,
46 + MMU_TRANSLATE_GPA_NO_WRITE_ACCESS = 6
47 +} MMUTranslateResult;
48 +
49 +MMUTranslateResult mmu_gva_to_gpa(CPUState *cpu, target_ulong gva, uint64_t *gpa, MMUTranslateFlags flags);
50 +
51 +/* Thin wrappers x86_write_mem_ex/x86_read_mem_ex for code readability */
52 +MMUTranslateResult x86_write_mem(CPUState *cpu, void *data, target_ulong gva, int bytes);
53 +MMUTranslateResult x86_read_mem(CPUState *cpu, void *data, target_ulong gva, int bytes);
54 +
55 +MMUTranslateResult x86_write_mem_priv(CPUState *cpu, void *data, target_ulong gva, int bytes);
56 +MMUTranslateResult x86_read_mem_priv(CPUState *cpu, void *data, target_ulong gva, int bytes);
57
41 -void vmx_write_mem(CPUState *cpu, target_ulong gva, void *data, int bytes);
42 -void vmx_read_mem(CPUState *cpu, void *data, target_ulong gva, int bytes);
58
59 #endif /* X86_MMU_H */
target/i386/hvf/hvf.c
+11 -20
@@ -252,27 +252,7 @@ static void hvf_read_segment_descriptor(CPUState *s, struct x86_segment_descript
252 vmx_segment_to_x86_descriptor(s, &vmx_segment, desc);
253 }
254
255 -static void hvf_read_mem(CPUState *cpu, void *data, target_ulong gva, int bytes)
256 -{
257 - X86CPU *x86_cpu = X86_CPU(cpu);
258 - CPUX86State *env = &x86_cpu->env;
259 - env->cr[0] = rvmcs(cpu->accel->fd, VMCS_GUEST_CR0);
260 - env->cr[3] = rvmcs(cpu->accel->fd, VMCS_GUEST_CR3);
261 - vmx_read_mem(cpu, data, gva, bytes);
262 -}
263 -
264 -static void hvf_write_mem(CPUState *cpu, void *data, target_ulong gva, int bytes)
265 -{
266 - X86CPU *x86_cpu = X86_CPU(cpu);
267 - CPUX86State *env = &x86_cpu->env;
268 - env->cr[0] = rvmcs(cpu->accel->fd, VMCS_GUEST_CR0);
269 - env->cr[3] = rvmcs(cpu->accel->fd, VMCS_GUEST_CR3);
270 - vmx_write_mem(cpu, gva, data, bytes);
271 -}
272 -
255 static const struct x86_emul_ops hvf_x86_emul_ops = {
274 - .read_mem = hvf_read_mem,
275 - .write_mem = hvf_write_mem,
256 .read_segment_descriptor = hvf_read_segment_descriptor,
257 .handle_io = hvf_handle_io,
258 .simulate_rdmsr = hvf_simulate_rdmsr,
@@ -490,6 +470,14 @@ static void hvf_cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
470 }
471 }
472
473 +static void hvf_load_crs(CPUState *cs)
474 +{
475 + X86CPU *x86_cpu = X86_CPU(cpu);
476 + CPUX86State *env = &x86_cpu->env;
477 +
478 + env->cr[0] = rvmcs(cpu->accel->fd, VMCS_GUEST_CR0);
479 + env->cr[3] = rvmcs(cpu->accel->fd, VMCS_GUEST_CR3);
480 +}
481 void hvf_load_regs(CPUState *cs)
482 {
483 X86CPU *cpu = X86_CPU(cs);
@@ -802,6 +790,7 @@ static int hvf_handle_vmexit(CPUState *cpu)
790 struct x86_decode decode;
791
792 hvf_load_regs(cpu);
793 + hvf_load_crs(cpu);
794 decode_instruction(env, &decode);
795 exec_instruction(env, &decode);
796 hvf_store_regs(cpu);
@@ -843,6 +832,7 @@ static int hvf_handle_vmexit(CPUState *cpu)
832 }
833
834 hvf_load_regs(cpu);
835 + hvf_load_crs(cpu);
836 decode_instruction(env, &decode);
837 assert(ins_len == decode.len);
838 exec_instruction(env, &decode);
@@ -948,6 +938,7 @@ static int hvf_handle_vmexit(CPUState *cpu)
938 struct x86_decode decode;
939
940 hvf_load_regs(cpu);
941 + hvf_load_crs(cpu);
942 decode_instruction(env, &decode);
943 exec_instruction(env, &decode);
944 hvf_store_regs(cpu);
target/i386/hvf/x86.c
+3 -3
@@ -72,7 +72,7 @@ bool x86_read_segment_descriptor(CPUState *cpu,
72 return false;
73 }
74
75 - vmx_read_mem(cpu, desc, base + sel.index * 8, sizeof(*desc));
75 + x86_read_mem_priv(cpu, desc, base + sel.index * 8, sizeof(*desc));
76 return true;
77 }
78
@@ -95,7 +95,7 @@ bool x86_write_segment_descriptor(CPUState *cpu,
95 printf("%s: gdt limit\n", __func__);
96 return false;
97 }
98 - vmx_write_mem(cpu, base + sel.index * 8, desc, sizeof(*desc));
98 + x86_write_mem_priv(cpu, desc, base + sel.index * 8, sizeof(*desc));
99 return true;
100 }
101
@@ -111,7 +111,7 @@ bool x86_read_call_gate(CPUState *cpu, struct x86_call_gate *idt_desc,
111 return false;
112 }
113
114 - vmx_read_mem(cpu, idt_desc, base + gate * 8, sizeof(*idt_desc));
114 + x86_read_mem_priv(cpu, idt_desc, base + gate * 8, sizeof(*idt_desc));
115 return true;
116 }
117
target/i386/hvf/x86_task.c
+4 -4
@@ -93,16 +93,16 @@ static int task_switch_32(CPUState *cpu, x86_segment_selector tss_sel, x86_segme
93 uint32_t eip_offset = offsetof(struct x86_tss_segment32, eip);
94 uint32_t ldt_sel_offset = offsetof(struct x86_tss_segment32, ldt);
95
96 - vmx_read_mem(cpu, &tss_seg, old_tss_base, sizeof(tss_seg));
96 + x86_read_mem_priv(cpu, &tss_seg, old_tss_base, sizeof(tss_seg));
97 save_state_to_tss32(cpu, &tss_seg);
98
99 - vmx_write_mem(cpu, old_tss_base + eip_offset, &tss_seg.eip, ldt_sel_offset - eip_offset);
100 - vmx_read_mem(cpu, &tss_seg, new_tss_base, sizeof(tss_seg));
99 + x86_write_mem_priv(cpu, &tss_seg.eip, old_tss_base + eip_offset, ldt_sel_offset - eip_offset);
100 + x86_read_mem_priv(cpu, &tss_seg, new_tss_base, sizeof(tss_seg));
101
102 if (old_tss_sel.sel != 0xffff) {
103 tss_seg.prev_tss = old_tss_sel.sel;
104
105 - vmx_write_mem(cpu, new_tss_base, &tss_seg.prev_tss, sizeof(tss_seg.prev_tss));
105 + x86_write_mem_priv(cpu, &tss_seg.prev_tss, new_tss_base, sizeof(tss_seg.prev_tss));
106 }
107 load_state_from_tss32(cpu, &tss_seg);
108 return 0;
target/i386/mshv/mshv-cpu.c
-71
@@ -1548,74 +1548,6 @@ int mshv_create_vcpu(int vm_fd, uint8_t vp_index, int *cpu_fd)
1548 return 0;
1549 }
1550
1551 -static int guest_mem_read_with_gva(const CPUState *cpu, uint64_t gva,
1552 - uint8_t *data, uintptr_t size,
1553 - bool fetch_instruction)
1554 -{
1555 - int ret;
1556 - uint64_t gpa, flags;
1557 -
1558 - flags = HV_TRANSLATE_GVA_VALIDATE_READ;
1559 - ret = translate_gva(cpu, gva, &gpa, flags);
1560 - if (ret < 0) {
1561 - error_report("failed to translate gva to gpa");
1562 - return -1;
1563 - }
1564 -
1565 - ret = mshv_guest_mem_read(gpa, data, size, false, fetch_instruction);
1566 - if (ret < 0) {
1567 - error_report("failed to read from guest memory");
1568 - return -1;
1569 - }
1570 -
1571 - return 0;
1572 -}
1573 -
1574 -static int guest_mem_write_with_gva(const CPUState *cpu, uint64_t gva,
1575 - const uint8_t *data, uintptr_t size)
1576 -{
1577 - int ret;
1578 - uint64_t gpa, flags;
1579 -
1580 - flags = HV_TRANSLATE_GVA_VALIDATE_WRITE;
1581 - ret = translate_gva(cpu, gva, &gpa, flags);
1582 - if (ret < 0) {
1583 - error_report("failed to translate gva to gpa");
1584 - return -1;
1585 - }
1586 - ret = mshv_guest_mem_write(gpa, data, size, false);
1587 - if (ret < 0) {
1588 - error_report("failed to write to guest memory");
1589 - return -1;
1590 - }
1591 - return 0;
1592 -}
1593 -
1594 -static void write_mem(CPUState *cpu, void *data, target_ulong addr, int bytes)
1595 -{
1596 - if (guest_mem_write_with_gva(cpu, addr, data, bytes) < 0) {
1597 - error_report("failed to write memory");
1598 - abort();
1599 - }
1600 -}
1601 -
1602 -static void fetch_instruction(CPUState *cpu, void *data,
1603 - target_ulong addr, int bytes)
1604 -{
1605 - if (guest_mem_read_with_gva(cpu, addr, data, bytes, true) < 0) {
1606 - error_report("failed to fetch instruction");
1607 - abort();
1608 - }
1609 -}
1610 -
1611 -static void read_mem(CPUState *cpu, void *data, target_ulong addr, int bytes)
1612 -{
1613 - if (guest_mem_read_with_gva(cpu, addr, data, bytes, false) < 0) {
1614 - error_report("failed to read memory");
1615 - abort();
1616 - }
1617 -}
1618 -
1551 static void read_segment_descriptor(CPUState *cpu,
1552 struct x86_segment_descriptor *desc,
1553 enum X86Seg seg_idx)
@@ -1634,9 +1566,6 @@ static void read_segment_descriptor(CPUState *cpu,
1566 }
1567
1568 static const struct x86_emul_ops mshv_x86_emul_ops = {
1637 - .fetch_instruction = fetch_instruction,
1638 - .read_mem = read_mem,
1639 - .write_mem = write_mem,
1569 .read_segment_descriptor = read_segment_descriptor,
1570 };
1571
target/i386/whpx/whpx-all.c
-12
@@ -862,16 +862,6 @@ static int whpx_handle_portio(CPUState *cpu,
862 return 0;
863 }
864
865 -static void write_mem(CPUState *cpu, void *data, target_ulong addr, int bytes)
866 -{
867 - vmx_write_mem(cpu, addr, data, bytes);
868 -}
869 -
870 -static void read_mem(CPUState *cpu, void *data, target_ulong addr, int bytes)
871 -{
872 - vmx_read_mem(cpu, data, addr, bytes);
873 -}
874 -
865 static void read_segment_descriptor(CPUState *cpu,
866 struct x86_segment_descriptor *desc,
867 enum X86Seg seg_idx)
@@ -891,8 +881,6 @@ static void read_segment_descriptor(CPUState *cpu,
881
882
883 static const struct x86_emul_ops whpx_x86_emul_ops = {
894 - .read_mem = read_mem,
895 - .write_mem = write_mem,
884 .read_segment_descriptor = read_segment_descriptor,
885 .handle_io = handle_io
886 };