Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/patches/2195166/?format=api
{ "id": 2195166, "url": "http://patchwork.ozlabs.org/api/patches/2195166/?format=api", "web_url": "http://patchwork.ozlabs.org/project/qemu-devel/patch/20260210135206.229528-14-peter.maydell@linaro.org/", "project": { "id": 14, "url": "http://patchwork.ozlabs.org/api/projects/14/?format=api", "name": "QEMU Development", "link_name": "qemu-devel", "list_id": "qemu-devel.nongnu.org", "list_email": "qemu-devel@nongnu.org", "web_url": "", "scm_url": "", "webscm_url": "", "list_archive_url": "", "list_archive_url_format": "", "commit_url_format": "" }, "msgid": "<20260210135206.229528-14-peter.maydell@linaro.org>", "list_archive_url": null, "date": "2026-02-10T13:51:53", "name": "[PULL,13/26] hw, target, accel: whpx: change apic_in_platform to kernel_irqchip", "commit_ref": null, "pull_url": null, "state": "not-applicable", "archived": false, "hash": "ce74fe946b5f6f886a5e3607baedaf0848e1939f", "submitter": { "id": 5111, "url": "http://patchwork.ozlabs.org/api/people/5111/?format=api", "name": "Peter Maydell", "email": "peter.maydell@linaro.org" }, "delegate": null, "mbox": "http://patchwork.ozlabs.org/project/qemu-devel/patch/20260210135206.229528-14-peter.maydell@linaro.org/mbox/", "series": [ { "id": 491680, "url": "http://patchwork.ozlabs.org/api/series/491680/?format=api", "web_url": "http://patchwork.ozlabs.org/project/qemu-devel/list/?series=491680", "date": "2026-02-10T13:51:40", "name": "[PULL,01/26] target/arm/kvm: add constants for new PSCI versions", "version": 1, "mbox": "http://patchwork.ozlabs.org/series/491680/mbox/" } ], "comments": "http://patchwork.ozlabs.org/api/patches/2195166/comments/", "check": "pending", "checks": "http://patchwork.ozlabs.org/api/patches/2195166/checks/", "tags": {}, "related": [], "headers": { "Return-Path": "<qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org>", "X-Original-To": "incoming@patchwork.ozlabs.org", "Delivered-To": "patchwork-incoming@legolas.ozlabs.org", "Authentication-Results": [ "legolas.ozlabs.org;\n\tdkim=pass (2048-bit key;\n unprotected) header.d=linaro.org header.i=@linaro.org header.a=rsa-sha256\n header.s=google header.b=m7nLKRFI;\n\tdkim-atps=neutral", "legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=nongnu.org\n (client-ip=209.51.188.17; helo=lists.gnu.org;\n envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org;\n receiver=patchwork.ozlabs.org)" ], "Received": [ "from lists.gnu.org (lists.gnu.org [209.51.188.17])\n\t(using TLSv1.2 with cipher ECDHE-ECDSA-AES256-GCM-SHA384 (256/256 bits))\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4f9NNF67ZXz1xtV\n\tfor <incoming@patchwork.ozlabs.org>; Wed, 11 Feb 2026 00:54:37 +1100 (AEDT)", "from localhost ([::1] helo=lists1p.gnu.org)\n\tby lists.gnu.org with esmtp (Exim 4.90_1)\n\t(envelope-from <qemu-devel-bounces@nongnu.org>)\n\tid 1vpoAG-0002BG-UQ; Tue, 10 Feb 2026 08:52:28 -0500", "from eggs.gnu.org ([2001:470:142:3::10])\n by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256)\n (Exim 4.90_1) (envelope-from <peter.maydell@linaro.org>)\n id 1vpoAD-00026d-S9\n for qemu-devel@nongnu.org; Tue, 10 Feb 2026 08:52:25 -0500", "from mail-wm1-x32f.google.com ([2a00:1450:4864:20::32f])\n by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128)\n (Exim 4.90_1) (envelope-from <peter.maydell@linaro.org>)\n id 1vpoAB-0006LZ-5f\n for qemu-devel@nongnu.org; Tue, 10 Feb 2026 08:52:25 -0500", "by mail-wm1-x32f.google.com with SMTP id\n 5b1f17b1804b1-48336a6e932so16499115e9.3\n for <qemu-devel@nongnu.org>; Tue, 10 Feb 2026 05:52:19 -0800 (PST)", "from lanath.. (wildly.archaic.org.uk. [81.2.115.145])\n by smtp.gmail.com with ESMTPSA id\n 5b1f17b1804b1-4834d5d77f9sm64344875e9.3.2026.02.10.05.52.17\n for <qemu-devel@nongnu.org>\n (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n Tue, 10 Feb 2026 05:52:18 -0800 (PST)" ], "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=linaro.org; s=google; t=1770731539; x=1771336339; darn=nongnu.org;\n h=content-transfer-encoding:mime-version:references:in-reply-to\n :message-id:date:subject:to:from:from:to:cc:subject:date:message-id\n :reply-to; bh=5xPq2fNqcw/oH0dNiPR3/K9/+sAUVQTjTaQpF6aGozQ=;\n b=m7nLKRFItcahzz3AkSBg6nlbmGeI+NHTWkJ0gpJbCydA8pZOl/CEMfqAG6k9WJgySO\n fYxQcQpCpqcrMvfY0uPkfx5o8YrXZQMI8xJ/eZuGaaXFh92xnP94nD44KY1Y92DWu6NW\n XnjMp2i0nzRWQW+CgnMATGLJ0Wp8jGtIu9HcY1gYiwqVdZyb3b9GM8BD2Lxv5FqS3wdg\n bywwH06A09ybx72EUfQIuue4hYkzdDC/9R1tuOYHY0SNyoEHF9TvQtQCfydwFaNMSYwt\n 8zOT4ds6Nm+VWlxd+IVcz0/6Ff+3pee1BcJW0jTnh1Oiq6bDgtoDCT3A3vtLhUwPTkpn\n 348Q==", "X-Google-DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=1e100.net; s=20230601; t=1770731539; x=1771336339;\n h=content-transfer-encoding:mime-version:references:in-reply-to\n :message-id:date:subject:to:from:x-gm-gg:x-gm-message-state:from:to\n :cc:subject:date:message-id:reply-to;\n bh=5xPq2fNqcw/oH0dNiPR3/K9/+sAUVQTjTaQpF6aGozQ=;\n b=TNYp5z4HIiMccbjiCV2luSSbwQY4AqtAwXl9+oc8bktZcGSWpu8QMxTnHnySx4tD1A\n i3AJSX0lBzfk+6Ks2MMhmJNSXp/SfSwE2uNqT5I8U6I512LO0giK6akJM9i4wgjAnNp2\n B0PVFdii0yHdyWsmcpNVx9NG6NFYRr4OukCmQktg1tdNtK58tvbhdmuvXEYk0sBQcGQA\n h/WjAidMS6giikO4d1S2klLcW7tXE53LQCt9IZ2fYnioahKzT7m2ExplAYmmq99TtXKT\n L0Q5pdZfNidr2rrSxxsj+n+L2Bkkj05JG7L1tQkJh0FBGDevcEqfNZQw3VDiWbFIRmQu\n l7UA==", "X-Gm-Message-State": "AOJu0YxmmTKdSUipPRB9bu+NMi0Q2Uw7o2T05DJWTfN4ninptEQLKJAg\n pybMhl0bA7oRcSI4hQ1ZgBhrKFFoU4m5DliT0gypgFB82FP25u/VRLGKgYfnp7PL5+DRujzuwd6\n toNJd", "X-Gm-Gg": "AZuq6aKxAX/zdU5qC0VhR4jYG35fAWK0ph+oAFko9DF+Wt1LPfjWXoUDFzPjJcKmczx\n eRW/jQQq5mGn6zjoRVuqWltj04kNCZIGBdISNYOUWKhZnTp/De2sWWmDHE+njusPvBsVd6vyrZV\n Eofh8u1ncGKTfXhn0iD4xXOcsCipKb8X90778suUDwzKb75/bhNM5/TfKzLNFPEkel0F5/Gnegn\n bk3zytWXwFfpFqWcVtR3EgZ/+tEMgxPLdCOsM/Gyp7kOVVjQyKNqnXrpqGa/Dpbt0hSW0xvcm3K\n gR4FsX4maVDwAEcoVmbTvJReWb7lixJuQPJwEb9Bqw8XcATv+coq1CkqwLBvCziWx2L2ww0J9ze\n 8E23nDyALpy+RUTuwIq9/U2jcNWVzjEahAUD2bdlfOXcX4WpdL4X8oiMIsHxJSlPSbmUpeS6ZPN\n hxJ8imwQkKtXaKWLfvYfyJDej49sh7MgIRT/XlFoUWToghfm0cNp1Q18Muep2aoWnvMcVliwoyS\n q4+oUrvHC5UVfwKGbqiTSXjoLdGGE89QXhc3eNNjQ==", "X-Received": "by 2002:a05:600c:34c5:b0:480:1b65:b744 with SMTP id\n 5b1f17b1804b1-4832021e972mr211015325e9.28.1770731538591;\n Tue, 10 Feb 2026 05:52:18 -0800 (PST)", "From": "Peter Maydell <peter.maydell@linaro.org>", "To": "qemu-devel@nongnu.org", "Subject": "[PULL 13/26] hw, target,\n accel: whpx: change apic_in_platform to kernel_irqchip", "Date": "Tue, 10 Feb 2026 13:51:53 +0000", "Message-ID": "<20260210135206.229528-14-peter.maydell@linaro.org>", "X-Mailer": "git-send-email 2.43.0", "In-Reply-To": "<20260210135206.229528-1-peter.maydell@linaro.org>", "References": "<20260210135206.229528-1-peter.maydell@linaro.org>", "MIME-Version": "1.0", "Content-Transfer-Encoding": "8bit", "Received-SPF": "pass client-ip=2a00:1450:4864:20::32f;\n envelope-from=peter.maydell@linaro.org; helo=mail-wm1-x32f.google.com", "X-Spam_score_int": "-20", "X-Spam_score": "-2.1", "X-Spam_bar": "--", "X-Spam_report": "(-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1,\n DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1,\n RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001,\n SPF_PASS=-0.001 autolearn=ham autolearn_force=no", "X-Spam_action": "no action", "X-BeenThere": "qemu-devel@nongnu.org", "X-Mailman-Version": "2.1.29", "Precedence": "list", "List-Id": "qemu development <qemu-devel.nongnu.org>", "List-Unsubscribe": "<https://lists.nongnu.org/mailman/options/qemu-devel>,\n <mailto:qemu-devel-request@nongnu.org?subject=unsubscribe>", "List-Archive": "<https://lists.nongnu.org/archive/html/qemu-devel>", "List-Post": "<mailto:qemu-devel@nongnu.org>", "List-Help": "<mailto:qemu-devel-request@nongnu.org?subject=help>", "List-Subscribe": "<https://lists.nongnu.org/mailman/listinfo/qemu-devel>,\n <mailto:qemu-devel-request@nongnu.org?subject=subscribe>", "Errors-To": "qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org", "Sender": "qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org" }, "content": "From: Mohamed Mediouni <mohamed@unpredictable.fr>\n\nChange terminology to match the KVM one, as APIC is x86-specific.\n\nAnd move out whpx_irqchip_in_kernel() to make it usable from common\ncode even when not compiling with WHPX support.\n\nSigned-off-by: Mohamed Mediouni <mohamed@unpredictable.fr>\nReviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>\nReviewed-by: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>\nSigned-off-by: Peter Maydell <peter.maydell@linaro.org>\n---\n MAINTAINERS | 1 +\n accel/stubs/whpx-stub.c | 1 +\n accel/whpx/whpx-accel-ops.c | 2 +-\n accel/whpx/whpx-common.c | 10 +-\n hw/arm/virt.c | 9 ++\n hw/i386/x86-cpu.c | 4 +-\n hw/intc/arm_gicv3_common.c | 3 +\n hw/intc/arm_gicv3_whpx.c | 237 +++++++++++++++++++++++++++++\n hw/intc/meson.build | 1 +\n include/hw/intc/arm_gicv3_common.h | 3 +\n include/system/whpx-internal.h | 1 -\n include/system/whpx.h | 5 +-\n target/i386/cpu-apic.c | 2 +-\n target/i386/whpx/whpx-all.c | 14 +-\n 14 files changed, 270 insertions(+), 23 deletions(-)\n create mode 100644 hw/intc/arm_gicv3_whpx.c", "diff": "diff --git a/MAINTAINERS b/MAINTAINERS\nindex 54326b1a5a..c6af6e10bb 100644\n--- a/MAINTAINERS\n+++ b/MAINTAINERS\n@@ -566,6 +566,7 @@ M: Mohamed Mediouni <mohamed@unpredictable.fr>\n S: Supported\n F: accel/whpx/\n F: target/i386/whpx/\n+F: hw/intc/arm_gicv3_whpx.c\n F: accel/stubs/whpx-stub.c\n F: include/system/whpx.h\n F: include/system/whpx-accel-ops.h\ndiff --git a/accel/stubs/whpx-stub.c b/accel/stubs/whpx-stub.c\nindex c564c89fd0..4529dc4f78 100644\n--- a/accel/stubs/whpx-stub.c\n+++ b/accel/stubs/whpx-stub.c\n@@ -10,3 +10,4 @@\n #include \"system/whpx.h\"\n \n bool whpx_allowed;\n+bool whpx_irqchip_in_kernel;\ndiff --git a/accel/whpx/whpx-accel-ops.c b/accel/whpx/whpx-accel-ops.c\nindex c84a25c273..50fadea0fd 100644\n--- a/accel/whpx/whpx-accel-ops.c\n+++ b/accel/whpx/whpx-accel-ops.c\n@@ -78,7 +78,7 @@ static void whpx_kick_vcpu_thread(CPUState *cpu)\n \n static bool whpx_vcpu_thread_is_idle(CPUState *cpu)\n {\n- return !whpx_apic_in_platform();\n+ return !whpx_irqchip_in_kernel();\n }\n \n static void whpx_accel_ops_class_init(ObjectClass *oc, const void *data)\ndiff --git a/accel/whpx/whpx-common.c b/accel/whpx/whpx-common.c\nindex c0610815d9..05f9e520b7 100644\n--- a/accel/whpx/whpx-common.c\n+++ b/accel/whpx/whpx-common.c\n@@ -35,6 +35,7 @@\n #include <winhvplatformdefs.h>\n \n bool whpx_allowed;\n+bool whpx_irqchip_in_kernel;\n static bool whp_dispatch_initialized;\n static HMODULE hWinHvPlatform;\n #ifdef HOST_X86_64\n@@ -488,15 +489,6 @@ static const TypeInfo whpx_cpu_accel_type = {\n .abstract = true,\n };\n \n-/*\n- * Partition support\n- */\n-\n-bool whpx_apic_in_platform(void)\n-{\n- return whpx_global.apic_in_platform;\n-}\n-\n static void whpx_accel_class_init(ObjectClass *oc, const void *data)\n {\n AccelClass *ac = ACCEL_CLASS(oc);\ndiff --git a/hw/arm/virt.c b/hw/arm/virt.c\nindex aa5e992712..b7eb0cec5e 100644\n--- a/hw/arm/virt.c\n+++ b/hw/arm/virt.c\n@@ -49,6 +49,7 @@\n #include \"system/tcg.h\"\n #include \"system/kvm.h\"\n #include \"system/hvf.h\"\n+#include \"system/whpx.h\"\n #include \"system/qtest.h\"\n #include \"system/system.h\"\n #include \"hw/core/loader.h\"\n@@ -2114,6 +2115,8 @@ static void finalize_gic_version(VirtMachineState *vms)\n /* KVM w/o kernel irqchip can only deal with GICv2 */\n gics_supported |= VIRT_GIC_VERSION_2_MASK;\n accel_name = \"KVM with kernel-irqchip=off\";\n+ } else if (whpx_enabled()) {\n+ gics_supported |= VIRT_GIC_VERSION_3_MASK;\n } else if (tcg_enabled() || hvf_enabled() || qtest_enabled()) {\n gics_supported |= VIRT_GIC_VERSION_2_MASK;\n if (module_object_class_by_name(\"arm-gicv3\")) {\n@@ -2154,6 +2157,8 @@ static void finalize_msi_controller(VirtMachineState *vms)\n if (vms->msi_controller == VIRT_MSI_CTRL_AUTO) {\n if (vms->gic_version == VIRT_GIC_VERSION_2) {\n vms->msi_controller = VIRT_MSI_CTRL_GICV2M;\n+ } else if (whpx_enabled()) {\n+ vms->msi_controller = VIRT_MSI_CTRL_GICV2M;\n } else {\n vms->msi_controller = VIRT_MSI_CTRL_ITS;\n }\n@@ -2169,6 +2174,10 @@ static void finalize_msi_controller(VirtMachineState *vms)\n error_report(\"GICv2 + ITS is an invalid configuration.\");\n exit(1);\n }\n+ if (whpx_enabled()) {\n+ error_report(\"ITS not supported on WHPX.\");\n+ exit(1);\n+ }\n }\n \n assert(vms->msi_controller != VIRT_MSI_CTRL_AUTO);\ndiff --git a/hw/i386/x86-cpu.c b/hw/i386/x86-cpu.c\nindex 276f2b0cdf..95e08e3c2a 100644\n--- a/hw/i386/x86-cpu.c\n+++ b/hw/i386/x86-cpu.c\n@@ -45,7 +45,7 @@ static void pic_irq_request(void *opaque, int irq, int level)\n \n trace_x86_pic_interrupt(irq, level);\n if (cpu_is_apic_enabled(cpu->apic_state) && !kvm_irqchip_in_kernel() &&\n- !whpx_apic_in_platform()) {\n+ !whpx_irqchip_in_kernel()) {\n CPU_FOREACH(cs) {\n cpu = X86_CPU(cs);\n if (apic_accept_pic_intr(cpu->apic_state)) {\n@@ -71,7 +71,7 @@ int cpu_get_pic_interrupt(CPUX86State *env)\n X86CPU *cpu = env_archcpu(env);\n int intno;\n \n- if (!kvm_irqchip_in_kernel() && !whpx_apic_in_platform()) {\n+ if (!kvm_irqchip_in_kernel() && !whpx_irqchip_in_kernel()) {\n intno = apic_get_interrupt(cpu->apic_state);\n if (intno >= 0) {\n return intno;\ndiff --git a/hw/intc/arm_gicv3_common.c b/hw/intc/arm_gicv3_common.c\nindex 0a2e5a3e2f..9054143ea7 100644\n--- a/hw/intc/arm_gicv3_common.c\n+++ b/hw/intc/arm_gicv3_common.c\n@@ -32,6 +32,7 @@\n #include \"gicv3_internal.h\"\n #include \"hw/arm/linux-boot-if.h\"\n #include \"system/kvm.h\"\n+#include \"system/whpx.h\"\n \n \n static void gicv3_gicd_no_migration_shift_bug_post_load(GICv3State *cs)\n@@ -663,6 +664,8 @@ const char *gicv3_class_name(void)\n {\n if (kvm_irqchip_in_kernel()) {\n return \"kvm-arm-gicv3\";\n+ } else if (whpx_enabled()) {\n+ return TYPE_WHPX_GICV3;\n } else {\n if (kvm_enabled()) {\n error_report(\"Userspace GICv3 is not supported with KVM\");\ndiff --git a/hw/intc/arm_gicv3_whpx.c b/hw/intc/arm_gicv3_whpx.c\nnew file mode 100644\nindex 0000000000..849a005242\n--- /dev/null\n+++ b/hw/intc/arm_gicv3_whpx.c\n@@ -0,0 +1,237 @@\n+/* SPDX-License-Identifier: GPL-2.0-or-later */\n+/*\n+ * ARM Generic Interrupt Controller using HVF platform support\n+ *\n+ * Copyright (c) 2025 Mohamed Mediouni\n+ * Based on vGICv3 KVM code by Pavel Fedin\n+ *\n+ */\n+\n+#include \"qemu/osdep.h\"\n+#include \"qapi/error.h\"\n+#include \"hw/intc/arm_gicv3_common.h\"\n+#include \"qemu/error-report.h\"\n+#include \"qemu/module.h\"\n+#include \"system/runstate.h\"\n+#include \"system/whpx.h\"\n+#include \"system/whpx-internal.h\"\n+#include \"gicv3_internal.h\"\n+#include \"vgic_common.h\"\n+#include \"migration/blocker.h\"\n+#include \"qom/object.h\"\n+#include \"target/arm/cpregs.h\"\n+\n+#include \"hw/arm/bsa.h\"\n+#include <winhvplatform.h>\n+#include <winhvplatformdefs.h>\n+#include <winnt.h>\n+\n+struct WHPXARMGICv3Class {\n+ ARMGICv3CommonClass parent_class;\n+ DeviceRealize parent_realize;\n+ ResettablePhases parent_phases;\n+};\n+\n+OBJECT_DECLARE_TYPE(GICv3State, WHPXARMGICv3Class, WHPX_GICV3)\n+\n+/* TODO: Implement GIC state save-restore */\n+static void whpx_gicv3_check(GICv3State *s)\n+{\n+}\n+\n+static void whpx_gicv3_put(GICv3State *s)\n+{\n+ whpx_gicv3_check(s);\n+}\n+\n+static void whpx_gicv3_get(GICv3State *s)\n+{\n+}\n+\n+static void whpx_gicv3_set_irq(void *opaque, int irq, int level)\n+{\n+ struct whpx_state *whpx = &whpx_global;\n+ GICv3State *s = opaque;\n+ WHV_INTERRUPT_CONTROL interrupt_control = {\n+ .InterruptControl.InterruptType = WHvArm64InterruptTypeFixed,\n+ .RequestedVector = GIC_INTERNAL + irq,\n+ .InterruptControl.Asserted = level\n+ };\n+\n+ if (irq > s->num_irq) {\n+ return;\n+ }\n+\n+\n+ whp_dispatch.WHvRequestInterrupt(whpx->partition, &interrupt_control,\n+ sizeof(interrupt_control));\n+}\n+\n+static void whpx_gicv3_icc_reset(CPUARMState *env, const ARMCPRegInfo *ri)\n+{\n+ GICv3CPUState *c;\n+\n+ c = env->gicv3state;\n+\n+ c->icc_pmr_el1 = 0;\n+ /*\n+ * Architecturally the reset value of the ICC_BPR registers\n+ * is UNKNOWN. We set them all to 0 here; when the kernel\n+ * uses these values to program the ICH_VMCR_EL2 fields that\n+ * determine the guest-visible ICC_BPR register values, the\n+ * hardware's \"writing a value less than the minimum sets\n+ * the field to the minimum value\" behaviour will result in\n+ * them effectively resetting to the correct minimum value\n+ * for the host GIC.\n+ */\n+ c->icc_bpr[GICV3_G0] = 0;\n+ c->icc_bpr[GICV3_G1] = 0;\n+ c->icc_bpr[GICV3_G1NS] = 0;\n+\n+ c->icc_sre_el1 = 0x7;\n+ memset(c->icc_apr, 0, sizeof(c->icc_apr));\n+ memset(c->icc_igrpen, 0, sizeof(c->icc_igrpen));\n+}\n+\n+static void whpx_gicv3_reset_hold(Object *obj, ResetType type)\n+{\n+ GICv3State *s = ARM_GICV3_COMMON(obj);\n+ WHPXARMGICv3Class *kgc = WHPX_GICV3_GET_CLASS(s);\n+\n+ if (kgc->parent_phases.hold) {\n+ kgc->parent_phases.hold(obj, type);\n+ }\n+\n+ whpx_gicv3_put(s);\n+}\n+\n+\n+/*\n+ * CPU interface registers of GIC needs to be reset on CPU reset.\n+ * For the calling arm_gicv3_icc_reset() on CPU reset, we register\n+ * below ARMCPRegInfo. As we reset the whole cpu interface under single\n+ * register reset, we define only one register of CPU interface instead\n+ * of defining all the registers.\n+ */\n+static const ARMCPRegInfo gicv3_cpuif_reginfo[] = {\n+ { .name = \"ICC_CTLR_EL1\", .state = ARM_CP_STATE_BOTH,\n+ .opc0 = 3, .opc1 = 0, .crn = 12, .crm = 12, .opc2 = 4,\n+ /*\n+ * If ARM_CP_NOP is used, resetfn is not called,\n+ * So ARM_CP_NO_RAW is appropriate type.\n+ */\n+ .type = ARM_CP_NO_RAW,\n+ .access = PL1_RW,\n+ .readfn = arm_cp_read_zero,\n+ .writefn = arm_cp_write_ignore,\n+ /*\n+ * We hang the whole cpu interface reset routine off here\n+ * rather than parcelling it out into one little function\n+ * per register\n+ */\n+ .resetfn = whpx_gicv3_icc_reset,\n+ },\n+};\n+\n+static void whpx_set_reg(CPUState *cpu, WHV_REGISTER_NAME reg, WHV_REGISTER_VALUE val)\n+{\n+ struct whpx_state *whpx = &whpx_global;\n+ HRESULT hr;\n+\n+ hr = whp_dispatch.WHvSetVirtualProcessorRegisters(whpx->partition, cpu->cpu_index,\n+ ®, 1, &val);\n+\n+ if (FAILED(hr)) {\n+ error_report(\"WHPX: Failed to set register %08x, hr=%08lx\", reg, hr);\n+ }\n+}\n+\n+static void whpx_gicv3_realize(DeviceState *dev, Error **errp)\n+{\n+ ERRP_GUARD();\n+ GICv3State *s = WHPX_GICV3(dev);\n+ WHPXARMGICv3Class *kgc = WHPX_GICV3_GET_CLASS(s);\n+ int i;\n+\n+ kgc->parent_realize(dev, errp);\n+ if (*errp) {\n+ return;\n+ }\n+\n+ if (s->revision != 3) {\n+ error_setg(errp, \"unsupported GIC revision %d for platform GIC\",\n+ s->revision);\n+ return;\n+ }\n+\n+ if (s->security_extn) {\n+ error_setg(errp, \"the platform vGICv3 does not implement the \"\n+ \"security extensions\");\n+ return;\n+ }\n+\n+ if (s->nmi_support) {\n+ error_setg(errp, \"NMI is not supported with the platform GIC\");\n+ return;\n+ }\n+\n+ if (s->nb_redist_regions > 1) {\n+ error_setg(errp, \"Multiple VGICv3 redistributor regions are not \"\n+ \"supported by WHPX\");\n+ error_append_hint(errp, \"A maximum of %d VCPUs can be used\",\n+ s->redist_region_count[0]);\n+ return;\n+ }\n+\n+ gicv3_init_irqs_and_mmio(s, whpx_gicv3_set_irq, NULL);\n+\n+ for (i = 0; i < s->num_cpu; i++) {\n+ CPUState *cpu_state = qemu_get_cpu(i);\n+ ARMCPU *cpu = ARM_CPU(cpu_state);\n+ WHV_REGISTER_VALUE val = {.Reg64 = 0x080A0000 + (GICV3_REDIST_SIZE * i)};\n+ whpx_set_reg(cpu_state, WHvArm64RegisterGicrBaseGpa, val);\n+ define_arm_cp_regs(cpu, gicv3_cpuif_reginfo);\n+ }\n+\n+ if (s->maint_irq) {\n+ error_setg(errp, \"Nested virtualisation not currently supported by WHPX.\");\n+ return;\n+ }\n+\n+ error_setg(&s->migration_blocker,\n+ \"Live migration disabled because GIC state save/restore not supported on WHPX\");\n+ if (migrate_add_blocker(&s->migration_blocker, errp) < 0) {\n+ error_report_err(*errp);\n+ }\n+}\n+\n+static void whpx_gicv3_class_init(ObjectClass *klass, const void *data)\n+{\n+ DeviceClass *dc = DEVICE_CLASS(klass);\n+ ResettableClass *rc = RESETTABLE_CLASS(klass);\n+ ARMGICv3CommonClass *agcc = ARM_GICV3_COMMON_CLASS(klass);\n+ WHPXARMGICv3Class *kgc = WHPX_GICV3_CLASS(klass);\n+\n+ agcc->pre_save = whpx_gicv3_get;\n+ agcc->post_load = whpx_gicv3_put;\n+\n+ device_class_set_parent_realize(dc, whpx_gicv3_realize,\n+ &kgc->parent_realize);\n+ resettable_class_set_parent_phases(rc, NULL, whpx_gicv3_reset_hold, NULL,\n+ &kgc->parent_phases);\n+}\n+\n+static const TypeInfo whpx_arm_gicv3_info = {\n+ .name = TYPE_WHPX_GICV3,\n+ .parent = TYPE_ARM_GICV3_COMMON,\n+ .instance_size = sizeof(GICv3State),\n+ .class_init = whpx_gicv3_class_init,\n+ .class_size = sizeof(WHPXARMGICv3Class),\n+};\n+\n+static void whpx_gicv3_register_types(void)\n+{\n+ type_register_static(&whpx_arm_gicv3_info);\n+}\n+\n+type_init(whpx_gicv3_register_types)\ndiff --git a/hw/intc/meson.build b/hw/intc/meson.build\nindex faae20b93d..96742df090 100644\n--- a/hw/intc/meson.build\n+++ b/hw/intc/meson.build\n@@ -41,6 +41,7 @@ specific_ss.add(when: 'CONFIG_APIC', if_true: files('apic.c', 'apic_common.c'))\n arm_common_ss.add(when: 'CONFIG_ARM_GIC', if_true: files('arm_gicv3_cpuif_common.c'))\n arm_common_ss.add(when: 'CONFIG_ARM_GICV3', if_true: files('arm_gicv3_cpuif.c'))\n specific_ss.add(when: 'CONFIG_ARM_GIC_KVM', if_true: files('arm_gic_kvm.c'))\n+specific_ss.add(when: ['CONFIG_WHPX', 'TARGET_AARCH64'], if_true: files('arm_gicv3_whpx.c'))\n specific_ss.add(when: ['CONFIG_ARM_GIC_KVM', 'TARGET_AARCH64'], if_true: files('arm_gicv3_kvm.c', 'arm_gicv3_its_kvm.c'))\n arm_common_ss.add(when: 'CONFIG_ARM_V7M', if_true: files('armv7m_nvic.c'))\n specific_ss.add(when: 'CONFIG_GRLIB', if_true: files('grlib_irqmp.c'))\ndiff --git a/include/hw/intc/arm_gicv3_common.h b/include/hw/intc/arm_gicv3_common.h\nindex 3d24ad22d2..c55cf18120 100644\n--- a/include/hw/intc/arm_gicv3_common.h\n+++ b/include/hw/intc/arm_gicv3_common.h\n@@ -313,6 +313,9 @@ typedef struct ARMGICv3CommonClass ARMGICv3CommonClass;\n DECLARE_OBJ_CHECKERS(GICv3State, ARMGICv3CommonClass,\n ARM_GICV3_COMMON, TYPE_ARM_GICV3_COMMON)\n \n+/* Types for GICv3 kernel-irqchip */\n+#define TYPE_WHPX_GICV3 \"whpx-arm-gicv3\"\n+\n struct ARMGICv3CommonClass {\n /*< private >*/\n SysBusDeviceClass parent_class;\ndiff --git a/include/system/whpx-internal.h b/include/system/whpx-internal.h\nindex 609d0e1c08..8ded54a39b 100644\n--- a/include/system/whpx-internal.h\n+++ b/include/system/whpx-internal.h\n@@ -45,7 +45,6 @@ struct whpx_state {\n \n bool kernel_irqchip_allowed;\n bool kernel_irqchip_required;\n- bool apic_in_platform;\n };\n \n extern struct whpx_state whpx_global;\ndiff --git a/include/system/whpx.h b/include/system/whpx.h\nindex 00f6a3e523..4217a27e91 100644\n--- a/include/system/whpx.h\n+++ b/include/system/whpx.h\n@@ -25,11 +25,12 @@\n \n #ifdef CONFIG_WHPX_IS_POSSIBLE\n extern bool whpx_allowed;\n+extern bool whpx_irqchip_in_kernel;\n #define whpx_enabled() (whpx_allowed)\n-bool whpx_apic_in_platform(void);\n+#define whpx_irqchip_in_kernel() (whpx_irqchip_in_kernel)\n #else /* !CONFIG_WHPX_IS_POSSIBLE */\n #define whpx_enabled() 0\n-#define whpx_apic_in_platform() (0)\n+#define whpx_irqchip_in_kernel() (0)\n #endif /* !CONFIG_WHPX_IS_POSSIBLE */\n \n #endif /* QEMU_WHPX_H */\ndiff --git a/target/i386/cpu-apic.c b/target/i386/cpu-apic.c\nindex f7ad7b5139..eaa10ad2a3 100644\n--- a/target/i386/cpu-apic.c\n+++ b/target/i386/cpu-apic.c\n@@ -33,7 +33,7 @@ APICCommonClass *apic_get_class(Error **errp)\n apic_type = \"kvm-apic\";\n } else if (xen_enabled()) {\n apic_type = \"xen-apic\";\n- } else if (whpx_apic_in_platform()) {\n+ } else if (whpx_irqchip_in_kernel()) {\n apic_type = \"whpx-apic\";\n }\n \ndiff --git a/target/i386/whpx/whpx-all.c b/target/i386/whpx/whpx-all.c\nindex 052cda42bf..8210250dc3 100644\n--- a/target/i386/whpx/whpx-all.c\n+++ b/target/i386/whpx/whpx-all.c\n@@ -607,7 +607,7 @@ void whpx_get_registers(CPUState *cpu)\n hr);\n }\n \n- if (whpx_apic_in_platform()) {\n+ if (whpx_irqchip_in_kernel()) {\n /*\n * Fetch the TPR value from the emulated APIC. It may get overwritten\n * below with the value from CR8 returned by\n@@ -749,7 +749,7 @@ void whpx_get_registers(CPUState *cpu)\n \n assert(idx == RTL_NUMBER_OF(whpx_register_names));\n \n- if (whpx_apic_in_platform()) {\n+ if (whpx_irqchip_in_kernel()) {\n whpx_apic_get(x86_cpu->apic_state);\n }\n \n@@ -1379,7 +1379,7 @@ static void whpx_vcpu_pre_run(CPUState *cpu)\n }\n \n /* Get pending hard interruption or replay one that was overwritten */\n- if (!whpx_apic_in_platform()) {\n+ if (!whpx_irqchip_in_kernel()) {\n if (!vcpu->interruption_pending &&\n vcpu->interruptable && (env->eflags & IF_MASK)) {\n assert(!new_int.InterruptionPending);\n@@ -1553,7 +1553,7 @@ int whpx_vcpu_run(CPUState *cpu)\n \n if (exclusive_step_mode == WHPX_STEP_NONE) {\n whpx_vcpu_process_async_events(cpu);\n- if (cpu->halted && !whpx_apic_in_platform()) {\n+ if (cpu->halted && !whpx_irqchip_in_kernel()) {\n cpu->exception_index = EXCP_HLT;\n qatomic_set(&cpu->exit_request, false);\n return 0;\n@@ -1642,7 +1642,7 @@ int whpx_vcpu_run(CPUState *cpu)\n break;\n \n case WHvRunVpExitReasonX64ApicEoi:\n- assert(whpx_apic_in_platform());\n+ assert(whpx_irqchip_in_kernel());\n ioapic_eoi_broadcast(vcpu->exit_ctx.ApicEoi.InterruptVector);\n break;\n \n@@ -2187,7 +2187,7 @@ int whpx_accel_init(AccelState *as, MachineState *ms)\n goto error;\n }\n } else {\n- whpx->apic_in_platform = true;\n+ whpx_irqchip_in_kernel = true;\n }\n }\n \n@@ -2196,7 +2196,7 @@ int whpx_accel_init(AccelState *as, MachineState *ms)\n prop.ExtendedVmExits.X64MsrExit = 1;\n prop.ExtendedVmExits.X64CpuidExit = 1;\n prop.ExtendedVmExits.ExceptionExit = 1;\n- if (whpx_apic_in_platform()) {\n+ if (whpx_irqchip_in_kernel()) {\n prop.ExtendedVmExits.X64ApicInitSipiExitTrap = 1;\n }\n \n", "prefixes": [ "PULL", "13/26" ] }