get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

GET /api/patches/2195172/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 2195172,
    "url": "http://patchwork.ozlabs.org/api/patches/2195172/?format=api",
    "web_url": "http://patchwork.ozlabs.org/project/qemu-devel/patch/20260210135206.229528-11-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-11-peter.maydell@linaro.org>",
    "list_archive_url": null,
    "date": "2026-02-10T13:51:50",
    "name": "[PULL,10/26] whpx: reshuffle common code",
    "commit_ref": null,
    "pull_url": null,
    "state": "not-applicable",
    "archived": false,
    "hash": "63c7eb95e964f7ea4bfd41aba4034d619059be09",
    "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-11-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/2195172/comments/",
    "check": "pending",
    "checks": "http://patchwork.ozlabs.org/api/patches/2195172/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=GnlS9FTS;\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 4f9NNq3yvWz1xtr\n\tfor <incoming@patchwork.ozlabs.org>; Wed, 11 Feb 2026 00:55:07 +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-0002Aj-Ch; 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 1vpoAB-00021K-HS\n for qemu-devel@nongnu.org; Tue, 10 Feb 2026 08:52:23 -0500",
            "from mail-wm1-x329.google.com ([2a00:1450:4864:20::329])\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 1vpoA6-0006L0-4q\n for qemu-devel@nongnu.org; Tue, 10 Feb 2026 08:52:21 -0500",
            "by mail-wm1-x329.google.com with SMTP id\n 5b1f17b1804b1-4806f3fc50bso47910585e9.0\n for <qemu-devel@nongnu.org>; Tue, 10 Feb 2026 05:52:17 -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.15\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:15 -0800 (PST)"
        ],
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=linaro.org; s=google; t=1770731536; x=1771336336; 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=LHRt76DpiTUXu+oYqus89Ea8WBq2OqReifFSpohvo54=;\n b=GnlS9FTS4/wEEHr7DvUAjLWgX7fYT1qrH4SNi91usONZJapmr/NGS57aPuCd/jYFu8\n Otm7HnUo0Y32Z4iUJhLPOKjjkM9Znb/0mmUAmO1CFTJbZHn6610WEErGCmEYt1TRflrn\n r8dWujmSIHyMO6RcoHGZgSzDxRDTGQfQMy1nnZyB9zqlvgK+WrsoYxuzNLDaQDsLK40m\n joeHZwJlWSHgc3j6uraKC5cNNqjmEq+V6N+SSu+fzTkyOiaKK8LblWv5+25iOFJKSfq0\n Yn8meMhtqaXGEveEr8ElXGTHnud9Jfp2WbZytg/2DXjnU56rT2dmIh+TDzEt3EbjnaQs\n APpg==",
        "X-Google-DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=1e100.net; s=20230601; t=1770731536; x=1771336336;\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=LHRt76DpiTUXu+oYqus89Ea8WBq2OqReifFSpohvo54=;\n b=FvkdYk6HpoFUSWOeJuONlEfp7a+41gc5ANbL1aepqipmz44FwYoss7rpnfc0JBrloj\n zevwp9/v497mLOyU7IaO0YYsjeh+iCmS6e8hAYqi3liBQv+8S1mxGfv9A8ztK7HwYY4u\n Qti+Kb9riwni9Wvan47br9PFtnN76tLv7xkyNKbgtptLN61Nw3oM/UpEF4ZDmCWX3ii5\n Bd47NwItbnseVS9F49NAYJoLKqWJwM2YxFGUz2C+Awcd47QNJ7EfoLgARklxgoxgKBxk\n yWDsNMTjH14D5ROfdD5tcf7YlmmGqKIsvaeoCpNQ9YCjjebpFx/N/QE8kxEaHf7DpNlm\n yW+g==",
        "X-Gm-Message-State": "AOJu0YxEp0mSKcvMtazlkSvjynJ3DnP1FY+QiyD4jc45+TAXbaE1pCVS\n mPF+lWBAUuNMaepFOKebLMb4xGq4uqEIZ8l/htNypZEM75663mzWfTn9xYwmgU+93X36EwYUQu1\n vV15N",
        "X-Gm-Gg": "AZuq6aJTKoVYLoMOnYFioLtiE+TqmRPW9M/5Mh9dGkyJe+irOjD07u3n95FgrXRkXTj\n zcW+Fl7xSeg0fPgLigcfGkRb+yZnMUJSELMRTNWKtVD5q2lQq6A6pPxCrDiJ3j2NoPVH/Qbxzd5\n +pneqYtP+z/TASjrVnigVlfUea3M3ioJBgy3Y+iAhSZddxS3w9kcJS1A50I/ODqan9SfiJVs+zS\n oCToglwJVqlvhkS+s1Kuu5/Eg7MyIpSFxtaBDDakWUtA3tF+gN2CtdHzzBNtuukezz3UDkPAL3u\n CCRJAUzg3QI/OWt3haouiDtQHzsjz5OMF5Kh3Is4U9Gqv2pS0lViVkZXRLsWA4FOhDIjrGw9dEJ\n w3k4pJi6wodRP5NXJ4aLP5U1pMPAa9fWvOxWs64NBDeB4irL6k7TDfL2IM1U37blnzZCeSuzDbO\n S8nUWLIDxwBSJyWuqY0L0hwxczqkhH/87Ir/rwS+sHLKR5m0JbDRbUMWbamd+4XCdCt9owjrA1I\n f4Jm+j15ZTp112NodH/a505bWVXhJM=",
        "X-Received": "by 2002:a05:600c:19c7:b0:480:1e9e:f9d with SMTP id\n 5b1f17b1804b1-483201db0bcmr222865225e9.8.1770731536144;\n Tue, 10 Feb 2026 05:52:16 -0800 (PST)",
        "From": "Peter Maydell <peter.maydell@linaro.org>",
        "To": "qemu-devel@nongnu.org",
        "Subject": "[PULL 10/26] whpx: reshuffle common code",
        "Date": "Tue, 10 Feb 2026 13:51:50 +0000",
        "Message-ID": "<20260210135206.229528-11-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::329;\n envelope-from=peter.maydell@linaro.org; helo=mail-wm1-x329.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\nSome code can be shared between x86_64 and arm64 WHPX. Do so as much as reasonable.\n\nSigned-off-by: Mohamed Mediouni <mohamed@unpredictable.fr>\n\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                  |   2 +\n accel/whpx/meson.build       |   1 +\n accel/whpx/whpx-common.c     | 558 +++++++++++++++++++++++++++++++++++\n include/system/whpx-all.h    |  20 ++\n include/system/whpx-common.h |  21 ++\n target/i386/whpx/whpx-all.c  | 551 +---------------------------------\n 6 files changed, 612 insertions(+), 541 deletions(-)\n create mode 100644 accel/whpx/whpx-common.c\n create mode 100644 include/system/whpx-all.h\n create mode 100644 include/system/whpx-common.h",
    "diff": "diff --git a/MAINTAINERS b/MAINTAINERS\nindex 3a0fe1081a..54326b1a5a 100644\n--- a/MAINTAINERS\n+++ b/MAINTAINERS\n@@ -569,6 +569,8 @@ F: target/i386/whpx/\n F: accel/stubs/whpx-stub.c\n F: include/system/whpx.h\n F: include/system/whpx-accel-ops.h\n+F: include/system/whpx-common.h\n+F: include/system/whpx-internal.h\n \n MSHV\n M: Magnus Kulke <magnus.kulke@linux.microsoft.com>\ndiff --git a/accel/whpx/meson.build b/accel/whpx/meson.build\nindex 7b3d6f1c1c..fad28dddcb 100644\n--- a/accel/whpx/meson.build\n+++ b/accel/whpx/meson.build\n@@ -1,6 +1,7 @@\n whpx_ss = ss.source_set()\n whpx_ss.add(files(\n   'whpx-accel-ops.c',\n+  'whpx-common.c'\n ))\n \n specific_ss.add_all(when: 'CONFIG_WHPX', if_true: whpx_ss)\ndiff --git a/accel/whpx/whpx-common.c b/accel/whpx/whpx-common.c\nnew file mode 100644\nindex 0000000000..0a6068fdde\n--- /dev/null\n+++ b/accel/whpx/whpx-common.c\n@@ -0,0 +1,558 @@\n+/* SPDX-License-Identifier: GPL-2.0-or-later */\n+/*\n+ * QEMU Windows Hypervisor Platform accelerator (WHPX)\n+ *\n+ * Copyright Microsoft Corp. 2017\n+ */\n+\n+#include \"qemu/osdep.h\"\n+#include \"cpu.h\"\n+#include \"system/address-spaces.h\"\n+#include \"system/ioport.h\"\n+#include \"gdbstub/helpers.h\"\n+#include \"qemu/accel.h\"\n+#include \"accel/accel-ops.h\"\n+#include \"system/whpx.h\"\n+#include \"system/cpus.h\"\n+#include \"system/runstate.h\"\n+#include \"qemu/main-loop.h\"\n+#include \"hw/core/boards.h\"\n+#include \"hw/intc/ioapic.h\"\n+#include \"qemu/error-report.h\"\n+#include \"qapi/error.h\"\n+#include \"qapi/qapi-types-common.h\"\n+#include \"qapi/qapi-visit-common.h\"\n+#include \"migration/blocker.h\"\n+#include \"accel/accel-cpu-target.h\"\n+#include <winerror.h>\n+\n+#include \"system/whpx-internal.h\"\n+#include \"system/whpx-accel-ops.h\"\n+#include \"system/whpx-common.h\"\n+#include \"system/whpx-all.h\"\n+\n+#include <winhvplatform.h>\n+#include <winhvplatformdefs.h>\n+\n+bool whpx_allowed;\n+static bool whp_dispatch_initialized;\n+static HMODULE hWinHvPlatform;\n+static HMODULE hWinHvEmulation;\n+\n+struct whpx_state whpx_global;\n+struct WHPDispatch whp_dispatch;\n+\n+/* Tries to find a breakpoint at the specified address. */\n+struct whpx_breakpoint *whpx_lookup_breakpoint_by_addr(uint64_t address)\n+{\n+    struct whpx_state *whpx = &whpx_global;\n+    int i;\n+\n+    if (whpx->breakpoints.breakpoints) {\n+        for (i = 0; i < whpx->breakpoints.breakpoints->used; i++) {\n+            if (address == whpx->breakpoints.breakpoints->data[i].address) {\n+                return &whpx->breakpoints.breakpoints->data[i];\n+            }\n+        }\n+    }\n+\n+    return NULL;\n+}\n+\n+/*\n+ * This function is called when the a VCPU is about to start and no other\n+ * VCPUs have been started so far. Since the VCPU start order could be\n+ * arbitrary, it doesn't have to be VCPU#0.\n+ *\n+ * It is used to commit the breakpoints into memory, and configure WHPX\n+ * to intercept debug exceptions.\n+ *\n+ * Note that whpx_set_exception_exit_bitmap() cannot be called if one or\n+ * more VCPUs are already running, so this is the best place to do it.\n+ */\n+int whpx_first_vcpu_starting(CPUState *cpu)\n+{\n+    struct whpx_state *whpx = &whpx_global;\n+\n+    g_assert(bql_locked());\n+\n+    if (!QTAILQ_EMPTY(&cpu->breakpoints) ||\n+            (whpx->breakpoints.breakpoints &&\n+             whpx->breakpoints.breakpoints->used)) {\n+        CPUBreakpoint *bp;\n+        int i = 0;\n+        bool update_pending = false;\n+\n+        QTAILQ_FOREACH(bp, &cpu->breakpoints, entry) {\n+            if (i >= whpx->breakpoints.original_address_count ||\n+                bp->pc != whpx->breakpoints.original_addresses[i]) {\n+                update_pending = true;\n+            }\n+\n+            i++;\n+        }\n+\n+        if (i != whpx->breakpoints.original_address_count) {\n+            update_pending = true;\n+        }\n+\n+        if (update_pending) {\n+            /*\n+             * The CPU breakpoints have changed since the last call to\n+             * whpx_translate_cpu_breakpoints(). WHPX breakpoints must\n+             * now be recomputed.\n+             */\n+            whpx_translate_cpu_breakpoints(&whpx->breakpoints, cpu, i);\n+        }\n+        /* Actually insert the breakpoints into the memory. */\n+        whpx_apply_breakpoints(whpx->breakpoints.breakpoints, cpu, true);\n+    }\n+    HRESULT hr;\n+    uint64_t exception_mask;\n+    if (whpx->step_pending ||\n+        (whpx->breakpoints.breakpoints &&\n+         whpx->breakpoints.breakpoints->used)) {\n+        /*\n+         * We are either attempting to single-step one or more CPUs, or\n+         * have one or more breakpoints enabled. Both require intercepting\n+         * the WHvX64ExceptionTypeBreakpointTrap exception.\n+         */\n+        exception_mask = 1UL << WHvX64ExceptionTypeDebugTrapOrFault;\n+    } else {\n+        /* Let the guest handle all exceptions. */\n+        exception_mask = 0;\n+    }\n+    hr = whpx_set_exception_exit_bitmap(exception_mask);\n+    if (!SUCCEEDED(hr)) {\n+        error_report(\"WHPX: Failed to update exception exit mask,\"\n+                     \"hr=%08lx.\", hr);\n+        return 1;\n+    }\n+    return 0;\n+}\n+\n+/*\n+ * This function is called when the last VCPU has finished running.\n+ * It is used to remove any previously set breakpoints from memory.\n+ */\n+int whpx_last_vcpu_stopping(CPUState *cpu)\n+{\n+    whpx_apply_breakpoints(whpx_global.breakpoints.breakpoints, cpu, false);\n+    return 0;\n+}\n+\n+static void do_whpx_cpu_synchronize_state(CPUState *cpu, run_on_cpu_data arg)\n+{\n+    if (!cpu->vcpu_dirty) {\n+        whpx_get_registers(cpu);\n+        cpu->vcpu_dirty = true;\n+    }\n+}\n+\n+static void do_whpx_cpu_synchronize_post_reset(CPUState *cpu,\n+                                               run_on_cpu_data arg)\n+{\n+    whpx_set_registers(cpu, WHPX_SET_RESET_STATE);\n+    cpu->vcpu_dirty = false;\n+}\n+\n+static void do_whpx_cpu_synchronize_post_init(CPUState *cpu,\n+                                              run_on_cpu_data arg)\n+{\n+    whpx_set_registers(cpu, WHPX_SET_FULL_STATE);\n+    cpu->vcpu_dirty = false;\n+}\n+\n+static void do_whpx_cpu_synchronize_pre_loadvm(CPUState *cpu,\n+                                               run_on_cpu_data arg)\n+{\n+    cpu->vcpu_dirty = true;\n+}\n+\n+/*\n+ * CPU support.\n+ */\n+\n+void whpx_cpu_synchronize_state(CPUState *cpu)\n+{\n+    if (!cpu->vcpu_dirty) {\n+        run_on_cpu(cpu, do_whpx_cpu_synchronize_state, RUN_ON_CPU_NULL);\n+    }\n+}\n+\n+void whpx_cpu_synchronize_post_reset(CPUState *cpu)\n+{\n+    run_on_cpu(cpu, do_whpx_cpu_synchronize_post_reset, RUN_ON_CPU_NULL);\n+}\n+\n+void whpx_cpu_synchronize_post_init(CPUState *cpu)\n+{\n+    run_on_cpu(cpu, do_whpx_cpu_synchronize_post_init, RUN_ON_CPU_NULL);\n+}\n+\n+void whpx_cpu_synchronize_pre_loadvm(CPUState *cpu)\n+{\n+    run_on_cpu(cpu, do_whpx_cpu_synchronize_pre_loadvm, RUN_ON_CPU_NULL);\n+}\n+\n+static void whpx_pre_resume_vm(AccelState *as, bool step_pending)\n+{\n+    whpx_global.step_pending = step_pending;\n+}\n+\n+/*\n+ * Vcpu support.\n+ */\n+\n+int whpx_vcpu_exec(CPUState *cpu)\n+{\n+    int ret;\n+    int fatal;\n+\n+    for (;;) {\n+        if (cpu->exception_index >= EXCP_INTERRUPT) {\n+            ret = cpu->exception_index;\n+            cpu->exception_index = -1;\n+            break;\n+        }\n+\n+        fatal = whpx_vcpu_run(cpu);\n+\n+        if (fatal) {\n+            error_report(\"WHPX: Failed to exec a virtual processor\");\n+            abort();\n+        }\n+    }\n+\n+    return ret;\n+}\n+\n+void whpx_destroy_vcpu(CPUState *cpu)\n+{\n+    struct whpx_state *whpx = &whpx_global;\n+\n+    whp_dispatch.WHvDeleteVirtualProcessor(whpx->partition, cpu->cpu_index);\n+    AccelCPUState *vcpu = cpu->accel;\n+    whp_dispatch.WHvEmulatorDestroyEmulator(vcpu->emulator);\n+    g_free(cpu->accel);\n+}\n+\n+\n+void whpx_vcpu_kick(CPUState *cpu)\n+{\n+    struct whpx_state *whpx = &whpx_global;\n+    whp_dispatch.WHvCancelRunVirtualProcessor(\n+        whpx->partition, cpu->cpu_index, 0);\n+}\n+\n+/*\n+ * Memory support.\n+ */\n+\n+static void whpx_update_mapping(hwaddr start_pa, ram_addr_t size,\n+                                void *host_va, int add, int rom,\n+                                const char *name)\n+{\n+    struct whpx_state *whpx = &whpx_global;\n+    HRESULT hr;\n+\n+    /*\n+    if (add) {\n+        printf(\"WHPX: ADD PA:%p Size:%p, Host:%p, %s, '%s'\\n\",\n+               (void*)start_pa, (void*)size, host_va,\n+               (rom ? \"ROM\" : \"RAM\"), name);\n+    } else {\n+        printf(\"WHPX: DEL PA:%p Size:%p, Host:%p,      '%s'\\n\",\n+               (void*)start_pa, (void*)size, host_va, name);\n+    }\n+    */\n+\n+    if (add) {\n+        hr = whp_dispatch.WHvMapGpaRange(whpx->partition,\n+                                         host_va,\n+                                         start_pa,\n+                                         size,\n+                                         (WHvMapGpaRangeFlagRead |\n+                                          WHvMapGpaRangeFlagExecute |\n+                                          (rom ? 0 : WHvMapGpaRangeFlagWrite)));\n+    } else {\n+        hr = whp_dispatch.WHvUnmapGpaRange(whpx->partition,\n+                                           start_pa,\n+                                           size);\n+    }\n+\n+    if (FAILED(hr)) {\n+        error_report(\"WHPX: Failed to %s GPA range '%s' PA:%p, Size:%p bytes,\"\n+                     \" Host:%p, hr=%08lx\",\n+                     (add ? \"MAP\" : \"UNMAP\"), name,\n+                     (void *)(uintptr_t)start_pa, (void *)size, host_va, hr);\n+    }\n+}\n+\n+static void whpx_process_section(MemoryRegionSection *section, int add)\n+{\n+    MemoryRegion *mr = section->mr;\n+    hwaddr start_pa = section->offset_within_address_space;\n+    ram_addr_t size = int128_get64(section->size);\n+    unsigned int delta;\n+    uint64_t host_va;\n+\n+    if (!memory_region_is_ram(mr)) {\n+        return;\n+    }\n+\n+    delta = qemu_real_host_page_size() - (start_pa & ~qemu_real_host_page_mask());\n+    delta &= ~qemu_real_host_page_mask();\n+    if (delta > size) {\n+        return;\n+    }\n+    start_pa += delta;\n+    size -= delta;\n+    size &= qemu_real_host_page_mask();\n+    if (!size || (start_pa & ~qemu_real_host_page_mask())) {\n+        return;\n+    }\n+\n+    host_va = (uintptr_t)memory_region_get_ram_ptr(mr)\n+            + section->offset_within_region + delta;\n+\n+    whpx_update_mapping(start_pa, size, (void *)(uintptr_t)host_va, add,\n+                        memory_region_is_rom(mr), mr->name);\n+}\n+\n+static void whpx_region_add(MemoryListener *listener,\n+                           MemoryRegionSection *section)\n+{\n+    memory_region_ref(section->mr);\n+    whpx_process_section(section, 1);\n+}\n+\n+static void whpx_region_del(MemoryListener *listener,\n+                           MemoryRegionSection *section)\n+{\n+    whpx_process_section(section, 0);\n+    memory_region_unref(section->mr);\n+}\n+\n+static void whpx_transaction_begin(MemoryListener *listener)\n+{\n+}\n+\n+static void whpx_transaction_commit(MemoryListener *listener)\n+{\n+}\n+\n+static void whpx_log_sync(MemoryListener *listener,\n+                         MemoryRegionSection *section)\n+{\n+    MemoryRegion *mr = section->mr;\n+\n+    if (!memory_region_is_ram(mr)) {\n+        return;\n+    }\n+\n+    memory_region_set_dirty(mr, 0, int128_get64(section->size));\n+}\n+\n+static MemoryListener whpx_memory_listener = {\n+    .name = \"whpx\",\n+    .begin = whpx_transaction_begin,\n+    .commit = whpx_transaction_commit,\n+    .region_add = whpx_region_add,\n+    .region_del = whpx_region_del,\n+    .log_sync = whpx_log_sync,\n+    .priority = MEMORY_LISTENER_PRIORITY_ACCEL,\n+};\n+\n+void whpx_memory_init(void)\n+{\n+    memory_listener_register(&whpx_memory_listener, &address_space_memory);\n+}\n+\n+/*\n+ * Load the functions from the given library, using the given handle. If a\n+ * handle is provided, it is used, otherwise the library is opened. The\n+ * handle will be updated on return with the opened one.\n+ */\n+static bool load_whp_dispatch_fns(HMODULE *handle,\n+    WHPFunctionList function_list)\n+{\n+    HMODULE hLib = *handle;\n+\n+    #define WINHV_PLATFORM_DLL \"WinHvPlatform.dll\"\n+    #define WINHV_EMULATION_DLL \"WinHvEmulation.dll\"\n+    #define WHP_LOAD_FIELD_OPTIONAL(return_type, function_name, signature) \\\n+        whp_dispatch.function_name = \\\n+            (function_name ## _t)GetProcAddress(hLib, #function_name); \\\n+\n+    #define WHP_LOAD_FIELD(return_type, function_name, signature) \\\n+        whp_dispatch.function_name = \\\n+            (function_name ## _t)GetProcAddress(hLib, #function_name); \\\n+        if (!whp_dispatch.function_name) { \\\n+            error_report(\"Could not load function %s\", #function_name); \\\n+            goto error; \\\n+        } \\\n+\n+    #define WHP_LOAD_LIB(lib_name, handle_lib) \\\n+    if (!handle_lib) { \\\n+        handle_lib = LoadLibrary(lib_name); \\\n+        if (!handle_lib) { \\\n+            error_report(\"Could not load library %s.\", lib_name); \\\n+            goto error; \\\n+        } \\\n+    } \\\n+\n+    switch (function_list) {\n+    case WINHV_PLATFORM_FNS_DEFAULT:\n+        WHP_LOAD_LIB(WINHV_PLATFORM_DLL, hLib)\n+        LIST_WINHVPLATFORM_FUNCTIONS(WHP_LOAD_FIELD)\n+        break;\n+    case WINHV_EMULATION_FNS_DEFAULT:\n+        WHP_LOAD_LIB(WINHV_EMULATION_DLL, hLib)\n+        LIST_WINHVEMULATION_FUNCTIONS(WHP_LOAD_FIELD)\n+        break;\n+    case WINHV_PLATFORM_FNS_SUPPLEMENTAL:\n+        WHP_LOAD_LIB(WINHV_PLATFORM_DLL, hLib)\n+        LIST_WINHVPLATFORM_FUNCTIONS_SUPPLEMENTAL(WHP_LOAD_FIELD_OPTIONAL)\n+        break;\n+    }\n+\n+    *handle = hLib;\n+    return true;\n+\n+error:\n+    if (hLib) {\n+        FreeLibrary(hLib);\n+    }\n+\n+    return false;\n+}\n+\n+static void whpx_set_kernel_irqchip(Object *obj, Visitor *v,\n+                                   const char *name, void *opaque,\n+                                   Error **errp)\n+{\n+    struct whpx_state *whpx = &whpx_global;\n+    OnOffSplit mode;\n+\n+    if (!visit_type_OnOffSplit(v, name, &mode, errp)) {\n+        return;\n+    }\n+\n+    switch (mode) {\n+    case ON_OFF_SPLIT_ON:\n+        whpx->kernel_irqchip_allowed = true;\n+        whpx->kernel_irqchip_required = true;\n+        break;\n+\n+    case ON_OFF_SPLIT_OFF:\n+        whpx->kernel_irqchip_allowed = false;\n+        whpx->kernel_irqchip_required = false;\n+        break;\n+\n+    case ON_OFF_SPLIT_SPLIT:\n+        error_setg(errp, \"WHPX: split irqchip currently not supported\");\n+        error_append_hint(errp,\n+            \"Try without kernel-irqchip or with kernel-irqchip=on|off\");\n+        break;\n+\n+    default:\n+        /*\n+         * The value was checked in visit_type_OnOffSplit() above. If\n+         * we get here, then something is wrong in QEMU.\n+         */\n+        abort();\n+    }\n+}\n+\n+static void whpx_cpu_accel_class_init(ObjectClass *oc, const void *data)\n+{\n+    AccelCPUClass *acc = ACCEL_CPU_CLASS(oc);\n+\n+    acc->cpu_instance_init = whpx_cpu_instance_init;\n+}\n+\n+static const TypeInfo whpx_cpu_accel_type = {\n+    .name = ACCEL_CPU_NAME(\"whpx\"),\n+\n+    .parent = TYPE_ACCEL_CPU,\n+    .class_init = whpx_cpu_accel_class_init,\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);\n+    ac->name = \"WHPX\";\n+    ac->init_machine = whpx_accel_init;\n+    ac->pre_resume_vm = whpx_pre_resume_vm;\n+    ac->allowed = &whpx_allowed;\n+\n+    object_class_property_add(oc, \"kernel-irqchip\", \"on|off|split\",\n+        NULL, whpx_set_kernel_irqchip,\n+        NULL, NULL);\n+    object_class_property_set_description(oc, \"kernel-irqchip\",\n+        \"Configure WHPX in-kernel irqchip\");\n+}\n+\n+static void whpx_accel_instance_init(Object *obj)\n+{\n+    struct whpx_state *whpx = &whpx_global;\n+\n+    memset(whpx, 0, sizeof(struct whpx_state));\n+    /* Turn on kernel-irqchip, by default */\n+    whpx->kernel_irqchip_allowed = true;\n+}\n+\n+static const TypeInfo whpx_accel_type = {\n+    .name = ACCEL_CLASS_NAME(\"whpx\"),\n+    .parent = TYPE_ACCEL,\n+    .instance_init = whpx_accel_instance_init,\n+    .class_init = whpx_accel_class_init,\n+};\n+\n+static void whpx_type_init(void)\n+{\n+    type_register_static(&whpx_accel_type);\n+    type_register_static(&whpx_cpu_accel_type);\n+}\n+\n+bool init_whp_dispatch(void)\n+{\n+    if (whp_dispatch_initialized) {\n+        return true;\n+    }\n+\n+    if (!load_whp_dispatch_fns(&hWinHvPlatform, WINHV_PLATFORM_FNS_DEFAULT)) {\n+        goto error;\n+    }\n+\n+    if (!load_whp_dispatch_fns(&hWinHvEmulation, WINHV_EMULATION_FNS_DEFAULT)) {\n+        goto error;\n+    }\n+\n+    assert(load_whp_dispatch_fns(&hWinHvPlatform,\n+        WINHV_PLATFORM_FNS_SUPPLEMENTAL));\n+    whp_dispatch_initialized = true;\n+\n+    return true;\n+error:\n+    if (hWinHvPlatform) {\n+        FreeLibrary(hWinHvPlatform);\n+    }\n+    if (hWinHvEmulation) {\n+        FreeLibrary(hWinHvEmulation);\n+    }\n+    return false;\n+}\n+\n+type_init(whpx_type_init);\ndiff --git a/include/system/whpx-all.h b/include/system/whpx-all.h\nnew file mode 100644\nindex 0000000000..f13cdf7f66\n--- /dev/null\n+++ b/include/system/whpx-all.h\n@@ -0,0 +1,20 @@\n+/* SPDX-License-Identifier: GPL-2.0-or-later */\n+#ifndef SYSTEM_WHPX_ALL_H\n+#define SYSTEM_WHPX_ALL_H\n+\n+/* Called by whpx-common */\n+int whpx_vcpu_run(CPUState *cpu);\n+void whpx_get_registers(CPUState *cpu);\n+void whpx_set_registers(CPUState *cpu, int level);\n+int whpx_accel_init(AccelState *as, MachineState *ms);\n+void whpx_cpu_instance_init(CPUState *cs);\n+HRESULT whpx_set_exception_exit_bitmap(UINT64 exceptions);\n+void whpx_apply_breakpoints(\n+struct whpx_breakpoint_collection *breakpoints,\n+    CPUState *cpu,\n+    bool resuming);\n+void whpx_translate_cpu_breakpoints(\n+    struct whpx_breakpoints *breakpoints,\n+    CPUState *cpu,\n+    int cpu_breakpoint_count);\n+#endif\ndiff --git a/include/system/whpx-common.h b/include/system/whpx-common.h\nnew file mode 100644\nindex 0000000000..e549c7539c\n--- /dev/null\n+++ b/include/system/whpx-common.h\n@@ -0,0 +1,21 @@\n+/* SPDX-License-Identifier: GPL-2.0-or-later */\n+#ifndef SYSTEM_WHPX_COMMON_H\n+#define SYSTEM_WHPX_COMMON_H\n+\n+struct AccelCPUState {\n+    WHV_EMULATOR_HANDLE emulator;\n+    bool window_registered;\n+    bool interruptable;\n+    bool ready_for_pic_interrupt;\n+    uint64_t tpr;\n+    uint64_t apic_base;\n+    bool interruption_pending;\n+    /* Must be the last field as it may have a tail */\n+    WHV_RUN_VP_EXIT_CONTEXT exit_ctx;\n+};\n+\n+int whpx_first_vcpu_starting(CPUState *cpu);\n+int whpx_last_vcpu_stopping(CPUState *cpu);\n+void whpx_memory_init(void);\n+struct whpx_breakpoint *whpx_lookup_breakpoint_by_addr(uint64_t address);\n+#endif\ndiff --git a/target/i386/whpx/whpx-all.c b/target/i386/whpx/whpx-all.c\nindex cef31fc1a8..052cda42bf 100644\n--- a/target/i386/whpx/whpx-all.c\n+++ b/target/i386/whpx/whpx-all.c\n@@ -33,6 +33,8 @@\n \n #include \"system/whpx-internal.h\"\n #include \"system/whpx-accel-ops.h\"\n+#include \"system/whpx-all.h\"\n+#include \"system/whpx-common.h\"\n \n #include <winhvplatform.h>\n #include <winhvemulation.h>\n@@ -232,28 +234,9 @@ typedef enum WhpxStepMode {\n     WHPX_STEP_EXCLUSIVE,\n } WhpxStepMode;\n \n-struct AccelCPUState {\n-    WHV_EMULATOR_HANDLE emulator;\n-    bool window_registered;\n-    bool interruptable;\n-    bool ready_for_pic_interrupt;\n-    uint64_t tpr;\n-    uint64_t apic_base;\n-    bool interruption_pending;\n-\n-    /* Must be the last field as it may have a tail */\n-    WHV_RUN_VP_EXIT_CONTEXT exit_ctx;\n-};\n-\n-bool whpx_allowed;\n-static bool whp_dispatch_initialized;\n-static HMODULE hWinHvPlatform, hWinHvEmulation;\n static uint32_t max_vcpu_index;\n static WHV_PROCESSOR_XSAVE_FEATURES whpx_xsave_cap;\n \n-struct whpx_state whpx_global;\n-struct WHPDispatch whp_dispatch;\n-\n static bool whpx_has_xsave(void)\n {\n     return whpx_xsave_cap.XsaveSupport;\n@@ -379,7 +362,7 @@ static uint64_t whpx_cr8_to_apic_tpr(uint64_t cr8)\n     return cr8 << 4;\n }\n \n-static void whpx_set_registers(CPUState *cpu, int level)\n+void whpx_set_registers(CPUState *cpu, int level)\n {\n     struct whpx_state *whpx = &whpx_global;\n     AccelCPUState *vcpu = cpu->accel;\n@@ -594,7 +577,7 @@ static void whpx_get_xcrs(CPUState *cpu)\n     cpu_env(cpu)->xcr0 = xcr0.Reg64;\n }\n \n-static void whpx_get_registers(CPUState *cpu)\n+void whpx_get_registers(CPUState *cpu)\n {\n     struct whpx_state *whpx = &whpx_global;\n     AccelCPUState *vcpu = cpu->accel;\n@@ -934,7 +917,7 @@ static int whpx_handle_portio(CPUState *cpu,\n  * The 'exceptions' argument accepts a bitmask, e.g:\n  * (1 << WHvX64ExceptionTypeDebugTrapOrFault) | (...)\n  */\n-static HRESULT whpx_set_exception_exit_bitmap(UINT64 exceptions)\n+HRESULT whpx_set_exception_exit_bitmap(UINT64 exceptions)\n {\n     struct whpx_state *whpx = &whpx_global;\n     WHV_PARTITION_PROPERTY prop = { 0, };\n@@ -1084,23 +1067,6 @@ static HRESULT whpx_vcpu_configure_single_stepping(CPUState *cpu,\n     return S_OK;\n }\n \n-/* Tries to find a breakpoint at the specified address. */\n-static struct whpx_breakpoint *whpx_lookup_breakpoint_by_addr(uint64_t address)\n-{\n-    struct whpx_state *whpx = &whpx_global;\n-    int i;\n-\n-    if (whpx->breakpoints.breakpoints) {\n-        for (i = 0; i < whpx->breakpoints.breakpoints->used; i++) {\n-            if (address == whpx->breakpoints.breakpoints->data[i].address) {\n-                return &whpx->breakpoints.breakpoints->data[i];\n-            }\n-        }\n-    }\n-\n-    return NULL;\n-}\n-\n /*\n  * Linux uses int3 (0xCC) during startup (see int3_selftest()) and for\n  * debugging user-mode applications. Since the WHPX API does not offer\n@@ -1136,7 +1102,7 @@ static const uint8_t whpx_breakpoint_instruction = 0xF1;\n  * memory, but doesn't actually do it. The memory accessing is done in\n  * whpx_apply_breakpoints().\n  */\n-static void whpx_translate_cpu_breakpoints(\n+void whpx_translate_cpu_breakpoints(\n     struct whpx_breakpoints *breakpoints,\n     CPUState *cpu,\n     int cpu_breakpoint_count)\n@@ -1230,7 +1196,7 @@ static void whpx_translate_cpu_breakpoints(\n  * Passing resuming=true  will try to set all previously unset breakpoints.\n  * Passing resuming=false will remove all inserted ones.\n  */\n-static void whpx_apply_breakpoints(\n+void whpx_apply_breakpoints(\n     struct whpx_breakpoint_collection *breakpoints,\n     CPUState *cpu,\n     bool resuming)\n@@ -1306,93 +1272,6 @@ static void whpx_apply_breakpoints(\n     }\n }\n \n-/*\n- * This function is called when the a VCPU is about to start and no other\n- * VCPUs have been started so far. Since the VCPU start order could be\n- * arbitrary, it doesn't have to be VCPU#0.\n- *\n- * It is used to commit the breakpoints into memory, and configure WHPX\n- * to intercept debug exceptions.\n- *\n- * Note that whpx_set_exception_exit_bitmap() cannot be called if one or\n- * more VCPUs are already running, so this is the best place to do it.\n- */\n-static int whpx_first_vcpu_starting(CPUState *cpu)\n-{\n-    struct whpx_state *whpx = &whpx_global;\n-    HRESULT hr;\n-\n-    g_assert(bql_locked());\n-\n-    if (!QTAILQ_EMPTY(&cpu->breakpoints) ||\n-            (whpx->breakpoints.breakpoints &&\n-             whpx->breakpoints.breakpoints->used)) {\n-        CPUBreakpoint *bp;\n-        int i = 0;\n-        bool update_pending = false;\n-\n-        QTAILQ_FOREACH(bp, &cpu->breakpoints, entry) {\n-            if (i >= whpx->breakpoints.original_address_count ||\n-                bp->pc != whpx->breakpoints.original_addresses[i]) {\n-                update_pending = true;\n-            }\n-\n-            i++;\n-        }\n-\n-        if (i != whpx->breakpoints.original_address_count) {\n-            update_pending = true;\n-        }\n-\n-        if (update_pending) {\n-            /*\n-             * The CPU breakpoints have changed since the last call to\n-             * whpx_translate_cpu_breakpoints(). WHPX breakpoints must\n-             * now be recomputed.\n-             */\n-            whpx_translate_cpu_breakpoints(&whpx->breakpoints, cpu, i);\n-        }\n-\n-        /* Actually insert the breakpoints into the memory. */\n-        whpx_apply_breakpoints(whpx->breakpoints.breakpoints, cpu, true);\n-    }\n-\n-    uint64_t exception_mask;\n-    if (whpx->step_pending ||\n-        (whpx->breakpoints.breakpoints &&\n-         whpx->breakpoints.breakpoints->used)) {\n-        /*\n-         * We are either attempting to single-step one or more CPUs, or\n-         * have one or more breakpoints enabled. Both require intercepting\n-         * the WHvX64ExceptionTypeBreakpointTrap exception.\n-         */\n-\n-        exception_mask = 1UL << WHvX64ExceptionTypeDebugTrapOrFault;\n-    } else {\n-        /* Let the guest handle all exceptions. */\n-        exception_mask = 0;\n-    }\n-\n-    hr = whpx_set_exception_exit_bitmap(exception_mask);\n-    if (!SUCCEEDED(hr)) {\n-        error_report(\"WHPX: Failed to update exception exit mask,\"\n-                     \"hr=%08lx.\", hr);\n-        return 1;\n-    }\n-\n-    return 0;\n-}\n-\n-/*\n- * This function is called when the last VCPU has finished running.\n- * It is used to remove any previously set breakpoints from memory.\n- */\n-static int whpx_last_vcpu_stopping(CPUState *cpu)\n-{\n-    whpx_apply_breakpoints(whpx_global.breakpoints.breakpoints, cpu, false);\n-    return 0;\n-}\n-\n /* Returns the address of the next instruction that is about to be executed. */\n static vaddr whpx_vcpu_get_pc(CPUState *cpu, bool exit_context_valid)\n {\n@@ -1634,7 +1513,7 @@ static void whpx_vcpu_process_async_events(CPUState *cpu)\n     }\n }\n \n-static int whpx_vcpu_run(CPUState *cpu)\n+int whpx_vcpu_run(CPUState *cpu)\n {\n     HRESULT hr;\n     struct whpx_state *whpx = &whpx_global;\n@@ -2057,65 +1936,6 @@ static int whpx_vcpu_run(CPUState *cpu)\n     return ret < 0;\n }\n \n-static void do_whpx_cpu_synchronize_state(CPUState *cpu, run_on_cpu_data arg)\n-{\n-    if (!cpu->vcpu_dirty) {\n-        whpx_get_registers(cpu);\n-        cpu->vcpu_dirty = true;\n-    }\n-}\n-\n-static void do_whpx_cpu_synchronize_post_reset(CPUState *cpu,\n-                                               run_on_cpu_data arg)\n-{\n-    whpx_set_registers(cpu, WHPX_SET_RESET_STATE);\n-    cpu->vcpu_dirty = false;\n-}\n-\n-static void do_whpx_cpu_synchronize_post_init(CPUState *cpu,\n-                                              run_on_cpu_data arg)\n-{\n-    whpx_set_registers(cpu, WHPX_SET_FULL_STATE);\n-    cpu->vcpu_dirty = false;\n-}\n-\n-static void do_whpx_cpu_synchronize_pre_loadvm(CPUState *cpu,\n-                                               run_on_cpu_data arg)\n-{\n-    cpu->vcpu_dirty = true;\n-}\n-\n-/*\n- * CPU support.\n- */\n-\n-void whpx_cpu_synchronize_state(CPUState *cpu)\n-{\n-    if (!cpu->vcpu_dirty) {\n-        run_on_cpu(cpu, do_whpx_cpu_synchronize_state, RUN_ON_CPU_NULL);\n-    }\n-}\n-\n-void whpx_cpu_synchronize_post_reset(CPUState *cpu)\n-{\n-    run_on_cpu(cpu, do_whpx_cpu_synchronize_post_reset, RUN_ON_CPU_NULL);\n-}\n-\n-void whpx_cpu_synchronize_post_init(CPUState *cpu)\n-{\n-    run_on_cpu(cpu, do_whpx_cpu_synchronize_post_init, RUN_ON_CPU_NULL);\n-}\n-\n-void whpx_cpu_synchronize_pre_loadvm(CPUState *cpu)\n-{\n-    run_on_cpu(cpu, do_whpx_cpu_synchronize_pre_loadvm, RUN_ON_CPU_NULL);\n-}\n-\n-static void whpx_pre_resume_vm(AccelState *as, bool step_pending)\n-{\n-    whpx_global.step_pending = step_pending;\n-}\n-\n /*\n  * Vcpu support.\n  */\n@@ -2244,295 +2064,18 @@ error:\n     return ret;\n }\n \n-int whpx_vcpu_exec(CPUState *cpu)\n-{\n-    int ret;\n-    int fatal;\n-\n-    for (;;) {\n-        if (cpu->exception_index >= EXCP_INTERRUPT) {\n-            ret = cpu->exception_index;\n-            cpu->exception_index = -1;\n-            break;\n-        }\n-\n-        fatal = whpx_vcpu_run(cpu);\n-\n-        if (fatal) {\n-            error_report(\"WHPX: Failed to exec a virtual processor\");\n-            abort();\n-        }\n-    }\n-\n-    return ret;\n-}\n-\n-void whpx_destroy_vcpu(CPUState *cpu)\n-{\n-    struct whpx_state *whpx = &whpx_global;\n-    AccelCPUState *vcpu = cpu->accel;\n-\n-    whp_dispatch.WHvDeleteVirtualProcessor(whpx->partition, cpu->cpu_index);\n-    whp_dispatch.WHvEmulatorDestroyEmulator(vcpu->emulator);\n-    g_free(cpu->accel);\n-}\n-\n-void whpx_vcpu_kick(CPUState *cpu)\n-{\n-    struct whpx_state *whpx = &whpx_global;\n-    whp_dispatch.WHvCancelRunVirtualProcessor(\n-        whpx->partition, cpu->cpu_index, 0);\n-}\n-\n-/*\n- * Memory support.\n- */\n-\n-static void whpx_update_mapping(hwaddr start_pa, ram_addr_t size,\n-                                void *host_va, int add, int rom,\n-                                const char *name)\n-{\n-    struct whpx_state *whpx = &whpx_global;\n-    HRESULT hr;\n-\n-    /*\n-    if (add) {\n-        printf(\"WHPX: ADD PA:%p Size:%p, Host:%p, %s, '%s'\\n\",\n-               (void*)start_pa, (void*)size, host_va,\n-               (rom ? \"ROM\" : \"RAM\"), name);\n-    } else {\n-        printf(\"WHPX: DEL PA:%p Size:%p, Host:%p,      '%s'\\n\",\n-               (void*)start_pa, (void*)size, host_va, name);\n-    }\n-    */\n-\n-    if (add) {\n-        hr = whp_dispatch.WHvMapGpaRange(whpx->partition,\n-                                         host_va,\n-                                         start_pa,\n-                                         size,\n-                                         (WHvMapGpaRangeFlagRead |\n-                                          WHvMapGpaRangeFlagExecute |\n-                                          (rom ? 0 : WHvMapGpaRangeFlagWrite)));\n-    } else {\n-        hr = whp_dispatch.WHvUnmapGpaRange(whpx->partition,\n-                                           start_pa,\n-                                           size);\n-    }\n-\n-    if (FAILED(hr)) {\n-        error_report(\"WHPX: Failed to %s GPA range '%s' PA:%p, Size:%p bytes,\"\n-                     \" Host:%p, hr=%08lx\",\n-                     (add ? \"MAP\" : \"UNMAP\"), name,\n-                     (void *)(uintptr_t)start_pa, (void *)size, host_va, hr);\n-    }\n-}\n-\n-static void whpx_process_section(MemoryRegionSection *section, int add)\n-{\n-    MemoryRegion *mr = section->mr;\n-    hwaddr start_pa = section->offset_within_address_space;\n-    ram_addr_t size = int128_get64(section->size);\n-    unsigned int delta;\n-    uint64_t host_va;\n-\n-    if (!memory_region_is_ram(mr)) {\n-        return;\n-    }\n-\n-    delta = qemu_real_host_page_size() - (start_pa & ~qemu_real_host_page_mask());\n-    delta &= ~qemu_real_host_page_mask();\n-    if (delta > size) {\n-        return;\n-    }\n-    start_pa += delta;\n-    size -= delta;\n-    size &= qemu_real_host_page_mask();\n-    if (!size || (start_pa & ~qemu_real_host_page_mask())) {\n-        return;\n-    }\n-\n-    host_va = (uintptr_t)memory_region_get_ram_ptr(mr)\n-            + section->offset_within_region + delta;\n-\n-    whpx_update_mapping(start_pa, size, (void *)(uintptr_t)host_va, add,\n-                        memory_region_is_rom(mr), mr->name);\n-}\n-\n-static void whpx_region_add(MemoryListener *listener,\n-                           MemoryRegionSection *section)\n-{\n-    memory_region_ref(section->mr);\n-    whpx_process_section(section, 1);\n-}\n-\n-static void whpx_region_del(MemoryListener *listener,\n-                           MemoryRegionSection *section)\n-{\n-    whpx_process_section(section, 0);\n-    memory_region_unref(section->mr);\n-}\n-\n-static void whpx_transaction_begin(MemoryListener *listener)\n-{\n-}\n-\n-static void whpx_transaction_commit(MemoryListener *listener)\n-{\n-}\n-\n-static void whpx_log_sync(MemoryListener *listener,\n-                         MemoryRegionSection *section)\n-{\n-    MemoryRegion *mr = section->mr;\n-\n-    if (!memory_region_is_ram(mr)) {\n-        return;\n-    }\n-\n-    memory_region_set_dirty(mr, 0, int128_get64(section->size));\n-}\n-\n-static MemoryListener whpx_memory_listener = {\n-    .name = \"whpx\",\n-    .begin = whpx_transaction_begin,\n-    .commit = whpx_transaction_commit,\n-    .region_add = whpx_region_add,\n-    .region_del = whpx_region_del,\n-    .log_sync = whpx_log_sync,\n-    .priority = MEMORY_LISTENER_PRIORITY_ACCEL,\n-};\n-\n-static void whpx_memory_init(void)\n-{\n-    memory_listener_register(&whpx_memory_listener, &address_space_memory);\n-}\n-\n-/*\n- * Load the functions from the given library, using the given handle. If a\n- * handle is provided, it is used, otherwise the library is opened. The\n- * handle will be updated on return with the opened one.\n- */\n-static bool load_whp_dispatch_fns(HMODULE *handle,\n-    WHPFunctionList function_list)\n-{\n-    HMODULE hLib = *handle;\n-\n-    #define WINHV_PLATFORM_DLL \"WinHvPlatform.dll\"\n-    #define WINHV_EMULATION_DLL \"WinHvEmulation.dll\"\n-    #define WHP_LOAD_FIELD_OPTIONAL(return_type, function_name, signature) \\\n-        whp_dispatch.function_name = \\\n-            (function_name ## _t)GetProcAddress(hLib, #function_name); \\\n-\n-    #define WHP_LOAD_FIELD(return_type, function_name, signature) \\\n-        whp_dispatch.function_name = \\\n-            (function_name ## _t)GetProcAddress(hLib, #function_name); \\\n-        if (!whp_dispatch.function_name) { \\\n-            error_report(\"Could not load function %s\", #function_name); \\\n-            goto error; \\\n-        } \\\n-\n-    #define WHP_LOAD_LIB(lib_name, handle_lib) \\\n-    if (!handle_lib) { \\\n-        handle_lib = LoadLibrary(lib_name); \\\n-        if (!handle_lib) { \\\n-            error_report(\"Could not load library %s.\", lib_name); \\\n-            goto error; \\\n-        } \\\n-    } \\\n-\n-    switch (function_list) {\n-    case WINHV_PLATFORM_FNS_DEFAULT:\n-        WHP_LOAD_LIB(WINHV_PLATFORM_DLL, hLib)\n-        LIST_WINHVPLATFORM_FUNCTIONS(WHP_LOAD_FIELD)\n-        break;\n-\n-    case WINHV_EMULATION_FNS_DEFAULT:\n-        WHP_LOAD_LIB(WINHV_EMULATION_DLL, hLib)\n-        LIST_WINHVEMULATION_FUNCTIONS(WHP_LOAD_FIELD)\n-        break;\n-\n-    case WINHV_PLATFORM_FNS_SUPPLEMENTAL:\n-        WHP_LOAD_LIB(WINHV_PLATFORM_DLL, hLib)\n-        LIST_WINHVPLATFORM_FUNCTIONS_SUPPLEMENTAL(WHP_LOAD_FIELD_OPTIONAL)\n-        break;\n-    }\n-\n-    *handle = hLib;\n-    return true;\n-\n-error:\n-    if (hLib) {\n-        FreeLibrary(hLib);\n-    }\n-\n-    return false;\n-}\n-\n-static void whpx_set_kernel_irqchip(Object *obj, Visitor *v,\n-                                   const char *name, void *opaque,\n-                                   Error **errp)\n-{\n-    struct whpx_state *whpx = &whpx_global;\n-    OnOffSplit mode;\n-\n-    if (!visit_type_OnOffSplit(v, name, &mode, errp)) {\n-        return;\n-    }\n-\n-    switch (mode) {\n-    case ON_OFF_SPLIT_ON:\n-        whpx->kernel_irqchip_allowed = true;\n-        whpx->kernel_irqchip_required = true;\n-        break;\n-\n-    case ON_OFF_SPLIT_OFF:\n-        whpx->kernel_irqchip_allowed = false;\n-        whpx->kernel_irqchip_required = false;\n-        break;\n-\n-    case ON_OFF_SPLIT_SPLIT:\n-        error_setg(errp, \"WHPX: split irqchip currently not supported\");\n-        error_append_hint(errp,\n-            \"Try without kernel-irqchip or with kernel-irqchip=on|off\");\n-        break;\n-\n-    default:\n-        /*\n-         * The value was checked in visit_type_OnOffSplit() above. If\n-         * we get here, then something is wrong in QEMU.\n-         */\n-        abort();\n-    }\n-}\n-\n-static void whpx_cpu_instance_init(CPUState *cs)\n+void whpx_cpu_instance_init(CPUState *cs)\n {\n     X86CPU *cpu = X86_CPU(cs);\n \n     host_cpu_instance_init(cpu);\n }\n \n-static void whpx_cpu_accel_class_init(ObjectClass *oc, const void *data)\n-{\n-    AccelCPUClass *acc = ACCEL_CPU_CLASS(oc);\n-\n-    acc->cpu_instance_init = whpx_cpu_instance_init;\n-}\n-\n-static const TypeInfo whpx_cpu_accel_type = {\n-    .name = ACCEL_CPU_NAME(\"whpx\"),\n-\n-    .parent = TYPE_ACCEL_CPU,\n-    .class_init = whpx_cpu_accel_class_init,\n-    .abstract = true,\n-};\n-\n /*\n  * Partition support\n  */\n \n-static int whpx_accel_init(AccelState *as, MachineState *ms)\n+int whpx_accel_init(AccelState *as, MachineState *ms)\n {\n     struct whpx_state *whpx;\n     int ret;\n@@ -2715,77 +2258,3 @@ error:\n \n     return ret;\n }\n-\n-bool whpx_apic_in_platform(void) {\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);\n-    ac->name = \"WHPX\";\n-    ac->init_machine = whpx_accel_init;\n-    ac->pre_resume_vm = whpx_pre_resume_vm;\n-    ac->allowed = &whpx_allowed;\n-\n-    object_class_property_add(oc, \"kernel-irqchip\", \"on|off|split\",\n-        NULL, whpx_set_kernel_irqchip,\n-        NULL, NULL);\n-    object_class_property_set_description(oc, \"kernel-irqchip\",\n-        \"Configure WHPX in-kernel irqchip\");\n-}\n-\n-static void whpx_accel_instance_init(Object *obj)\n-{\n-    struct whpx_state *whpx = &whpx_global;\n-\n-    memset(whpx, 0, sizeof(struct whpx_state));\n-    /* Turn on kernel-irqchip, by default */\n-    whpx->kernel_irqchip_allowed = true;\n-}\n-\n-static const TypeInfo whpx_accel_type = {\n-    .name = ACCEL_CLASS_NAME(\"whpx\"),\n-    .parent = TYPE_ACCEL,\n-    .instance_init = whpx_accel_instance_init,\n-    .class_init = whpx_accel_class_init,\n-};\n-\n-static void whpx_type_init(void)\n-{\n-    type_register_static(&whpx_accel_type);\n-    type_register_static(&whpx_cpu_accel_type);\n-}\n-\n-bool init_whp_dispatch(void)\n-{\n-    if (whp_dispatch_initialized) {\n-        return true;\n-    }\n-\n-    if (!load_whp_dispatch_fns(&hWinHvPlatform, WINHV_PLATFORM_FNS_DEFAULT)) {\n-        goto error;\n-    }\n-\n-    if (!load_whp_dispatch_fns(&hWinHvEmulation, WINHV_EMULATION_FNS_DEFAULT)) {\n-        goto error;\n-    }\n-\n-    assert(load_whp_dispatch_fns(&hWinHvPlatform,\n-        WINHV_PLATFORM_FNS_SUPPLEMENTAL));\n-    whp_dispatch_initialized = true;\n-\n-    return true;\n-error:\n-    if (hWinHvPlatform) {\n-        FreeLibrary(hWinHvPlatform);\n-    }\n-\n-    if (hWinHvEmulation) {\n-        FreeLibrary(hWinHvEmulation);\n-    }\n-\n-    return false;\n-}\n-\n-type_init(whpx_type_init);\n",
    "prefixes": [
        "PULL",
        "10/26"
    ]
}