* [RFC 0/9] WHPX support for Arm
@ 2025-07-31 5:27 Mohamed Mediouni
2025-07-31 5:27 ` [RFC 1/9] whpx: Move around files before introducing AArch64 support Mohamed Mediouni
` (9 more replies)
0 siblings, 10 replies; 26+ messages in thread
From: Mohamed Mediouni @ 2025-07-31 5:27 UTC (permalink / raw)
To: qemu-devel
Cc: Daniel P. Berrangé, Paolo Bonzini, Sunil Muthuswamy,
Marc-André Lureau, Philippe Mathieu-Daudé,
Peter Maydell, qemu-arm, Mohamed Mediouni
This one took way longer for me to publish than I should have.
There are a number of lingering bugs in this one including u-boot not working.
Interrupt controller save/restore is entirely missing in this RFC, and some other state
bits are likely still missing too.
ITS not blocked by default yet, remember to use its=off when testing this series.
You might also want the GICv3 + GICv2m support patch as part of the HVF vGIC patch series, which
is not duplicated here.
PS: on both this and HVF, interrupt controller initialisation needs to be done early so I ended
up with hardcoded addresses. Wonder if the right way to go might be to defer virt and vCPU initialisation
until late in the process post-gic_realize...
Other than that, this boots both EDK2 and Linux in SMP, when using devicetree or ACPI.
Mohamed Mediouni (9):
whpx: Move around files before introducing AArch64 support
whpx: reshuffle common code
whpx: common: use whpx_cpu_instance_init on x86 only
whpx: interrupt controller support
hw/virt: make Qemu aware that WHPX has a vGICv3
hw: intc: arm_gicv3_common: add whpx
whpx: add arm64 support
whpx: copy over memory tracking logic from hvf
target/arm: cpu: mark WHPX as supporting PSCI 1.1
accel/meson.build | 1 +
accel/whpx/meson.build | 7 +
{target/i386 => accel}/whpx/whpx-accel-ops.c | 8 +-
accel/whpx/whpx-common.c | 670 ++++++++++++++++
hw/arm/virt.c | 3 +
hw/intc/arm_gicv3_common.c | 3 +
hw/intc/arm_gicv3_whpx.c | 285 +++++++
hw/intc/meson.build | 1 +
.../whpx => include/system}/whpx-accel-ops.h | 4 +-
include/system/whpx-all.h | 12 +
include/system/whpx-common.h | 22 +
.../whpx => include/system}/whpx-internal.h | 11 +-
meson.build | 5 +-
target/arm/cpu.c | 3 +-
target/arm/meson.build | 1 +
target/arm/whpx/meson.build | 3 +
target/arm/whpx/whpx-all.c | 744 ++++++++++++++++++
target/i386/whpx/meson.build | 1 -
target/i386/whpx/whpx-all.c | 524 +-----------
target/i386/whpx/whpx-apic.c | 2 +-
20 files changed, 1780 insertions(+), 530 deletions(-)
create mode 100644 accel/whpx/meson.build
rename {target/i386 => accel}/whpx/whpx-accel-ops.c (96%)
create mode 100644 accel/whpx/whpx-common.c
create mode 100644 hw/intc/arm_gicv3_whpx.c
rename {target/i386/whpx => include/system}/whpx-accel-ops.h (92%)
create mode 100644 include/system/whpx-all.h
create mode 100644 include/system/whpx-common.h
rename {target/i386/whpx => include/system}/whpx-internal.h (97%)
create mode 100644 target/arm/whpx/meson.build
create mode 100644 target/arm/whpx/whpx-all.c
--
2.39.5 (Apple Git-154)
^ permalink raw reply [flat|nested] 26+ messages in thread
* [RFC 1/9] whpx: Move around files before introducing AArch64 support
2025-07-31 5:27 [RFC 0/9] WHPX support for Arm Mohamed Mediouni
@ 2025-07-31 5:27 ` Mohamed Mediouni
2025-07-31 8:27 ` Philippe Mathieu-Daudé
2025-08-01 5:44 ` Richard Henderson
2025-07-31 5:27 ` [RFC 2/9] whpx: reshuffle common code Mohamed Mediouni
` (8 subsequent siblings)
9 siblings, 2 replies; 26+ messages in thread
From: Mohamed Mediouni @ 2025-07-31 5:27 UTC (permalink / raw)
To: qemu-devel
Cc: Daniel P. Berrangé, Paolo Bonzini, Sunil Muthuswamy,
Marc-André Lureau, Philippe Mathieu-Daudé,
Peter Maydell, qemu-arm, Mohamed Mediouni
Switch to a design where we can share whpx code between x86 and AArch64 when it makes sense to do so.
Signed-off-by: Mohamed Mediouni <mohamed@unpredictable.fr>
---
accel/meson.build | 1 +
accel/whpx/meson.build | 6 ++++++
{target/i386 => accel}/whpx/whpx-accel-ops.c | 8 ++++++--
{target/i386/whpx => include/system}/whpx-accel-ops.h | 0
{target/i386/whpx => include/system}/whpx-internal.h | 7 ++++++-
target/i386/whpx/meson.build | 1 -
target/i386/whpx/whpx-all.c | 4 ++--
7 files changed, 21 insertions(+), 6 deletions(-)
create mode 100644 accel/whpx/meson.build
rename {target/i386 => accel}/whpx/whpx-accel-ops.c (96%)
rename {target/i386/whpx => include/system}/whpx-accel-ops.h (100%)
rename {target/i386/whpx => include/system}/whpx-internal.h (98%)
diff --git a/accel/meson.build b/accel/meson.build
index 25b0f100b5..de927a3b37 100644
--- a/accel/meson.build
+++ b/accel/meson.build
@@ -6,6 +6,7 @@ user_ss.add(files('accel-user.c'))
subdir('tcg')
if have_system
subdir('hvf')
+ subdir('whpx')
subdir('qtest')
subdir('kvm')
subdir('xen')
diff --git a/accel/whpx/meson.build b/accel/whpx/meson.build
new file mode 100644
index 0000000000..659efb13c9
--- /dev/null
+++ b/accel/whpx/meson.build
@@ -0,0 +1,6 @@
+whpx_ss = ss.source_set()
+whpx_ss.add(files(
+ 'whpx-accel-ops.c',
+))
+
+specific_ss.add_all(when: 'CONFIG_WHPX', if_true: whpx_ss)
\ No newline at end of file
diff --git a/target/i386/whpx/whpx-accel-ops.c b/accel/whpx/whpx-accel-ops.c
similarity index 96%
rename from target/i386/whpx/whpx-accel-ops.c
rename to accel/whpx/whpx-accel-ops.c
index da58805b1a..364d99b660 100644
--- a/target/i386/whpx/whpx-accel-ops.c
+++ b/accel/whpx/whpx-accel-ops.c
@@ -16,8 +16,8 @@
#include "qemu/guest-random.h"
#include "system/whpx.h"
-#include "whpx-internal.h"
-#include "whpx-accel-ops.h"
+#include "system/whpx-internal.h"
+#include "system/whpx-accel-ops.h"
static void *whpx_cpu_thread_fn(void *arg)
{
@@ -80,7 +80,11 @@ static void whpx_kick_vcpu_thread(CPUState *cpu)
static bool whpx_vcpu_thread_is_idle(CPUState *cpu)
{
+#ifndef __aarch64__
return !whpx_apic_in_platform();
+#else
+ return 0;
+#endif
}
static void whpx_accel_ops_class_init(ObjectClass *oc, const void *data)
diff --git a/target/i386/whpx/whpx-accel-ops.h b/include/system/whpx-accel-ops.h
similarity index 100%
rename from target/i386/whpx/whpx-accel-ops.h
rename to include/system/whpx-accel-ops.h
diff --git a/target/i386/whpx/whpx-internal.h b/include/system/whpx-internal.h
similarity index 98%
rename from target/i386/whpx/whpx-internal.h
rename to include/system/whpx-internal.h
index 6633e9c4ca..af1e46a491 100644
--- a/target/i386/whpx/whpx-internal.h
+++ b/include/system/whpx-internal.h
@@ -3,8 +3,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,
@@ -97,12 +98,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)
};
diff --git a/target/i386/whpx/meson.build b/target/i386/whpx/meson.build
index 9c54aaad39..c3aaaff9fd 100644
--- a/target/i386/whpx/meson.build
+++ b/target/i386/whpx/meson.build
@@ -1,5 +1,4 @@
i386_system_ss.add(when: 'CONFIG_WHPX', if_true: files(
'whpx-all.c',
'whpx-apic.c',
- 'whpx-accel-ops.c',
))
diff --git a/target/i386/whpx/whpx-all.c b/target/i386/whpx/whpx-all.c
index b72dcff3c8..5a431fc3c7 100644
--- a/target/i386/whpx/whpx-all.c
+++ b/target/i386/whpx/whpx-all.c
@@ -31,8 +31,8 @@
#include "accel/accel-cpu-target.h"
#include <winerror.h>
-#include "whpx-internal.h"
-#include "whpx-accel-ops.h"
+#include "system/whpx-internal.h"
+#include "system/whpx-accel-ops.h"
#include <winhvplatform.h>
#include <winhvemulation.h>
--
2.39.5 (Apple Git-154)
^ permalink raw reply related [flat|nested] 26+ messages in thread
* [RFC 2/9] whpx: reshuffle common code
2025-07-31 5:27 [RFC 0/9] WHPX support for Arm Mohamed Mediouni
2025-07-31 5:27 ` [RFC 1/9] whpx: Move around files before introducing AArch64 support Mohamed Mediouni
@ 2025-07-31 5:27 ` Mohamed Mediouni
2025-07-31 5:27 ` [RFC 3/9] whpx: common: use whpx_cpu_instance_init on x86 only Mohamed Mediouni
` (7 subsequent siblings)
9 siblings, 0 replies; 26+ messages in thread
From: Mohamed Mediouni @ 2025-07-31 5:27 UTC (permalink / raw)
To: qemu-devel
Cc: Daniel P. Berrangé, Paolo Bonzini, Sunil Muthuswamy,
Marc-André Lureau, Philippe Mathieu-Daudé,
Peter Maydell, qemu-arm, Mohamed Mediouni
Some code can be shared between x86_64 and arm64 WHPX. Do so as much as reasonable.
Signed-off-by: Mohamed Mediouni <mohamed@unpredictable.fr>
---
accel/whpx/meson.build | 1 +
accel/whpx/whpx-common.c | 578 ++++++++++++++++++++++++++++++++
include/system/whpx-accel-ops.h | 4 +-
include/system/whpx-all.h | 12 +
include/system/whpx-common.h | 22 ++
include/system/whpx-internal.h | 4 +-
target/i386/whpx/whpx-all.c | 520 +---------------------------
target/i386/whpx/whpx-apic.c | 2 +-
8 files changed, 622 insertions(+), 521 deletions(-)
create mode 100644 accel/whpx/whpx-common.c
create mode 100644 include/system/whpx-all.h
create mode 100644 include/system/whpx-common.h
diff --git a/accel/whpx/meson.build b/accel/whpx/meson.build
index 659efb13c9..344b2b45d0 100644
--- a/accel/whpx/meson.build
+++ b/accel/whpx/meson.build
@@ -1,6 +1,7 @@
whpx_ss = ss.source_set()
whpx_ss.add(files(
'whpx-accel-ops.c',
+ 'whpx-common.c'
))
specific_ss.add_all(when: 'CONFIG_WHPX', if_true: whpx_ss)
\ No newline at end of file
diff --git a/accel/whpx/whpx-common.c b/accel/whpx/whpx-common.c
new file mode 100644
index 0000000000..0b23deb7c4
--- /dev/null
+++ b/accel/whpx/whpx-common.c
@@ -0,0 +1,578 @@
+/*
+ * QEMU Windows Hypervisor Platform accelerator (WHPX)
+ *
+ * Copyright Microsoft Corp. 2017
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ *
+ */
+
+#include "qemu/osdep.h"
+#include "cpu.h"
+#include "system/address-spaces.h"
+#include "system/ioport.h"
+#include "gdbstub/helpers.h"
+#include "qemu/accel.h"
+#include "accel/accel-ops.h"
+#include "system/whpx.h"
+#include "system/cpus.h"
+#include "system/runstate.h"
+#include "qemu/main-loop.h"
+#include "hw/boards.h"
+#include "hw/intc/ioapic.h"
+#include "qemu/error-report.h"
+#include "qapi/error.h"
+#include "qapi/qapi-types-common.h"
+#include "qapi/qapi-visit-common.h"
+#include "migration/blocker.h"
+#include "accel/accel-cpu-target.h"
+#include <winerror.h>
+
+#include "system/whpx-internal.h"
+#include "system/whpx-accel-ops.h"
+#include "system/whpx-common.h"
+#include "system/whpx-all.h"
+
+#include <winhvplatform.h>
+#include <winhvplatformdefs.h>
+
+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;
+
+/* Tries to find a breakpoint at the specified address. */
+struct whpx_breakpoint *whpx_lookup_breakpoint_by_addr(uint64_t address)
+{
+ struct whpx_state *whpx = &whpx_global;
+ int i;
+
+ if (whpx->breakpoints.breakpoints) {
+ for (i = 0; i < whpx->breakpoints.breakpoints->used; i++) {
+ if (address == whpx->breakpoints.breakpoints->data[i].address) {
+ return &whpx->breakpoints.breakpoints->data[i];
+ }
+ }
+ }
+
+ return NULL;
+}
+
+/*
+ * This function is called when the a VCPU is about to start and no other
+ * VCPUs have been started so far. Since the VCPU start order could be
+ * arbitrary, it doesn't have to be VCPU#0.
+ *
+ * It is used to commit the breakpoints into memory, and configure WHPX
+ * to intercept debug exceptions.
+ *
+ * Note that whpx_set_exception_exit_bitmap() cannot be called if one or
+ * more VCPUs are already running, so this is the best place to do it.
+ */
+int whpx_first_vcpu_starting(CPUState *cpu)
+{
+ struct whpx_state *whpx = &whpx_global;
+
+ g_assert(bql_locked());
+
+ if (!QTAILQ_EMPTY(&cpu->breakpoints) ||
+ (whpx->breakpoints.breakpoints &&
+ whpx->breakpoints.breakpoints->used)) {
+ CPUBreakpoint *bp;
+ int i = 0;
+ bool update_pending = false;
+
+ QTAILQ_FOREACH(bp, &cpu->breakpoints, entry) {
+ if (i >= whpx->breakpoints.original_address_count ||
+ bp->pc != whpx->breakpoints.original_addresses[i]) {
+ update_pending = true;
+ }
+
+ i++;
+ }
+
+ if (i != whpx->breakpoints.original_address_count) {
+ update_pending = true;
+ }
+
+ if (update_pending) {
+ /*
+ * The CPU breakpoints have changed since the last call to
+ * 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 ||
+ (whpx->breakpoints.breakpoints &&
+ whpx->breakpoints.breakpoints->used)) {
+ /*
+ * We are either attempting to single-step one or more CPUs, or
+ * have one or more breakpoints enabled. Both require intercepting
+ * the WHvX64ExceptionTypeBreakpointTrap exception.
+ */
+ exception_mask = 1UL << WHvX64ExceptionTypeDebugTrapOrFault;
+ } else {
+ /* Let the guest handle all exceptions. */
+ exception_mask = 0;
+ }
+ hr = whpx_set_exception_exit_bitmap(exception_mask);
+ if (!SUCCEEDED(hr)) {
+ error_report("WHPX: Failed to update exception exit mask,"
+ "hr=%08lx.", hr);
+ return 1;
+ }
+#endif
+ return 0;
+}
+
+/*
+ * This function is called when the last VCPU has finished running.
+ * It is used to remove any previously set breakpoints from memory.
+ */
+int whpx_last_vcpu_stopping(CPUState *cpu)
+{
+#ifdef __x86_64__
+ whpx_apply_breakpoints(whpx_global.breakpoints.breakpoints, cpu, false);
+#endif
+ return 0;
+}
+
+static void do_whpx_cpu_synchronize_state(CPUState *cpu, run_on_cpu_data arg)
+{
+ if (!cpu->vcpu_dirty) {
+ whpx_get_registers(cpu);
+ cpu->vcpu_dirty = true;
+ }
+}
+
+static void do_whpx_cpu_synchronize_post_reset(CPUState *cpu,
+ run_on_cpu_data arg)
+{
+ whpx_set_registers(cpu, WHPX_SET_RESET_STATE);
+ cpu->vcpu_dirty = false;
+}
+
+static void do_whpx_cpu_synchronize_post_init(CPUState *cpu,
+ run_on_cpu_data arg)
+{
+ whpx_set_registers(cpu, WHPX_SET_FULL_STATE);
+ cpu->vcpu_dirty = false;
+}
+
+static void do_whpx_cpu_synchronize_pre_loadvm(CPUState *cpu,
+ run_on_cpu_data arg)
+{
+ cpu->vcpu_dirty = true;
+}
+
+/*
+ * CPU support.
+ */
+
+void whpx_cpu_synchronize_state(CPUState *cpu)
+{
+ if (!cpu->vcpu_dirty) {
+ run_on_cpu(cpu, do_whpx_cpu_synchronize_state, RUN_ON_CPU_NULL);
+ }
+}
+
+void whpx_cpu_synchronize_post_reset(CPUState *cpu)
+{
+ run_on_cpu(cpu, do_whpx_cpu_synchronize_post_reset, RUN_ON_CPU_NULL);
+}
+
+void whpx_cpu_synchronize_post_init(CPUState *cpu)
+{
+ run_on_cpu(cpu, do_whpx_cpu_synchronize_post_init, RUN_ON_CPU_NULL);
+}
+
+void whpx_cpu_synchronize_pre_loadvm(CPUState *cpu)
+{
+ run_on_cpu(cpu, do_whpx_cpu_synchronize_pre_loadvm, RUN_ON_CPU_NULL);
+}
+
+static void whpx_pre_resume_vm(AccelState *as, bool step_pending)
+{
+ whpx_global.step_pending = step_pending;
+}
+
+/*
+ * Vcpu support.
+ */
+
+int whpx_vcpu_exec(CPUState *cpu)
+{
+ int ret;
+ int fatal;
+
+ for (;;) {
+ if (cpu->exception_index >= EXCP_INTERRUPT) {
+ ret = cpu->exception_index;
+ cpu->exception_index = -1;
+ break;
+ }
+
+ fatal = whpx_vcpu_run(cpu);
+
+ if (fatal) {
+ error_report("WHPX: Failed to exec a virtual processor");
+ abort();
+ }
+ }
+
+ return ret;
+}
+
+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);
+}
+
+
+void whpx_vcpu_kick(CPUState *cpu)
+{
+ struct whpx_state *whpx = &whpx_global;
+ whp_dispatch.WHvCancelRunVirtualProcessor(
+ whpx->partition, cpu->cpu_index, 0);
+}
+
+/*
+ * Memory support.
+ */
+
+static void whpx_update_mapping(hwaddr start_pa, ram_addr_t size,
+ void *host_va, int add, int rom,
+ const char *name)
+{
+ struct whpx_state *whpx = &whpx_global;
+ HRESULT hr;
+
+ /*
+ if (add) {
+ printf("WHPX: ADD PA:%p Size:%p, Host:%p, %s, '%s'\n",
+ (void*)start_pa, (void*)size, host_va,
+ (rom ? "ROM" : "RAM"), name);
+ } else {
+ printf("WHPX: DEL PA:%p Size:%p, Host:%p, '%s'\n",
+ (void*)start_pa, (void*)size, host_va, name);
+ }
+ */
+
+ if (add) {
+ hr = whp_dispatch.WHvMapGpaRange(whpx->partition,
+ host_va,
+ start_pa,
+ size,
+ (WHvMapGpaRangeFlagRead |
+ WHvMapGpaRangeFlagExecute |
+ (rom ? 0 : WHvMapGpaRangeFlagWrite)));
+ } else {
+ hr = whp_dispatch.WHvUnmapGpaRange(whpx->partition,
+ start_pa,
+ size);
+ }
+
+ if (FAILED(hr)) {
+ error_report("WHPX: Failed to %s GPA range '%s' PA:%p, Size:%p bytes,"
+ " Host:%p, hr=%08lx",
+ (add ? "MAP" : "UNMAP"), name,
+ (void *)(uintptr_t)start_pa, (void *)size, host_va, hr);
+ }
+}
+
+static void whpx_process_section(MemoryRegionSection *section, int add)
+{
+ MemoryRegion *mr = section->mr;
+ hwaddr start_pa = section->offset_within_address_space;
+ ram_addr_t size = int128_get64(section->size);
+ unsigned int delta;
+ uint64_t host_va;
+
+ if (!memory_region_is_ram(mr)) {
+ return;
+ }
+
+ delta = qemu_real_host_page_size() - (start_pa & ~qemu_real_host_page_mask());
+ delta &= ~qemu_real_host_page_mask();
+ if (delta > size) {
+ return;
+ }
+ start_pa += delta;
+ size -= delta;
+ size &= qemu_real_host_page_mask();
+ if (!size || (start_pa & ~qemu_real_host_page_mask())) {
+ return;
+ }
+
+ host_va = (uintptr_t)memory_region_get_ram_ptr(mr)
+ + section->offset_within_region + delta;
+
+ whpx_update_mapping(start_pa, size, (void *)(uintptr_t)host_va, add,
+ memory_region_is_rom(mr), mr->name);
+}
+
+static void whpx_region_add(MemoryListener *listener,
+ MemoryRegionSection *section)
+{
+ memory_region_ref(section->mr);
+ whpx_process_section(section, 1);
+}
+
+static void whpx_region_del(MemoryListener *listener,
+ MemoryRegionSection *section)
+{
+ whpx_process_section(section, 0);
+ memory_region_unref(section->mr);
+}
+
+static void whpx_transaction_begin(MemoryListener *listener)
+{
+}
+
+static void whpx_transaction_commit(MemoryListener *listener)
+{
+}
+
+static void whpx_log_sync(MemoryListener *listener,
+ MemoryRegionSection *section)
+{
+ MemoryRegion *mr = section->mr;
+
+ if (!memory_region_is_ram(mr)) {
+ return;
+ }
+
+ memory_region_set_dirty(mr, 0, int128_get64(section->size));
+}
+
+static MemoryListener whpx_memory_listener = {
+ .name = "whpx",
+ .begin = whpx_transaction_begin,
+ .commit = whpx_transaction_commit,
+ .region_add = whpx_region_add,
+ .region_del = whpx_region_del,
+ .log_sync = whpx_log_sync,
+ .priority = MEMORY_LISTENER_PRIORITY_ACCEL,
+};
+
+void whpx_memory_init(void)
+{
+ memory_listener_register(&whpx_memory_listener, &address_space_memory);
+}
+
+/*
+ * Load the functions from the given library, using the given handle. If a
+ * handle is provided, it is used, otherwise the library is opened. The
+ * handle will be updated on return with the opened one.
+ */
+static bool load_whp_dispatch_fns(HMODULE *handle,
+ WHPFunctionList function_list)
+{
+ HMODULE hLib = *handle;
+
+ #define WINHV_PLATFORM_DLL "WinHvPlatform.dll"
+ #define WINHV_EMULATION_DLL "WinHvEmulation.dll"
+ #define WHP_LOAD_FIELD_OPTIONAL(return_type, function_name, signature) \
+ whp_dispatch.function_name = \
+ (function_name ## _t)GetProcAddress(hLib, #function_name); \
+
+ #define WHP_LOAD_FIELD(return_type, function_name, signature) \
+ whp_dispatch.function_name = \
+ (function_name ## _t)GetProcAddress(hLib, #function_name); \
+ if (!whp_dispatch.function_name) { \
+ error_report("Could not load function %s", #function_name); \
+ goto error; \
+ } \
+
+ #define WHP_LOAD_LIB(lib_name, handle_lib) \
+ if (!handle_lib) { \
+ handle_lib = LoadLibrary(lib_name); \
+ if (!handle_lib) { \
+ error_report("Could not load library %s.", lib_name); \
+ goto error; \
+ } \
+ } \
+
+ switch (function_list) {
+ case WINHV_PLATFORM_FNS_DEFAULT:
+ WHP_LOAD_LIB(WINHV_PLATFORM_DLL, hLib)
+ 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)
+ LIST_WINHVPLATFORM_FUNCTIONS_SUPPLEMENTAL(WHP_LOAD_FIELD_OPTIONAL)
+ break;
+ }
+
+ *handle = hLib;
+ return true;
+
+error:
+ if (hLib) {
+ FreeLibrary(hLib);
+ }
+
+ return false;
+}
+
+static void whpx_set_kernel_irqchip(Object *obj, Visitor *v,
+ const char *name, void *opaque,
+ Error **errp)
+{
+ struct whpx_state *whpx = &whpx_global;
+ OnOffSplit mode;
+
+ if (!visit_type_OnOffSplit(v, name, &mode, errp)) {
+ return;
+ }
+
+ switch (mode) {
+ case ON_OFF_SPLIT_ON:
+ whpx->kernel_irqchip_allowed = true;
+ whpx->kernel_irqchip_required = true;
+ break;
+
+ case ON_OFF_SPLIT_OFF:
+ whpx->kernel_irqchip_allowed = false;
+ whpx->kernel_irqchip_required = false;
+ break;
+
+ case ON_OFF_SPLIT_SPLIT:
+ error_setg(errp, "WHPX: split irqchip currently not supported");
+ error_append_hint(errp,
+ "Try without kernel-irqchip or with kernel-irqchip=on|off");
+ break;
+
+ default:
+ /*
+ * The value was checked in visit_type_OnOffSplit() above. If
+ * we get here, then something is wrong in QEMU.
+ */
+ abort();
+ }
+}
+
+static void whpx_cpu_accel_class_init(ObjectClass *oc, const void *data)
+{
+ AccelCPUClass *acc = ACCEL_CPU_CLASS(oc);
+
+ acc->cpu_instance_init = whpx_cpu_instance_init;
+}
+
+static const TypeInfo whpx_cpu_accel_type = {
+ .name = ACCEL_CPU_NAME("whpx"),
+
+ .parent = TYPE_ACCEL_CPU,
+ .class_init = whpx_cpu_accel_class_init,
+ .abstract = true,
+};
+
+/*
+ * Partition support
+ */
+
+bool whpx_apic_in_platform(void) {
+ return whpx_global.apic_in_platform;
+}
+
+static void whpx_accel_class_init(ObjectClass *oc, const void *data)
+{
+ AccelClass *ac = ACCEL_CLASS(oc);
+ ac->name = "WHPX";
+ ac->init_machine = whpx_accel_init;
+ ac->pre_resume_vm = whpx_pre_resume_vm;
+ ac->allowed = &whpx_allowed;
+
+ object_class_property_add(oc, "kernel-irqchip", "on|off|split",
+ NULL, whpx_set_kernel_irqchip,
+ NULL, NULL);
+ object_class_property_set_description(oc, "kernel-irqchip",
+ "Configure WHPX in-kernel irqchip");
+}
+
+static void whpx_accel_instance_init(Object *obj)
+{
+ struct whpx_state *whpx = &whpx_global;
+
+ memset(whpx, 0, sizeof(struct whpx_state));
+ /* Turn on kernel-irqchip, by default */
+ whpx->kernel_irqchip_allowed = true;
+}
+
+static const TypeInfo whpx_accel_type = {
+ .name = ACCEL_CLASS_NAME("whpx"),
+ .parent = TYPE_ACCEL,
+ .instance_init = whpx_accel_instance_init,
+ .class_init = whpx_accel_class_init,
+};
+
+static void whpx_type_init(void)
+{
+ type_register_static(&whpx_accel_type);
+ type_register_static(&whpx_cpu_accel_type);
+}
+
+bool init_whp_dispatch(void)
+{
+ if (whp_dispatch_initialized) {
+ return true;
+ }
+
+ 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;
+
+ return true;
+error:
+ if (hWinHvPlatform) {
+ FreeLibrary(hWinHvPlatform);
+ }
+#ifdef __x86_64__
+ if (hWinHvEmulation) {
+ FreeLibrary(hWinHvEmulation);
+ }
+#endif
+ return false;
+}
+
+type_init(whpx_type_init);
diff --git a/include/system/whpx-accel-ops.h b/include/system/whpx-accel-ops.h
index 54cfc25a14..ed9d4c49f4 100644
--- a/include/system/whpx-accel-ops.h
+++ b/include/system/whpx-accel-ops.h
@@ -7,8 +7,8 @@
* See the COPYING file in the top-level directory.
*/
-#ifndef TARGET_I386_WHPX_ACCEL_OPS_H
-#define TARGET_I386_WHPX_ACCEL_OPS_H
+#ifndef SYSTEM_WHPX_ACCEL_OPS_H
+#define SYSTEM_WHPX_ACCEL_OPS_H
#include "system/cpus.h"
diff --git a/include/system/whpx-all.h b/include/system/whpx-all.h
new file mode 100644
index 0000000000..382b028c83
--- /dev/null
+++ b/include/system/whpx-all.h
@@ -0,0 +1,12 @@
+#ifndef SYSTEM_WHPX_ALL_H
+#define SYSTEM_WHPX_ALL_H
+
+/* Called by whpx-common */
+int whpx_vcpu_run(CPUState *cpu);
+void whpx_get_registers(CPUState *cpu);
+void whpx_set_registers(CPUState *cpu, int level);
+int whpx_accel_init(AccelState *as, MachineState *ms);
+#ifdef __x86_64__
+void whpx_cpu_instance_init(CPUState *cs);
+#endif
+#endif
diff --git a/include/system/whpx-common.h b/include/system/whpx-common.h
new file mode 100644
index 0000000000..57c73448a7
--- /dev/null
+++ b/include/system/whpx-common.h
@@ -0,0 +1,22 @@
+#ifndef SYSTEM_WHPX_COMMON_H
+#define SYSTEM_WHPX_COMMON_H
+
+struct AccelCPUState {
+#ifdef __x86_64__
+ WHV_EMULATOR_HANDLE emulator;
+ bool window_registered;
+ bool interruptable;
+ bool ready_for_pic_interrupt;
+ 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;
+};
+
+int whpx_first_vcpu_starting(CPUState *cpu);
+int whpx_last_vcpu_stopping(CPUState *cpu);
+void whpx_memory_init(void);
+struct whpx_breakpoint *whpx_lookup_breakpoint_by_addr(uint64_t address);
+#endif
\ No newline at end of file
diff --git a/include/system/whpx-internal.h b/include/system/whpx-internal.h
index af1e46a491..4b613c4bb5 100644
--- a/include/system/whpx-internal.h
+++ b/include/system/whpx-internal.h
@@ -1,5 +1,5 @@
-#ifndef TARGET_I386_WHPX_INTERNAL_H
-#define TARGET_I386_WHPX_INTERNAL_H
+#ifndef SYSTEM_WHPX_INTERNAL_H
+#define SYSTEM_WHPX_INTERNAL_H
#include <windows.h>
#include <winhvplatform.h>
diff --git a/target/i386/whpx/whpx-all.c b/target/i386/whpx/whpx-all.c
index 5a431fc3c7..de013ba88c 100644
--- a/target/i386/whpx/whpx-all.c
+++ b/target/i386/whpx/whpx-all.c
@@ -33,6 +33,8 @@
#include "system/whpx-internal.h"
#include "system/whpx-accel-ops.h"
+#include "system/whpx-all.h"
+#include "system/whpx-common.h"
#include <winhvplatform.h>
#include <winhvemulation.h>
@@ -1081,23 +1083,6 @@ static HRESULT whpx_vcpu_configure_single_stepping(CPUState *cpu,
return S_OK;
}
-/* Tries to find a breakpoint at the specified address. */
-static struct whpx_breakpoint *whpx_lookup_breakpoint_by_addr(uint64_t address)
-{
- struct whpx_state *whpx = &whpx_global;
- int i;
-
- if (whpx->breakpoints.breakpoints) {
- for (i = 0; i < whpx->breakpoints.breakpoints->used; i++) {
- if (address == whpx->breakpoints.breakpoints->data[i].address) {
- return &whpx->breakpoints.breakpoints->data[i];
- }
- }
- }
-
- return NULL;
-}
-
/*
* Linux uses int3 (0xCC) during startup (see int3_selftest()) and for
* debugging user-mode applications. Since the WHPX API does not offer
@@ -1303,93 +1288,6 @@ static void whpx_apply_breakpoints(
}
}
-/*
- * This function is called when the a VCPU is about to start and no other
- * VCPUs have been started so far. Since the VCPU start order could be
- * arbitrary, it doesn't have to be VCPU#0.
- *
- * It is used to commit the breakpoints into memory, and configure WHPX
- * to intercept debug exceptions.
- *
- * Note that whpx_set_exception_exit_bitmap() cannot be called if one or
- * more VCPUs are already running, so this is the best place to do it.
- */
-static int whpx_first_vcpu_starting(CPUState *cpu)
-{
- struct whpx_state *whpx = &whpx_global;
- HRESULT hr;
-
- g_assert(bql_locked());
-
- if (!QTAILQ_EMPTY(&cpu->breakpoints) ||
- (whpx->breakpoints.breakpoints &&
- whpx->breakpoints.breakpoints->used)) {
- CPUBreakpoint *bp;
- int i = 0;
- bool update_pending = false;
-
- QTAILQ_FOREACH(bp, &cpu->breakpoints, entry) {
- if (i >= whpx->breakpoints.original_address_count ||
- bp->pc != whpx->breakpoints.original_addresses[i]) {
- update_pending = true;
- }
-
- i++;
- }
-
- if (i != whpx->breakpoints.original_address_count) {
- update_pending = true;
- }
-
- if (update_pending) {
- /*
- * The CPU breakpoints have changed since the last call to
- * whpx_translate_cpu_breakpoints(). WHPX breakpoints must
- * now be recomputed.
- */
- whpx_translate_cpu_breakpoints(&whpx->breakpoints, cpu, i);
- }
-
- /* Actually insert the breakpoints into the memory. */
- whpx_apply_breakpoints(whpx->breakpoints.breakpoints, cpu, true);
- }
-
- uint64_t exception_mask;
- if (whpx->step_pending ||
- (whpx->breakpoints.breakpoints &&
- whpx->breakpoints.breakpoints->used)) {
- /*
- * We are either attempting to single-step one or more CPUs, or
- * have one or more breakpoints enabled. Both require intercepting
- * the WHvX64ExceptionTypeBreakpointTrap exception.
- */
-
- exception_mask = 1UL << WHvX64ExceptionTypeDebugTrapOrFault;
- } else {
- /* Let the guest handle all exceptions. */
- exception_mask = 0;
- }
-
- hr = whpx_set_exception_exit_bitmap(exception_mask);
- if (!SUCCEEDED(hr)) {
- error_report("WHPX: Failed to update exception exit mask,"
- "hr=%08lx.", hr);
- return 1;
- }
-
- return 0;
-}
-
-/*
- * This function is called when the last VCPU has finished running.
- * It is used to remove any previously set breakpoints from memory.
- */
-static int whpx_last_vcpu_stopping(CPUState *cpu)
-{
- whpx_apply_breakpoints(whpx_global.breakpoints.breakpoints, cpu, false);
- return 0;
-}
-
/* Returns the address of the next instruction that is about to be executed. */
static vaddr whpx_vcpu_get_pc(CPUState *cpu, bool exit_context_valid)
{
@@ -2054,65 +1952,6 @@ static int whpx_vcpu_run(CPUState *cpu)
return ret < 0;
}
-static void do_whpx_cpu_synchronize_state(CPUState *cpu, run_on_cpu_data arg)
-{
- if (!cpu->vcpu_dirty) {
- whpx_get_registers(cpu);
- cpu->vcpu_dirty = true;
- }
-}
-
-static void do_whpx_cpu_synchronize_post_reset(CPUState *cpu,
- run_on_cpu_data arg)
-{
- whpx_set_registers(cpu, WHPX_SET_RESET_STATE);
- cpu->vcpu_dirty = false;
-}
-
-static void do_whpx_cpu_synchronize_post_init(CPUState *cpu,
- run_on_cpu_data arg)
-{
- whpx_set_registers(cpu, WHPX_SET_FULL_STATE);
- cpu->vcpu_dirty = false;
-}
-
-static void do_whpx_cpu_synchronize_pre_loadvm(CPUState *cpu,
- run_on_cpu_data arg)
-{
- cpu->vcpu_dirty = true;
-}
-
-/*
- * CPU support.
- */
-
-void whpx_cpu_synchronize_state(CPUState *cpu)
-{
- if (!cpu->vcpu_dirty) {
- run_on_cpu(cpu, do_whpx_cpu_synchronize_state, RUN_ON_CPU_NULL);
- }
-}
-
-void whpx_cpu_synchronize_post_reset(CPUState *cpu)
-{
- run_on_cpu(cpu, do_whpx_cpu_synchronize_post_reset, RUN_ON_CPU_NULL);
-}
-
-void whpx_cpu_synchronize_post_init(CPUState *cpu)
-{
- run_on_cpu(cpu, do_whpx_cpu_synchronize_post_init, RUN_ON_CPU_NULL);
-}
-
-void whpx_cpu_synchronize_pre_loadvm(CPUState *cpu)
-{
- run_on_cpu(cpu, do_whpx_cpu_synchronize_pre_loadvm, RUN_ON_CPU_NULL);
-}
-
-static void whpx_pre_resume_vm(AccelState *as, bool step_pending)
-{
- whpx_global.step_pending = step_pending;
-}
-
/*
* Vcpu support.
*/
@@ -2241,295 +2080,18 @@ error:
return ret;
}
-int whpx_vcpu_exec(CPUState *cpu)
-{
- int ret;
- int fatal;
-
- for (;;) {
- if (cpu->exception_index >= EXCP_INTERRUPT) {
- ret = cpu->exception_index;
- cpu->exception_index = -1;
- break;
- }
-
- fatal = whpx_vcpu_run(cpu);
-
- if (fatal) {
- error_report("WHPX: Failed to exec a virtual processor");
- abort();
- }
- }
-
- return ret;
-}
-
-void whpx_destroy_vcpu(CPUState *cpu)
-{
- struct whpx_state *whpx = &whpx_global;
- AccelCPUState *vcpu = cpu->accel;
-
- whp_dispatch.WHvDeleteVirtualProcessor(whpx->partition, cpu->cpu_index);
- whp_dispatch.WHvEmulatorDestroyEmulator(vcpu->emulator);
- g_free(cpu->accel);
-}
-
-void whpx_vcpu_kick(CPUState *cpu)
-{
- struct whpx_state *whpx = &whpx_global;
- whp_dispatch.WHvCancelRunVirtualProcessor(
- whpx->partition, cpu->cpu_index, 0);
-}
-
-/*
- * Memory support.
- */
-
-static void whpx_update_mapping(hwaddr start_pa, ram_addr_t size,
- void *host_va, int add, int rom,
- const char *name)
-{
- struct whpx_state *whpx = &whpx_global;
- HRESULT hr;
-
- /*
- if (add) {
- printf("WHPX: ADD PA:%p Size:%p, Host:%p, %s, '%s'\n",
- (void*)start_pa, (void*)size, host_va,
- (rom ? "ROM" : "RAM"), name);
- } else {
- printf("WHPX: DEL PA:%p Size:%p, Host:%p, '%s'\n",
- (void*)start_pa, (void*)size, host_va, name);
- }
- */
-
- if (add) {
- hr = whp_dispatch.WHvMapGpaRange(whpx->partition,
- host_va,
- start_pa,
- size,
- (WHvMapGpaRangeFlagRead |
- WHvMapGpaRangeFlagExecute |
- (rom ? 0 : WHvMapGpaRangeFlagWrite)));
- } else {
- hr = whp_dispatch.WHvUnmapGpaRange(whpx->partition,
- start_pa,
- size);
- }
-
- if (FAILED(hr)) {
- error_report("WHPX: Failed to %s GPA range '%s' PA:%p, Size:%p bytes,"
- " Host:%p, hr=%08lx",
- (add ? "MAP" : "UNMAP"), name,
- (void *)(uintptr_t)start_pa, (void *)size, host_va, hr);
- }
-}
-
-static void whpx_process_section(MemoryRegionSection *section, int add)
-{
- MemoryRegion *mr = section->mr;
- hwaddr start_pa = section->offset_within_address_space;
- ram_addr_t size = int128_get64(section->size);
- unsigned int delta;
- uint64_t host_va;
-
- if (!memory_region_is_ram(mr)) {
- return;
- }
-
- delta = qemu_real_host_page_size() - (start_pa & ~qemu_real_host_page_mask());
- delta &= ~qemu_real_host_page_mask();
- if (delta > size) {
- return;
- }
- start_pa += delta;
- size -= delta;
- size &= qemu_real_host_page_mask();
- if (!size || (start_pa & ~qemu_real_host_page_mask())) {
- return;
- }
-
- host_va = (uintptr_t)memory_region_get_ram_ptr(mr)
- + section->offset_within_region + delta;
-
- whpx_update_mapping(start_pa, size, (void *)(uintptr_t)host_va, add,
- memory_region_is_rom(mr), mr->name);
-}
-
-static void whpx_region_add(MemoryListener *listener,
- MemoryRegionSection *section)
-{
- memory_region_ref(section->mr);
- whpx_process_section(section, 1);
-}
-
-static void whpx_region_del(MemoryListener *listener,
- MemoryRegionSection *section)
-{
- whpx_process_section(section, 0);
- memory_region_unref(section->mr);
-}
-
-static void whpx_transaction_begin(MemoryListener *listener)
-{
-}
-
-static void whpx_transaction_commit(MemoryListener *listener)
-{
-}
-
-static void whpx_log_sync(MemoryListener *listener,
- MemoryRegionSection *section)
-{
- MemoryRegion *mr = section->mr;
-
- if (!memory_region_is_ram(mr)) {
- return;
- }
-
- memory_region_set_dirty(mr, 0, int128_get64(section->size));
-}
-
-static MemoryListener whpx_memory_listener = {
- .name = "whpx",
- .begin = whpx_transaction_begin,
- .commit = whpx_transaction_commit,
- .region_add = whpx_region_add,
- .region_del = whpx_region_del,
- .log_sync = whpx_log_sync,
- .priority = MEMORY_LISTENER_PRIORITY_ACCEL,
-};
-
-static void whpx_memory_init(void)
-{
- memory_listener_register(&whpx_memory_listener, &address_space_memory);
-}
-
-/*
- * Load the functions from the given library, using the given handle. If a
- * handle is provided, it is used, otherwise the library is opened. The
- * handle will be updated on return with the opened one.
- */
-static bool load_whp_dispatch_fns(HMODULE *handle,
- WHPFunctionList function_list)
-{
- HMODULE hLib = *handle;
-
- #define WINHV_PLATFORM_DLL "WinHvPlatform.dll"
- #define WINHV_EMULATION_DLL "WinHvEmulation.dll"
- #define WHP_LOAD_FIELD_OPTIONAL(return_type, function_name, signature) \
- whp_dispatch.function_name = \
- (function_name ## _t)GetProcAddress(hLib, #function_name); \
-
- #define WHP_LOAD_FIELD(return_type, function_name, signature) \
- whp_dispatch.function_name = \
- (function_name ## _t)GetProcAddress(hLib, #function_name); \
- if (!whp_dispatch.function_name) { \
- error_report("Could not load function %s", #function_name); \
- goto error; \
- } \
-
- #define WHP_LOAD_LIB(lib_name, handle_lib) \
- if (!handle_lib) { \
- handle_lib = LoadLibrary(lib_name); \
- if (!handle_lib) { \
- error_report("Could not load library %s.", lib_name); \
- goto error; \
- } \
- } \
-
- switch (function_list) {
- case WINHV_PLATFORM_FNS_DEFAULT:
- WHP_LOAD_LIB(WINHV_PLATFORM_DLL, hLib)
- LIST_WINHVPLATFORM_FUNCTIONS(WHP_LOAD_FIELD)
- break;
-
- case WINHV_EMULATION_FNS_DEFAULT:
- WHP_LOAD_LIB(WINHV_EMULATION_DLL, hLib)
- LIST_WINHVEMULATION_FUNCTIONS(WHP_LOAD_FIELD)
- break;
-
- case WINHV_PLATFORM_FNS_SUPPLEMENTAL:
- WHP_LOAD_LIB(WINHV_PLATFORM_DLL, hLib)
- LIST_WINHVPLATFORM_FUNCTIONS_SUPPLEMENTAL(WHP_LOAD_FIELD_OPTIONAL)
- break;
- }
-
- *handle = hLib;
- return true;
-
-error:
- if (hLib) {
- FreeLibrary(hLib);
- }
-
- return false;
-}
-
-static void whpx_set_kernel_irqchip(Object *obj, Visitor *v,
- const char *name, void *opaque,
- Error **errp)
-{
- struct whpx_state *whpx = &whpx_global;
- OnOffSplit mode;
-
- if (!visit_type_OnOffSplit(v, name, &mode, errp)) {
- return;
- }
-
- switch (mode) {
- case ON_OFF_SPLIT_ON:
- whpx->kernel_irqchip_allowed = true;
- whpx->kernel_irqchip_required = true;
- break;
-
- case ON_OFF_SPLIT_OFF:
- whpx->kernel_irqchip_allowed = false;
- whpx->kernel_irqchip_required = false;
- break;
-
- case ON_OFF_SPLIT_SPLIT:
- error_setg(errp, "WHPX: split irqchip currently not supported");
- error_append_hint(errp,
- "Try without kernel-irqchip or with kernel-irqchip=on|off");
- break;
-
- default:
- /*
- * The value was checked in visit_type_OnOffSplit() above. If
- * we get here, then something is wrong in QEMU.
- */
- abort();
- }
-}
-
-static void whpx_cpu_instance_init(CPUState *cs)
+void whpx_cpu_instance_init(CPUState *cs)
{
X86CPU *cpu = X86_CPU(cs);
host_cpu_instance_init(cpu);
}
-static void whpx_cpu_accel_class_init(ObjectClass *oc, const void *data)
-{
- AccelCPUClass *acc = ACCEL_CPU_CLASS(oc);
-
- acc->cpu_instance_init = whpx_cpu_instance_init;
-}
-
-static const TypeInfo whpx_cpu_accel_type = {
- .name = ACCEL_CPU_NAME("whpx"),
-
- .parent = TYPE_ACCEL_CPU,
- .class_init = whpx_cpu_accel_class_init,
- .abstract = true,
-};
-
/*
* Partition support
*/
-static int whpx_accel_init(AccelState *as, MachineState *ms)
+int whpx_accel_init(AccelState *as, MachineState *ms)
{
struct whpx_state *whpx;
int ret;
@@ -2712,77 +2274,3 @@ error:
return ret;
}
-
-bool whpx_apic_in_platform(void) {
- return whpx_global.apic_in_platform;
-}
-
-static void whpx_accel_class_init(ObjectClass *oc, const void *data)
-{
- AccelClass *ac = ACCEL_CLASS(oc);
- ac->name = "WHPX";
- ac->init_machine = whpx_accel_init;
- ac->pre_resume_vm = whpx_pre_resume_vm;
- ac->allowed = &whpx_allowed;
-
- object_class_property_add(oc, "kernel-irqchip", "on|off|split",
- NULL, whpx_set_kernel_irqchip,
- NULL, NULL);
- object_class_property_set_description(oc, "kernel-irqchip",
- "Configure WHPX in-kernel irqchip");
-}
-
-static void whpx_accel_instance_init(Object *obj)
-{
- struct whpx_state *whpx = &whpx_global;
-
- memset(whpx, 0, sizeof(struct whpx_state));
- /* Turn on kernel-irqchip, by default */
- whpx->kernel_irqchip_allowed = true;
-}
-
-static const TypeInfo whpx_accel_type = {
- .name = ACCEL_CLASS_NAME("whpx"),
- .parent = TYPE_ACCEL,
- .instance_init = whpx_accel_instance_init,
- .class_init = whpx_accel_class_init,
-};
-
-static void whpx_type_init(void)
-{
- type_register_static(&whpx_accel_type);
- type_register_static(&whpx_cpu_accel_type);
-}
-
-bool init_whp_dispatch(void)
-{
- if (whp_dispatch_initialized) {
- return true;
- }
-
- if (!load_whp_dispatch_fns(&hWinHvPlatform, WINHV_PLATFORM_FNS_DEFAULT)) {
- goto error;
- }
-
- if (!load_whp_dispatch_fns(&hWinHvEmulation, WINHV_EMULATION_FNS_DEFAULT)) {
- goto error;
- }
-
- assert(load_whp_dispatch_fns(&hWinHvPlatform,
- WINHV_PLATFORM_FNS_SUPPLEMENTAL));
- whp_dispatch_initialized = true;
-
- return true;
-error:
- if (hWinHvPlatform) {
- FreeLibrary(hWinHvPlatform);
- }
-
- if (hWinHvEmulation) {
- FreeLibrary(hWinHvEmulation);
- }
-
- return false;
-}
-
-type_init(whpx_type_init);
diff --git a/target/i386/whpx/whpx-apic.c b/target/i386/whpx/whpx-apic.c
index e1ef6d4e6d..badb404b63 100644
--- a/target/i386/whpx/whpx-apic.c
+++ b/target/i386/whpx/whpx-apic.c
@@ -18,7 +18,7 @@
#include "hw/pci/msi.h"
#include "system/hw_accel.h"
#include "system/whpx.h"
-#include "whpx-internal.h"
+#include "system/whpx-internal.h"
struct whpx_lapic_state {
struct {
--
2.39.5 (Apple Git-154)
^ permalink raw reply related [flat|nested] 26+ messages in thread
* [RFC 3/9] whpx: common: use whpx_cpu_instance_init on x86 only
2025-07-31 5:27 [RFC 0/9] WHPX support for Arm Mohamed Mediouni
2025-07-31 5:27 ` [RFC 1/9] whpx: Move around files before introducing AArch64 support Mohamed Mediouni
2025-07-31 5:27 ` [RFC 2/9] whpx: reshuffle common code Mohamed Mediouni
@ 2025-07-31 5:27 ` Mohamed Mediouni
2025-07-31 8:30 ` Philippe Mathieu-Daudé
2025-07-31 5:27 ` [RFC 4/9] whpx: interrupt controller support Mohamed Mediouni
` (6 subsequent siblings)
9 siblings, 1 reply; 26+ messages in thread
From: Mohamed Mediouni @ 2025-07-31 5:27 UTC (permalink / raw)
To: qemu-devel
Cc: Daniel P. Berrangé, Paolo Bonzini, Sunil Muthuswamy,
Marc-André Lureau, Philippe Mathieu-Daudé,
Peter Maydell, qemu-arm, Mohamed Mediouni
We aren't using it on arm64.
Signed-off-by: Mohamed Mediouni <mohamed@unpredictable.fr>
---
accel/whpx/whpx-common.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/accel/whpx/whpx-common.c b/accel/whpx/whpx-common.c
index 0b23deb7c4..43d0200afd 100644
--- a/accel/whpx/whpx-common.c
+++ b/accel/whpx/whpx-common.c
@@ -486,9 +486,10 @@ static void whpx_set_kernel_irqchip(Object *obj, Visitor *v,
static void whpx_cpu_accel_class_init(ObjectClass *oc, const void *data)
{
+#ifdef __x86_64__
AccelCPUClass *acc = ACCEL_CPU_CLASS(oc);
-
acc->cpu_instance_init = whpx_cpu_instance_init;
+#endif
}
static const TypeInfo whpx_cpu_accel_type = {
--
2.39.5 (Apple Git-154)
^ permalink raw reply related [flat|nested] 26+ messages in thread
* [RFC 4/9] whpx: interrupt controller support
2025-07-31 5:27 [RFC 0/9] WHPX support for Arm Mohamed Mediouni
` (2 preceding siblings ...)
2025-07-31 5:27 ` [RFC 3/9] whpx: common: use whpx_cpu_instance_init on x86 only Mohamed Mediouni
@ 2025-07-31 5:27 ` Mohamed Mediouni
2025-07-31 5:27 ` [RFC 5/9] hw/virt: make Qemu aware that WHPX has a vGICv3 Mohamed Mediouni
` (5 subsequent siblings)
9 siblings, 0 replies; 26+ messages in thread
From: Mohamed Mediouni @ 2025-07-31 5:27 UTC (permalink / raw)
To: qemu-devel
Cc: Daniel P. Berrangé, Paolo Bonzini, Sunil Muthuswamy,
Marc-André Lureau, Philippe Mathieu-Daudé,
Peter Maydell, qemu-arm, Mohamed Mediouni
Signed-off-by: Mohamed Mediouni <mohamed@unpredictable.fr>
---
hw/intc/arm_gicv3_whpx.c | 285 +++++++++++++++++++++++++++++++++++++++
hw/intc/meson.build | 1 +
2 files changed, 286 insertions(+)
create mode 100644 hw/intc/arm_gicv3_whpx.c
diff --git a/hw/intc/arm_gicv3_whpx.c b/hw/intc/arm_gicv3_whpx.c
new file mode 100644
index 0000000000..97ab164518
--- /dev/null
+++ b/hw/intc/arm_gicv3_whpx.c
@@ -0,0 +1,285 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * ARM Generic Interrupt Controller using HVF platform support
+ *
+ * Copyright (c) 2025 Mohamed Mediouni
+ * Based on vGICv3 KVM code by Pavel Fedin
+ *
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "hw/intc/arm_gicv3_common.h"
+#include "qemu/error-report.h"
+#include "qemu/module.h"
+#include "system/runstate.h"
+#include "system/whpx.h"
+#include "system/whpx-internal.h"
+#include "gicv3_internal.h"
+#include "vgic_common.h"
+#include "qom/object.h"
+#include "target/arm/cpregs.h"
+
+#include "hw/arm/bsa.h"
+#include <winhvplatform.h>
+#include <winhvplatformdefs.h>
+#include <winnt.h>
+
+struct WHPXARMGICv3Class {
+ ARMGICv3CommonClass parent_class;
+ DeviceRealize parent_realize;
+ ResettablePhases parent_phases;
+};
+
+#define TYPE_WHPX_GICV3 "whpx-arm-gicv3"
+typedef struct WHPXARMGICv3Class WHPXARMGICv3Class;
+
+/* This is reusing the GICv3State typedef from ARM_GICV3_ITS_COMMON */
+DECLARE_OBJ_CHECKERS(GICv3State, WHPXARMGICv3Class,
+ WHPX_GICV3, TYPE_WHPX_GICV3);
+
+static void whpx_gicv3_check(GICv3State *s)
+{
+}
+
+static void whpx_gicv3_put_cpu(CPUState *cpu_state, run_on_cpu_data arg)
+{
+}
+
+static void whpx_gicv3_put(GICv3State *s)
+{
+ int ncpu;
+
+ whpx_gicv3_check(s);
+
+ for (ncpu = 0; ncpu < s->num_cpu; ncpu++) {
+ run_on_cpu_data data;
+ data.host_ptr = &s->cpu[ncpu];
+ run_on_cpu(s->cpu[ncpu].cpu, whpx_gicv3_put_cpu, data);
+ }
+}
+
+static void whpx_gicv3_get_cpu(CPUState *cpu_state, run_on_cpu_data arg)
+{
+}
+
+static void whpx_gicv3_get(GICv3State *s)
+{
+ int ncpu;
+
+ for (ncpu = 0; ncpu < s->num_cpu; ncpu++) {
+ run_on_cpu_data data;
+ data.host_ptr = &s->cpu[ncpu];
+ run_on_cpu(s->cpu[ncpu].cpu, whpx_gicv3_get_cpu, data);
+ }
+}
+
+static void whpx_gicv3_set_irq(void *opaque, int irq, int level)
+{
+ struct whpx_state *whpx = &whpx_global;
+
+ GICv3State *s = (GICv3State *)opaque;
+ if (irq > s->num_irq) {
+ return;
+ }
+ WHV_INTERRUPT_TYPE interrupt_type = WHvArm64InterruptTypeFixed;
+ WHV_INTERRUPT_CONTROL interrupt_control =
+ {interrupt_type = WHvArm64InterruptTypeFixed,
+ .RequestedVector = GIC_INTERNAL + irq, .InterruptControl.Asserted=1};
+
+ whp_dispatch.WHvRequestInterrupt(whpx->partition, &interrupt_control, sizeof(interrupt_control));
+
+ if (!level) {
+ interrupt_control.InterruptControl.Asserted = 0;
+ whp_dispatch.WHvRequestInterrupt(whpx->partition, &interrupt_control, sizeof(interrupt_control));
+ }
+
+}
+
+static void whpx_gicv3_icc_reset(CPUARMState *env, const ARMCPRegInfo *ri)
+{
+ GICv3State *s;
+ GICv3CPUState *c;
+
+ c = (GICv3CPUState *)env->gicv3state;
+ s = c->gic;
+
+ c->icc_pmr_el1 = 0;
+ /*
+ * Architecturally the reset value of the ICC_BPR registers
+ * is UNKNOWN. We set them all to 0 here; when the kernel
+ * uses these values to program the ICH_VMCR_EL2 fields that
+ * determine the guest-visible ICC_BPR register values, the
+ * hardware's "writing a value less than the minimum sets
+ * the field to the minimum value" behaviour will result in
+ * them effectively resetting to the correct minimum value
+ * for the host GIC.
+ */
+ c->icc_bpr[GICV3_G0] = 0;
+ c->icc_bpr[GICV3_G1] = 0;
+ c->icc_bpr[GICV3_G1NS] = 0;
+
+ c->icc_sre_el1 = 0x7;
+ memset(c->icc_apr, 0, sizeof(c->icc_apr));
+ memset(c->icc_igrpen, 0, sizeof(c->icc_igrpen));
+
+ if (s->migration_blocker) {
+ return;
+ }
+
+ c->icc_ctlr_el1[GICV3_S] = c->icc_ctlr_el1[GICV3_NS];
+}
+
+static void whpx_gicv3_reset_hold(Object *obj, ResetType type)
+{
+ GICv3State *s = ARM_GICV3_COMMON(obj);
+ WHPXARMGICv3Class *kgc = WHPX_GICV3_GET_CLASS(s);
+
+ if (kgc->parent_phases.hold) {
+ kgc->parent_phases.hold(obj, type);
+ }
+
+ whpx_gicv3_put(s);
+}
+
+
+/*
+ * CPU interface registers of GIC needs to be reset on CPU reset.
+ * For the calling arm_gicv3_icc_reset() on CPU reset, we register
+ * below ARMCPRegInfo. As we reset the whole cpu interface under single
+ * register reset, we define only one register of CPU interface instead
+ * of defining all the registers.
+ */
+static const ARMCPRegInfo gicv3_cpuif_reginfo[] = {
+ { .name = "ICC_CTLR_EL1", .state = ARM_CP_STATE_BOTH,
+ .opc0 = 3, .opc1 = 0, .crn = 12, .crm = 12, .opc2 = 4,
+ /*
+ * If ARM_CP_NOP is used, resetfn is not called,
+ * So ARM_CP_NO_RAW is appropriate type.
+ */
+ .type = ARM_CP_NO_RAW,
+ .access = PL1_RW,
+ .readfn = arm_cp_read_zero,
+ .writefn = arm_cp_write_ignore,
+ /*
+ * We hang the whole cpu interface reset routine off here
+ * rather than parcelling it out into one little function
+ * per register
+ */
+ .resetfn = whpx_gicv3_icc_reset,
+ },
+};
+
+static void whpx_set_reg(CPUState *cpu, WHV_REGISTER_NAME reg, WHV_REGISTER_VALUE val)
+{
+ struct whpx_state *whpx = &whpx_global;
+ HRESULT hr;
+ hr = whp_dispatch.WHvSetVirtualProcessorRegisters(whpx->partition, cpu->cpu_index,
+ ®, 1, &val);
+
+ if (FAILED(hr)) {
+ error_report("WHPX: Failed to set register %08x, hr=%08lx", reg, hr);
+ }
+}
+
+static void whpx_gicv3_realize(DeviceState *dev, Error **errp)
+{
+ GICv3State *s = WHPX_GICV3(dev);
+ WHPXARMGICv3Class *kgc = WHPX_GICV3_GET_CLASS(s);
+ Error *local_err = NULL;
+ int i;
+
+ kgc->parent_realize(dev, &local_err);
+ if (local_err) {
+ error_propagate(errp, local_err);
+ return;
+ }
+
+ if (s->revision != 3) {
+ error_setg(errp, "unsupported GIC revision %d for platform GIC",
+ s->revision);
+ }
+
+ if (s->security_extn) {
+ error_setg(errp, "the platform vGICv3 does not implement the "
+ "security extensions");
+ return;
+ }
+
+ if (s->nmi_support) {
+ error_setg(errp, "NMI is not supported with the platform GIC");
+ return;
+ }
+
+ if (s->nb_redist_regions > 1) {
+ error_setg(errp, "Multiple VGICv3 redistributor regions are not "
+ "supported by WHPX");
+ error_append_hint(errp, "A maximum of %d VCPUs can be used",
+ s->redist_region_count[0]);
+ return;
+ }
+
+ gicv3_init_irqs_and_mmio(s, whpx_gicv3_set_irq, NULL);
+/*
+ WHV_ARM64_IC_PARAMETERS param = {
+ .EmulationMode = WHvArm64IcEmulationModeGicV3,
+ .GicV3Parameters = {
+ .GicdBaseAddress = s->iomem_dist.addr,
+ .GicPpiPerformanceMonitorsInterrupt = VIRTUAL_PMU_IRQ,
+ .GicPpiOverflowInterruptFromCntv = ARCH_TIMER_VIRT_IRQ
+ }
+ };
+ hr = whp_dispatch.WHvSetPartitionProperty(
+ whpx->partition,
+ WHvPartitionPropertyCodeArm64IcParameters,
+ ¶m,
+ sizeof(WHV_ARM64_IC_PARAMETERS));
+ if (FAILED(hr)) {
+ error_report("WHPX: failed to set up interrupt controller");
+ }
+*/
+ for (i = 0; i < s->num_cpu; i++) {
+ CPUState *cpu_state = qemu_get_cpu(i);
+ ARMCPU *cpu = ARM_CPU(cpu_state);
+ WHV_REGISTER_VALUE val = {.Reg64 = 0x080A0000 + (0x20000 * i)};
+ whpx_set_reg(cpu_state, WHvArm64RegisterGicrBaseGpa, val);
+ define_arm_cp_regs(cpu, gicv3_cpuif_reginfo);
+ printf("addr: 0x%lld\n", s->redist_regions[0].iomem.addr);
+ }
+
+ if (s->maint_irq) {
+ error_setg(errp, "Nested virtualisation not currently supported by WHPX.");
+ return;
+ }
+}
+
+static void whpx_gicv3_class_init(ObjectClass *klass, const void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
+ ARMGICv3CommonClass *agcc = ARM_GICV3_COMMON_CLASS(klass);
+ WHPXARMGICv3Class *kgc = WHPX_GICV3_CLASS(klass);
+
+ agcc->pre_save = whpx_gicv3_get;
+ agcc->post_load = whpx_gicv3_put;
+
+ device_class_set_parent_realize(dc, whpx_gicv3_realize,
+ &kgc->parent_realize);
+ resettable_class_set_parent_phases(rc, NULL, whpx_gicv3_reset_hold, NULL,
+ &kgc->parent_phases);
+}
+
+static const TypeInfo whpx_arm_gicv3_info = {
+ .name = TYPE_WHPX_GICV3,
+ .parent = TYPE_ARM_GICV3_COMMON,
+ .instance_size = sizeof(GICv3State),
+ .class_init = whpx_gicv3_class_init,
+ .class_size = sizeof(WHPXARMGICv3Class),
+};
+
+static void whpx_gicv3_register_types(void)
+{
+ type_register_static(&whpx_arm_gicv3_info);
+}
+
+type_init(whpx_gicv3_register_types)
diff --git a/hw/intc/meson.build b/hw/intc/meson.build
index 3137521a4a..9342ff0e2c 100644
--- a/hw/intc/meson.build
+++ b/hw/intc/meson.build
@@ -41,6 +41,7 @@ specific_ss.add(when: 'CONFIG_APIC', if_true: files('apic.c', 'apic_common.c'))
specific_ss.add(when: 'CONFIG_ARM_GIC', if_true: files('arm_gicv3_cpuif_common.c'))
specific_ss.add(when: 'CONFIG_ARM_GICV3', if_true: files('arm_gicv3_cpuif.c'))
specific_ss.add(when: 'CONFIG_ARM_GIC_KVM', if_true: files('arm_gic_kvm.c'))
+specific_ss.add(when: 'CONFIG_WHPX', if_true: files('arm_gicv3_whpx.c'))
specific_ss.add(when: ['CONFIG_ARM_GIC_KVM', 'TARGET_AARCH64'], if_true: files('arm_gicv3_kvm.c', 'arm_gicv3_its_kvm.c'))
specific_ss.add(when: 'CONFIG_ARM_V7M', if_true: files('armv7m_nvic.c'))
specific_ss.add(when: 'CONFIG_GRLIB', if_true: files('grlib_irqmp.c'))
--
2.39.5 (Apple Git-154)
^ permalink raw reply related [flat|nested] 26+ messages in thread
* [RFC 5/9] hw/virt: make Qemu aware that WHPX has a vGICv3
2025-07-31 5:27 [RFC 0/9] WHPX support for Arm Mohamed Mediouni
` (3 preceding siblings ...)
2025-07-31 5:27 ` [RFC 4/9] whpx: interrupt controller support Mohamed Mediouni
@ 2025-07-31 5:27 ` Mohamed Mediouni
2025-07-31 8:35 ` Philippe Mathieu-Daudé
2025-07-31 5:27 ` [RFC 6/9] hw: intc: arm_gicv3_common: add whpx Mohamed Mediouni
` (4 subsequent siblings)
9 siblings, 1 reply; 26+ messages in thread
From: Mohamed Mediouni @ 2025-07-31 5:27 UTC (permalink / raw)
To: qemu-devel
Cc: Daniel P. Berrangé, Paolo Bonzini, Sunil Muthuswamy,
Marc-André Lureau, Philippe Mathieu-Daudé,
Peter Maydell, qemu-arm, Mohamed Mediouni
WHPX is a vGICv3-only target without vGICv2 or user-mode irqchip
support.
Signed-off-by: Mohamed Mediouni <mohamed@unpredictable.fr>
---
hw/arm/virt.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index ef6be3660f..4996c2075e 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -49,6 +49,7 @@
#include "system/tcg.h"
#include "system/kvm.h"
#include "system/hvf.h"
+#include "system/whpx.h"
#include "system/qtest.h"
#include "hw/loader.h"
#include "qapi/error.h"
@@ -2058,6 +2059,8 @@ static void finalize_gic_version(VirtMachineState *vms)
/* KVM w/o kernel irqchip can only deal with GICv2 */
gics_supported |= VIRT_GIC_VERSION_2_MASK;
accel_name = "KVM with kernel-irqchip=off";
+ } else if (whpx_enabled()) {
+ gics_supported |= VIRT_GIC_VERSION_3_MASK;
} else if (tcg_enabled() || hvf_enabled() || qtest_enabled()) {
gics_supported |= VIRT_GIC_VERSION_2_MASK;
if (module_object_class_by_name("arm-gicv3")) {
--
2.39.5 (Apple Git-154)
^ permalink raw reply related [flat|nested] 26+ messages in thread
* [RFC 6/9] hw: intc: arm_gicv3_common: add whpx
2025-07-31 5:27 [RFC 0/9] WHPX support for Arm Mohamed Mediouni
` (4 preceding siblings ...)
2025-07-31 5:27 ` [RFC 5/9] hw/virt: make Qemu aware that WHPX has a vGICv3 Mohamed Mediouni
@ 2025-07-31 5:27 ` Mohamed Mediouni
2025-07-31 8:33 ` Philippe Mathieu-Daudé
2025-07-31 5:27 ` [RFC 7/9] whpx: add arm64 support Mohamed Mediouni
` (3 subsequent siblings)
9 siblings, 1 reply; 26+ messages in thread
From: Mohamed Mediouni @ 2025-07-31 5:27 UTC (permalink / raw)
To: qemu-devel
Cc: Daniel P. Berrangé, Paolo Bonzini, Sunil Muthuswamy,
Marc-André Lureau, Philippe Mathieu-Daudé,
Peter Maydell, qemu-arm, Mohamed Mediouni
Redirect to the platform-specific vGICv3.
Signed-off-by: Mohamed Mediouni <mohamed@unpredictable.fr>
---
hw/intc/arm_gicv3_common.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/hw/intc/arm_gicv3_common.c b/hw/intc/arm_gicv3_common.c
index e438d8c042..a83b075517 100644
--- a/hw/intc/arm_gicv3_common.c
+++ b/hw/intc/arm_gicv3_common.c
@@ -32,6 +32,7 @@
#include "gicv3_internal.h"
#include "hw/arm/linux-boot-if.h"
#include "system/kvm.h"
+#include "system/whpx.h"
static void gicv3_gicd_no_migration_shift_bug_post_load(GICv3State *cs)
@@ -662,6 +663,8 @@ const char *gicv3_class_name(void)
{
if (kvm_irqchip_in_kernel()) {
return "kvm-arm-gicv3";
+ } else if (whpx_enabled()) {
+ return "whpx-arm-gicv3";
} else {
if (kvm_enabled()) {
error_report("Userspace GICv3 is not supported with KVM");
--
2.39.5 (Apple Git-154)
^ permalink raw reply related [flat|nested] 26+ messages in thread
* [RFC 7/9] whpx: add arm64 support
2025-07-31 5:27 [RFC 0/9] WHPX support for Arm Mohamed Mediouni
` (5 preceding siblings ...)
2025-07-31 5:27 ` [RFC 6/9] hw: intc: arm_gicv3_common: add whpx Mohamed Mediouni
@ 2025-07-31 5:27 ` Mohamed Mediouni
2025-08-01 6:03 ` Richard Henderson
2025-07-31 5:27 ` [RFC 8/9] whpx: copy over memory tracking logic from hvf Mohamed Mediouni
` (2 subsequent siblings)
9 siblings, 1 reply; 26+ messages in thread
From: Mohamed Mediouni @ 2025-07-31 5:27 UTC (permalink / raw)
To: qemu-devel
Cc: Daniel P. Berrangé, Paolo Bonzini, Sunil Muthuswamy,
Marc-André Lureau, Philippe Mathieu-Daudé,
Peter Maydell, qemu-arm, Mohamed Mediouni
Signed-off-by: Mohamed Mediouni <mohamed@unpredictable.fr>
---
accel/whpx/whpx-common.c | 1 +
meson.build | 5 +-
target/arm/meson.build | 1 +
target/arm/whpx/meson.build | 3 +
target/arm/whpx/whpx-all.c | 744 ++++++++++++++++++++++++++++++++++++
5 files changed, 752 insertions(+), 2 deletions(-)
create mode 100644 target/arm/whpx/meson.build
create mode 100644 target/arm/whpx/whpx-all.c
diff --git a/accel/whpx/whpx-common.c b/accel/whpx/whpx-common.c
index 43d0200afd..58fd6287ed 100644
--- a/accel/whpx/whpx-common.c
+++ b/accel/whpx/whpx-common.c
@@ -15,6 +15,7 @@
#include "gdbstub/helpers.h"
#include "qemu/accel.h"
#include "accel/accel-ops.h"
+#include "system/memory.h"
#include "system/whpx.h"
#include "system/cpus.h"
#include "system/runstate.h"
diff --git a/meson.build b/meson.build
index e53cd5b413..f5823e3c86 100644
--- a/meson.build
+++ b/meson.build
@@ -327,7 +327,8 @@ accelerator_targets += { 'CONFIG_XEN': xen_targets }
if cpu == 'aarch64'
accelerator_targets += {
- 'CONFIG_HVF': ['aarch64-softmmu']
+ 'CONFIG_HVF': ['aarch64-softmmu'],
+ 'CONFIG_WHPX': ['aarch64-softmmu']
}
elif cpu == 'x86_64'
accelerator_targets += {
@@ -885,7 +886,7 @@ if get_option('kvm').allowed() and host_os == 'linux'
accelerators += 'CONFIG_KVM'
endif
if get_option('whpx').allowed() and host_os == 'windows'
- if get_option('whpx').enabled() and host_machine.cpu() != 'x86_64'
+ if get_option('whpx').enabled() and host_machine.cpu() in ['x86_64', 'aarch64']
error('WHPX requires 64-bit host')
elif cc.has_header('winhvplatform.h', required: get_option('whpx')) and \
cc.has_header('winhvemulation.h', required: get_option('whpx'))
diff --git a/target/arm/meson.build b/target/arm/meson.build
index 07d9271aa4..e28bd3f8e2 100644
--- a/target/arm/meson.build
+++ b/target/arm/meson.build
@@ -46,6 +46,7 @@ arm_common_system_ss.add(files(
))
subdir('hvf')
+subdir('whpx')
if 'CONFIG_TCG' in config_all_accel
subdir('tcg')
diff --git a/target/arm/whpx/meson.build b/target/arm/whpx/meson.build
new file mode 100644
index 0000000000..1de2ef0283
--- /dev/null
+++ b/target/arm/whpx/meson.build
@@ -0,0 +1,3 @@
+arm_system_ss.add(when: 'CONFIG_WHPX', if_true: files(
+ 'whpx-all.c',
+))
diff --git a/target/arm/whpx/whpx-all.c b/target/arm/whpx/whpx-all.c
new file mode 100644
index 0000000000..5769d3497e
--- /dev/null
+++ b/target/arm/whpx/whpx-all.c
@@ -0,0 +1,744 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * QEMU Windows Hypervisor Platform accelerator (WHPX)
+ *
+ * Copyright (c) 2025 Mohamed Mediouni
+ *
+ */
+
+#include "qemu/osdep.h"
+#include "cpu.h"
+#include "system/address-spaces.h"
+#include "system/ioport.h"
+#include "gdbstub/helpers.h"
+#include "qemu/accel.h"
+#include "accel/accel-ops.h"
+#include "system/whpx.h"
+#include "system/cpus.h"
+#include "system/runstate.h"
+#include "qemu/main-loop.h"
+#include "hw/boards.h"
+#include "qemu/error-report.h"
+#include "qapi/error.h"
+#include "qapi/qapi-types-common.h"
+#include "qapi/qapi-visit-common.h"
+#include "migration/blocker.h"
+#include "accel/accel-cpu-target.h"
+#include <winerror.h>
+
+#include "syndrome.h"
+#include "cpu.h"
+#include "cpregs.h"
+#include "internals.h"
+
+#include "system/whpx-internal.h"
+#include "system/whpx-accel-ops.h"
+#include "system/whpx-all.h"
+#include "system/whpx-common.h"
+#include "hw/arm/bsa.h"
+
+#include <winhvplatform.h>
+#include <winhvplatformdefs.h>
+
+struct whpx_reg_match {
+ WHV_REGISTER_NAME reg;
+ uint64_t offset;
+};
+
+static const struct whpx_reg_match whpx_reg_match[] = {
+ { WHvArm64RegisterX0, offsetof(CPUARMState, xregs[0]) },
+ { WHvArm64RegisterX1, offsetof(CPUARMState, xregs[1]) },
+ { WHvArm64RegisterX2, offsetof(CPUARMState, xregs[2]) },
+ { WHvArm64RegisterX3, offsetof(CPUARMState, xregs[3]) },
+ { WHvArm64RegisterX4, offsetof(CPUARMState, xregs[4]) },
+ { WHvArm64RegisterX5, offsetof(CPUARMState, xregs[5]) },
+ { WHvArm64RegisterX6, offsetof(CPUARMState, xregs[6]) },
+ { WHvArm64RegisterX7, offsetof(CPUARMState, xregs[7]) },
+ { WHvArm64RegisterX8, offsetof(CPUARMState, xregs[8]) },
+ { WHvArm64RegisterX9, offsetof(CPUARMState, xregs[9]) },
+ { WHvArm64RegisterX10, offsetof(CPUARMState, xregs[10]) },
+ { WHvArm64RegisterX11, offsetof(CPUARMState, xregs[11]) },
+ { WHvArm64RegisterX12, offsetof(CPUARMState, xregs[12]) },
+ { WHvArm64RegisterX13, offsetof(CPUARMState, xregs[13]) },
+ { WHvArm64RegisterX14, offsetof(CPUARMState, xregs[14]) },
+ { WHvArm64RegisterX15, offsetof(CPUARMState, xregs[15]) },
+ { WHvArm64RegisterX16, offsetof(CPUARMState, xregs[16]) },
+ { WHvArm64RegisterX17, offsetof(CPUARMState, xregs[17]) },
+ { WHvArm64RegisterX18, offsetof(CPUARMState, xregs[18]) },
+ { WHvArm64RegisterX19, offsetof(CPUARMState, xregs[19]) },
+ { WHvArm64RegisterX20, offsetof(CPUARMState, xregs[20]) },
+ { WHvArm64RegisterX21, offsetof(CPUARMState, xregs[21]) },
+ { WHvArm64RegisterX22, offsetof(CPUARMState, xregs[22]) },
+ { WHvArm64RegisterX23, offsetof(CPUARMState, xregs[23]) },
+ { WHvArm64RegisterX24, offsetof(CPUARMState, xregs[24]) },
+ { WHvArm64RegisterX25, offsetof(CPUARMState, xregs[25]) },
+ { WHvArm64RegisterX26, offsetof(CPUARMState, xregs[26]) },
+ { WHvArm64RegisterX27, offsetof(CPUARMState, xregs[27]) },
+ { WHvArm64RegisterX28, offsetof(CPUARMState, xregs[28]) },
+ { WHvArm64RegisterFp, offsetof(CPUARMState, xregs[29]) },
+ { WHvArm64RegisterLr, offsetof(CPUARMState, xregs[30]) },
+ { WHvArm64RegisterPc, offsetof(CPUARMState, pc) },
+};
+
+static const struct whpx_reg_match whpx_fpreg_match[] = {
+ { WHvArm64RegisterQ0, offsetof(CPUARMState, vfp.zregs[0]) },
+ { WHvArm64RegisterQ1, offsetof(CPUARMState, vfp.zregs[1]) },
+ { WHvArm64RegisterQ2, offsetof(CPUARMState, vfp.zregs[2]) },
+ { WHvArm64RegisterQ3, offsetof(CPUARMState, vfp.zregs[3]) },
+ { WHvArm64RegisterQ4, offsetof(CPUARMState, vfp.zregs[4]) },
+ { WHvArm64RegisterQ5, offsetof(CPUARMState, vfp.zregs[5]) },
+ { WHvArm64RegisterQ6, offsetof(CPUARMState, vfp.zregs[6]) },
+ { WHvArm64RegisterQ7, offsetof(CPUARMState, vfp.zregs[7]) },
+ { WHvArm64RegisterQ8, offsetof(CPUARMState, vfp.zregs[8]) },
+ { WHvArm64RegisterQ9, offsetof(CPUARMState, vfp.zregs[9]) },
+ { WHvArm64RegisterQ10, offsetof(CPUARMState, vfp.zregs[10]) },
+ { WHvArm64RegisterQ11, offsetof(CPUARMState, vfp.zregs[11]) },
+ { WHvArm64RegisterQ12, offsetof(CPUARMState, vfp.zregs[12]) },
+ { WHvArm64RegisterQ13, offsetof(CPUARMState, vfp.zregs[13]) },
+ { WHvArm64RegisterQ14, offsetof(CPUARMState, vfp.zregs[14]) },
+ { WHvArm64RegisterQ15, offsetof(CPUARMState, vfp.zregs[15]) },
+ { WHvArm64RegisterQ16, offsetof(CPUARMState, vfp.zregs[16]) },
+ { WHvArm64RegisterQ17, offsetof(CPUARMState, vfp.zregs[17]) },
+ { WHvArm64RegisterQ18, offsetof(CPUARMState, vfp.zregs[18]) },
+ { WHvArm64RegisterQ19, offsetof(CPUARMState, vfp.zregs[19]) },
+ { WHvArm64RegisterQ20, offsetof(CPUARMState, vfp.zregs[20]) },
+ { WHvArm64RegisterQ21, offsetof(CPUARMState, vfp.zregs[21]) },
+ { WHvArm64RegisterQ22, offsetof(CPUARMState, vfp.zregs[22]) },
+ { WHvArm64RegisterQ23, offsetof(CPUARMState, vfp.zregs[23]) },
+ { WHvArm64RegisterQ24, offsetof(CPUARMState, vfp.zregs[24]) },
+ { WHvArm64RegisterQ25, offsetof(CPUARMState, vfp.zregs[25]) },
+ { WHvArm64RegisterQ26, offsetof(CPUARMState, vfp.zregs[26]) },
+ { WHvArm64RegisterQ27, offsetof(CPUARMState, vfp.zregs[27]) },
+ { WHvArm64RegisterQ28, offsetof(CPUARMState, vfp.zregs[28]) },
+ { WHvArm64RegisterQ29, offsetof(CPUARMState, vfp.zregs[29]) },
+ { WHvArm64RegisterQ30, offsetof(CPUARMState, vfp.zregs[30]) },
+ { WHvArm64RegisterQ31, offsetof(CPUARMState, vfp.zregs[31]) },
+};
+
+#define WHPX_SYSREG(crn, crm, op0, op1, op2) \
+ ENCODE_AA64_CP_REG(CP_REG_ARM64_SYSREG_CP, crn, crm, op0, op1, op2)
+
+struct whpx_sreg_match {
+ WHV_REGISTER_NAME reg;
+ uint32_t key;
+ uint32_t cp_idx;
+};
+
+static struct whpx_sreg_match whpx_sreg_match[] = {
+/* { WHvArm64RegisterDbgbvr0El1, WHPX_SYSREG(0, 0, 2, 0, 4) },
+ { WHvArm64RegisterDbgbcr0El1, WHPX_SYSREG(0, 0, 2, 0, 5) },
+ { WHvArm64RegisterDbgwvr0El1, WHPX_SYSREG(0, 0, 2, 0, 6) },
+ { WHvArm64RegisterDbgwcr0El1, WHPX_SYSREG(0, 0, 2, 0, 7) },
+
+ { WHvArm64RegisterDbgbvr0El1, WHPX_SYSREG(0, 1, 2, 0, 4) },
+ { WHvArm64RegisterDbgbcr0El1, WHPX_SYSREG(0, 1, 2, 0, 5) },
+ { WHvArm64RegisterDbgwvr0El1, WHPX_SYSREG(0, 1, 2, 0, 6) },
+ { WHvArm64RegisterDbgwcr0El1, WHPX_SYSREG(0, 1, 2, 0, 7) },
+
+ { WHvArm64RegisterDbgbvr2El1, WHPX_SYSREG(0, 2, 2, 0, 4) },
+ { WHvArm64RegisterDbgbcr2El1, WHPX_SYSREG(0, 2, 2, 0, 5) },
+ { WHvArm64RegisterDbgwvr2El1, WHPX_SYSREG(0, 2, 2, 0, 6) },
+ { WHvArm64RegisterDbgwcr2El1, WHPX_SYSREG(0, 2, 2, 0, 7) },
+
+ { WHvArm64RegisterDbgbvr3El1, WHPX_SYSREG(0, 3, 2, 0, 4) },
+ { WHvArm64RegisterDbgbcr3El1, WHPX_SYSREG(0, 3, 2, 0, 5) },
+ { WHvArm64RegisterDbgwvr3El1, WHPX_SYSREG(0, 3, 2, 0, 6) },
+ { WHvArm64RegisterDbgwcr3El1, WHPX_SYSREG(0, 3, 2, 0, 7) },
+
+ { WHvArm64RegisterDbgbvr4El1, WHPX_SYSREG(0, 4, 2, 0, 4) },
+ { WHvArm64RegisterDbgbcr4El1, WHPX_SYSREG(0, 4, 2, 0, 5) },
+ { WHvArm64RegisterDbgwvr4El1, WHPX_SYSREG(0, 4, 2, 0, 6) },
+ { WHvArm64RegisterDbgwcr4El1, WHPX_SYSREG(0, 4, 2, 0, 7) },
+
+ { WHvArm64RegisterDbgbvr5El1, WHPX_SYSREG(0, 5, 2, 0, 4) },
+ { WHvArm64RegisterDbgbcr5El1, WHPX_SYSREG(0, 5, 2, 0, 5) },
+ { WHvArm64RegisterDbgwvr5El1, WHPX_SYSREG(0, 5, 2, 0, 6) },
+ { WHvArm64RegisterDbgwcr5El1, WHPX_SYSREG(0, 5, 2, 0, 7) },
+
+ { WHvArm64RegisterDbgbvr6El1, WHPX_SYSREG(0, 6, 2, 0, 4) },
+ { WHvArm64RegisterDbgbcr6El1, WHPX_SYSREG(0, 6, 2, 0, 5) },
+ { WHvArm64RegisterDbgwvr6El1, WHPX_SYSREG(0, 6, 2, 0, 6) },
+ { WHvArm64RegisterDbgwcr6El1, WHPX_SYSREG(0, 6, 2, 0, 7) },
+
+ { WHvArm64RegisterDbgbvr7El1, WHPX_SYSREG(0, 7, 2, 0, 4) },
+ { WHvArm64RegisterDbgbcr7El1, WHPX_SYSREG(0, 7, 2, 0, 5) },
+ { WHvArm64RegisterDbgwvr7El1, WHPX_SYSREG(0, 7, 2, 0, 6) },
+ { WHvArm64RegisterDbgwcr7El1, WHPX_SYSREG(0, 7, 2, 0, 7) },
+
+ { WHvArm64RegisterDbgbvr8El1, WHPX_SYSREG(0, 8, 2, 0, 4) },
+ { WHvArm64RegisterDbgbcr8El1, WHPX_SYSREG(0, 8, 2, 0, 5) },
+ { WHvArm64RegisterDbgwvr8El1, WHPX_SYSREG(0, 8, 2, 0, 6) },
+ { WHvArm64RegisterDbgwcr8El1, WHPX_SYSREG(0, 8, 2, 0, 7) },
+
+ { WHvArm64RegisterDbgbvr9El1, WHPX_SYSREG(0, 9, 2, 0, 4) },
+ { WHvArm64RegisterDbgbcr9El1, WHPX_SYSREG(0, 9, 2, 0, 5) },
+ { WHvArm64RegisterDbgwvr9El1, WHPX_SYSREG(0, 9, 2, 0, 6) },
+ { WHvArm64RegisterDbgwcr9El1, WHPX_SYSREG(0, 9, 2, 0, 7) },
+
+ { WHvArm64RegisterDbgbvr10El1, WHPX_SYSREG(0, 10, 2, 0, 4) },
+ { WHvArm64RegisterDbgbcr10El1, WHPX_SYSREG(0, 10, 2, 0, 5) },
+ { WHvArm64RegisterDbgwvr10El1, WHPX_SYSREG(0, 10, 2, 0, 6) },
+ { WHvArm64RegisterDbgwcr10El1, WHPX_SYSREG(0, 10, 2, 0, 7) },
+
+ { WHvArm64RegisterDbgbvr11El1, WHPX_SYSREG(0, 11, 2, 0, 4) },
+ { WHvArm64RegisterDbgbcr11El1, WHPX_SYSREG(0, 11, 2, 0, 5) },
+ { WHvArm64RegisterDbgwvr11El1, WHPX_SYSREG(0, 11, 2, 0, 6) },
+ { WHvArm64RegisterDbgwcr11El1, WHPX_SYSREG(0, 11, 2, 0, 7) },
+
+ { WHvArm64RegisterDbgbvr12El1, WHPX_SYSREG(0, 12, 2, 0, 4) },
+ { WHvArm64RegisterDbgbcr12El1, WHPX_SYSREG(0, 12, 2, 0, 5) },
+ { WHvArm64RegisterDbgwvr12El1, WHPX_SYSREG(0, 12, 2, 0, 6) },
+ { WHvArm64RegisterDbgwcr12El1, WHPX_SYSREG(0, 12, 2, 0, 7) },
+
+ { WHvArm64RegisterDbgbvr13El1, WHPX_SYSREG(0, 13, 2, 0, 4) },
+ { WHvArm64RegisterDbgbcr13El1, WHPX_SYSREG(0, 13, 2, 0, 5) },
+ { WHvArm64RegisterDbgwvr13El1, WHPX_SYSREG(0, 13, 2, 0, 6) },
+ { WHvArm64RegisterDbgwcr13El1, WHPX_SYSREG(0, 13, 2, 0, 7) },
+
+ { WHvArm64RegisterDbgbvr14El1, WHPX_SYSREG(0, 14, 2, 0, 4) },
+ { WHvArm64RegisterDbgbcr14El1, WHPX_SYSREG(0, 14, 2, 0, 5) },
+ { WHvArm64RegisterDbgwvr14El1, WHPX_SYSREG(0, 14, 2, 0, 6) },
+ { WHvArm64RegisterDbgwcr14El1, WHPX_SYSREG(0, 14, 2, 0, 7) },
+
+ { WHvArm64RegisterDbgbvr15El1, WHPX_SYSREG(0, 15, 2, 0, 4) },
+ { WHvArm64RegisterDbgbcr15El1, WHPX_SYSREG(0, 15, 2, 0, 5) },
+ { WHvArm64RegisterDbgwvr15El1, WHPX_SYSREG(0, 15, 2, 0, 6) },
+ { WHvArm64RegisterDbgwcr15El1, WHPX_SYSREG(0, 15, 2, 0, 7) },
+*/
+#ifdef SYNC_NO_RAW_REGS
+ /*
+ * The registers below are manually synced on init because they are
+ * marked as NO_RAW. We still list them to make number space sync easier.
+ */
+ { WHvArm64RegisterMidrEl1, WHPX_SYSREG(0, 0, 3, 0, 0) },
+ { WHvArm64RegisterMpidrEl1, WHPX_SYSREG(0, 0, 3, 0, 5) },
+ { WHvArm64RegisterIdPfr0El1, WHPX_SYSREG(0, 4, 3, 0, 0) },
+#endif
+// { WHvArm64RegisterIdPfr1El1, WHPX_SYSREG(0, 4, 3, 0, 1) },
+// { WHvArm64RegisterIdDfr0El1, WHPX_SYSREG(0, 5, 3, 0, 0) },
+// { WHvArm64RegisterIdAa64Dfr1El1, WHPX_SYSREG(0, 5, 3, 0, 1) },
+// { WHvArm64RegisterIdAa64Isar0El1, WHPX_SYSREG(0, 6, 3, 0, 0) },
+// { WHvArm64RegisterIdAa64Isar1El1, WHPX_SYSREG(0, 6, 3, 0, 1) },
+#ifdef SYNC_NO_MMFR0
+ /* We keep the hardware MMFR0 around. HW limits are there anyway */
+ { WHvArm64RegisterIdAa64Mmfr0El1, WHPX_SYSREG(0, 7, 3, 0, 0) },
+#endif
+// { WHvArm64RegisterIdAa64Mmfr1El1, WHPX_SYSREG(0, 7, 3, 0, 1) },
+// { WHvArm64RegisterIdAa64Mmfr2El1, WHPX_SYSREG(0, 7, 3, 0, 2) },
+// { WHvArm64RegisterIdAa64Mmfr3El1, WHPX_SYSREG(0, 7, 3, 0, 3) },
+
+ { WHvArm64RegisterMdscrEl1, WHPX_SYSREG(0, 2, 2, 0, 2) },
+ { WHvArm64RegisterSctlrEl1, WHPX_SYSREG(1, 0, 3, 0, 0) },
+ { WHvArm64RegisterCpacrEl1, WHPX_SYSREG(1, 0, 3, 0, 2) },
+ { WHvArm64RegisterTtbr0El1, WHPX_SYSREG(2, 0, 3, 0, 0) },
+ { WHvArm64RegisterTtbr1El1, WHPX_SYSREG(2, 0, 3, 0, 1) },
+ { WHvArm64RegisterTcrEl1, WHPX_SYSREG(2, 0, 3, 0, 2) },
+
+ { WHvArm64RegisterApiAKeyLoEl1, WHPX_SYSREG(2, 1, 3, 0, 0) },
+ { WHvArm64RegisterApiAKeyHiEl1, WHPX_SYSREG(2, 1, 3, 0, 1) },
+ { WHvArm64RegisterApiBKeyLoEl1, WHPX_SYSREG(2, 1, 3, 0, 2) },
+ { WHvArm64RegisterApiBKeyHiEl1, WHPX_SYSREG(2, 1, 3, 0, 3) },
+ { WHvArm64RegisterApdAKeyLoEl1, WHPX_SYSREG(2, 2, 3, 0, 0) },
+ { WHvArm64RegisterApdAKeyHiEl1, WHPX_SYSREG(2, 2, 3, 0, 1) },
+ { WHvArm64RegisterApdBKeyLoEl1, WHPX_SYSREG(2, 2, 3, 0, 2) },
+ { WHvArm64RegisterApdBKeyHiEl1, WHPX_SYSREG(2, 2, 3, 0, 3) },
+ { WHvArm64RegisterApgAKeyLoEl1, WHPX_SYSREG(2, 3, 3, 0, 0) },
+ { WHvArm64RegisterApgAKeyHiEl1, WHPX_SYSREG(2, 3, 3, 0, 1) },
+
+ { WHvArm64RegisterSpsrEl1, WHPX_SYSREG(4, 0, 3, 0, 0) },
+ { WHvArm64RegisterElrEl1, WHPX_SYSREG(4, 0, 3, 0, 1) },
+ { WHvArm64RegisterSpEl1, WHPX_SYSREG(4, 1, 3, 0, 0) },
+ { WHvArm64RegisterEsrEl1, WHPX_SYSREG(5, 2, 3, 0, 0) },
+ { WHvArm64RegisterFarEl1, WHPX_SYSREG(6, 0, 3, 0, 0) },
+ { WHvArm64RegisterParEl1, WHPX_SYSREG(7, 4, 3, 0, 0) },
+ { WHvArm64RegisterMairEl1, WHPX_SYSREG(10, 2, 3, 0, 0) },
+ { WHvArm64RegisterVbarEl1, WHPX_SYSREG(12, 0, 3, 0, 0) },
+ { WHvArm64RegisterContextidrEl1, WHPX_SYSREG(13, 0, 3, 0, 1) },
+ { WHvArm64RegisterTpidrEl1, WHPX_SYSREG(13, 0, 3, 0, 4) },
+ { WHvArm64RegisterCntkctlEl1, WHPX_SYSREG(14, 1, 3, 0, 0) },
+ { WHvArm64RegisterCsselrEl1, WHPX_SYSREG(0, 0, 3, 2, 0) },
+ { WHvArm64RegisterTpidrEl0, WHPX_SYSREG(13, 0, 3, 3, 2) },
+ { WHvArm64RegisterTpidrroEl0, WHPX_SYSREG(13, 0, 3, 3, 3) },
+ { WHvArm64RegisterCntvCtlEl0, WHPX_SYSREG(14, 3, 3, 3, 1) },
+ { WHvArm64RegisterCntvCvalEl0, WHPX_SYSREG(14, 3, 3, 3, 2) },
+ { WHvArm64RegisterSpEl1, WHPX_SYSREG(4, 1, 3, 4, 0) },
+};
+
+static void flush_cpu_state(CPUState *cpu)
+{
+ if (cpu->vcpu_dirty) {
+ whpx_set_registers(cpu, WHPX_SET_RUNTIME_STATE);
+ cpu->vcpu_dirty = false;
+ }
+}
+
+static void whpx_get_reg(CPUState *cpu, WHV_REGISTER_NAME reg, WHV_REGISTER_VALUE* val)
+{
+ struct whpx_state *whpx = &whpx_global;
+ HRESULT hr;
+
+ flush_cpu_state(cpu);
+
+ hr = whp_dispatch.WHvGetVirtualProcessorRegisters(whpx->partition, cpu->cpu_index,
+ ®, 1, val);
+
+ if (FAILED(hr)) {
+ error_report("WHPX: Failed to get register %08x, hr=%08lx", reg, hr);
+ }
+}
+
+static void whpx_set_reg(CPUState *cpu, WHV_REGISTER_NAME reg, WHV_REGISTER_VALUE val)
+{
+ struct whpx_state *whpx = &whpx_global;
+ HRESULT hr;
+ hr = whp_dispatch.WHvSetVirtualProcessorRegisters(whpx->partition, cpu->cpu_index,
+ ®, 1, &val);
+
+ if (FAILED(hr)) {
+ error_report("WHPX: Failed to set register %08x, hr=%08lx", reg, hr);
+ }
+}
+
+static uint64_t whpx_get_gp_reg(CPUState *cpu, int rt)
+{
+ if (rt >= 31) {
+ return 0;
+ }
+ WHV_REGISTER_NAME reg = WHvArm64RegisterX0 + rt;
+ WHV_REGISTER_VALUE val;
+ whpx_get_reg(cpu, reg, &val);
+
+ return val.Reg64;
+}
+
+static void whpx_set_gp_reg(CPUState *cpu, int rt, uint64_t val)
+{
+ if (rt >= 31) {
+ abort();
+ }
+ WHV_REGISTER_NAME reg = WHvArm64RegisterX0 + rt;
+ WHV_REGISTER_VALUE reg_val = {.Reg64 = val};
+
+ whpx_set_reg(cpu, reg, reg_val);
+}
+
+static int whpx_handle_mmio(CPUState *cpu, WHV_MEMORY_ACCESS_CONTEXT *ctx)
+{
+ uint64_t syndrome = ctx->Syndrome;
+
+ bool isv = syndrome & ARM_EL_ISV;
+ bool iswrite = (syndrome >> 6) & 1;
+ bool sse = (syndrome >> 21) & 1;
+ uint32_t sas = (syndrome >> 22) & 3;
+ uint32_t len = 1 << sas;
+ uint32_t srt = (syndrome >> 16) & 0x1f;
+ uint32_t cm = (syndrome >> 8) & 0x1;
+ uint64_t val = 0;
+
+ if (cm) {
+ /* We don't cache MMIO regions */
+ abort();
+ return 0;
+ }
+
+ assert(isv);
+
+ if (iswrite) {
+ val = whpx_get_gp_reg(cpu, srt);
+ address_space_write(&address_space_memory,
+ ctx->Gpa,
+ MEMTXATTRS_UNSPECIFIED, &val, len);
+ } else {
+ address_space_read(&address_space_memory,
+ ctx->Gpa,
+ MEMTXATTRS_UNSPECIFIED, &val, len);
+ if (sse) {
+ val = sextract64(val, 0, len * 8);
+ }
+ whpx_set_gp_reg(cpu, srt, val);
+ }
+
+ return 0;
+}
+
+int whpx_vcpu_run(CPUState *cpu) {
+ HRESULT hr;
+ struct whpx_state *whpx = &whpx_global;
+ AccelCPUState *vcpu = cpu->accel;
+ int ret;
+
+
+ g_assert(bql_locked());
+
+ if (whpx->running_cpus++ == 0) {
+ ret = whpx_first_vcpu_starting(cpu);
+ if (ret != 0) {
+ return ret;
+ }
+ }
+
+ bql_unlock();
+
+
+ cpu_exec_start(cpu);
+ do {
+ bool advance_pc = false;
+ if (cpu->vcpu_dirty) {
+ whpx_set_registers(cpu, WHPX_SET_RUNTIME_STATE);
+ cpu->vcpu_dirty = false;
+ }
+
+ if (qatomic_read(&cpu->exit_request)) {
+ whpx_vcpu_kick(cpu);
+ }
+
+ hr = whp_dispatch.WHvRunVirtualProcessor(
+ whpx->partition, cpu->cpu_index,
+ &vcpu->exit_ctx, sizeof(vcpu->exit_ctx));
+
+ if (FAILED(hr)) {
+ error_report("WHPX: Failed to exec a virtual processor,"
+ " hr=%08lx", hr);
+ ret = -1;
+ break;
+ }
+
+ switch (vcpu->exit_ctx.ExitReason) {
+ case WHvRunVpExitReasonGpaIntercept:
+ case WHvRunVpExitReasonUnmappedGpa:
+ advance_pc = true;
+ ret = whpx_handle_mmio(cpu, &vcpu->exit_ctx.MemoryAccess);
+ break;
+ case WHvRunVpExitReasonCanceled:
+ cpu->exception_index = EXCP_INTERRUPT;
+ ret = 1;
+ break;
+ case WHvRunVpExitReasonNone:
+ case WHvRunVpExitReasonUnrecoverableException:
+ case WHvRunVpExitReasonInvalidVpRegisterValue:
+ case WHvRunVpExitReasonUnsupportedFeature:
+ default:
+ error_report("WHPX: Unexpected VP exit code 0x%08x",
+ vcpu->exit_ctx.ExitReason);
+ whpx_get_registers(cpu);
+ bql_lock();
+ qemu_system_guest_panicked(cpu_get_crash_info(cpu));
+ bql_unlock();
+ break;
+ }
+ if (advance_pc) {
+ WHV_REGISTER_VALUE pc;
+
+ flush_cpu_state(cpu);
+
+ whpx_get_reg(cpu, WHvArm64RegisterPc, &pc);
+ pc.Reg64 += 4;
+ whpx_set_reg(cpu, WHvArm64RegisterPc, pc);
+ }
+ } while (!ret);
+
+ cpu_exec_end(cpu);
+
+ bql_lock();
+ current_cpu = cpu;
+
+ if (--whpx->running_cpus == 0) {
+ whpx_last_vcpu_stopping(cpu);
+ }
+
+ qatomic_set(&cpu->exit_request, false);
+
+ return ret < 0;
+}
+
+void whpx_get_registers(CPUState *cpu) {
+ ARMCPU *arm_cpu = ARM_CPU(cpu);
+ CPUARMState *env = &arm_cpu->env;
+ WHV_REGISTER_VALUE val;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(whpx_reg_match); i++) {
+ whpx_get_reg(cpu, whpx_reg_match[i].reg, &val);
+ *(uint64_t *)((void *)env + whpx_reg_match[i].offset) = val.Reg64;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(whpx_fpreg_match); i++) {
+ whpx_get_reg(cpu, whpx_reg_match[i].reg, &val);
+ memcpy((void *)env + whpx_fpreg_match[i].offset, &val, sizeof(val.Reg128));
+ }
+
+ whpx_get_reg(cpu, WHvArm64RegisterPc, &val);
+ env->pc = val.Reg64;
+
+ whpx_get_reg(cpu, WHvArm64RegisterFpcr, &val);
+ vfp_set_fpcr(env, val.Reg32);
+
+ whpx_get_reg(cpu, WHvArm64RegisterFpsr, &val);
+ vfp_set_fpsr(env, val.Reg32);
+
+ whpx_get_reg(cpu, WHvArm64RegisterPstate, &val);
+ pstate_write(env, val.Reg32);
+
+ for (i = 0; i < ARRAY_SIZE(whpx_sreg_match); i++) {
+ if (whpx_sreg_match[i].cp_idx == -1) {
+ continue;
+ }
+
+ whpx_get_reg(cpu, whpx_sreg_match[i].reg, &val);
+
+ arm_cpu->cpreg_values[whpx_sreg_match[i].cp_idx] = val.Reg64;
+ }
+ assert(write_list_to_cpustate(arm_cpu));
+
+ aarch64_restore_sp(env, arm_current_el(env));
+}
+
+void whpx_set_registers(CPUState *cpu, int level) {
+ ARMCPU *arm_cpu = ARM_CPU(cpu);
+ CPUARMState *env = &arm_cpu->env;
+ WHV_REGISTER_VALUE val;
+ int i;
+
+ assert(cpu_is_stopped(cpu) || qemu_cpu_is_self(cpu));
+
+ for (i = 0; i < ARRAY_SIZE(whpx_reg_match); i++) {
+ val.Reg64 = *(uint64_t *)((void *)env + whpx_reg_match[i].offset);
+ whpx_set_reg(cpu, whpx_reg_match[i].reg, val);
+ }
+
+ for (i = 0; i < ARRAY_SIZE(whpx_fpreg_match); i++) {
+ memcpy(&val.Reg128, (void *)env + whpx_fpreg_match[i].offset, sizeof(val.Reg128));
+ whpx_set_reg(cpu, whpx_reg_match[i].reg, val);
+ }
+
+ val.Reg64 = env->pc;
+ whpx_set_reg(cpu, WHvArm64RegisterPc, val);
+
+ val.Reg32 = vfp_get_fpcr(env);
+ whpx_set_reg(cpu, WHvArm64RegisterFpcr, val);
+ val.Reg32 = vfp_get_fpsr(env);
+ whpx_set_reg(cpu, WHvArm64RegisterFpsr, val);
+ val.Reg32 = pstate_read(env);
+ whpx_set_reg(cpu, WHvArm64RegisterPstate, val);
+
+ aarch64_save_sp(env, arm_current_el(env));
+
+ assert(write_cpustate_to_list(arm_cpu, false));
+ for (i = 0; i < ARRAY_SIZE(whpx_sreg_match); i++) {
+ if (whpx_sreg_match[i].cp_idx == -1) {
+ continue;
+ }
+
+ val.Reg64 = arm_cpu->cpreg_values[whpx_sreg_match[i].cp_idx];
+ whpx_set_reg(cpu, whpx_sreg_match[i].reg, val);
+ }
+}
+
+static uint32_t max_vcpu_index;
+
+static void whpx_cpu_update_state(void *opaque, bool running, RunState state)
+{
+ //CPUARMState *env = opaque;
+
+ if (running) {
+ //env->tsc_valid = false;
+ }
+}
+
+int whpx_init_vcpu(CPUState *cpu) {
+ HRESULT hr;
+ struct whpx_state *whpx = &whpx_global;
+ AccelCPUState *vcpu = NULL;
+ ARMCPU *arm_cpu = ARM_CPU(cpu);
+ CPUARMState *env = &arm_cpu->env;
+ int ret;
+
+ uint32_t sregs_match_len = ARRAY_SIZE(whpx_sreg_match);
+ uint32_t sregs_cnt = 0;
+ WHV_REGISTER_VALUE val;
+ int i;
+
+ vcpu = g_new0(AccelCPUState, 1);
+
+ hr = whp_dispatch.WHvCreateVirtualProcessor(
+ whpx->partition, cpu->cpu_index, 0);
+ if (FAILED(hr)) {
+ error_report("WHPX: Failed to create a virtual processor,"
+ " hr=%08lx", hr);
+ ret = -EINVAL;
+ goto error;
+ }
+
+ /* Assumption that CNTFRQ_EL0 is the same between the VMM and the partition. */
+ asm volatile("mrs %0, cntfrq_el0" : "=r"(arm_cpu->gt_cntfrq_hz));
+
+ cpu->vcpu_dirty = true;
+ cpu->accel = vcpu;
+ max_vcpu_index = max(max_vcpu_index, cpu->cpu_index);
+ qemu_add_vm_change_state_handler(whpx_cpu_update_state, env);
+
+ env->aarch64 = true;
+
+ /* Allocate enough space for our sysreg sync */
+ arm_cpu->cpreg_indexes = g_renew(uint64_t, arm_cpu->cpreg_indexes,
+ sregs_match_len);
+ arm_cpu->cpreg_values = g_renew(uint64_t, arm_cpu->cpreg_values,
+ sregs_match_len);
+ arm_cpu->cpreg_vmstate_indexes = g_renew(uint64_t,
+ arm_cpu->cpreg_vmstate_indexes,
+ sregs_match_len);
+ arm_cpu->cpreg_vmstate_values = g_renew(uint64_t,
+ arm_cpu->cpreg_vmstate_values,
+ sregs_match_len);
+
+ memset(arm_cpu->cpreg_values, 0, sregs_match_len * sizeof(uint64_t));
+
+ /* Populate cp list for all known sysregs */
+ for (i = 0; i < sregs_match_len; i++) {
+ const ARMCPRegInfo *ri;
+ uint32_t key = whpx_sreg_match[i].key;
+
+ ri = get_arm_cp_reginfo(arm_cpu->cp_regs, key);
+ if (ri) {
+ assert(!(ri->type & ARM_CP_NO_RAW));
+ whpx_sreg_match[i].cp_idx = sregs_cnt;
+ arm_cpu->cpreg_indexes[sregs_cnt++] = cpreg_to_kvm_id(key);
+ } else {
+ whpx_sreg_match[i].cp_idx = -1;
+ }
+ }
+ arm_cpu->cpreg_array_len = sregs_cnt;
+ arm_cpu->cpreg_vmstate_array_len = sregs_cnt;
+
+ assert(write_cpustate_to_list(arm_cpu, false));
+
+ /* Set CP_NO_RAW system registers on init */
+ val.Reg64 = arm_cpu->midr;
+ whpx_set_reg(cpu, WHvArm64RegisterMidrEl1,
+ val);
+ return 0;
+
+error:
+ g_free(vcpu);
+
+ return ret;
+
+}
+
+int whpx_accel_init(AccelState *as, MachineState *ms) {
+ struct whpx_state *whpx;
+ int ret;
+ HRESULT hr;
+ WHV_CAPABILITY whpx_cap;
+ UINT32 whpx_cap_size;
+ WHV_PARTITION_PROPERTY prop;
+ WHV_CAPABILITY_FEATURES features = {0};
+
+ whpx = &whpx_global;
+
+ if (!init_whp_dispatch()) {
+ ret = -ENOSYS;
+ goto error;
+ }
+
+ whpx->mem_quota = ms->ram_size;
+
+ hr = whp_dispatch.WHvGetCapability(
+ WHvCapabilityCodeHypervisorPresent, &whpx_cap,
+ sizeof(whpx_cap), &whpx_cap_size);
+ if (FAILED(hr) || !whpx_cap.HypervisorPresent) {
+ error_report("WHPX: No accelerator found, hr=%08lx", hr);
+ ret = -ENOSPC;
+ goto error;
+ }
+
+ hr = whp_dispatch.WHvGetCapability(
+ WHvCapabilityCodeFeatures, &features, sizeof(features), NULL);
+ if (FAILED(hr)) {
+ error_report("WHPX: Failed to query capabilities, hr=%08lx", hr);
+ ret = -EINVAL;
+ goto error;
+ }
+
+ if (!features.Arm64Support) {
+ error_report("WHPX: host OS exposing pre-release WHPX implementation. "
+ "Please update your operating system to at least build 26100.3915");
+ ret = -EINVAL;
+ goto error;
+ }
+
+ hr = whp_dispatch.WHvCreatePartition(&whpx->partition);
+ if (FAILED(hr)) {
+ error_report("WHPX: Failed to create partition, hr=%08lx", hr);
+ ret = -EINVAL;
+ goto error;
+ }
+
+ memset(&prop, 0, sizeof(WHV_PARTITION_PROPERTY));
+ prop.ProcessorCount = ms->smp.cpus;
+ hr = whp_dispatch.WHvSetPartitionProperty(
+ whpx->partition,
+ WHvPartitionPropertyCodeProcessorCount,
+ &prop,
+ sizeof(WHV_PARTITION_PROPERTY));
+
+ if (FAILED(hr)) {
+ error_report("WHPX: Failed to set partition processor count to %u,"
+ " hr=%08lx", prop.ProcessorCount, hr);
+ ret = -EINVAL;
+ goto error;
+ }
+
+ if (!whpx->kernel_irqchip_allowed) {
+ error_report("WHPX: on Arm, only kernel-irqchip=on is currently supported");
+ ret = -EINVAL;
+ goto error;
+ }
+
+ memset(&prop, 0, sizeof(WHV_PARTITION_PROPERTY));
+
+ //prop.Arm64IcParameters =
+ WHV_ARM64_IC_PARAMETERS ic_params = {
+ .EmulationMode = WHvArm64IcEmulationModeGicV3,
+ .GicV3Parameters = {
+ .GicdBaseAddress = 0x08000000,
+ .GitsTranslaterBaseAddress = 0x08080000,
+ .GicLpiIntIdBits = 1,
+ .GicPpiPerformanceMonitorsInterrupt = VIRTUAL_PMU_IRQ,
+ .GicPpiOverflowInterruptFromCntv = ARCH_TIMER_VIRT_IRQ
+ }
+ };
+ prop.Arm64IcParameters = ic_params;
+
+ hr = whp_dispatch.WHvSetPartitionProperty(
+ whpx->partition,
+ WHvPartitionPropertyCodeArm64IcParameters,
+ &prop,
+ sizeof(WHV_PARTITION_PROPERTY));
+ if (FAILED(hr)) {
+ error_report("WHPX: Failed to enable GICv3 interrupt controller, hr=%08lx", hr);
+ ret = -EINVAL;
+ goto error;
+ }
+
+ hr = whp_dispatch.WHvSetupPartition(whpx->partition);
+ if (FAILED(hr)) {
+ error_report("WHPX: Failed to setup partition, hr=%08lx", hr);
+ ret = -EINVAL;
+ goto error;
+ }
+
+ whpx_memory_init();
+
+ printf("Windows Hypervisor Platform accelerator is operational\n");
+ return 0;
+
+error:
+
+ if (NULL != whpx->partition) {
+ whp_dispatch.WHvDeletePartition(whpx->partition);
+ whpx->partition = NULL;
+ }
+
+ return ret;
+}
\ No newline at end of file
--
2.39.5 (Apple Git-154)
^ permalink raw reply related [flat|nested] 26+ messages in thread
* [RFC 8/9] whpx: copy over memory tracking logic from hvf
2025-07-31 5:27 [RFC 0/9] WHPX support for Arm Mohamed Mediouni
` (6 preceding siblings ...)
2025-07-31 5:27 ` [RFC 7/9] whpx: add arm64 support Mohamed Mediouni
@ 2025-07-31 5:27 ` Mohamed Mediouni
2025-07-31 5:27 ` [RFC 9/9] target/arm: cpu: mark WHPX as supporting PSCI 1.1 Mohamed Mediouni
2025-08-01 1:15 ` [RFC 0/9] WHPX support for Arm Pierrick Bouvier
9 siblings, 0 replies; 26+ messages in thread
From: Mohamed Mediouni @ 2025-07-31 5:27 UTC (permalink / raw)
To: qemu-devel
Cc: Daniel P. Berrangé, Paolo Bonzini, Sunil Muthuswamy,
Marc-André Lureau, Philippe Mathieu-Daudé,
Peter Maydell, qemu-arm, Mohamed Mediouni
This allows edk2 to work, although u-boot is still not functional.
Signed-off-by: Mohamed Mediouni <mohamed@unpredictable.fr>
---
accel/whpx/whpx-common.c | 198 ++++++++++++++++++++++++++++-----------
1 file changed, 144 insertions(+), 54 deletions(-)
diff --git a/accel/whpx/whpx-common.c b/accel/whpx/whpx-common.c
index 58fd6287ed..19415767e4 100644
--- a/accel/whpx/whpx-common.c
+++ b/accel/whpx/whpx-common.c
@@ -265,89 +265,171 @@ void whpx_vcpu_kick(CPUState *cpu)
* Memory support.
*/
-static void whpx_update_mapping(hwaddr start_pa, ram_addr_t size,
- void *host_va, int add, int rom,
- const char *name)
+ /* hvf_slot flags */
+#define WHPX_SLOT_LOG (1 << 0)
+typedef struct whpx_slot {
+ uint64_t start;
+ uint64_t size;
+ uint8_t *mem;
+ int slot_id;
+ uint32_t flags;
+ MemoryRegion *region;
+} whpx_slot;
+
+typedef struct WHPXState {
+ whpx_slot slots[32];
+ int num_slots;
+} WHPXState;
+
+ WHPXState *whpx_state;
+
+ struct mac_slot {
+ int present;
+ uint64_t size;
+ uint64_t gpa_start;
+ uint64_t gva;
+};
+
+struct mac_slot mac_slots[32];
+
+static int do_hvf_set_memory(whpx_slot *slot, WHV_MAP_GPA_RANGE_FLAGS flags)
{
struct whpx_state *whpx = &whpx_global;
+ struct mac_slot *macslot;
HRESULT hr;
- /*
- if (add) {
- printf("WHPX: ADD PA:%p Size:%p, Host:%p, %s, '%s'\n",
- (void*)start_pa, (void*)size, host_va,
- (rom ? "ROM" : "RAM"), name);
- } else {
- printf("WHPX: DEL PA:%p Size:%p, Host:%p, '%s'\n",
- (void*)start_pa, (void*)size, host_va, name);
+ macslot = &mac_slots[slot->slot_id];
+
+ if (macslot->present) {
+ if (macslot->size != slot->size) {
+ macslot->present = 0;
+ hr = whp_dispatch.WHvUnmapGpaRange(whpx->partition, macslot->gpa_start, macslot->size);
+ if (FAILED(hr)) {
+ abort();
+ }
+ }
}
- */
-
- if (add) {
- hr = whp_dispatch.WHvMapGpaRange(whpx->partition,
- host_va,
- start_pa,
- size,
- (WHvMapGpaRangeFlagRead |
- WHvMapGpaRangeFlagExecute |
- (rom ? 0 : WHvMapGpaRangeFlagWrite)));
- } else {
- hr = whp_dispatch.WHvUnmapGpaRange(whpx->partition,
- start_pa,
- size);
+
+ if (!slot->size) {
+ return 0;
}
- if (FAILED(hr)) {
- error_report("WHPX: Failed to %s GPA range '%s' PA:%p, Size:%p bytes,"
- " Host:%p, hr=%08lx",
- (add ? "MAP" : "UNMAP"), name,
- (void *)(uintptr_t)start_pa, (void *)size, host_va, hr);
+ macslot->present = 1;
+ macslot->gpa_start = slot->start;
+ macslot->size = slot->size;
+ hr = whp_dispatch.WHvMapGpaRange(whpx->partition, slot->mem, slot->start, slot->size, flags);
+ return 0;
+}
+
+static whpx_slot *whpx_find_overlap_slot(uint64_t start, uint64_t size)
+{
+ whpx_slot *slot;
+ int x;
+ for (x = 0; x < whpx_state->num_slots; ++x) {
+ slot = &whpx_state->slots[x];
+ if (slot->size && start < (slot->start + slot->size) &&
+ (start + size) > slot->start) {
+ return slot;
+ }
}
+ return NULL;
}
-static void whpx_process_section(MemoryRegionSection *section, int add)
+static void whpx_set_phys_mem(MemoryRegionSection *section, bool add)
{
- MemoryRegion *mr = section->mr;
- hwaddr start_pa = section->offset_within_address_space;
- ram_addr_t size = int128_get64(section->size);
- unsigned int delta;
- uint64_t host_va;
+ whpx_slot *mem;
+ MemoryRegion *area = section->mr;
+ bool writable = !area->readonly && !area->rom_device;
+ WHV_MAP_GPA_RANGE_FLAGS flags;
+ uint64_t page_size = qemu_real_host_page_size();
+
+ if (!memory_region_is_ram(area)) {
+ if (writable) {
+ return;
+ } else if (!memory_region_is_romd(area)) {
+ /*
+ * If the memory device is not in romd_mode, then we actually want
+ * to remove the hvf memory slot so all accesses will trap.
+ */
+ add = false;
+ }
+ }
- if (!memory_region_is_ram(mr)) {
- return;
+ if (!QEMU_IS_ALIGNED(int128_get64(section->size), page_size) ||
+ !QEMU_IS_ALIGNED(section->offset_within_address_space, page_size)) {
+ /* Not page aligned, so we can not map as RAM */
+ add = false;
}
- delta = qemu_real_host_page_size() - (start_pa & ~qemu_real_host_page_mask());
- delta &= ~qemu_real_host_page_mask();
- if (delta > size) {
- return;
+ mem = whpx_find_overlap_slot(
+ section->offset_within_address_space,
+ int128_get64(section->size));
+
+ if (mem && add) {
+ if (mem->size == int128_get64(section->size) &&
+ mem->start == section->offset_within_address_space &&
+ mem->mem == (memory_region_get_ram_ptr(area) +
+ section->offset_within_region)) {
+ return; /* Same region was attempted to register, go away. */
+ }
+ }
+
+ /* Region needs to be reset. set the size to 0 and remap it. */
+ if (mem) {
+ mem->size = 0;
+ if (do_hvf_set_memory(mem, 0)) {
+ error_report("Failed to reset overlapping slot");
+ abort();
+ }
}
- start_pa += delta;
- size -= delta;
- size &= qemu_real_host_page_mask();
- if (!size || (start_pa & ~qemu_real_host_page_mask())) {
+
+ if (!add) {
return;
}
- host_va = (uintptr_t)memory_region_get_ram_ptr(mr)
- + section->offset_within_region + delta;
+ if (area->readonly ||
+ (!memory_region_is_ram(area) && memory_region_is_romd(area))) {
+ flags = WHvMapGpaRangeFlagRead | WHvMapGpaRangeFlagExecute;
+ } else {
+ flags = WHvMapGpaRangeFlagRead | WHvMapGpaRangeFlagWrite | WHvMapGpaRangeFlagExecute;
+ }
+
+ /* Now make a new slot. */
+ int x;
+
+ for (x = 0; x < whpx_state->num_slots; ++x) {
+ mem = &whpx_state->slots[x];
+ if (!mem->size) {
+ break;
+ }
+ }
+
+ if (x == whpx_state->num_slots) {
+ error_report("No free slots");
+ abort();
+ }
- whpx_update_mapping(start_pa, size, (void *)(uintptr_t)host_va, add,
- memory_region_is_rom(mr), mr->name);
+ mem->size = int128_get64(section->size);
+ mem->mem = memory_region_get_ram_ptr(area) + section->offset_within_region;
+ mem->start = section->offset_within_address_space;
+ mem->region = area;
+
+ if (do_hvf_set_memory(mem, flags)) {
+ error_report("Error registering new memory slot");
+ abort();
+ }
}
static void whpx_region_add(MemoryListener *listener,
MemoryRegionSection *section)
{
- memory_region_ref(section->mr);
- whpx_process_section(section, 1);
+ whpx_set_phys_mem(section, true);
}
static void whpx_region_del(MemoryListener *listener,
MemoryRegionSection *section)
{
- whpx_process_section(section, 0);
- memory_region_unref(section->mr);
+ whpx_set_phys_mem(section, false);
}
static void whpx_transaction_begin(MemoryListener *listener)
@@ -531,6 +613,14 @@ static void whpx_accel_instance_init(Object *obj)
memset(whpx, 0, sizeof(struct whpx_state));
/* Turn on kernel-irqchip, by default */
whpx->kernel_irqchip_allowed = true;
+
+ int x;
+ whpx_state = malloc(sizeof(WHPXState));
+ whpx_state->num_slots = ARRAY_SIZE(whpx_state->slots);
+ for (x = 0; x < whpx_state->num_slots; ++x) {
+ whpx_state->slots[x].size = 0;
+ whpx_state->slots[x].slot_id = x;
+ }
}
static const TypeInfo whpx_accel_type = {
--
2.39.5 (Apple Git-154)
^ permalink raw reply related [flat|nested] 26+ messages in thread
* [RFC 9/9] target/arm: cpu: mark WHPX as supporting PSCI 1.1
2025-07-31 5:27 [RFC 0/9] WHPX support for Arm Mohamed Mediouni
` (7 preceding siblings ...)
2025-07-31 5:27 ` [RFC 8/9] whpx: copy over memory tracking logic from hvf Mohamed Mediouni
@ 2025-07-31 5:27 ` Mohamed Mediouni
2025-08-01 1:15 ` [RFC 0/9] WHPX support for Arm Pierrick Bouvier
9 siblings, 0 replies; 26+ messages in thread
From: Mohamed Mediouni @ 2025-07-31 5:27 UTC (permalink / raw)
To: qemu-devel
Cc: Daniel P. Berrangé, Paolo Bonzini, Sunil Muthuswamy,
Marc-André Lureau, Philippe Mathieu-Daudé,
Peter Maydell, qemu-arm, Mohamed Mediouni
Signed-off-by: Mohamed Mediouni <mohamed@unpredictable.fr>
---
target/arm/cpu.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
index e2b2337399..3b69c9786a 100644
--- a/target/arm/cpu.c
+++ b/target/arm/cpu.c
@@ -23,6 +23,7 @@
#include "qemu/timer.h"
#include "qemu/log.h"
#include "exec/page-vary.h"
+#include "system/whpx.h"
#include "target/arm/idau.h"
#include "qemu/module.h"
#include "qapi/error.h"
@@ -1496,7 +1497,7 @@ static void arm_cpu_initfn(Object *obj)
cpu->psci_version = QEMU_PSCI_VERSION_0_1; /* By default assume PSCI v0.1 */
cpu->kvm_target = QEMU_KVM_ARM_TARGET_NONE;
- if (tcg_enabled() || hvf_enabled()) {
+ if (tcg_enabled() || hvf_enabled() || whpx_enabled()) {
/* TCG and HVF implement PSCI 1.1 */
cpu->psci_version = QEMU_PSCI_VERSION_1_1;
}
--
2.39.5 (Apple Git-154)
^ permalink raw reply related [flat|nested] 26+ messages in thread
* Re: [RFC 1/9] whpx: Move around files before introducing AArch64 support
2025-07-31 5:27 ` [RFC 1/9] whpx: Move around files before introducing AArch64 support Mohamed Mediouni
@ 2025-07-31 8:27 ` Philippe Mathieu-Daudé
2025-08-01 5:44 ` Richard Henderson
1 sibling, 0 replies; 26+ messages in thread
From: Philippe Mathieu-Daudé @ 2025-07-31 8:27 UTC (permalink / raw)
To: Mohamed Mediouni, qemu-devel
Cc: Daniel P. Berrangé, Paolo Bonzini, Sunil Muthuswamy,
Marc-André Lureau, Peter Maydell, qemu-arm
Hi Mohamed,
On 31/7/25 07:27, Mohamed Mediouni wrote:
> Switch to a design where we can share whpx code between x86 and AArch64 when it makes sense to do so.
>
> Signed-off-by: Mohamed Mediouni <mohamed@unpredictable.fr>
> ---
> accel/meson.build | 1 +
> accel/whpx/meson.build | 6 ++++++
> {target/i386 => accel}/whpx/whpx-accel-ops.c | 8 ++++++--
> {target/i386/whpx => include/system}/whpx-accel-ops.h | 0
> {target/i386/whpx => include/system}/whpx-internal.h | 7 ++++++-
> target/i386/whpx/meson.build | 1 -
> target/i386/whpx/whpx-all.c | 4 ++--
> 7 files changed, 21 insertions(+), 6 deletions(-)
> create mode 100644 accel/whpx/meson.build
> rename {target/i386 => accel}/whpx/whpx-accel-ops.c (96%)
> rename {target/i386/whpx => include/system}/whpx-accel-ops.h (100%)
> rename {target/i386/whpx => include/system}/whpx-internal.h (98%)
Missing updates in MAINTAINERS, otherwise:
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [RFC 3/9] whpx: common: use whpx_cpu_instance_init on x86 only
2025-07-31 5:27 ` [RFC 3/9] whpx: common: use whpx_cpu_instance_init on x86 only Mohamed Mediouni
@ 2025-07-31 8:30 ` Philippe Mathieu-Daudé
0 siblings, 0 replies; 26+ messages in thread
From: Philippe Mathieu-Daudé @ 2025-07-31 8:30 UTC (permalink / raw)
To: Mohamed Mediouni, qemu-devel
Cc: Daniel P. Berrangé, Paolo Bonzini, Sunil Muthuswamy,
Marc-André Lureau, Peter Maydell, qemu-arm
Hi Mohamed,
On 31/7/25 07:27, Mohamed Mediouni wrote:
> We aren't using it on arm64.
>
> Signed-off-by: Mohamed Mediouni <mohamed@unpredictable.fr>
> ---
> accel/whpx/whpx-common.c | 3 ++-
> 1 file changed, 2 insertions(+), 1 deletion(-)
>
> diff --git a/accel/whpx/whpx-common.c b/accel/whpx/whpx-common.c
> index 0b23deb7c4..43d0200afd 100644
> --- a/accel/whpx/whpx-common.c
> +++ b/accel/whpx/whpx-common.c
> @@ -486,9 +486,10 @@ static void whpx_set_kernel_irqchip(Object *obj, Visitor *v,
>
> static void whpx_cpu_accel_class_init(ObjectClass *oc, const void *data)
> {
> +#ifdef __x86_64__
> AccelCPUClass *acc = ACCEL_CPU_CLASS(oc);
> -
> acc->cpu_instance_init = whpx_cpu_instance_init;
> +#endif
> }
I'd rather keep whpx-*common* without any #ifdef'ry: add hooks
when architecture-specific code need to be handled, and add empty
arch stub when nothing to be done there (preferably with a comment
in the stub).
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [RFC 6/9] hw: intc: arm_gicv3_common: add whpx
2025-07-31 5:27 ` [RFC 6/9] hw: intc: arm_gicv3_common: add whpx Mohamed Mediouni
@ 2025-07-31 8:33 ` Philippe Mathieu-Daudé
0 siblings, 0 replies; 26+ messages in thread
From: Philippe Mathieu-Daudé @ 2025-07-31 8:33 UTC (permalink / raw)
To: Mohamed Mediouni, qemu-devel
Cc: Daniel P. Berrangé, Paolo Bonzini, Sunil Muthuswamy,
Marc-André Lureau, Peter Maydell, qemu-arm
On 31/7/25 07:27, Mohamed Mediouni wrote:
> Redirect to the platform-specific vGICv3.
>
> Signed-off-by: Mohamed Mediouni <mohamed@unpredictable.fr>
> ---
> hw/intc/arm_gicv3_common.c | 3 +++
> 1 file changed, 3 insertions(+)
>
> diff --git a/hw/intc/arm_gicv3_common.c b/hw/intc/arm_gicv3_common.c
> index e438d8c042..a83b075517 100644
> --- a/hw/intc/arm_gicv3_common.c
> +++ b/hw/intc/arm_gicv3_common.c
> @@ -32,6 +32,7 @@
> #include "gicv3_internal.h"
> #include "hw/arm/linux-boot-if.h"
> #include "system/kvm.h"
> +#include "system/whpx.h"
>
>
> static void gicv3_gicd_no_migration_shift_bug_post_load(GICv3State *cs)
> @@ -662,6 +663,8 @@ const char *gicv3_class_name(void)
> {
> if (kvm_irqchip_in_kernel()) {
> return "kvm-arm-gicv3";
> + } else if (whpx_enabled()) {
> + return "whpx-arm-gicv3";
While you follow a pre-existing pattern, here I'd prefer to use
TYPE_WHPX_GICV3 (after defining it in hw/intc/arm_gicv3_common.h).
> } else {
> if (kvm_enabled()) {
> error_report("Userspace GICv3 is not supported with KVM");
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [RFC 5/9] hw/virt: make Qemu aware that WHPX has a vGICv3
2025-07-31 5:27 ` [RFC 5/9] hw/virt: make Qemu aware that WHPX has a vGICv3 Mohamed Mediouni
@ 2025-07-31 8:35 ` Philippe Mathieu-Daudé
2025-07-31 14:47 ` Mohamed Mediouni
0 siblings, 1 reply; 26+ messages in thread
From: Philippe Mathieu-Daudé @ 2025-07-31 8:35 UTC (permalink / raw)
To: Mohamed Mediouni, qemu-devel
Cc: Daniel P. Berrangé, Paolo Bonzini, Sunil Muthuswamy,
Marc-André Lureau, Peter Maydell, qemu-arm
On 31/7/25 07:27, Mohamed Mediouni wrote:
> WHPX is a vGICv3-only target without vGICv2 or user-mode irqchip
> support.
>
> Signed-off-by: Mohamed Mediouni <mohamed@unpredictable.fr>
> ---
> hw/arm/virt.c | 3 +++
> 1 file changed, 3 insertions(+)
>
> diff --git a/hw/arm/virt.c b/hw/arm/virt.c
> index ef6be3660f..4996c2075e 100644
> --- a/hw/arm/virt.c
> +++ b/hw/arm/virt.c
> @@ -49,6 +49,7 @@
> #include "system/tcg.h"
> #include "system/kvm.h"
> #include "system/hvf.h"
> +#include "system/whpx.h"
> #include "system/qtest.h"
> #include "hw/loader.h"
> #include "qapi/error.h"
> @@ -2058,6 +2059,8 @@ static void finalize_gic_version(VirtMachineState *vms)
> /* KVM w/o kernel irqchip can only deal with GICv2 */
> gics_supported |= VIRT_GIC_VERSION_2_MASK;
> accel_name = "KVM with kernel-irqchip=off";
> + } else if (whpx_enabled()) {
> + gics_supported |= VIRT_GIC_VERSION_3_MASK;
> } else if (tcg_enabled() || hvf_enabled() || qtest_enabled()) {
> gics_supported |= VIRT_GIC_VERSION_2_MASK;
> if (module_object_class_by_name("arm-gicv3")) {
Should this patch be the last of the series to avoid breaking
git bisectability?
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [RFC 5/9] hw/virt: make Qemu aware that WHPX has a vGICv3
2025-07-31 8:35 ` Philippe Mathieu-Daudé
@ 2025-07-31 14:47 ` Mohamed Mediouni
0 siblings, 0 replies; 26+ messages in thread
From: Mohamed Mediouni @ 2025-07-31 14:47 UTC (permalink / raw)
To: Philippe Mathieu-Daudé
Cc: qemu-devel, "Daniel P. Berrangé", Paolo Bonzini,
Sunil Muthuswamy, Marc-André Lureau, Peter Maydell, qemu-arm
[-- Attachment #1: Type: text/plain, Size: 1459 bytes --]
> On 31. Jul 2025, at 10:35, Philippe Mathieu-Daudé <philmd@linaro.org> wrote:
>
> On 31/7/25 07:27, Mohamed Mediouni wrote:
>> WHPX is a vGICv3-only target without vGICv2 or user-mode irqchip
>> support.
>> Signed-off-by: Mohamed Mediouni <mohamed@unpredictable.fr>
>> ---
>> hw/arm/virt.c | 3 +++
>> 1 file changed, 3 insertions(+)
>> diff --git a/hw/arm/virt.c b/hw/arm/virt.c
>> index ef6be3660f..4996c2075e 100644
>> --- a/hw/arm/virt.c
>> +++ b/hw/arm/virt.c
>> @@ -49,6 +49,7 @@
>> #include "system/tcg.h"
>> #include "system/kvm.h"
>> #include "system/hvf.h"
>> +#include "system/whpx.h"
>> #include "system/qtest.h"
>> #include "hw/loader.h"
>> #include "qapi/error.h"
>> @@ -2058,6 +2059,8 @@ static void finalize_gic_version(VirtMachineState *vms)
>> /* KVM w/o kernel irqchip can only deal with GICv2 */
>> gics_supported |= VIRT_GIC_VERSION_2_MASK;
>> accel_name = "KVM with kernel-irqchip=off";
>> + } else if (whpx_enabled()) {
>> + gics_supported |= VIRT_GIC_VERSION_3_MASK;
>> } else if (tcg_enabled() || hvf_enabled() || qtest_enabled()) {
>> gics_supported |= VIRT_GIC_VERSION_2_MASK;
>> if (module_object_class_by_name("arm-gicv3")) {
>
> Should this patch be the last of the series to avoid breaking
> git bisectability?
Not needed for buildability I think, as system/whpx.h was already present before because of x86 whpx
[-- Attachment #2: Type: text/html, Size: 4641 bytes --]
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [RFC 0/9] WHPX support for Arm
2025-07-31 5:27 [RFC 0/9] WHPX support for Arm Mohamed Mediouni
` (8 preceding siblings ...)
2025-07-31 5:27 ` [RFC 9/9] target/arm: cpu: mark WHPX as supporting PSCI 1.1 Mohamed Mediouni
@ 2025-08-01 1:15 ` Pierrick Bouvier
2025-08-01 12:43 ` Mohamed Mediouni
9 siblings, 1 reply; 26+ messages in thread
From: Pierrick Bouvier @ 2025-08-01 1:15 UTC (permalink / raw)
To: Mohamed Mediouni, qemu-devel
Cc: Daniel P. Berrangé, Paolo Bonzini, Sunil Muthuswamy,
Marc-André Lureau, Philippe Mathieu-Daudé,
Peter Maydell, qemu-arm
Hi Mohamed,
On 7/30/25 10:27 PM, Mohamed Mediouni wrote:
> This one took way longer for me to publish than I should have.
>
> There are a number of lingering bugs in this one including u-boot not working.
>
> Interrupt controller save/restore is entirely missing in this RFC, and some other state
> bits are likely still missing too.
>
> ITS not blocked by default yet, remember to use its=off when testing this series.
> You might also want the GICv3 + GICv2m support patch as part of the HVF vGIC patch series, which
> is not duplicated here.
>
> PS: on both this and HVF, interrupt controller initialisation needs to be done early so I ended
> up with hardcoded addresses. Wonder if the right way to go might be to defer virt and vCPU initialisation
> until late in the process post-gic_realize...
>
> Other than that, this boots both EDK2 and Linux in SMP, when using devicetree or ACPI.
>
thanks for posting this, that's an exciting series!
I applied it on top of your other series
(20250728134114.77545-1-mohamed@unpredictable.fr) and solved the conflicts.
However, it would really help if you could push that exact branch
somewhere, so people can easily pull it and try.
I'm fine if you want to duplicate gic patches in this series as well.
I tried to direct boot a kernel (6.15 defconfig) and ran into this error
[1]:
$ ./build/qemu-system-aarch64.exe -M virt,its=off -cpu cortex-a76 -m 2G
-nographic -accel whpx -kernel out/Image.gz out/host.ext4
Could you please share your exact command line?
Does it work with direct kernel boot also?
Kind Regards,
Pierrick
[1] Error when booting:
[ 1.381525] Internal error: Oops: 0000000096000002 [#1] SMP
[ 1.458060] Modules linked in:
[ 1.461172] CPU: 0 UID: 0 PID: 1 Comm: swapper/0 Not tainted
6.15.0-00001-g7797e43a2520 #1 PREEMPT
[ 1.470502] Hardware name: linux,dummy-virt (DT)
[ 1.475102] pstate: 204000c5 (nzCv daIF +PAN -UAO -TCO -DIT -SSBS
BTYPE=--)
[ 1.482023] pc : pci_generic_config_read+0x38/0xb8
[ 1.486970] lr : pci_generic_config_read+0x24/0xb8
[ 1.491734] sp : ffff80008000b940
[ 1.495079] x29: ffff80008000b940 x28: 0000000000000000 x27:
ffffbb8fe13f00ec
[ 1.502473] x26: ffffbb8fe14f9060 x25: ffffbb8fe14f9078 x24:
ffffbb8fe1c99990
[ 1.509564] x23: 0000000000000000 x22: ffff80008000b9f4 x21:
ffff574c83b7c000
[ 1.516636] x20: ffff80008000b964 x19: 0000000000000004 x18:
0000000000000006
[ 1.523722] x17: 6666666666666666 x16: 6678302d30303030 x15:
0720072007200720
[ 1.531583] x14: 0720072007200720 x13: 0720072007200720 x12:
ffffbb8fe1736838
[ 1.539094] x11: 0000000000000058 x10: 0000000000000018 x9 :
ffffbb8fe1736838
[ 1.546212] x8 : 00000000000000c5 x7 : ffffbb8fe187ff40 x6 :
00000000000000ff
[ 1.553370] x5 : 0000000000000000 x4 : 0000000000000000 x3 :
ffff800090000000
[ 1.560676] x2 : 0000000000000000 x1 : 0000000000000000 x0 :
ffff800090000000
[ 1.567890] Call trace:
[ 1.570509] pci_generic_config_read+0x38/0xb8 (P)
[ 1.575362] pci_bus_read_config_dword+0x80/0xe4
[ 1.580231] pci_bus_generic_read_dev_vendor_id+0x30/0x164
[ 1.586164] pci_scan_single_device+0x118/0x18c
[ 1.590912] pci_scan_slot+0x58/0x214
[ 1.594782] pci_scan_child_bus_extend+0x40/0x234
[ 1.599606] pci_scan_root_bus_bridge+0x64/0xd8
[ 1.604194] pci_host_probe+0x30/0xec
[ 1.607972] pci_host_common_probe+0x128/0x1c0
[ 1.612430] platform_probe+0x68/0xdc
[ 1.616220] really_probe+0xbc/0x2c0
[ 1.619814] __driver_probe_device+0x78/0x120
[ 1.624435] driver_probe_device+0x3c/0x154
[ 1.628620] __driver_attach+0x90/0x1a0
[ 1.632509] bus_for_each_dev+0x7c/0xdc
[ 1.636449] driver_attach+0x24/0x30
[ 1.640067] bus_add_driver+0xe4/0x208
[ 1.643774] driver_register+0x68/0x130
[ 1.647667] __platform_driver_register+0x24/0x30
[ 1.652704] gen_pci_driver_init+0x1c/0x28
[ 1.657181] do_one_initcall+0x60/0x1d4
[ 1.661172] kernel_init_freeable+0x210/0x274
[ 1.665749] kernel_init+0x20/0x140
[ 1.669341] ret_from_fork+0x10/0x20
[ 1.673034] Code: 7100067f 540002c0 71000a7f 54000180 (b9400000)
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [RFC 1/9] whpx: Move around files before introducing AArch64 support
2025-07-31 5:27 ` [RFC 1/9] whpx: Move around files before introducing AArch64 support Mohamed Mediouni
2025-07-31 8:27 ` Philippe Mathieu-Daudé
@ 2025-08-01 5:44 ` Richard Henderson
1 sibling, 0 replies; 26+ messages in thread
From: Richard Henderson @ 2025-08-01 5:44 UTC (permalink / raw)
To: Mohamed Mediouni, qemu-devel
Cc: Daniel P. Berrangé, Paolo Bonzini, Sunil Muthuswamy,
Marc-André Lureau, Philippe Mathieu-Daudé,
Peter Maydell, qemu-arm
On 7/31/25 15:27, Mohamed Mediouni wrote:
> --- /dev/null
> +++ b/accel/whpx/meson.build
> @@ -0,0 +1,6 @@
> +whpx_ss = ss.source_set()
> +whpx_ss.add(files(
> + 'whpx-accel-ops.c',
> +))
> +
> +specific_ss.add_all(when: 'CONFIG_WHPX', if_true: whpx_ss)
> \ No newline at end of file
Add the newline.
> diff --git a/target/i386/whpx/whpx-accel-ops.c b/accel/whpx/whpx-accel-ops.c
> similarity index 96%
> rename from target/i386/whpx/whpx-accel-ops.c
> rename to accel/whpx/whpx-accel-ops.c
> index da58805b1a..364d99b660 100644
> --- a/target/i386/whpx/whpx-accel-ops.c
> +++ b/accel/whpx/whpx-accel-ops.c
> @@ -16,8 +16,8 @@
> #include "qemu/guest-random.h"
>
> #include "system/whpx.h"
> -#include "whpx-internal.h"
> -#include "whpx-accel-ops.h"
> +#include "system/whpx-internal.h"
> +#include "system/whpx-accel-ops.h"
>
> static void *whpx_cpu_thread_fn(void *arg)
> {
> @@ -80,7 +80,11 @@ static void whpx_kick_vcpu_thread(CPUState *cpu)
>
> static bool whpx_vcpu_thread_is_idle(CPUState *cpu)
> {
> +#ifndef __aarch64__
> return !whpx_apic_in_platform();
> +#else
> + return 0;
> +#endif
> }
Better as code movement only.
Save new code for a subsequent patch.
> --- a/target/i386/whpx/whpx-internal.h
> +++ b/include/system/whpx-internal.h
> @@ -3,8 +3,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,
> @@ -97,12 +98,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)
> };
Likewise.
r~
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [RFC 7/9] whpx: add arm64 support
2025-07-31 5:27 ` [RFC 7/9] whpx: add arm64 support Mohamed Mediouni
@ 2025-08-01 6:03 ` Richard Henderson
0 siblings, 0 replies; 26+ messages in thread
From: Richard Henderson @ 2025-08-01 6:03 UTC (permalink / raw)
To: qemu-devel
On 7/31/25 15:27, Mohamed Mediouni wrote:
> @@ -885,7 +886,7 @@ if get_option('kvm').allowed() and host_os == 'linux'
> accelerators += 'CONFIG_KVM'
> endif
> if get_option('whpx').allowed() and host_os == 'windows'
> - if get_option('whpx').enabled() and host_machine.cpu() != 'x86_64'
> + if get_option('whpx').enabled() and host_machine.cpu() in ['x86_64', 'aarch64']
> error('WHPX requires 64-bit host')
This is wrong, since the sense of "in" is incorrect.
But I think this really should be
if cpu == 'i386'
if get_option('whpx').enabled()
error('WHPX requires 64-bit host')
endif
# Leave CONFIG_WHPX disabled
else
if cc.has_header('winhvplatform.h', required: get_option('whpx')) and \
cc.has_header('winhvemulation.h', required: get_option('whpx'))
accelerators += 'CONFIG_WHPX'
endif
endif
because that's the only way that the error message makes sense.
General reject of --enable-whpx on unsupported host will be handled later with
> if 'CONFIG_WHPX' not in accelerators and get_option('whpx').enabled()
> error('WHPX not available on this platform')
> endif
r~
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [RFC 0/9] WHPX support for Arm
2025-08-01 1:15 ` [RFC 0/9] WHPX support for Arm Pierrick Bouvier
@ 2025-08-01 12:43 ` Mohamed Mediouni
2025-08-01 17:22 ` Pierrick Bouvier
0 siblings, 1 reply; 26+ messages in thread
From: Mohamed Mediouni @ 2025-08-01 12:43 UTC (permalink / raw)
To: Pierrick Bouvier
Cc: qemu-devel, "Daniel P. Berrangé", Paolo Bonzini,
Sunil Muthuswamy, Marc-André Lureau,
Philippe Mathieu-Daudé, Peter Maydell, qemu-arm
> On 1. Aug 2025, at 03:15, Pierrick Bouvier <pierrick.bouvier@linaro.org> wrote:
>
> Hi Mohamed,
>
> On 7/30/25 10:27 PM, Mohamed Mediouni wrote:
>> This one took way longer for me to publish than I should have.
>> There are a number of lingering bugs in this one including u-boot not working.
>> Interrupt controller save/restore is entirely missing in this RFC, and some other state
>> bits are likely still missing too.
>> ITS not blocked by default yet, remember to use its=off when testing this series.
>> You might also want the GICv3 + GICv2m support patch as part of the HVF vGIC patch series, which
>> is not duplicated here.
>> PS: on both this and HVF, interrupt controller initialisation needs to be done early so I ended
>> up with hardcoded addresses. Wonder if the right way to go might be to defer virt and vCPU initialisation
>> until late in the process post-gic_realize...
>> Other than that, this boots both EDK2 and Linux in SMP, when using devicetree or ACPI.
>
> thanks for posting this, that's an exciting series!
>
> I applied it on top of your other series (20250728134114.77545-1-mohamed@unpredictable.fr) and solved the conflicts.
> However, it would really help if you could push that exact branch somewhere, so people can easily pull it and try.
> I'm fine if you want to duplicate gic patches in this series as well.
Hello,
My branches are at https://github.com/mediouni-m/qemu
whpx-v1 corresponding to this RFC, but latest rev of the whpx branch has some fixes
Have some additional notes and binaries here too: https://github.com/mediouni-m/qemu/releases/tag/whpx-v1.1
Thank you,
-Mohamed
> I tried to direct boot a kernel (6.15 defconfig) and ran into this error [1]:
> $ ./build/qemu-system-aarch64.exe -M virt,its=off -cpu cortex-a76 -m 2G -nographic -accel whpx -kernel out/Image.gz out/host.ext4
Syntax that I use is -M virt,accel=whpx,its=off -m 2048-cpu cortex-a72 -bios share/edk2-aarch64-code.fd.
And on some kernel versions, you’ll also need irqchip.gicv3_nolpi=1.
> Could you please share your exact command line?
> Does it work with direct kernel boot also?
>
> Kind Regards,
> Pierrick
>
> [1] Error when booting:
> [ 1.381525] Internal error: Oops: 0000000096000002 [#1] SMP
> [ 1.458060] Modules linked in:
> [ 1.461172] CPU: 0 UID: 0 PID: 1 Comm: swapper/0 Not tainted 6.15.0-00001-g7797e43a2520 #1 PREEMPT
> [ 1.470502] Hardware name: linux,dummy-virt (DT)
> [ 1.475102] pstate: 204000c5 (nzCv daIF +PAN -UAO -TCO -DIT -SSBS BTYPE=--)
> [ 1.482023] pc : pci_generic_config_read+0x38/0xb8
> [ 1.486970] lr : pci_generic_config_read+0x24/0xb8
I don’t think I saw this particular one before… which Windows version and hardware are you testing this on?
(Message was sent from the wrong email alias on mobile, resending)
Thank you,
-Mohamed
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [RFC 0/9] WHPX support for Arm
2025-08-01 12:43 ` Mohamed Mediouni
@ 2025-08-01 17:22 ` Pierrick Bouvier
2025-08-01 18:52 ` Mohamed Mediouni
0 siblings, 1 reply; 26+ messages in thread
From: Pierrick Bouvier @ 2025-08-01 17:22 UTC (permalink / raw)
To: Mohamed Mediouni
Cc: qemu-devel, Daniel P. Berrangé, Paolo Bonzini,
Sunil Muthuswamy, Marc-André Lureau,
Philippe Mathieu-Daudé, Peter Maydell, qemu-arm
On 8/1/25 5:43 AM, Mohamed Mediouni wrote:
>
>
>> On 1. Aug 2025, at 03:15, Pierrick Bouvier <pierrick.bouvier@linaro.org> wrote:
>>
>> Hi Mohamed,
>>
>> On 7/30/25 10:27 PM, Mohamed Mediouni wrote:
>>> This one took way longer for me to publish than I should have.
>>> There are a number of lingering bugs in this one including u-boot not working.
>>> Interrupt controller save/restore is entirely missing in this RFC, and some other state
>>> bits are likely still missing too.
>>> ITS not blocked by default yet, remember to use its=off when testing this series.
>>> You might also want the GICv3 + GICv2m support patch as part of the HVF vGIC patch series, which
>>> is not duplicated here.
>>> PS: on both this and HVF, interrupt controller initialisation needs to be done early so I ended
>>> up with hardcoded addresses. Wonder if the right way to go might be to defer virt and vCPU initialisation
>>> until late in the process post-gic_realize...
>>> Other than that, this boots both EDK2 and Linux in SMP, when using devicetree or ACPI.
>>
>> thanks for posting this, that's an exciting series!
>>
>> I applied it on top of your other series (20250728134114.77545-1-mohamed@unpredictable.fr) and solved the conflicts.
>> However, it would really help if you could push that exact branch somewhere, so people can easily pull it and try.
>> I'm fine if you want to duplicate gic patches in this series as well.
> Hello,
>
> My branches are at https://github.com/mediouni-m/qemu
>
Thanks, it's worth adding it in cover letter for next versions.
> whpx-v1 corresponding to this RFC, but latest rev of the whpx branch has some fixes
>
> Have some additional notes and binaries here too: https://github.com/mediouni-m/qemu/releases/tag/whpx-v1.1
>
> Thank you,
> -Mohamed
>
>> I tried to direct boot a kernel (6.15 defconfig) and ran into this error [1]:
>> $ ./build/qemu-system-aarch64.exe -M virt,its=off -cpu cortex-a76 -m 2G -nographic -accel whpx -kernel out/Image.gz out/host.ext4
>
> Syntax that I use is -M virt,accel=whpx,its=off -m 2048-cpu cortex-a72 -bios share/edk2-aarch64-code.fd.
>
> And on some kernel versions, you’ll also need irqchip.gicv3_nolpi=1.
>
>> Could you please share your exact command line?
>> Does it work with direct kernel boot also?
>>
>> Kind Regards,
>> Pierrick
>>
>> [1] Error when booting:
>> [ 1.381525] Internal error: Oops: 0000000096000002 [#1] SMP
>> [ 1.458060] Modules linked in:
>> [ 1.461172] CPU: 0 UID: 0 PID: 1 Comm: swapper/0 Not tainted 6.15.0-00001-g7797e43a2520 #1 PREEMPT
>> [ 1.470502] Hardware name: linux,dummy-virt (DT)
>> [ 1.475102] pstate: 204000c5 (nzCv daIF +PAN -UAO -TCO -DIT -SSBS BTYPE=--)
>> [ 1.482023] pc : pci_generic_config_read+0x38/0xb8
>> [ 1.486970] lr : pci_generic_config_read+0x24/0xb8
> I don’t think I saw this particular one before… which Windows version and hardware are you testing this on?
>
I see the same error as before.
I tried also binaries from
https://github.com/mediouni-m/qemu/releases/tag/whpx-v1.1, when directly
booting kernel, I still see the same pci issue with both binaries and my
compiled whpx-v1.3.
When booting edk2 provided, I ran into this other error instead with
both binaries [1].
I'm running latest Windows 11 (stable channel, fully updated), on a
microsoft volterra (devkit). It might be an issue specific to this platform.
In case you're interested, we can arrange an access to the machine, but
I understand if it's not your priority now.
[1]
Windows Hypervisor Platform accelerator is operational
UEFI firmware (version edk2-stable202408-prebuilt.qemu.org built at
16:28:50 on Sep 12 2024)
ArmTrngLib could not be correctly initialized.
Error: Image at 000BFDB6000 start failed: 00000001
Error: Image at 000BFD6D000 start failed: Not Found
MapGcdMmioSpace: failed to add GCD memory space for region
[0x4010000000+0x10000000)
ASSERT_EFI_ERROR (Status = Unsupported)
ASSERT [PciHostBridgeDxe]
/home/kraxel/projects/qemu/roms/edk2/OvmfPkg/Fdt/FdtPciHostBridgeLib/FdtPciHostBridgeLib.c(326):
!(((INTN)(RETURN_STATUS)(Status)) < 0)
> (Message was sent from the wrong email alias on mobile, resending)
> Thank you,
> -Mohamed
>
Thanks,
Pierrick
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [RFC 0/9] WHPX support for Arm
2025-08-01 17:22 ` Pierrick Bouvier
@ 2025-08-01 18:52 ` Mohamed Mediouni
2025-08-01 19:16 ` Pierrick Bouvier
0 siblings, 1 reply; 26+ messages in thread
From: Mohamed Mediouni @ 2025-08-01 18:52 UTC (permalink / raw)
To: Pierrick Bouvier
Cc: qemu-devel, "Daniel P. Berrangé", Paolo Bonzini,
Sunil Muthuswamy, Marc-André Lureau,
Philippe Mathieu-Daudé, Peter Maydell, qemu-arm
> On 1. Aug 2025, at 19:22, Pierrick Bouvier <pierrick.bouvier@linaro.org> wrote:
>
> On 8/1/25 5:43 AM, Mohamed Mediouni wrote:
>>> On 1. Aug 2025, at 03:15, Pierrick Bouvier <pierrick.bouvier@linaro.org> wrote:
>>>
>>> Hi Mohamed,
>>>
>>> On 7/30/25 10:27 PM, Mohamed Mediouni wrote:
>>>> This one took way longer for me to publish than I should have.
>>>> There are a number of lingering bugs in this one including u-boot not working.
>>>> Interrupt controller save/restore is entirely missing in this RFC, and some other state
>>>> bits are likely still missing too.
>>>> ITS not blocked by default yet, remember to use its=off when testing this series.
>>>> You might also want the GICv3 + GICv2m support patch as part of the HVF vGIC patch series, which
>>>> is not duplicated here.
>>>> PS: on both this and HVF, interrupt controller initialisation needs to be done early so I ended
>>>> up with hardcoded addresses. Wonder if the right way to go might be to defer virt and vCPU initialisation
>>>> until late in the process post-gic_realize...
>>>> Other than that, this boots both EDK2 and Linux in SMP, when using devicetree or ACPI.
>>>
>>> thanks for posting this, that's an exciting series!
>>>
>>> I applied it on top of your other series (20250728134114.77545-1-mohamed@unpredictable.fr) and solved the conflicts.
>>> However, it would really help if you could push that exact branch somewhere, so people can easily pull it and try.
>>> I'm fine if you want to duplicate gic patches in this series as well.
>> Hello,
>> My branches are at https://github.com/mediouni-m/qemu
>>
>
> Thanks, it's worth adding it in cover letter for next versions.
>
>> whpx-v1 corresponding to this RFC, but latest rev of the whpx branch has some fixes
>> Have some additional notes and binaries here too: https://github.com/mediouni-m/qemu/releases/tag/whpx-v1.1
>> Thank you,
>> -Mohamed
>>> I tried to direct boot a kernel (6.15 defconfig) and ran into this error [1]:
>>> $ ./build/qemu-system-aarch64.exe -M virt,its=off -cpu cortex-a76 -m 2G -nographic -accel whpx -kernel out/Image.gz out/host.ext4
>> Syntax that I use is -M virt,accel=whpx,its=off -m 2048-cpu cortex-a72 -bios share/edk2-aarch64-code.fd.
>> And on some kernel versions, you’ll also need irqchip.gicv3_nolpi=1.
>>> Could you please share your exact command line?
>>> Does it work with direct kernel boot also?
>>>
>>> Kind Regards,
>>> Pierrick
>>>
>>> [1] Error when booting:
>>> [ 1.381525] Internal error: Oops: 0000000096000002 [#1] SMP
>>> [ 1.458060] Modules linked in:
>>> [ 1.461172] CPU: 0 UID: 0 PID: 1 Comm: swapper/0 Not tainted 6.15.0-00001-g7797e43a2520 #1 PREEMPT
>>> [ 1.470502] Hardware name: linux,dummy-virt (DT)
>>> [ 1.475102] pstate: 204000c5 (nzCv daIF +PAN -UAO -TCO -DIT -SSBS BTYPE=--)
>>> [ 1.482023] pc : pci_generic_config_read+0x38/0xb8
>>> [ 1.486970] lr : pci_generic_config_read+0x24/0xb8
>> I don’t think I saw this particular one before… which Windows version and hardware are you testing this on?
>>
>
> I see the same error as before.
>
> I tried also binaries from https://github.com/mediouni-m/qemu/releases/tag/whpx-v1.1, when directly booting kernel, I still see the same pci issue with both binaries and my compiled whpx-v1.3.
> When booting edk2 provided, I ran into this other error instead with both binaries [1].
>
> I'm running latest Windows 11 (stable channel, fully updated), on a microsoft volterra (devkit). It might be an issue specific to this platform.
>
I didn’t test anything on the stable branch for now but only on Canary so far.
Just cursorily tested (EDK2 only) an X Elite device on prod (26100.4652) and this issue doesn’t appear.
I have 8cx Gen 3 and 8cx Gen 1 (SQ1) devices around, will test on those older SoCs later and see.
Random idea for testing: what if you put -M highmem=off, does that change anything?
Thanks,
-Mohamed
> In case you're interested, we can arrange an access to the machine, but I understand if it's not your priority now.
>
> [1]
> Windows Hypervisor Platform accelerator is operational
> UEFI firmware (version edk2-stable202408-prebuilt.qemu.org built at 16:28:50 on Sep 12 2024)
> ArmTrngLib could not be correctly initialized.
> Error: Image at 000BFDB6000 start failed: 00000001
> Error: Image at 000BFD6D000 start failed: Not Found
> MapGcdMmioSpace: failed to add GCD memory space for region [0x4010000000+0x10000000)
> ASSERT_EFI_ERROR (Status = Unsupported)
> ASSERT [PciHostBridgeDxe] /home/kraxel/projects/qemu/roms/edk2/OvmfPkg/Fdt/FdtPciHostBridgeLib/FdtPciHostBridgeLib.c(326): !(((INTN)(RETURN_STATUS)(Status)) < 0)
>
>> (Message was sent from the wrong email alias on mobile, resending)
>> Thank you,
>> -Mohamed
>
> Thanks,
> Pierrick
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [RFC 0/9] WHPX support for Arm
2025-08-01 18:52 ` Mohamed Mediouni
@ 2025-08-01 19:16 ` Pierrick Bouvier
2025-08-01 19:31 ` Mohamed Mediouni
0 siblings, 1 reply; 26+ messages in thread
From: Pierrick Bouvier @ 2025-08-01 19:16 UTC (permalink / raw)
To: Mohamed Mediouni
Cc: qemu-devel, Daniel P. Berrangé, Paolo Bonzini,
Sunil Muthuswamy, Marc-André Lureau,
Philippe Mathieu-Daudé, Peter Maydell, qemu-arm
On 8/1/25 11:52 AM, Mohamed Mediouni wrote:
>
>
>> On 1. Aug 2025, at 19:22, Pierrick Bouvier <pierrick.bouvier@linaro.org> wrote:
>>
>> On 8/1/25 5:43 AM, Mohamed Mediouni wrote:
>>>> On 1. Aug 2025, at 03:15, Pierrick Bouvier <pierrick.bouvier@linaro.org> wrote:
>>>>
>>>> Hi Mohamed,
>>>>
>>>> On 7/30/25 10:27 PM, Mohamed Mediouni wrote:
>>>>> This one took way longer for me to publish than I should have.
>>>>> There are a number of lingering bugs in this one including u-boot not working.
>>>>> Interrupt controller save/restore is entirely missing in this RFC, and some other state
>>>>> bits are likely still missing too.
>>>>> ITS not blocked by default yet, remember to use its=off when testing this series.
>>>>> You might also want the GICv3 + GICv2m support patch as part of the HVF vGIC patch series, which
>>>>> is not duplicated here.
>>>>> PS: on both this and HVF, interrupt controller initialisation needs to be done early so I ended
>>>>> up with hardcoded addresses. Wonder if the right way to go might be to defer virt and vCPU initialisation
>>>>> until late in the process post-gic_realize...
>>>>> Other than that, this boots both EDK2 and Linux in SMP, when using devicetree or ACPI.
>>>>
>>>> thanks for posting this, that's an exciting series!
>>>>
>>>> I applied it on top of your other series (20250728134114.77545-1-mohamed@unpredictable.fr) and solved the conflicts.
>>>> However, it would really help if you could push that exact branch somewhere, so people can easily pull it and try.
>>>> I'm fine if you want to duplicate gic patches in this series as well.
>>> Hello,
>>> My branches are at https://github.com/mediouni-m/qemu
>>>
>>
>> Thanks, it's worth adding it in cover letter for next versions.
>>
>>> whpx-v1 corresponding to this RFC, but latest rev of the whpx branch has some fixes
>>> Have some additional notes and binaries here too: https://github.com/mediouni-m/qemu/releases/tag/whpx-v1.1
>>> Thank you,
>>> -Mohamed
>>>> I tried to direct boot a kernel (6.15 defconfig) and ran into this error [1]:
>>>> $ ./build/qemu-system-aarch64.exe -M virt,its=off -cpu cortex-a76 -m 2G -nographic -accel whpx -kernel out/Image.gz out/host.ext4
>>> Syntax that I use is -M virt,accel=whpx,its=off -m 2048-cpu cortex-a72 -bios share/edk2-aarch64-code.fd.
>>> And on some kernel versions, you’ll also need irqchip.gicv3_nolpi=1.
>>>> Could you please share your exact command line?
>>>> Does it work with direct kernel boot also?
>>>>
>>>> Kind Regards,
>>>> Pierrick
>>>>
>>>> [1] Error when booting:
>>>> [ 1.381525] Internal error: Oops: 0000000096000002 [#1] SMP
>>>> [ 1.458060] Modules linked in:
>>>> [ 1.461172] CPU: 0 UID: 0 PID: 1 Comm: swapper/0 Not tainted 6.15.0-00001-g7797e43a2520 #1 PREEMPT
>>>> [ 1.470502] Hardware name: linux,dummy-virt (DT)
>>>> [ 1.475102] pstate: 204000c5 (nzCv daIF +PAN -UAO -TCO -DIT -SSBS BTYPE=--)
>>>> [ 1.482023] pc : pci_generic_config_read+0x38/0xb8
>>>> [ 1.486970] lr : pci_generic_config_read+0x24/0xb8
>>> I don’t think I saw this particular one before… which Windows version and hardware are you testing this on?
>>>
>>
>> I see the same error as before.
>>
>> I tried also binaries from https://github.com/mediouni-m/qemu/releases/tag/whpx-v1.1, when directly booting kernel, I still see the same pci issue with both binaries and my compiled whpx-v1.3.
>> When booting edk2 provided, I ran into this other error instead with both binaries [1].
>>
>> I'm running latest Windows 11 (stable channel, fully updated), on a microsoft volterra (devkit). It might be an issue specific to this platform.
>>
> I didn’t test anything on the stable branch for now but only on Canary so far.
> Just cursorily tested (EDK2 only) an X Elite device on prod (26100.4652) and this issue doesn’t appear.
>
> I have 8cx Gen 3 and 8cx Gen 1 (SQ1) devices around, will test on those older SoCs later and see.
>
> Random idea for testing: what if you put -M highmem=off, does that change anything?
>
Good guess, it solves the problem with edk2, and direct boots linux
kernel successfully now.
> Thanks,
> -Mohamed
>
>> In case you're interested, we can arrange an access to the machine, but I understand if it's not your priority now.
>>
>> [1]
>> Windows Hypervisor Platform accelerator is operational
>> UEFI firmware (version edk2-stable202408-prebuilt.qemu.org built at 16:28:50 on Sep 12 2024)
>> ArmTrngLib could not be correctly initialized.
>> Error: Image at 000BFDB6000 start failed: 00000001
>> Error: Image at 000BFD6D000 start failed: Not Found
>> MapGcdMmioSpace: failed to add GCD memory space for region [0x4010000000+0x10000000)
>> ASSERT_EFI_ERROR (Status = Unsupported)
>> ASSERT [PciHostBridgeDxe] /home/kraxel/projects/qemu/roms/edk2/OvmfPkg/Fdt/FdtPciHostBridgeLib/FdtPciHostBridgeLib.c(326): !(((INTN)(RETURN_STATUS)(Status)) < 0)
>>
>>> (Message was sent from the wrong email alias on mobile, resending)
>>> Thank you,
>>> -Mohamed
>>
>> Thanks,
>> Pierrick
>
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [RFC 0/9] WHPX support for Arm
2025-08-01 19:16 ` Pierrick Bouvier
@ 2025-08-01 19:31 ` Mohamed Mediouni
2025-08-01 19:42 ` Pierrick Bouvier
0 siblings, 1 reply; 26+ messages in thread
From: Mohamed Mediouni @ 2025-08-01 19:31 UTC (permalink / raw)
To: Pierrick Bouvier
Cc: qemu-devel, "Daniel P. Berrangé", Paolo Bonzini,
Sunil Muthuswamy, Marc-André Lureau,
Philippe Mathieu-Daudé, Peter Maydell, qemu-arm
> On 1. Aug 2025, at 21:16, Pierrick Bouvier <pierrick.bouvier@linaro.org> wrote:
>
> On 8/1/25 11:52 AM, Mohamed Mediouni wrote:
>>> On 1. Aug 2025, at 19:22, Pierrick Bouvier <pierrick.bouvier@linaro.org> wrote:
>>>
>>> On 8/1/25 5:43 AM, Mohamed Mediouni wrote:
>>>>> On 1. Aug 2025, at 03:15, Pierrick Bouvier <pierrick.bouvier@linaro.org> wrote:
>>>>>
>>>>> Hi Mohamed,
>>>>>
>>>>> On 7/30/25 10:27 PM, Mohamed Mediouni wrote:
>>>>>> This one took way longer for me to publish than I should have.
>>>>>> There are a number of lingering bugs in this one including u-boot not working.
>>>>>> Interrupt controller save/restore is entirely missing in this RFC, and some other state
>>>>>> bits are likely still missing too.
>>>>>> ITS not blocked by default yet, remember to use its=off when testing this series.
>>>>>> You might also want the GICv3 + GICv2m support patch as part of the HVF vGIC patch series, which
>>>>>> is not duplicated here.
>>>>>> PS: on both this and HVF, interrupt controller initialisation needs to be done early so I ended
>>>>>> up with hardcoded addresses. Wonder if the right way to go might be to defer virt and vCPU initialisation
>>>>>> until late in the process post-gic_realize...
>>>>>> Other than that, this boots both EDK2 and Linux in SMP, when using devicetree or ACPI.
>>>>>
>>>>> thanks for posting this, that's an exciting series!
>>>>>
>>>>> I applied it on top of your other series (20250728134114.77545-1-mohamed@unpredictable.fr) and solved the conflicts.
>>>>> However, it would really help if you could push that exact branch somewhere, so people can easily pull it and try.
>>>>> I'm fine if you want to duplicate gic patches in this series as well.
>>>> Hello,
>>>> My branches are at https://github.com/mediouni-m/qemu
>>>>
>>>
>>> Thanks, it's worth adding it in cover letter for next versions.
>>>
>>>> whpx-v1 corresponding to this RFC, but latest rev of the whpx branch has some fixes
>>>> Have some additional notes and binaries here too: https://github.com/mediouni-m/qemu/releases/tag/whpx-v1.1
>>>> Thank you,
>>>> -Mohamed
>>>>> I tried to direct boot a kernel (6.15 defconfig) and ran into this error [1]:
>>>>> $ ./build/qemu-system-aarch64.exe -M virt,its=off -cpu cortex-a76 -m 2G -nographic -accel whpx -kernel out/Image.gz out/host.ext4
>>>> Syntax that I use is -M virt,accel=whpx,its=off -m 2048-cpu cortex-a72 -bios share/edk2-aarch64-code.fd.
>>>> And on some kernel versions, you’ll also need irqchip.gicv3_nolpi=1.
>>>>> Could you please share your exact command line?
>>>>> Does it work with direct kernel boot also?
>>>>>
>>>>> Kind Regards,
>>>>> Pierrick
>>>>>
>>>>> [1] Error when booting:
>>>>> [ 1.381525] Internal error: Oops: 0000000096000002 [#1] SMP
>>>>> [ 1.458060] Modules linked in:
>>>>> [ 1.461172] CPU: 0 UID: 0 PID: 1 Comm: swapper/0 Not tainted 6.15.0-00001-g7797e43a2520 #1 PREEMPT
>>>>> [ 1.470502] Hardware name: linux,dummy-virt (DT)
>>>>> [ 1.475102] pstate: 204000c5 (nzCv daIF +PAN -UAO -TCO -DIT -SSBS BTYPE=--)
>>>>> [ 1.482023] pc : pci_generic_config_read+0x38/0xb8
>>>>> [ 1.486970] lr : pci_generic_config_read+0x24/0xb8
>>>> I don’t think I saw this particular one before… which Windows version and hardware are you testing this on?
>>>>
>>>
>>> I see the same error as before.
>>>
>>> I tried also binaries from https://github.com/mediouni-m/qemu/releases/tag/whpx-v1.1, when directly booting kernel, I still see the same pci issue with both binaries and my compiled whpx-v1.3.
>>> When booting edk2 provided, I ran into this other error instead with both binaries [1].
>>>
>>> I'm running latest Windows 11 (stable channel, fully updated), on a microsoft volterra (devkit). It might be an issue specific to this platform.
>>>
>> I didn’t test anything on the stable branch for now but only on Canary so far.
>> Just cursorily tested (EDK2 only) an X Elite device on prod (26100.4652) and this issue doesn’t appear.
>> I have 8cx Gen 3 and 8cx Gen 1 (SQ1) devices around, will test on those older SoCs later and see.
>> Random idea for testing: what if you put -M highmem=off, does that change anything?
>>
>
> Good guess, it solves the problem with edk2, and direct boots linux kernel successfully now.
>
If you don’t mind, could you please test the latest commit I just put on the Git repo (whpx branch)? It should address this properly.
Thank you,
-Mohamed
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [RFC 0/9] WHPX support for Arm
2025-08-01 19:31 ` Mohamed Mediouni
@ 2025-08-01 19:42 ` Pierrick Bouvier
2025-08-01 19:57 ` Mohamed Mediouni
0 siblings, 1 reply; 26+ messages in thread
From: Pierrick Bouvier @ 2025-08-01 19:42 UTC (permalink / raw)
To: Mohamed Mediouni
Cc: qemu-devel, Daniel P. Berrangé, Paolo Bonzini,
Sunil Muthuswamy, Marc-André Lureau,
Philippe Mathieu-Daudé, Peter Maydell, qemu-arm
On 8/1/25 12:31 PM, Mohamed Mediouni wrote:
>>> I didn’t test anything on the stable branch for now but only on Canary so far.
>>> Just cursorily tested (EDK2 only) an X Elite device on prod (26100.4652) and this issue doesn’t appear.
>>> I have 8cx Gen 3 and 8cx Gen 1 (SQ1) devices around, will test on those older SoCs later and see.
>>> Random idea for testing: what if you put -M highmem=off, does that change anything?
>>>
>>
>> Good guess, it solves the problem with edk2, and direct boots linux kernel successfully now.
>>
>
> If you don’t mind, could you please test the latest commit I just put on the Git repo (whpx branch)? It should address this properly.
>
Sure.
Without highmem=off, I get a new error:
Physical address width: 36
C:\msys64\home\tcwg\qemu\build\qemu-system-aarch64.exe: VCPU supports
less PA bits (36) than requested by the memory map (40)
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [RFC 0/9] WHPX support for Arm
2025-08-01 19:42 ` Pierrick Bouvier
@ 2025-08-01 19:57 ` Mohamed Mediouni
2025-08-01 20:10 ` Pierrick Bouvier
0 siblings, 1 reply; 26+ messages in thread
From: Mohamed Mediouni @ 2025-08-01 19:57 UTC (permalink / raw)
To: Pierrick Bouvier
Cc: qemu-devel, "Daniel P. Berrangé", Paolo Bonzini,
Sunil Muthuswamy, Marc-André Lureau,
Philippe Mathieu-Daudé, Peter Maydell, qemu-arm
> On 1. Aug 2025, at 21:42, Pierrick Bouvier <pierrick.bouvier@linaro.org> wrote:
>
> On 8/1/25 12:31 PM, Mohamed Mediouni wrote:
>>>> I didn’t test anything on the stable branch for now but only on Canary so far.
>>>> Just cursorily tested (EDK2 only) an X Elite device on prod (26100.4652) and this issue doesn’t appear.
>>>> I have 8cx Gen 3 and 8cx Gen 1 (SQ1) devices around, will test on those older SoCs later and see.
>>>> Random idea for testing: what if you put -M highmem=off, does that change anything?
>>>>
>>>
>>> Good guess, it solves the problem with edk2, and direct boots linux kernel successfully now.
>>>
>> If you don’t mind, could you please test the latest commit I just put on the Git repo (whpx branch)? It should address this properly.
>
> Sure.
> Without highmem=off, I get a new error:
> Physical address width: 36
> C:\msys64\home\tcwg\qemu\build\qemu-system-aarch64.exe: VCPU supports less PA bits (36) than requested by the memory map (40)
>
Oh this confirms what I thought, just pushed a new commit which should be a complete fix. :)
And accessorily is also a good thing for Snapdragon X too, as 40 VA bits were used there despite the hardware having 39.
Thank you,
-Mohamed
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [RFC 0/9] WHPX support for Arm
2025-08-01 19:57 ` Mohamed Mediouni
@ 2025-08-01 20:10 ` Pierrick Bouvier
0 siblings, 0 replies; 26+ messages in thread
From: Pierrick Bouvier @ 2025-08-01 20:10 UTC (permalink / raw)
To: Mohamed Mediouni
Cc: qemu-devel, Daniel P. Berrangé, Paolo Bonzini,
Sunil Muthuswamy, Marc-André Lureau,
Philippe Mathieu-Daudé, Peter Maydell, qemu-arm
On 8/1/25 12:57 PM, Mohamed Mediouni wrote:
>
>
>> On 1. Aug 2025, at 21:42, Pierrick Bouvier <pierrick.bouvier@linaro.org> wrote:
>>
>> On 8/1/25 12:31 PM, Mohamed Mediouni wrote:
>>>>> I didn’t test anything on the stable branch for now but only on Canary so far.
>>>>> Just cursorily tested (EDK2 only) an X Elite device on prod (26100.4652) and this issue doesn’t appear.
>>>>> I have 8cx Gen 3 and 8cx Gen 1 (SQ1) devices around, will test on those older SoCs later and see.
>>>>> Random idea for testing: what if you put -M highmem=off, does that change anything?
>>>>>
>>>>
>>>> Good guess, it solves the problem with edk2, and direct boots linux kernel successfully now.
>>>>
>>> If you don’t mind, could you please test the latest commit I just put on the Git repo (whpx branch)? It should address this properly.
>>
>> Sure.
>> Without highmem=off, I get a new error:
>> Physical address width: 36
>> C:\msys64\home\tcwg\qemu\build\qemu-system-aarch64.exe: VCPU supports less PA bits (36) than requested by the memory map (40)
>>
> Oh this confirms what I thought, just pushed a new commit which should be a complete fix. :)
>
It works fine now, on top of c6e3d4d.
Excellent work!
> And accessorily is also a good thing for Snapdragon X too, as 40 VA bits were used there despite the hardware having 39.
>
Yes.
> Thank you,
> -Mohamed
This seems like a good time for cleaning up, address the few comments
that have been made, and send a v2.
Feel free to add the gic related patches in it, so we have a "complete"
series to review.
Thanks,
Pierrick
^ permalink raw reply [flat|nested] 26+ messages in thread
end of thread, other threads:[~2025-08-01 21:06 UTC | newest]
Thread overview: 26+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-07-31 5:27 [RFC 0/9] WHPX support for Arm Mohamed Mediouni
2025-07-31 5:27 ` [RFC 1/9] whpx: Move around files before introducing AArch64 support Mohamed Mediouni
2025-07-31 8:27 ` Philippe Mathieu-Daudé
2025-08-01 5:44 ` Richard Henderson
2025-07-31 5:27 ` [RFC 2/9] whpx: reshuffle common code Mohamed Mediouni
2025-07-31 5:27 ` [RFC 3/9] whpx: common: use whpx_cpu_instance_init on x86 only Mohamed Mediouni
2025-07-31 8:30 ` Philippe Mathieu-Daudé
2025-07-31 5:27 ` [RFC 4/9] whpx: interrupt controller support Mohamed Mediouni
2025-07-31 5:27 ` [RFC 5/9] hw/virt: make Qemu aware that WHPX has a vGICv3 Mohamed Mediouni
2025-07-31 8:35 ` Philippe Mathieu-Daudé
2025-07-31 14:47 ` Mohamed Mediouni
2025-07-31 5:27 ` [RFC 6/9] hw: intc: arm_gicv3_common: add whpx Mohamed Mediouni
2025-07-31 8:33 ` Philippe Mathieu-Daudé
2025-07-31 5:27 ` [RFC 7/9] whpx: add arm64 support Mohamed Mediouni
2025-08-01 6:03 ` Richard Henderson
2025-07-31 5:27 ` [RFC 8/9] whpx: copy over memory tracking logic from hvf Mohamed Mediouni
2025-07-31 5:27 ` [RFC 9/9] target/arm: cpu: mark WHPX as supporting PSCI 1.1 Mohamed Mediouni
2025-08-01 1:15 ` [RFC 0/9] WHPX support for Arm Pierrick Bouvier
2025-08-01 12:43 ` Mohamed Mediouni
2025-08-01 17:22 ` Pierrick Bouvier
2025-08-01 18:52 ` Mohamed Mediouni
2025-08-01 19:16 ` Pierrick Bouvier
2025-08-01 19:31 ` Mohamed Mediouni
2025-08-01 19:42 ` Pierrick Bouvier
2025-08-01 19:57 ` Mohamed Mediouni
2025-08-01 20:10 ` Pierrick Bouvier
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).