diff mbox series

[v3,05/10] hvf: arm: Mark CPU as dirty on reset

Message ID 20201202190408.2041-6-agraf@csgraf.de (mailing list archive)
State New, archived
Headers show
Series hvf: Implement Apple Silicon Support | expand

Commit Message

Alexander Graf Dec. 2, 2020, 7:04 p.m. UTC
When clearing internal state of a CPU, we should also make sure that HVF
knows about it and can push the new values down to vcpu state.

Make sure that with HVF enabled, we tell it that it should synchronize
CPU state on next entry after a reset.

This fixes PSCI handling, because now newly pushed state such as X0 and
PC on remote CPU enablement also get pushed into HVF.

Signed-off-by: Alexander Graf <agraf@csgraf.de>
---
 target/arm/arm-powerctl.c | 1 +
 target/arm/cpu.c          | 2 ++
 2 files changed, 3 insertions(+)

Comments

Roman Bolshakov Dec. 3, 2020, 1:52 a.m. UTC | #1
On Wed, Dec 02, 2020 at 08:04:03PM +0100, Alexander Graf wrote:
> When clearing internal state of a CPU, we should also make sure that HVF
> knows about it and can push the new values down to vcpu state.
> 

I'm sorry if I'm asking something dumb. But isn't
cpu_synchronize_all_post_reset() is supposed to push QEMU state into HVF
(or any other accel) after reset?

For x86 it used to work:

  static void do_hvf_cpu_synchronize_post_reset(CPUState *cpu,
                                                run_on_cpu_data arg)
  {
      hvf_put_registers(cpu);                                                                                                                                                                cpu->vcpu_dirty = false;
  }

Thanks,
Roman

> Make sure that with HVF enabled, we tell it that it should synchronize
> CPU state on next entry after a reset.
> 
> This fixes PSCI handling, because now newly pushed state such as X0 and
> PC on remote CPU enablement also get pushed into HVF.
> 
> Signed-off-by: Alexander Graf <agraf@csgraf.de>
> ---
>  target/arm/arm-powerctl.c | 1 +
>  target/arm/cpu.c          | 2 ++
>  2 files changed, 3 insertions(+)
> 
> diff --git a/target/arm/arm-powerctl.c b/target/arm/arm-powerctl.c
> index b75f813b40..a49a5b32e6 100644
> --- a/target/arm/arm-powerctl.c
> +++ b/target/arm/arm-powerctl.c
> @@ -15,6 +15,7 @@
>  #include "arm-powerctl.h"
>  #include "qemu/log.h"
>  #include "qemu/main-loop.h"
> +#include "sysemu/hw_accel.h"
>  
>  #ifndef DEBUG_ARM_POWERCTL
>  #define DEBUG_ARM_POWERCTL 0
> diff --git a/target/arm/cpu.c b/target/arm/cpu.c
> index db6f7c34ed..9a501ea4bd 100644
> --- a/target/arm/cpu.c
> +++ b/target/arm/cpu.c
> @@ -411,6 +411,8 @@ static void arm_cpu_reset(DeviceState *dev)
>  #ifndef CONFIG_USER_ONLY
>      if (kvm_enabled()) {
>          kvm_arm_reset_vcpu(cpu);
> +    } else if (hvf_enabled()) {
> +        s->vcpu_dirty = true;
>      }
>  #endif
>  
> -- 
> 2.24.3 (Apple Git-128)
>
Alexander Graf Dec. 3, 2020, 10:55 a.m. UTC | #2
On 03.12.20 02:52, Roman Bolshakov wrote:
> On Wed, Dec 02, 2020 at 08:04:03PM +0100, Alexander Graf wrote:
>> When clearing internal state of a CPU, we should also make sure that HVF
>> knows about it and can push the new values down to vcpu state.
>>
> I'm sorry if I'm asking something dumb. But isn't
> cpu_synchronize_all_post_reset() is supposed to push QEMU state into HVF
> (or any other accel) after reset?
>
> For x86 it used to work:
>
>    static void do_hvf_cpu_synchronize_post_reset(CPUState *cpu,
>                                                  run_on_cpu_data arg)
>    {
>        hvf_put_registers(cpu);                                                                                                                                                                cpu->vcpu_dirty = false;
>    }


Yes, it works because after the reset is done, there is no other 
register modification happening. With the PSCI emulation code in QEMU, 
we still do modify CPU state after reset though.

Different question though: Why do we need the post_reset() call at all 
here to push state? We would just push it on the next run anyways, 
right? So if we don't set vcpu_dirty to false then, we wouldn't need 
this patch here I think.


Alex
Roman Bolshakov Dec. 3, 2020, 1:02 p.m. UTC | #3
On Thu, Dec 03, 2020 at 11:55:17AM +0100, Alexander Graf wrote:
> 
> On 03.12.20 02:52, Roman Bolshakov wrote:
> > On Wed, Dec 02, 2020 at 08:04:03PM +0100, Alexander Graf wrote:
> > > When clearing internal state of a CPU, we should also make sure that HVF
> > > knows about it and can push the new values down to vcpu state.
> > > 
> > I'm sorry if I'm asking something dumb. But isn't
> > cpu_synchronize_all_post_reset() is supposed to push QEMU state into HVF
> > (or any other accel) after reset?
> > 
> > For x86 it used to work:
> > 
> >    static void do_hvf_cpu_synchronize_post_reset(CPUState *cpu,
> >                                                  run_on_cpu_data arg)
> >    {
> >        hvf_put_registers(cpu);
> >        cpu->vcpu_dirty = false;
> >    }
> 
> 
> Yes, it works because after the reset is done, there is no other register
> modification happening. With the PSCI emulation code in QEMU, we still do
> modify CPU state after reset though.
> 

Maybe I miss something but that doesn't seem correct. Why PSCI reset is
split from machine reset?

> Different question though: Why do we need the post_reset() call at all here
> to push state?

My understanding that post_reset is akin to a commit of the CPU state
after all reset actions have been done to QEMU CPU Arch env state. i.e.
arch/machine reset modifies env state and then the env is pushed to
accel. cpu->vcpu_dirty is cleared because env is in-sync with vcpu.

> We would just push it on the next run anyways, right?

That's correct (at least for x86 HVF).

> So if we don't set vcpu_dirty to false then, we wouldn't need this
> patch here I think.
>

That's right but the same post-reset approach is used for all accels,
including KVM. But I haven't found this for TCG.

Regards,
Roman
Alexander Graf Dec. 3, 2020, 2:13 p.m. UTC | #4
On 03.12.20 14:02, Roman Bolshakov wrote:
> On Thu, Dec 03, 2020 at 11:55:17AM +0100, Alexander Graf wrote:
>> On 03.12.20 02:52, Roman Bolshakov wrote:
>>> On Wed, Dec 02, 2020 at 08:04:03PM +0100, Alexander Graf wrote:
>>>> When clearing internal state of a CPU, we should also make sure that HVF
>>>> knows about it and can push the new values down to vcpu state.
>>>>
>>> I'm sorry if I'm asking something dumb. But isn't
>>> cpu_synchronize_all_post_reset() is supposed to push QEMU state into HVF
>>> (or any other accel) after reset?
>>>
>>> For x86 it used to work:
>>>
>>>     static void do_hvf_cpu_synchronize_post_reset(CPUState *cpu,
>>>                                                   run_on_cpu_data arg)
>>>     {
>>>         hvf_put_registers(cpu);
>>>         cpu->vcpu_dirty = false;
>>>     }
>>
>> Yes, it works because after the reset is done, there is no other register
>> modification happening. With the PSCI emulation code in QEMU, we still do
>> modify CPU state after reset though.
>>
> Maybe I miss something but that doesn't seem correct. Why PSCI reset is
> split from machine reset?

Because with PSCI, you can online/offline individual CPUs, not just the 
full system.


>
>> Different question though: Why do we need the post_reset() call at all here
>> to push state?
> My understanding that post_reset is akin to a commit of the CPU state
> after all reset actions have been done to QEMU CPU Arch env state. i.e.
> arch/machine reset modifies env state and then the env is pushed to
> accel. cpu->vcpu_dirty is cleared because env is in-sync with vcpu.


I think that's only half the truth. What it semantically means is 
"QEMU's env structure is what holds the current state." Which basically 
translates to cpu->vcpu_dirty = true.

So all of these callbacks could literally just be that, no?


Alex
diff mbox series

Patch

diff --git a/target/arm/arm-powerctl.c b/target/arm/arm-powerctl.c
index b75f813b40..a49a5b32e6 100644
--- a/target/arm/arm-powerctl.c
+++ b/target/arm/arm-powerctl.c
@@ -15,6 +15,7 @@ 
 #include "arm-powerctl.h"
 #include "qemu/log.h"
 #include "qemu/main-loop.h"
+#include "sysemu/hw_accel.h"
 
 #ifndef DEBUG_ARM_POWERCTL
 #define DEBUG_ARM_POWERCTL 0
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
index db6f7c34ed..9a501ea4bd 100644
--- a/target/arm/cpu.c
+++ b/target/arm/cpu.c
@@ -411,6 +411,8 @@  static void arm_cpu_reset(DeviceState *dev)
 #ifndef CONFIG_USER_ONLY
     if (kvm_enabled()) {
         kvm_arm_reset_vcpu(cpu);
+    } else if (hvf_enabled()) {
+        s->vcpu_dirty = true;
     }
 #endif