accel/accel-system.c | 9 +++++++++ accel/whpx/whpx-common.c | 13 +++++++++++++ include/accel/accel-ops.h | 1 + include/qemu/accel.h | 3 +++ system/runstate.c | 5 +++++ target/arm/whpx/whpx-all.c | 2 -- 6 files changed, 31 insertions(+), 2 deletions(-)
WHvResetPartition resets partition state, and is not supported on Windows 10.
On Arm, it's supposed to be used for reboots. The prior location of the
WHvResetPartition call wasn't right, as other vCPUs might still have
been running, causing the call to fail.
Signed-off-by: Mohamed Mediouni <mohamed@unpredictable.fr>
---
accel/accel-system.c | 9 +++++++++
accel/whpx/whpx-common.c | 13 +++++++++++++
include/accel/accel-ops.h | 1 +
include/qemu/accel.h | 3 +++
system/runstate.c | 5 +++++
target/arm/whpx/whpx-all.c | 2 --
6 files changed, 31 insertions(+), 2 deletions(-)
diff --git a/accel/accel-system.c b/accel/accel-system.c
index 150af05bf5..5352ccd937 100644
--- a/accel/accel-system.c
+++ b/accel/accel-system.c
@@ -75,6 +75,15 @@ void accel_pre_resume(MachineState *ms, bool step_pending)
}
}
+void accel_reset(MachineState *ms)
+{
+ AccelState *accel = ms->accelerator;
+ AccelClass *acc = ACCEL_GET_CLASS(accel);
+ if (acc->reset_vm) {
+ acc->reset_vm(accel);
+ }
+}
+
/* initialize the arch-independent accel operation interfaces */
void accel_init_ops_interfaces(AccelClass *ac)
{
diff --git a/accel/whpx/whpx-common.c b/accel/whpx/whpx-common.c
index 6fe44d5910..1f7b7d764d 100644
--- a/accel/whpx/whpx-common.c
+++ b/accel/whpx/whpx-common.c
@@ -205,6 +205,18 @@ static void do_whpx_cpu_synchronize_pre_loadvm(CPUState *cpu,
cpu->vcpu_dirty = true;
}
+/*
+ * Partition support
+ */
+
+static void whpx_partition_reset(AccelState* as)
+{
+ struct whpx_state *whpx = &whpx_global;
+ if (whp_dispatch.WHvResetPartition) {
+ whp_dispatch.WHvResetPartition(whpx->partition);
+ }
+}
+
/*
* CPU support.
*/
@@ -622,6 +634,7 @@ static void whpx_accel_class_init(ObjectClass *oc, const void *data)
ac->name = "WHPX";
ac->init_machine = whpx_accel_init;
ac->pre_resume_vm = whpx_pre_resume_vm;
+ ac->reset_vm = whpx_partition_reset;
ac->allowed = &whpx_allowed;
object_class_property_add(oc, "kernel-irqchip", "on|off|split",
diff --git a/include/accel/accel-ops.h b/include/accel/accel-ops.h
index f46492e3fe..a1c9f3ae7b 100644
--- a/include/accel/accel-ops.h
+++ b/include/accel/accel-ops.h
@@ -33,6 +33,7 @@ struct AccelClass {
/* system related hooks */
void (*setup_post)(AccelState *as);
void (*pre_resume_vm)(AccelState *as, bool step_pending);
+ void (*reset_vm)(AccelState *as);
bool (*has_memory)(AccelState *accel, AddressSpace *as,
hwaddr start_addr, hwaddr size);
diff --git a/include/qemu/accel.h b/include/qemu/accel.h
index d3638c7bfd..0e12aea7db 100644
--- a/include/qemu/accel.h
+++ b/include/qemu/accel.h
@@ -54,6 +54,9 @@ void accel_setup_post(MachineState *ms);
void accel_pre_resume(MachineState *ms, bool step_pending);
+/* Reset accelerator state. */
+void accel_reset(MachineState *ms);
+
/**
* accel_cpu_instance_init:
* @cpu: The CPU that needs to do accel-specific object initializations.
diff --git a/system/runstate.c b/system/runstate.c
index 2d4e95a216..734e3c037c 100644
--- a/system/runstate.c
+++ b/system/runstate.c
@@ -564,6 +564,11 @@ void qemu_system_reset(ShutdownCause reason)
qapi_event_send_reset(shutdown_caused_by_guest(reason), reason);
}
+ if (current_machine) {
+ /* Tell the accelerator that the VM is being reset. */
+ accel_reset(current_machine);
+ }
+
/*
* Some boards use the machine reset callback to point CPUs to the firmware
* entry point. Assume that this is not the case for boards that support
diff --git a/target/arm/whpx/whpx-all.c b/target/arm/whpx/whpx-all.c
index 4019a513aa..f345fea4fe 100644
--- a/target/arm/whpx/whpx-all.c
+++ b/target/arm/whpx/whpx-all.c
@@ -472,8 +472,6 @@ int whpx_vcpu_run(CPUState *cpu)
if (arm_cpu->power_state != PSCI_OFF) {
whpx_psci_cpu_off(arm_cpu);
}
- /* Partition-wide reset, to reset state for reboots to succeed. */
- whp_dispatch.WHvResetPartition(whpx->partition);
bql_unlock();
break;
case WHvRunVpExitReasonNone:
--
2.50.1 (Apple Git-155)
+Ani
On 21/4/26 22:57, Mohamed Mediouni wrote:
> WHvResetPartition resets partition state, and is not supported on Windows 10.
>
> On Arm, it's supposed to be used for reboots. The prior location of the
> WHvResetPartition call wasn't right, as other vCPUs might still have
> been running, causing the call to fail.
Is it very different from the conceptual step introduced in commit
4003e5e65fe ("hw/accel: add a per-accelerator callback to change
VM accelerator handle")?
>
> Signed-off-by: Mohamed Mediouni <mohamed@unpredictable.fr>
> ---
> accel/accel-system.c | 9 +++++++++
> accel/whpx/whpx-common.c | 13 +++++++++++++
> include/accel/accel-ops.h | 1 +
> include/qemu/accel.h | 3 +++
> system/runstate.c | 5 +++++
> target/arm/whpx/whpx-all.c | 2 --
> 6 files changed, 31 insertions(+), 2 deletions(-)
>
> diff --git a/accel/accel-system.c b/accel/accel-system.c
> index 150af05bf5..5352ccd937 100644
> --- a/accel/accel-system.c
> +++ b/accel/accel-system.c
> @@ -75,6 +75,15 @@ void accel_pre_resume(MachineState *ms, bool step_pending)
> }
> }
>
> +void accel_reset(MachineState *ms)
> +{
> + AccelState *accel = ms->accelerator;
> + AccelClass *acc = ACCEL_GET_CLASS(accel);
> + if (acc->reset_vm) {
> + acc->reset_vm(accel);
> + }
> +}
> +
> /* initialize the arch-independent accel operation interfaces */
> void accel_init_ops_interfaces(AccelClass *ac)
> {
> diff --git a/accel/whpx/whpx-common.c b/accel/whpx/whpx-common.c
> index 6fe44d5910..1f7b7d764d 100644
> --- a/accel/whpx/whpx-common.c
> +++ b/accel/whpx/whpx-common.c
> @@ -205,6 +205,18 @@ static void do_whpx_cpu_synchronize_pre_loadvm(CPUState *cpu,
> cpu->vcpu_dirty = true;
> }
>
> +/*
> + * Partition support
> + */
> +
> +static void whpx_partition_reset(AccelState* as)
> +{
> + struct whpx_state *whpx = &whpx_global;
> + if (whp_dispatch.WHvResetPartition) {
> + whp_dispatch.WHvResetPartition(whpx->partition);
> + }
> +}
> +
> /*
> * CPU support.
> */
> @@ -622,6 +634,7 @@ static void whpx_accel_class_init(ObjectClass *oc, const void *data)
> ac->name = "WHPX";
> ac->init_machine = whpx_accel_init;
> ac->pre_resume_vm = whpx_pre_resume_vm;
> + ac->reset_vm = whpx_partition_reset;
> ac->allowed = &whpx_allowed;
>
> object_class_property_add(oc, "kernel-irqchip", "on|off|split",
> diff --git a/include/accel/accel-ops.h b/include/accel/accel-ops.h
> index f46492e3fe..a1c9f3ae7b 100644
> --- a/include/accel/accel-ops.h
> +++ b/include/accel/accel-ops.h
> @@ -33,6 +33,7 @@ struct AccelClass {
> /* system related hooks */
> void (*setup_post)(AccelState *as);
> void (*pre_resume_vm)(AccelState *as, bool step_pending);
> + void (*reset_vm)(AccelState *as);
> bool (*has_memory)(AccelState *accel, AddressSpace *as,
> hwaddr start_addr, hwaddr size);
>
> diff --git a/include/qemu/accel.h b/include/qemu/accel.h
> index d3638c7bfd..0e12aea7db 100644
> --- a/include/qemu/accel.h
> +++ b/include/qemu/accel.h
> @@ -54,6 +54,9 @@ void accel_setup_post(MachineState *ms);
>
> void accel_pre_resume(MachineState *ms, bool step_pending);
>
> +/* Reset accelerator state. */
> +void accel_reset(MachineState *ms);
> +
> /**
> * accel_cpu_instance_init:
> * @cpu: The CPU that needs to do accel-specific object initializations.
> diff --git a/system/runstate.c b/system/runstate.c
> index 2d4e95a216..734e3c037c 100644
> --- a/system/runstate.c
> +++ b/system/runstate.c
> @@ -564,6 +564,11 @@ void qemu_system_reset(ShutdownCause reason)
> qapi_event_send_reset(shutdown_caused_by_guest(reason), reason);
> }
>
> + if (current_machine) {
> + /* Tell the accelerator that the VM is being reset. */
> + accel_reset(current_machine);
> + }
> +
> /*
> * Some boards use the machine reset callback to point CPUs to the firmware
> * entry point. Assume that this is not the case for boards that support
> diff --git a/target/arm/whpx/whpx-all.c b/target/arm/whpx/whpx-all.c
> index 4019a513aa..f345fea4fe 100644
> --- a/target/arm/whpx/whpx-all.c
> +++ b/target/arm/whpx/whpx-all.c
> @@ -472,8 +472,6 @@ int whpx_vcpu_run(CPUState *cpu)
> if (arm_cpu->power_state != PSCI_OFF) {
> whpx_psci_cpu_off(arm_cpu);
> }
> - /* Partition-wide reset, to reset state for reboots to succeed. */
> - whp_dispatch.WHvResetPartition(whpx->partition);
> bql_unlock();
> break;
> case WHvRunVpExitReasonNone:
> On 22. Apr 2026, at 14:46, Philippe Mathieu-Daudé <philmd@linaro.org> wrote:
>
> +Ani
>
> On 21/4/26 22:57, Mohamed Mediouni wrote:
>> WHvResetPartition resets partition state, and is not supported on Windows 10.
>> On Arm, it's supposed to be used for reboots. The prior location of the
>> WHvResetPartition call wasn't right, as other vCPUs might still have
>> been running, causing the call to fail.
>
> Is it very different from the conceptual step introduced in commit
> 4003e5e65fe ("hw/accel: add a per-accelerator callback to change
> VM accelerator handle")?
Hello,
The difference is that we reset the partition state but don’t have to
re-do any of the memory mappings in the Hyper-V case (or otherwise tear
down the context).
We could fallback outright into the CoCo case which would work too.
>
>> Signed-off-by: Mohamed Mediouni <mohamed@unpredictable.fr>
>> ---
>> accel/accel-system.c | 9 +++++++++
>> accel/whpx/whpx-common.c | 13 +++++++++++++
>> include/accel/accel-ops.h | 1 +
>> include/qemu/accel.h | 3 +++
>> system/runstate.c | 5 +++++
>> target/arm/whpx/whpx-all.c | 2 --
>> 6 files changed, 31 insertions(+), 2 deletions(-)
>> diff --git a/accel/accel-system.c b/accel/accel-system.c
>> index 150af05bf5..5352ccd937 100644
>> --- a/accel/accel-system.c
>> +++ b/accel/accel-system.c
>> @@ -75,6 +75,15 @@ void accel_pre_resume(MachineState *ms, bool step_pending)
>> }
>> }
>> +void accel_reset(MachineState *ms)
>> +{
>> + AccelState *accel = ms->accelerator;
>> + AccelClass *acc = ACCEL_GET_CLASS(accel);
>> + if (acc->reset_vm) {
>> + acc->reset_vm(accel);
>> + }
>> +}
>> +
>> /* initialize the arch-independent accel operation interfaces */
>> void accel_init_ops_interfaces(AccelClass *ac)
>> {
>> diff --git a/accel/whpx/whpx-common.c b/accel/whpx/whpx-common.c
>> index 6fe44d5910..1f7b7d764d 100644
>> --- a/accel/whpx/whpx-common.c
>> +++ b/accel/whpx/whpx-common.c
>> @@ -205,6 +205,18 @@ static void do_whpx_cpu_synchronize_pre_loadvm(CPUState *cpu,
>> cpu->vcpu_dirty = true;
>> }
>> +/*
>> + * Partition support
>> + */
>> +
>> +static void whpx_partition_reset(AccelState* as)
>> +{
>> + struct whpx_state *whpx = &whpx_global;
>> + if (whp_dispatch.WHvResetPartition) {
>> + whp_dispatch.WHvResetPartition(whpx->partition);
>> + }
>> +}
>> +
>> /*
>> * CPU support.
>> */
>> @@ -622,6 +634,7 @@ static void whpx_accel_class_init(ObjectClass *oc, const void *data)
>> ac->name = "WHPX";
>> ac->init_machine = whpx_accel_init;
>> ac->pre_resume_vm = whpx_pre_resume_vm;
>> + ac->reset_vm = whpx_partition_reset;
>> ac->allowed = &whpx_allowed;
>> object_class_property_add(oc, "kernel-irqchip", "on|off|split",
>> diff --git a/include/accel/accel-ops.h b/include/accel/accel-ops.h
>> index f46492e3fe..a1c9f3ae7b 100644
>> --- a/include/accel/accel-ops.h
>> +++ b/include/accel/accel-ops.h
>> @@ -33,6 +33,7 @@ struct AccelClass {
>> /* system related hooks */
>> void (*setup_post)(AccelState *as);
>> void (*pre_resume_vm)(AccelState *as, bool step_pending);
>> + void (*reset_vm)(AccelState *as);
>> bool (*has_memory)(AccelState *accel, AddressSpace *as,
>> hwaddr start_addr, hwaddr size);
>> diff --git a/include/qemu/accel.h b/include/qemu/accel.h
>> index d3638c7bfd..0e12aea7db 100644
>> --- a/include/qemu/accel.h
>> +++ b/include/qemu/accel.h
>> @@ -54,6 +54,9 @@ void accel_setup_post(MachineState *ms);
>> void accel_pre_resume(MachineState *ms, bool step_pending);
>> +/* Reset accelerator state. */
>> +void accel_reset(MachineState *ms);
>> +
>> /**
>> * accel_cpu_instance_init:
>> * @cpu: The CPU that needs to do accel-specific object initializations.
>> diff --git a/system/runstate.c b/system/runstate.c
>> index 2d4e95a216..734e3c037c 100644
>> --- a/system/runstate.c
>> +++ b/system/runstate.c
>> @@ -564,6 +564,11 @@ void qemu_system_reset(ShutdownCause reason)
>> qapi_event_send_reset(shutdown_caused_by_guest(reason), reason);
>> }
>> + if (current_machine) {
>> + /* Tell the accelerator that the VM is being reset. */
>> + accel_reset(current_machine);
>> + }
>> +
>> /*
>> * Some boards use the machine reset callback to point CPUs to the firmware
>> * entry point. Assume that this is not the case for boards that support
>> diff --git a/target/arm/whpx/whpx-all.c b/target/arm/whpx/whpx-all.c
>> index 4019a513aa..f345fea4fe 100644
>> --- a/target/arm/whpx/whpx-all.c
>> +++ b/target/arm/whpx/whpx-all.c
>> @@ -472,8 +472,6 @@ int whpx_vcpu_run(CPUState *cpu)
>> if (arm_cpu->power_state != PSCI_OFF) {
>> whpx_psci_cpu_off(arm_cpu);
>> }
>> - /* Partition-wide reset, to reset state for reboots to succeed. */
>> - whp_dispatch.WHvResetPartition(whpx->partition);
>> bql_unlock();
>> break;
>> case WHvRunVpExitReasonNone:
>
>
> On 22 Apr 2026, at 6:38 PM, Mohamed Mediouni <mohamed@unpredictable.fr> wrote:
>
>
>
>> On 22. Apr 2026, at 14:46, Philippe Mathieu-Daudé <philmd@linaro.org> wrote:
>>
>> +Ani
>>
>> On 21/4/26 22:57, Mohamed Mediouni wrote:
>>> WHvResetPartition resets partition state, and is not supported on Windows 10.
>>> On Arm, it's supposed to be used for reboots. The prior location of the
>>> WHvResetPartition call wasn't right, as other vCPUs might still have
>>> been running, causing the call to fail.
>>
>> Is it very different from the conceptual step introduced in commit
>> 4003e5e65fe ("hw/accel: add a per-accelerator callback to change
>> VM accelerator handle")?
>
> Hello,
>
> The difference is that we reset the partition state but don’t have to
> re-do any of the memory mappings in the Hyper-V case (or otherwise tear
> down the context).
>
> We could fallback outright into the CoCo case which would work too.
The rebuild_vm() callback is used only when the vcpus are not resettable (so Coco case). If vcpus are resettable (non-CoCo), then that callback won’t be called. Within the callback, you can do whatever you need to do.
> On 22. Apr 2026, at 15:08, Mohamed Mediouni <mohamed@unpredictable.fr> wrote:
>
>
>
>> On 22. Apr 2026, at 14:46, Philippe Mathieu-Daudé <philmd@linaro.org> wrote:
>>
>> +Ani
>>
>> On 21/4/26 22:57, Mohamed Mediouni wrote:
>>> WHvResetPartition resets partition state, and is not supported on Windows 10.
>>> On Arm, it's supposed to be used for reboots. The prior location of the
>>> WHvResetPartition call wasn't right, as other vCPUs might still have
>>> been running, causing the call to fail.
>>
>> Is it very different from the conceptual step introduced in commit
>> 4003e5e65fe ("hw/accel: add a per-accelerator callback to change
>> VM accelerator handle")?
>
> Hello,
>
> The difference is that we reset the partition state but don’t have to
> re-do any of the memory mappings in the Hyper-V case (or otherwise tear
> down the context).
>
> We could fallback outright into the CoCo case which would work too.
More context:
Another potential option for the arm64 functionality issues on reboots
is to poke the proper activity registers for PSCI state and skip
WHvResetPartition() outright (we might need to do save/restore those
registers later on for proper anyhow for migration).
But Microsoft told me that I’m expected to call WHvResetPartition().
> On 21. Apr 2026, at 22:57, Mohamed Mediouni <mohamed@unpredictable.fr> wrote:
>
> WHvResetPartition resets partition state, and is not supported on Windows 10.
>
> On Arm, it's supposed to be used for reboots. The prior location of the
> WHvResetPartition call wasn't right, as other vCPUs might still have
> been running, causing the call to fail.
>
> Signed-off-by: Mohamed Mediouni <mohamed@unpredictable.fr>
cc qemu-stable@
I believe this one is a good candidate for qemu-stable too
> ---
> accel/accel-system.c | 9 +++++++++
> accel/whpx/whpx-common.c | 13 +++++++++++++
> include/accel/accel-ops.h | 1 +
> include/qemu/accel.h | 3 +++
> system/runstate.c | 5 +++++
> target/arm/whpx/whpx-all.c | 2 --
> 6 files changed, 31 insertions(+), 2 deletions(-)
>
> diff --git a/accel/accel-system.c b/accel/accel-system.c
> index 150af05bf5..5352ccd937 100644
> --- a/accel/accel-system.c
> +++ b/accel/accel-system.c
> @@ -75,6 +75,15 @@ void accel_pre_resume(MachineState *ms, bool step_pending)
> }
> }
>
> +void accel_reset(MachineState *ms)
> +{
> + AccelState *accel = ms->accelerator;
> + AccelClass *acc = ACCEL_GET_CLASS(accel);
> + if (acc->reset_vm) {
> + acc->reset_vm(accel);
> + }
> +}
> +
> /* initialize the arch-independent accel operation interfaces */
> void accel_init_ops_interfaces(AccelClass *ac)
> {
> diff --git a/accel/whpx/whpx-common.c b/accel/whpx/whpx-common.c
> index 6fe44d5910..1f7b7d764d 100644
> --- a/accel/whpx/whpx-common.c
> +++ b/accel/whpx/whpx-common.c
> @@ -205,6 +205,18 @@ static void do_whpx_cpu_synchronize_pre_loadvm(CPUState *cpu,
> cpu->vcpu_dirty = true;
> }
>
> +/*
> + * Partition support
> + */
> +
> +static void whpx_partition_reset(AccelState* as)
> +{
> + struct whpx_state *whpx = &whpx_global;
> + if (whp_dispatch.WHvResetPartition) {
> + whp_dispatch.WHvResetPartition(whpx->partition);
> + }
> +}
> +
> /*
> * CPU support.
> */
> @@ -622,6 +634,7 @@ static void whpx_accel_class_init(ObjectClass *oc, const void *data)
> ac->name = "WHPX";
> ac->init_machine = whpx_accel_init;
> ac->pre_resume_vm = whpx_pre_resume_vm;
> + ac->reset_vm = whpx_partition_reset;
> ac->allowed = &whpx_allowed;
>
> object_class_property_add(oc, "kernel-irqchip", "on|off|split",
> diff --git a/include/accel/accel-ops.h b/include/accel/accel-ops.h
> index f46492e3fe..a1c9f3ae7b 100644
> --- a/include/accel/accel-ops.h
> +++ b/include/accel/accel-ops.h
> @@ -33,6 +33,7 @@ struct AccelClass {
> /* system related hooks */
> void (*setup_post)(AccelState *as);
> void (*pre_resume_vm)(AccelState *as, bool step_pending);
> + void (*reset_vm)(AccelState *as);
> bool (*has_memory)(AccelState *accel, AddressSpace *as,
> hwaddr start_addr, hwaddr size);
>
> diff --git a/include/qemu/accel.h b/include/qemu/accel.h
> index d3638c7bfd..0e12aea7db 100644
> --- a/include/qemu/accel.h
> +++ b/include/qemu/accel.h
> @@ -54,6 +54,9 @@ void accel_setup_post(MachineState *ms);
>
> void accel_pre_resume(MachineState *ms, bool step_pending);
>
> +/* Reset accelerator state. */
> +void accel_reset(MachineState *ms);
> +
> /**
> * accel_cpu_instance_init:
> * @cpu: The CPU that needs to do accel-specific object initializations.
> diff --git a/system/runstate.c b/system/runstate.c
> index 2d4e95a216..734e3c037c 100644
> --- a/system/runstate.c
> +++ b/system/runstate.c
> @@ -564,6 +564,11 @@ void qemu_system_reset(ShutdownCause reason)
> qapi_event_send_reset(shutdown_caused_by_guest(reason), reason);
> }
>
> + if (current_machine) {
> + /* Tell the accelerator that the VM is being reset. */
> + accel_reset(current_machine);
> + }
> +
> /*
> * Some boards use the machine reset callback to point CPUs to the firmware
> * entry point. Assume that this is not the case for boards that support
> diff --git a/target/arm/whpx/whpx-all.c b/target/arm/whpx/whpx-all.c
> index 4019a513aa..f345fea4fe 100644
> --- a/target/arm/whpx/whpx-all.c
> +++ b/target/arm/whpx/whpx-all.c
> @@ -472,8 +472,6 @@ int whpx_vcpu_run(CPUState *cpu)
> if (arm_cpu->power_state != PSCI_OFF) {
> whpx_psci_cpu_off(arm_cpu);
> }
> - /* Partition-wide reset, to reset state for reboots to succeed. */
> - whp_dispatch.WHvResetPartition(whpx->partition);
> bql_unlock();
> break;
> case WHvRunVpExitReasonNone:
> --
> 2.50.1 (Apple Git-155)
>
© 2016 - 2026 Red Hat, Inc.