winhvemulation is x86_64 only.
Exception exit bitmaps are also x86_64 only
Others are just variable definitions not used on arm64.
Signed-off-by: Mohamed Mediouni <mohamed@unpredictable.fr>
---
accel/whpx/whpx-common.c | 20 ++++++++++++++++++--
include/system/whpx-all.h | 2 ++
include/system/whpx-common.h | 2 ++
include/system/whpx-internal.h | 7 ++++++-
4 files changed, 28 insertions(+), 3 deletions(-)
diff --git a/accel/whpx/whpx-common.c b/accel/whpx/whpx-common.c
index b5e5fda696..eeefaea329 100644
--- a/accel/whpx/whpx-common.c
+++ b/accel/whpx/whpx-common.c
@@ -41,7 +41,9 @@
bool whpx_allowed;
static bool whp_dispatch_initialized;
static HMODULE hWinHvPlatform;
+#ifdef __x86_64__
static HMODULE hWinHvEmulation;
+#endif
struct whpx_state whpx_global;
struct WHPDispatch whp_dispatch;
@@ -106,11 +108,16 @@ int whpx_first_vcpu_starting(CPUState *cpu)
* whpx_translate_cpu_breakpoints(). WHPX breakpoints must
* now be recomputed.
*/
+#ifdef __x86_64__
whpx_translate_cpu_breakpoints(&whpx->breakpoints, cpu, i);
+#endif
}
+#ifdef __x86_64__
/* Actually insert the breakpoints into the memory. */
whpx_apply_breakpoints(whpx->breakpoints.breakpoints, cpu, true);
+#endif
}
+#ifdef __x86_64__
HRESULT hr;
uint64_t exception_mask;
if (whpx->step_pending ||
@@ -132,6 +139,7 @@ int whpx_first_vcpu_starting(CPUState *cpu)
"hr=%08lx.", hr);
return 1;
}
+#endif
return 0;
}
@@ -238,8 +246,10 @@ void whpx_destroy_vcpu(CPUState *cpu)
struct whpx_state *whpx = &whpx_global;
whp_dispatch.WHvDeleteVirtualProcessor(whpx->partition, cpu->cpu_index);
+#ifdef __x86_64__
AccelCPUState *vcpu = cpu->accel;
whp_dispatch.WHvEmulatorDestroyEmulator(vcpu->emulator);
+#endif
g_free(cpu->accel);
}
@@ -414,8 +424,12 @@ static bool load_whp_dispatch_fns(HMODULE *handle,
LIST_WINHVPLATFORM_FUNCTIONS(WHP_LOAD_FIELD)
break;
case WINHV_EMULATION_FNS_DEFAULT:
+#ifdef __x86_64__
WHP_LOAD_LIB(WINHV_EMULATION_DLL, hLib)
LIST_WINHVEMULATION_FUNCTIONS(WHP_LOAD_FIELD)
+#else
+ abort();
+#endif
break;
case WINHV_PLATFORM_FNS_SUPPLEMENTAL:
WHP_LOAD_LIB(WINHV_PLATFORM_DLL, hLib)
@@ -541,11 +555,11 @@ bool init_whp_dispatch(void)
if (!load_whp_dispatch_fns(&hWinHvPlatform, WINHV_PLATFORM_FNS_DEFAULT)) {
goto error;
}
-
+#ifdef __x86_64__
if (!load_whp_dispatch_fns(&hWinHvEmulation, WINHV_EMULATION_FNS_DEFAULT)) {
goto error;
}
-
+#endif
assert(load_whp_dispatch_fns(&hWinHvPlatform,
WINHV_PLATFORM_FNS_SUPPLEMENTAL));
whp_dispatch_initialized = true;
@@ -555,9 +569,11 @@ error:
if (hWinHvPlatform) {
FreeLibrary(hWinHvPlatform);
}
+#ifdef __x86_64__
if (hWinHvEmulation) {
FreeLibrary(hWinHvEmulation);
}
+#endif
return false;
}
diff --git a/include/system/whpx-all.h b/include/system/whpx-all.h
index a82b083284..838a25fa75 100644
--- a/include/system/whpx-all.h
+++ b/include/system/whpx-all.h
@@ -8,5 +8,7 @@ void whpx_get_registers(CPUState *cpu);
void whpx_set_registers(CPUState *cpu, int level);
int whpx_accel_init(AccelState *as, MachineState *ms);
void whpx_cpu_instance_init(CPUState *cs);
+#ifdef __x86_64__
HRESULT whpx_set_exception_exit_bitmap(UINT64 exceptions);
#endif
+#endif
diff --git a/include/system/whpx-common.h b/include/system/whpx-common.h
index e549c7539c..629810b384 100644
--- a/include/system/whpx-common.h
+++ b/include/system/whpx-common.h
@@ -3,6 +3,7 @@
#define SYSTEM_WHPX_COMMON_H
struct AccelCPUState {
+#ifdef __x86_64__
WHV_EMULATOR_HANDLE emulator;
bool window_registered;
bool interruptable;
@@ -10,6 +11,7 @@ struct AccelCPUState {
uint64_t tpr;
uint64_t apic_base;
bool interruption_pending;
+#endif
/* Must be the last field as it may have a tail */
WHV_RUN_VP_EXIT_CONTEXT exit_ctx;
};
diff --git a/include/system/whpx-internal.h b/include/system/whpx-internal.h
index e61375d554..e57d2c8526 100644
--- a/include/system/whpx-internal.h
+++ b/include/system/whpx-internal.h
@@ -4,8 +4,9 @@
#include <windows.h>
#include <winhvplatform.h>
+#ifdef __x86_64__
#include <winhvemulation.h>
-
+#endif
typedef enum WhpxBreakpointState {
WHPX_BP_CLEARED = 0,
WHPX_BP_SET_PENDING,
@@ -98,12 +99,16 @@ void whpx_apic_get(DeviceState *s);
/* Define function typedef */
LIST_WINHVPLATFORM_FUNCTIONS(WHP_DEFINE_TYPE)
+#ifdef __x86_64__
LIST_WINHVEMULATION_FUNCTIONS(WHP_DEFINE_TYPE)
+#endif
LIST_WINHVPLATFORM_FUNCTIONS_SUPPLEMENTAL(WHP_DEFINE_TYPE)
struct WHPDispatch {
LIST_WINHVPLATFORM_FUNCTIONS(WHP_DECLARE_MEMBER)
+#ifdef __x86_64__
LIST_WINHVEMULATION_FUNCTIONS(WHP_DECLARE_MEMBER)
+#endif
LIST_WINHVPLATFORM_FUNCTIONS_SUPPLEMENTAL(WHP_DECLARE_MEMBER)
};
--
2.39.5 (Apple Git-154)
On 8/2/25 18:17, Mohamed Mediouni wrote: > @@ -414,8 +424,12 @@ static bool load_whp_dispatch_fns(HMODULE *handle, > LIST_WINHVPLATFORM_FUNCTIONS(WHP_LOAD_FIELD) > break; > case WINHV_EMULATION_FNS_DEFAULT: > +#ifdef __x86_64__ > WHP_LOAD_LIB(WINHV_EMULATION_DLL, hLib) > LIST_WINHVEMULATION_FUNCTIONS(WHP_LOAD_FIELD) > +#else > + abort(); > +#endif > break; BTW, are there import libraries for these? If not, could we use dlltool or something to create one at build time? Since they are required for whpx to function, I just thought it might be easier to have them auto-loaded with the executable, and functions dispatched by the linker, rather than go through whp_dispatch. r~
On 8/2/25 18:17, Mohamed Mediouni wrote:
> winhvemulation is x86_64 only.
> Exception exit bitmaps are also x86_64 only
> Others are just variable definitions not used on arm64.
>
> Signed-off-by: Mohamed Mediouni <mohamed@unpredictable.fr>
> ---
> accel/whpx/whpx-common.c | 20 ++++++++++++++++++--
> include/system/whpx-all.h | 2 ++
> include/system/whpx-common.h | 2 ++
> include/system/whpx-internal.h | 7 ++++++-
> 4 files changed, 28 insertions(+), 3 deletions(-)
>
> diff --git a/accel/whpx/whpx-common.c b/accel/whpx/whpx-common.c
> index b5e5fda696..eeefaea329 100644
> --- a/accel/whpx/whpx-common.c
> +++ b/accel/whpx/whpx-common.c
> @@ -41,7 +41,9 @@
> bool whpx_allowed;
> static bool whp_dispatch_initialized;
> static HMODULE hWinHvPlatform;
> +#ifdef __x86_64__
> static HMODULE hWinHvEmulation;
> +#endif
>
> struct whpx_state whpx_global;
> struct WHPDispatch whp_dispatch;
> @@ -106,11 +108,16 @@ int whpx_first_vcpu_starting(CPUState *cpu)
> * whpx_translate_cpu_breakpoints(). WHPX breakpoints must
> * now be recomputed.
> */
> +#ifdef __x86_64__
> whpx_translate_cpu_breakpoints(&whpx->breakpoints, cpu, i);
> +#endif
> }
> +#ifdef __x86_64__
> /* Actually insert the breakpoints into the memory. */
> whpx_apply_breakpoints(whpx->breakpoints.breakpoints, cpu, true);
> +#endif
> }
These are still static in target/i386/whpx/whpx-all.c, so the split in the previous patch
didn't work. You probably want arm to *have* these functions, even if they're empty.
> +#ifdef __x86_64__
> HRESULT hr;
> uint64_t exception_mask;
> if (whpx->step_pending ||
> @@ -132,6 +139,7 @@ int whpx_first_vcpu_starting(CPUState *cpu)
> "hr=%08lx.", hr);
> return 1;
> }
> +#endif
I'm not quite sure what this is doing, but it probably needs to be split out to a new
function which can be specialized between architectures.
> @@ -238,8 +246,10 @@ void whpx_destroy_vcpu(CPUState *cpu)
> struct whpx_state *whpx = &whpx_global;
>
> whp_dispatch.WHvDeleteVirtualProcessor(whpx->partition, cpu->cpu_index);
> +#ifdef __x86_64__
> AccelCPUState *vcpu = cpu->accel;
> whp_dispatch.WHvEmulatorDestroyEmulator(vcpu->emulator);
> +#endif
Does the os function exist on arm? The answer to that determines whether we must split
this out to an architecture function or if we can do
if (vcpu->emulator) {
destroy
}
> @@ -414,8 +424,12 @@ static bool load_whp_dispatch_fns(HMODULE *handle,
> LIST_WINHVPLATFORM_FUNCTIONS(WHP_LOAD_FIELD)
> break;
> case WINHV_EMULATION_FNS_DEFAULT:
> +#ifdef __x86_64__
> WHP_LOAD_LIB(WINHV_EMULATION_DLL, hLib)
> LIST_WINHVEMULATION_FUNCTIONS(WHP_LOAD_FIELD)
> +#else
> + abort();
> +#endif
Use g_assert_not_reached not abort.
That said, it might be cleaner to split this into two functions, rather than select pieces
of the function via an enumerator. At which point I could see the entire set of emulation
code staying in target/i386/.
r~
> On 3. Aug 2025, at 02:41, Richard Henderson <richard.henderson@linaro.org> wrote:
>
> On 8/2/25 18:17, Mohamed Mediouni wrote:
>> winhvemulation is x86_64 only.
>> Exception exit bitmaps are also x86_64 only
>> Others are just variable definitions not used on arm64.
>> Signed-off-by: Mohamed Mediouni <mohamed@unpredictable.fr>
>> ---
>> accel/whpx/whpx-common.c | 20 ++++++++++++++++++--
>> include/system/whpx-all.h | 2 ++
>> include/system/whpx-common.h | 2 ++
>> include/system/whpx-internal.h | 7 ++++++-
>> 4 files changed, 28 insertions(+), 3 deletions(-)
>> diff --git a/accel/whpx/whpx-common.c b/accel/whpx/whpx-common.c
>> index b5e5fda696..eeefaea329 100644
>> --- a/accel/whpx/whpx-common.c
>> +++ b/accel/whpx/whpx-common.c
>> @@ -41,7 +41,9 @@
>> bool whpx_allowed;
>> static bool whp_dispatch_initialized;
>> static HMODULE hWinHvPlatform;
>> +#ifdef __x86_64__
>> static HMODULE hWinHvEmulation;
>> +#endif
>> struct whpx_state whpx_global;
>> struct WHPDispatch whp_dispatch;
>> @@ -106,11 +108,16 @@ int whpx_first_vcpu_starting(CPUState *cpu)
>> * whpx_translate_cpu_breakpoints(). WHPX breakpoints must
>> * now be recomputed.
>> */
>> +#ifdef __x86_64__
>> whpx_translate_cpu_breakpoints(&whpx->breakpoints, cpu, i);
>> +#endif
>> }
>> +#ifdef __x86_64__
>> /* Actually insert the breakpoints into the memory. */
>> whpx_apply_breakpoints(whpx->breakpoints.breakpoints, cpu, true);
>> +#endif
>> }
>
> These are still static in target/i386/whpx/whpx-all.c, so the split in the previous patch didn't work. You probably want arm to *have* these functions, even if they're empty.
>
>> +#ifdef __x86_64__
>> HRESULT hr;
>> uint64_t exception_mask;
>> if (whpx->step_pending ||
>> @@ -132,6 +139,7 @@ int whpx_first_vcpu_starting(CPUState *cpu)
>> "hr=%08lx.", hr);
>> return 1;
>> }
>> +#endif
>
> I'm not quite sure what this is doing, but it probably needs to be split out to a new function which can be specialized between architectures.
Hello,
Arm WHPX has no specific functionality for debugging today, but we could support kernel mode breakpoints via replacing them by an unhandled hvc #2, stubbing might be the right route to go...
>
>> @@ -238,8 +246,10 @@ void whpx_destroy_vcpu(CPUState *cpu)
>> struct whpx_state *whpx = &whpx_global;
>> whp_dispatch.WHvDeleteVirtualProcessor(whpx->partition, cpu->cpu_index);
>> +#ifdef __x86_64__
>> AccelCPUState *vcpu = cpu->accel;
>> whp_dispatch.WHvEmulatorDestroyEmulator(vcpu->emulator);
>> +#endif
>
> Does the os function exist on arm? The answer to that determines whether we must split this out to an architecture function or if we can do
>
> if (vcpu->emulator) {
> destroy
> }
The winhvemulation header has x86-isms and isn’t parsable on arm unfortunately.
The whole winhvemulation library is x86_64 specific.
That said, I don’t think we need winhvemulation on x86 in the first place and it could be a good idea to get rid of the dependency there too.
>> @@ -414,8 +424,12 @@ static bool load_whp_dispatch_fns(HMODULE *handle,
>> LIST_WINHVPLATFORM_FUNCTIONS(WHP_LOAD_FIELD)
>> break;
>> case WINHV_EMULATION_FNS_DEFAULT:
>> +#ifdef __x86_64__
>> WHP_LOAD_LIB(WINHV_EMULATION_DLL, hLib)
>> LIST_WINHVEMULATION_FUNCTIONS(WHP_LOAD_FIELD)
>> +#else
>> + abort();
>> +#endif
>
> Use g_assert_not_reached not abort.
>
> That said, it might be cleaner to split this into two functions, rather than select pieces of the function via an enumerator. At which point I could see the entire set of emulation code staying in target/i386/.
There’s still significant shared code that might be worth keeping I think… will test a bit on x86 and see what makes sense to do…
Thank you,
>
> r~
>
On 8/3/25 10:55, Mohamed Mediouni wrote: > Arm WHPX has no specific functionality for debugging today, but we could support kernel mode breakpoints via replacing them by an unhandled hvc #2, stubbing might be the right route to go... Surely the debug registers are usable? In the meantime, stub functions which do nothing are better than ifdefs wherever possible. r~
> On 3. Aug 2025, at 03:03, Richard Henderson <richard.henderson@linaro.org> wrote: > > On 8/3/25 10:55, Mohamed Mediouni wrote: >> Arm WHPX has no specific functionality for debugging today, but we could support kernel mode breakpoints via replacing them by an unhandled hvc #2, stubbing might be the right route to go... > > Surely the debug registers are usable? In the meantime, stub functions which do nothing are better than ifdefs wherever possible. The debug exception goes to EL1 if we do so instead of the hypervisor because there aren't exit bitmaps/a debug trap API on arm64 WHP to make the HV vmexit in that case > r~
On 8/3/25 11:08, Mohamed Mediouni wrote: > > >> On 3. Aug 2025, at 03:03, Richard Henderson <richard.henderson@linaro.org> wrote: >> >> On 8/3/25 10:55, Mohamed Mediouni wrote: >>> Arm WHPX has no specific functionality for debugging today, but we could support kernel mode breakpoints via replacing them by an unhandled hvc #2, stubbing might be the right route to go... >> >> Surely the debug registers are usable? In the meantime, stub functions which do nothing are better than ifdefs wherever possible. > The debug exception goes to EL1 if we do so instead of the hypervisor because there aren't exit bitmaps/a debug trap API on arm64 WHP to make the HV vmexit in that case Huh. I thought I remembered some el2 debugging. Oh well. Leaving it support as stub functions is good enough for now. r~
© 2016 - 2025 Red Hat, Inc.