[PATCH v6 20/28] hvf: i386: save/restore CR0/2/3

Mohamed Mediouni posted 28 patches 1 month, 2 weeks ago
Maintainers: Pedro Barbuda <pbarbuda@microsoft.com>, Mohamed Mediouni <mohamed@unpredictable.fr>, Paolo Bonzini <pbonzini@redhat.com>, "Marc-André Lureau" <marcandre.lureau@redhat.com>, "Daniel P. Berrangé" <berrange@redhat.com>, "Philippe Mathieu-Daudé" <philmd@linaro.org>, Peter Maydell <peter.maydell@linaro.org>, Zhao Liu <zhao1.liu@intel.com>, Cameron Esfahani <dirty@apple.com>, Roman Bolshakov <rbolshakov@ddn.com>, Phil Dennis-Jordan <phil@philjordan.eu>, Wei Liu <wei.liu@kernel.org>, Magnus Kulke <magnus.kulke@linux.microsoft.com>
[PATCH v6 20/28] hvf: i386: save/restore CR0/2/3
Posted by Mohamed Mediouni 1 month, 2 weeks ago
For symmetry, save/restore the same set of registers even when not needed.

CR2 save/restore needed as page faults injected to the guest imply modifying CR2.

Signed-off-by: Mohamed Mediouni <mohamed@unpredictable.fr>
---
 target/i386/hvf/hvf.c | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/target/i386/hvf/hvf.c b/target/i386/hvf/hvf.c
index fb039ff7bd..a70f8461b0 100644
--- a/target/i386/hvf/hvf.c
+++ b/target/i386/hvf/hvf.c
@@ -477,7 +477,19 @@ static void hvf_load_crs(CPUState *cs)
 
     env->cr[0] = rvmcs(cpu->accel->fd, VMCS_GUEST_CR0);
     env->cr[3] = rvmcs(cpu->accel->fd, VMCS_GUEST_CR3);
+    env->cr[2] = rreg(cpu->accel->fd, HV_X86_CR2);
 }
+
+static void hvf_save_crs(CPUState *cs)
+{
+    X86CPU *x86_cpu = X86_CPU(cpu);
+    CPUX86State *env = &x86_cpu->env;
+
+    wvmcs(cpu->accel->fd, VMCS_GUEST_CR0, env->cr[0]);
+    wvmcs(cpu->accel->fd, VMCS_GUEST_CR3, env->cr[3]);
+    wreg(cs->accel->fd, HV_X86_CR2, env->cr[2]);
+}
+
 void hvf_load_regs(CPUState *cs)
 {
     X86CPU *cpu = X86_CPU(cs);
@@ -794,6 +806,7 @@ static int hvf_handle_vmexit(CPUState *cpu)
             decode_instruction(env, &decode);
             exec_instruction(env, &decode);
             hvf_store_regs(cpu);
+            hvf_save_crs(cpu);
             break;
         }
         break;
@@ -837,6 +850,7 @@ static int hvf_handle_vmexit(CPUState *cpu)
         assert(ins_len == decode.len);
         exec_instruction(env, &decode);
         hvf_store_regs(cpu);
+        hvf_save_crs(cpu);
 
         break;
     }
@@ -942,6 +956,7 @@ static int hvf_handle_vmexit(CPUState *cpu)
         decode_instruction(env, &decode);
         exec_instruction(env, &decode);
         hvf_store_regs(cpu);
+        hvf_save_crs(cpu);
         break;
     }
     case EXIT_REASON_TPR: {
-- 
2.50.1 (Apple Git-155)
Re: [PATCH v6 20/28] hvf: i386: save/restore CR0/2/3
Posted by Pierrick Bouvier 1 month, 1 week ago
On 2/23/26 3:39 PM, Mohamed Mediouni wrote:
> For symmetry, save/restore the same set of registers even when not needed.
> 
> CR2 save/restore needed as page faults injected to the guest imply modifying CR2.
> 
> Signed-off-by: Mohamed Mediouni <mohamed@unpredictable.fr>
> ---
>   target/i386/hvf/hvf.c | 15 +++++++++++++++
>   1 file changed, 15 insertions(+)
> 
> diff --git a/target/i386/hvf/hvf.c b/target/i386/hvf/hvf.c
> index fb039ff7bd..a70f8461b0 100644
> --- a/target/i386/hvf/hvf.c
> +++ b/target/i386/hvf/hvf.c
> @@ -477,7 +477,19 @@ static void hvf_load_crs(CPUState *cs)
>   
>       env->cr[0] = rvmcs(cpu->accel->fd, VMCS_GUEST_CR0);
>       env->cr[3] = rvmcs(cpu->accel->fd, VMCS_GUEST_CR3);
> +    env->cr[2] = rreg(cpu->accel->fd, HV_X86_CR2);
>   }
> +
> +static void hvf_save_crs(CPUState *cs)
> +{
> +    X86CPU *x86_cpu = X86_CPU(cpu);
> +    CPUX86State *env = &x86_cpu->env;
> +
> +    wvmcs(cpu->accel->fd, VMCS_GUEST_CR0, env->cr[0]);
> +    wvmcs(cpu->accel->fd, VMCS_GUEST_CR3, env->cr[3]);
> +    wreg(cs->accel->fd, HV_X86_CR2, env->cr[2]);
> +}
> +
>   void hvf_load_regs(CPUState *cs)
>   {
>       X86CPU *cpu = X86_CPU(cs);
> @@ -794,6 +806,7 @@ static int hvf_handle_vmexit(CPUState *cpu)
>               decode_instruction(env, &decode);
>               exec_instruction(env, &decode);
>               hvf_store_regs(cpu);
> +            hvf_save_crs(cpu);
>               break;
>           }
>           break;
> @@ -837,6 +850,7 @@ static int hvf_handle_vmexit(CPUState *cpu)
>           assert(ins_len == decode.len);
>           exec_instruction(env, &decode);
>           hvf_store_regs(cpu);
> +        hvf_save_crs(cpu);
>   
>           break;
>       }
> @@ -942,6 +956,7 @@ static int hvf_handle_vmexit(CPUState *cpu)
>           decode_instruction(env, &decode);
>           exec_instruction(env, &decode);
>           hvf_store_regs(cpu);
> +        hvf_save_crs(cpu);
>           break;
>       }
>       case EXIT_REASON_TPR: {

This patch doesn't compile.
See a fixing patch I'll let you upstream.
I'm a bit puzzled about how this has been tested though.

If you don't have access to a Mac intel based, you can use a 
github-runner for free [1].

[1] https://github.com/second-reality/github-runners

Regards,
Pierrick
Re: [PATCH v6 20/28] hvf: i386: save/restore CR0/2/3
Posted by Mohamed Mediouni 1 month, 1 week ago

> On 3. Mar 2026, at 20:03, Pierrick Bouvier <pierrick.bouvier@linaro.org> wrote:
> 
> On 2/23/26 3:39 PM, Mohamed Mediouni wrote:
>> For symmetry, save/restore the same set of registers even when not needed.
>> CR2 save/restore needed as page faults injected to the guest imply modifying CR2.
>> Signed-off-by: Mohamed Mediouni <mohamed@unpredictable.fr>
>> ---
>>  target/i386/hvf/hvf.c | 15 +++++++++++++++
>>  1 file changed, 15 insertions(+)
>> diff --git a/target/i386/hvf/hvf.c b/target/i386/hvf/hvf.c
>> index fb039ff7bd..a70f8461b0 100644
>> --- a/target/i386/hvf/hvf.c
>> +++ b/target/i386/hvf/hvf.c
>> @@ -477,7 +477,19 @@ static void hvf_load_crs(CPUState *cs)
>>        env->cr[0] = rvmcs(cpu->accel->fd, VMCS_GUEST_CR0);
>>      env->cr[3] = rvmcs(cpu->accel->fd, VMCS_GUEST_CR3);
>> +    env->cr[2] = rreg(cpu->accel->fd, HV_X86_CR2);
>>  }
>> +
>> +static void hvf_save_crs(CPUState *cs)
>> +{
>> +    X86CPU *x86_cpu = X86_CPU(cpu);
>> +    CPUX86State *env = &x86_cpu->env;
>> +
>> +    wvmcs(cpu->accel->fd, VMCS_GUEST_CR0, env->cr[0]);
>> +    wvmcs(cpu->accel->fd, VMCS_GUEST_CR3, env->cr[3]);
>> +    wreg(cs->accel->fd, HV_X86_CR2, env->cr[2]);
>> +}
>> +
>>  void hvf_load_regs(CPUState *cs)
>>  {
>>      X86CPU *cpu = X86_CPU(cs);
>> @@ -794,6 +806,7 @@ static int hvf_handle_vmexit(CPUState *cpu)
>>              decode_instruction(env, &decode);
>>              exec_instruction(env, &decode);
>>              hvf_store_regs(cpu);
>> +            hvf_save_crs(cpu);
>>              break;
>>          }
>>          break;
>> @@ -837,6 +850,7 @@ static int hvf_handle_vmexit(CPUState *cpu)
>>          assert(ins_len == decode.len);
>>          exec_instruction(env, &decode);
>>          hvf_store_regs(cpu);
>> +        hvf_save_crs(cpu);
>>            break;
>>      }
>> @@ -942,6 +956,7 @@ static int hvf_handle_vmexit(CPUState *cpu)
>>          decode_instruction(env, &decode);
>>          exec_instruction(env, &decode);
>>          hvf_store_regs(cpu);
>> +        hvf_save_crs(cpu);
>>          break;
>>      }
>>      case EXIT_REASON_TPR: {
> 
> This patch doesn't compile.
> See a fixing patch I'll let you upstream.
> I'm a bit puzzled about how this has been tested though.
> 
> If you don't have access to a Mac intel based, you can use a github-runner for free [1].
> 
Hello,

My bad, I had this tested locally but I I screwed up on a rebase…

Thank you,
-Mohamed
> [1] https://github.com/second-reality/github-runners
> 
> Regards,
> Pierrick<0001-target-i386-hvf-hvf.c-fix-compilation.patch>