get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 2218937,
    "url": "http://patchwork.ozlabs.org/api/1.0/patches/2218937/?format=api",
    "project": {
        "id": 14,
        "url": "http://patchwork.ozlabs.org/api/1.0/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": ""
    },
    "msgid": "<20260402053326.23402-3-mohamed@unpredictable.fr>",
    "date": "2026-04-02T05:33:24",
    "name": "[2/4] whpx: i386: x2apic emulation",
    "commit_ref": null,
    "pull_url": null,
    "state": "new",
    "archived": false,
    "hash": "f8a3434dc0b80498ee06ee496ee9a530b46cbaab",
    "submitter": {
        "id": 91318,
        "url": "http://patchwork.ozlabs.org/api/1.0/people/91318/?format=api",
        "name": "Mohamed Mediouni",
        "email": "mohamed@unpredictable.fr"
    },
    "delegate": null,
    "mbox": "http://patchwork.ozlabs.org/project/qemu-devel/patch/20260402053326.23402-3-mohamed@unpredictable.fr/mbox/",
    "series": [
        {
            "id": 498430,
            "url": "http://patchwork.ozlabs.org/api/1.0/series/498430/?format=api",
            "date": "2026-04-02T05:33:22",
            "name": "whpx: i386: x2apic emulation for kernel-irqchip=off, feature probing",
            "version": 1,
            "mbox": "http://patchwork.ozlabs.org/series/498430/mbox/"
        }
    ],
    "check": "pending",
    "checks": "http://patchwork.ozlabs.org/api/patches/2218937/checks/",
    "tags": {},
    "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=unpredictable.fr header.i=@unpredictable.fr\n header.a=rsa-sha256 header.s=sig1 header.b=I58gikVm;\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 4fmVtk285qz1yFv\n\tfor <incoming@patchwork.ozlabs.org>; Thu, 02 Apr 2026 16:35:26 +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 1w8AgX-0002Ta-GN; Thu, 02 Apr 2026 01:33:41 -0400",
            "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 <mohamed@unpredictable.fr>)\n id 1w8AgU-0002OJ-6B\n for qemu-devel@nongnu.org; Thu, 02 Apr 2026 01:33:38 -0400",
            "from qs-2007a-snip4-3.eps.apple.com ([57.103.84.134]\n helo=outbound.qs.icloud.com)\n by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256)\n (Exim 4.90_1) (envelope-from <mohamed@unpredictable.fr>)\n id 1w8AgS-0004vo-EX\n for qemu-devel@nongnu.org; Thu, 02 Apr 2026 01:33:37 -0400",
            "from outbound.qs.icloud.com (unknown [127.0.0.2])\n by p00-icloudmta-asmtp-us-east-2d-100-percent-0 (Postfix) with ESMTPS id\n 56E5918000BE; Thu, 02 Apr 2026 05:33:33 +0000 (UTC)",
            "from localhost.localdomain (unknown [17.57.155.37])\n by p00-icloudmta-asmtp-us-east-2d-100-percent-0 (Postfix) with ESMTPSA id\n B127F1800365; Thu, 02 Apr 2026 05:33:31 +0000 (UTC)"
        ],
        "Dkim-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed; d=unpredictable.fr;\n s=sig1; t=1775108015; x=1777700015;\n bh=8jTy0gf7qMH8U5KzSkYzttZHwJqtRQSF990AWX8r1Uo=;\n h=From:To:Subject:Date:Message-ID:MIME-Version:x-icloud-hme;\n b=I58gikVmsogm04zl/H+UGqQ4roTrI3R3eQbT4hNS2+Lbke+fs8cDfiRpfm7VBycuLrQ+6cbcC7qbRkYkQ0wm2MizkWHX/YfuBlPbJs3y5Ig47LQQXiTZ6RUfE0oyeX+LoCuBh+CJCPOalNzesxIfiHtyFRhWI7Rsdniwo3Pbmp2acCto/CH75CRfG7acWl3eW2kEnfcoj3JRzsYmKXupix0aDuHSwPQqUIIGljINUX0Ee/FnLLIBd6zedsaC4DOHpTFE83J6XZrGw+y673JnhLjKC4M1VZ9DNvucqjCL/BAMoxh4knFFjS4BCtE9rRBsoWGncfbUXZqPScJwRgvttw==",
        "mail-alias-created-date": "1752046281608",
        "From": "Mohamed Mediouni <mohamed@unpredictable.fr>",
        "To": "qemu-devel@nongnu.org",
        "Cc": "Wei Liu <wei.liu@kernel.org>, Roman Bolshakov <rbolshakov@ddn.com>,\n Pedro Barbuda <pbarbuda@microsoft.com>, Zhao Liu <zhao1.liu@intel.com>,\n Paolo Bonzini <pbonzini@redhat.com>,\n Mohamed Mediouni <mohamed@unpredictable.fr>,\n Phil Dennis-Jordan <phil@philjordan.eu>",
        "Subject": "[PATCH 2/4] whpx: i386: x2apic emulation",
        "Date": "Thu,  2 Apr 2026 07:33:24 +0200",
        "Message-ID": "<20260402053326.23402-3-mohamed@unpredictable.fr>",
        "X-Mailer": "git-send-email 2.50.1",
        "In-Reply-To": "<20260402053326.23402-1-mohamed@unpredictable.fr>",
        "References": "<20260402053326.23402-1-mohamed@unpredictable.fr>",
        "MIME-Version": "1.0",
        "Content-Transfer-Encoding": "8bit",
        "X-Proofpoint-Spam-Details-Enc": "AW1haW4tMjYwNDAyMDA0NyBTYWx0ZWRfX/VblUMSQQwWi\n tGUeqA6GlTb9pasRYIePp2rSmToEGIH/bn5yy5MgSJGp0203lvsk5ac2GMOWpJOTBbPiqnQATL8\n Xf1CzoYCjKRvm2DDkfRYbAPOYgNPr5mkybBanimRDhBwThALJavcaJ5Gc6tgj/mY3ZFH3hUAgbf\n SUhg4rXxJpJUAGurkmqmQVDMwU6FaIewLgQAhl1tSlCT5BkUflSg2vYm95St8RiR8Y7oNGX/yzf\n MHnIklmse73S2N2vfZmgGW1CgAtQ2eISTJcYSIM5UlZg0NVAeHYsOtoAW8jYFYL5BqcDPXQAlzL\n vfK+c3sgEL0Oy6Nqz1XJ+lH3K5O6356nh9maRRcZemsv6cRW6mZhF6AHC6o1nA=",
        "X-Authority-Info-Out": "v=2.4 cv=Y4j1cxeN c=1 sm=1 tr=0 ts=69cdffae\n cx=c_apl:c_pps:t_out a=bsP7O+dXZ5uKcj+dsLqiMw==:117\n a=bsP7O+dXZ5uKcj+dsLqiMw==:17 a=A5OVakUREuEA:10 a=VkNPw1HP01LnGYTKEx00:22\n a=ZRGgWdpwccs3gJCA4M8A:9",
        "X-Proofpoint-GUID": "Z-X7x3-WyXwsISqw7jW2rT3FZASTzqpW",
        "X-Proofpoint-ORIG-GUID": "Z-X7x3-WyXwsISqw7jW2rT3FZASTzqpW",
        "X-Proofpoint-Virus-Version": "vendor=baseguard\n engine=ICAP:2.0.293,Aquarius:18.0.1143,Hydra:6.1.51,FMLib:17.12.100.49\n definitions=2026-04-02_01,2026-04-01_02,2025-10-01_01",
        "X-Proofpoint-Spam-Details": "rule=notspam policy=default score=0 adultscore=0\n mlxscore=0 clxscore=1030 malwarescore=0 suspectscore=0 phishscore=0\n lowpriorityscore=0 spamscore=0 bulkscore=0 mlxlogscore=627 classifier=spam\n authscore=0 adjust=0 reason=mlx scancount=1 engine=8.22.0-2601150000\n definitions=main-2604020047",
        "Received-SPF": "pass client-ip=57.103.84.134;\n envelope-from=mohamed@unpredictable.fr; helo=outbound.qs.icloud.com",
        "X-Spam_score_int": "0",
        "X-Spam_score": "-0.1",
        "X-Spam_bar": "/",
        "X-Spam_report": "(-0.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_VALIDITY_CERTIFIED_BLOCKED=1, RCVD_IN_VALIDITY_RPBL_BLOCKED=1,\n SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=no 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": "Add x2apic emulation to WHPX for the kernel-irqchip=off case.\n\nUnfortunately, it looks like there isn't a workaround available\nfor proper behavior of PIC interrupts when kernel-irqchip=on\nfor Windows 10. The OS is out of support outside of extended\nsecurity updates so this will not be addressed.\n\nOn Windows 11, x2apic will be enabled straight away because\nLinux enables it even without an IOMMU when using Hyper-V.\n\nFor Windows 10, you need: -device intel-iommu,intremap=on,eim=on\n\nThe performance impact is worthwhile for multicore guests.\n\nSigned-off-by: Mohamed Mediouni <mohamed@unpredictable.fr>\n---\n target/i386/whpx/whpx-all.c | 128 +++++++++++++++++++++++++++++++++++-\n 1 file changed, 127 insertions(+), 1 deletion(-)",
    "diff": "diff --git a/target/i386/whpx/whpx-all.c b/target/i386/whpx/whpx-all.c\nindex e56ae2b343..f06474c31b 100644\n--- a/target/i386/whpx/whpx-all.c\n+++ b/target/i386/whpx/whpx-all.c\n@@ -1082,6 +1082,8 @@ HRESULT whpx_set_exception_exit_bitmap(UINT64 exceptions)\n     /* Register for MSR and CPUID exits */\n     memset(&prop, 0, sizeof(WHV_PARTITION_PROPERTY));\n     prop.ExtendedVmExits.X64MsrExit = 1;\n+    prop.ExtendedVmExits.X64CpuidExit = 1;\n+\n     if (exceptions != 0) {\n         prop.ExtendedVmExits.ExceptionExit = 1;\n     }\n@@ -1898,6 +1900,12 @@ int whpx_vcpu_run(CPUState *cpu)\n             WHV_REGISTER_NAME reg_names[3];\n             UINT32 reg_count;\n             bool is_known_msr = 0; \n+            uint64_t val;\n+\n+            if (vcpu->exit_ctx.MsrAccess.AccessInfo.IsWrite) {\n+                val = ((uint32_t)vcpu->exit_ctx.MsrAccess.Rax) |\n+                    ((uint64_t)(vcpu->exit_ctx.MsrAccess.Rdx) << 32);\n+            }\n \n             reg_names[0] = WHvX64RegisterRip;\n             reg_names[1] = WHvX64RegisterRax;\n@@ -1911,7 +1919,47 @@ int whpx_vcpu_run(CPUState *cpu)\n                 && !vcpu->exit_ctx.MsrAccess.AccessInfo.IsWrite\n                 && !whpx_irqchip_in_kernel()) {\n                 is_known_msr = 1;\n-                reg_values[1].Reg32 = (uint32_t)X86_CPU(cpu)->env.apic_bus_freq;\n+                val = X86_CPU(cpu)->env.apic_bus_freq;\n+            }\n+\n+            if (!whpx_irqchip_in_kernel() &&\n+                vcpu->exit_ctx.MsrAccess.MsrNumber == MSR_IA32_APICBASE) {\n+                is_known_msr = 1;\n+                if (!vcpu->exit_ctx.MsrAccess.AccessInfo.IsWrite) {\n+                    /* Read path unreachable on Hyper-V */\n+                    abort();\n+                } else {\n+                    WHV_REGISTER_VALUE reg = {.Reg64 = val};\n+                    int ret = cpu_set_apic_base(X86_CPU(cpu)->apic_state, val);\n+                    if (ret < 0) {\n+                        x86_emul_raise_exception(&X86_CPU(cpu)->env, EXCP0D_GPF, 0);\n+                    }\n+                    whpx_set_reg(cpu, WHvX64RegisterApicBase, reg);\n+                }\n+            }\n+\n+            if (!whpx_irqchip_in_kernel() &&\n+                vcpu->exit_ctx.MsrAccess.MsrNumber >= MSR_APIC_START &&\n+                vcpu->exit_ctx.MsrAccess.MsrNumber <= MSR_APIC_END) {\n+                int index = vcpu->exit_ctx.MsrAccess.MsrNumber - MSR_APIC_START;\n+                int ret;\n+                is_known_msr = 1;\n+                if (!vcpu->exit_ctx.MsrAccess.AccessInfo.IsWrite) {\n+                    bql_lock();\n+                    ret = apic_msr_read(X86_CPU(cpu)->apic_state, index, &val);\n+                    bql_unlock();\n+                    reg_values[1].Reg64 = val;\n+                    if (ret < 0) {\n+                        x86_emul_raise_exception(&X86_CPU(cpu)->env, EXCP0D_GPF, 0);\n+                    }\n+                } else {\n+                    bql_lock();\n+                    ret = apic_msr_write(X86_CPU(cpu)->apic_state, index, val);\n+                    bql_unlock();\n+                    if (ret < 0) {\n+                        x86_emul_raise_exception(&X86_CPU(cpu)->env, EXCP0D_GPF, 0);\n+                    }\n+                }\n             }\n             /*\n              * For all unsupported MSR access we:\n@@ -1921,6 +1969,11 @@ int whpx_vcpu_run(CPUState *cpu)\n             reg_count = vcpu->exit_ctx.MsrAccess.AccessInfo.IsWrite ?\n                         1 : 3;\n \n+            if (!vcpu->exit_ctx.MsrAccess.AccessInfo.IsWrite) {\n+                reg_values[1].Reg32 = (uint32_t)val;\n+                reg_values[2].Reg32 = (uint32_t)(val >> 32);\n+            }\n+\n             if (!is_known_msr) {\n                 trace_whpx_unsupported_msr_access(vcpu->exit_ctx.MsrAccess.MsrNumber,\n                     vcpu->exit_ctx.MsrAccess.AccessInfo.IsWrite);\n@@ -1939,6 +1992,47 @@ int whpx_vcpu_run(CPUState *cpu)\n             ret = 0;\n             break;\n         }\n+        case WHvRunVpExitReasonX64Cpuid: {\n+            WHV_REGISTER_VALUE reg_values[5] = {0};\n+            WHV_REGISTER_NAME reg_names[5];\n+            UINT32 reg_count = 5;\n+            X86CPU *x86_cpu = X86_CPU(cpu);\n+            CPUX86State *env = &x86_cpu->env;\n+\n+            reg_names[0] = WHvX64RegisterRip;\n+            reg_names[1] = WHvX64RegisterRax;\n+            reg_names[2] = WHvX64RegisterRcx;\n+            reg_names[3] = WHvX64RegisterRdx;\n+            reg_names[4] = WHvX64RegisterRbx;\n+\n+            reg_values[0].Reg64 =\n+                vcpu->exit_ctx.VpContext.Rip +\n+                vcpu->exit_ctx.VpContext.InstructionLength;\n+\n+            reg_values[1].Reg64 = vcpu->exit_ctx.CpuidAccess.DefaultResultRax;\n+            reg_values[2].Reg64 = vcpu->exit_ctx.CpuidAccess.DefaultResultRcx;\n+            reg_values[3].Reg64 = vcpu->exit_ctx.CpuidAccess.DefaultResultRdx;\n+            reg_values[4].Reg64 = vcpu->exit_ctx.CpuidAccess.DefaultResultRbx;\n+\n+            if (vcpu->exit_ctx.CpuidAccess.Rax == 1) {\n+                if (cpu_has_x2apic_feature(env)) {\n+                    reg_values[2].Reg64 |= CPUID_EXT_X2APIC;\n+                }\n+            }\n+\n+            hr = whp_dispatch.WHvSetVirtualProcessorRegisters(\n+                whpx->partition,\n+                cpu->cpu_index,\n+                reg_names, reg_count,\n+                reg_values);\n+\n+            if (FAILED(hr)) {\n+                error_report(\"WHPX: Failed to set CpuidAccess state \"\n+                             \" registers, hr=%08lx\", hr);\n+            }\n+            ret = 0;\n+            break;\n+        }\n         case WHvRunVpExitReasonException:\n             whpx_get_registers(cpu, WHPX_LEVEL_FULL_STATE);\n \n@@ -2136,6 +2230,7 @@ int whpx_accel_init(AccelState *as, MachineState *ms)\n     WHV_PROCESSOR_FEATURES_BANKS processor_features;\n     WHV_PROCESSOR_PERFMON_FEATURES perfmon_features;\n     bool is_legacy_os = false;\n+    UINT32 cpuidExitList[] = {1};\n \n     whpx = &whpx_global;\n \n@@ -2354,6 +2449,7 @@ int whpx_accel_init(AccelState *as, MachineState *ms)\n     /* Register for MSR and CPUID exits */\n     memset(&prop, 0, sizeof(WHV_PARTITION_PROPERTY));\n     prop.ExtendedVmExits.X64MsrExit = 1;\n+    prop.ExtendedVmExits.X64CpuidExit = 1;\n \n     hr = whp_dispatch.WHvSetPartitionProperty(\n             whpx->partition,\n@@ -2366,6 +2462,36 @@ int whpx_accel_init(AccelState *as, MachineState *ms)\n         goto error;\n     }\n \n+    memset(&prop, 0, sizeof(WHV_PARTITION_PROPERTY));\n+    prop.X64MsrExitBitmap.UnhandledMsrs = 1;\n+    if (!whpx_irqchip_in_kernel()) {\n+        prop.X64MsrExitBitmap.ApicBaseMsrWrite = 1;\n+    }\n+\n+    hr = whp_dispatch.WHvSetPartitionProperty(\n+            whpx->partition,\n+            WHvPartitionPropertyCodeX64MsrExitBitmap,\n+            &prop,\n+            sizeof(WHV_PARTITION_PROPERTY));\n+    if (FAILED(hr)) {\n+        error_report(\"WHPX: Failed to set MSR exit bitmap, hr=%08lx\", hr);\n+        ret = -EINVAL;\n+        goto error;\n+    }\n+\n+    hr = whp_dispatch.WHvSetPartitionProperty(\n+        whpx->partition,\n+        WHvPartitionPropertyCodeCpuidExitList,\n+        cpuidExitList,\n+        RTL_NUMBER_OF(cpuidExitList) * sizeof(UINT32));\n+\n+    if (FAILED(hr)) {\n+        error_report(\"WHPX: Failed to set partition CpuidExitList hr=%08lx\",\n+                     hr);\n+        ret = -EINVAL;\n+        goto error;\n+    }\n+\n     /*\n      * We do not want to intercept any exceptions from the guest,\n      * until we actually start debugging with gdb.\n",
    "prefixes": [
        "2/4"
    ]
}