target/i386: emulate: indirect access to CRs
Prepare to have on-demand fetch of registers from the backend during faults. For x86_64 macOS, copy the function there too. Signed-off-by: Mohamed Mediouni <mohamed@unpredictable.fr> Link: https://lore.kernel.org/r/20260324151323.74473-9-mohamed@unpredictable.fr Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Mohamed Mediouni committed
Mar 24, 2026 at 16:13 UTC
9548e5b2fe5054dfc5c9cff939ce807e7ea8a418
4 files changed
+32
-17
target/i386/emulate/x86_emu.h
+3
@@ -28,6 +28,7 @@ struct x86_emul_ops {
28
MMUTranslateResult (*mmu_gva_to_gpa) (CPUState *cpu, target_ulong gva, uint64_t *gpa, MMUTranslateFlags flags);
29
void (*read_segment_descriptor)(CPUState *cpu, struct x86_segment_descriptor *desc,
30
enum X86Seg seg);
31
+ target_ulong (*read_cr) (CPUState *cpu, int cr);
32
void (*handle_io)(CPUState *cpu, uint16_t port, void *data, int direction,
33
int size, int count);
34
void (*simulate_rdmsr)(CPUState *cs);
@@ -45,6 +46,8 @@ void x86_emul_raise_exception(CPUX86State *env, int exception_index, int error_c
46
47
target_ulong read_reg(CPUX86State *env, int reg, int size);
48
void write_reg(CPUX86State *env, int reg, target_ulong val, int size);
49
+target_ulong x86_read_cr(CPUState *cpu, int cr);
50
+
51
target_ulong read_val_from_reg(void *reg_ptr, int size);
52
void write_val_to_reg(void *reg_ptr, target_ulong val, int size);
53
bool write_val_ext(CPUX86State *env, struct x86_decode_op *decode, target_ulong val, int size);
target/i386/emulate/x86_helpers.c
+16
-11
@@ -206,15 +206,26 @@ bool x86_read_call_gate(CPUState *cpu, struct x86_call_gate *idt_desc,
206
return true;
207
}
208
209
-bool x86_is_protected(CPUState *cpu)
209
+target_ulong x86_read_cr(CPUState *cpu, int cr)
210
{
211
X86CPU *x86_cpu = X86_CPU(cpu);
212
CPUX86State *env = &x86_cpu->env;
213
- uint64_t cr0 = env->cr[0];
213
+
214
+ if (emul_ops->read_cr) {
215
+ return emul_ops->read_cr(cpu, cr);
216
+ }
217
+ return env->cr[cr];
218
+}
219
+
220
+bool x86_is_protected(CPUState *cpu)
221
+{
222
+ uint64_t cr0;
223
+
224
if (emul_ops->is_protected_mode) {
225
return emul_ops->is_protected_mode(cpu);
226
}
227
228
+ cr0 = x86_read_cr(cpu, 0);
229
return cr0 & CR0_PE_MASK;
230
}
231
@@ -245,9 +256,7 @@ bool x86_is_long_mode(CPUState *cpu)
256
257
bool x86_is_la57(CPUState *cpu)
258
{
248
- X86CPU *x86_cpu = X86_CPU(cpu);
249
- CPUX86State *env = &x86_cpu->env;
250
- uint64_t is_la57 = env->cr[4] & CR4_LA57_MASK;
259
+ uint64_t is_la57 = x86_read_cr(cpu, 4) & CR4_LA57_MASK;
260
return is_la57;
261
}
262
@@ -259,18 +268,14 @@ bool x86_is_long64_mode(CPUState *cpu)
268
269
bool x86_is_paging_mode(CPUState *cpu)
270
{
262
- X86CPU *x86_cpu = X86_CPU(cpu);
263
- CPUX86State *env = &x86_cpu->env;
264
- uint64_t cr0 = env->cr[0];
271
+ uint64_t cr0 = x86_read_cr(cpu, 0);
272
273
return cr0 & CR0_PG_MASK;
274
}
275
276
bool x86_is_pae_enabled(CPUState *cpu)
277
{
271
- X86CPU *x86_cpu = X86_CPU(cpu);
272
- CPUX86State *env = &x86_cpu->env;
273
- uint64_t cr4 = env->cr[4];
278
+ uint64_t cr4 = x86_read_cr(cpu, 4);
279
280
return cr4 & CR4_PAE_MASK;
281
}
target/i386/emulate/x86_mmu.c
+2
-6
@@ -114,8 +114,6 @@ static bool get_pt_entry(CPUState *cpu, struct gpt_translation *pt,
114
static MMUTranslateResult test_pt_entry(CPUState *cpu, struct gpt_translation *pt,
115
int level, int *largeness, bool pae, MMUTranslateFlags flags)
116
{
117
- X86CPU *x86_cpu = X86_CPU(cpu);
118
- CPUX86State *env = &x86_cpu->env;
117
uint64_t pte = pt->pte[level];
118
119
if (!pte_present(pte)) {
@@ -130,7 +128,7 @@ static MMUTranslateResult test_pt_entry(CPUState *cpu, struct gpt_translation *p
128
*largeness = level;
129
}
130
133
- uint32_t cr0 = env->cr[0];
131
+ uint32_t cr0 = x86_read_cr(cpu, 0);
132
/* check protection */
133
if (cr0 & CR0_WP_MASK) {
134
if (mmu_validate_write(flags) && !pte_write_access(pte)) {
@@ -184,11 +182,9 @@ static inline uint64_t large_page_gpa(struct gpt_translation *pt, bool pae,
182
static MMUTranslateResult walk_gpt(CPUState *cpu, target_ulong addr, MMUTranslateFlags flags,
183
struct gpt_translation *pt, bool pae)
184
{
187
- X86CPU *x86_cpu = X86_CPU(cpu);
188
- CPUX86State *env = &x86_cpu->env;
185
int top_level, level;
186
int largeness = 0;
191
- target_ulong cr3 = env->cr[3];
187
+ target_ulong cr3 = x86_read_cr(cpu, 3);
188
uint64_t page_mask = pae ? PAE_PTE_PAGE_MASK : LEGACY_PTE_PAGE_MASK;
189
MMUTranslateResult res;
190
target/i386/hvf/x86.c
+11
@@ -143,6 +143,17 @@ bool x86_is_la57(CPUState *cpu)
143
return false;
144
}
145
146
+target_ulong x86_read_cr(CPUState *cpu, int cr)
147
+{
148
+ X86CPU *x86_cpu = X86_CPU(cpu);
149
+ CPUX86State *env = &x86_cpu->env;
150
+
151
+ if (emul_ops->read_cr) {
152
+ return emul_ops->read_cr(cpu, cr);
153
+ }
154
+ return env->cr[cr];
155
+}
156
+
157
bool x86_is_long64_mode(CPUState *cpu)
158
{
159
struct vmx_segment desc;