Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/patches/2195175/?format=api
{ "id": 2195175, "url": "http://patchwork.ozlabs.org/api/patches/2195175/?format=api", "web_url": "http://patchwork.ozlabs.org/project/qemu-devel/patch/20260210135206.229528-15-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-15-peter.maydell@linaro.org>", "list_archive_url": null, "date": "2026-02-10T13:51:54", "name": "[PULL,14/26] whpx: add arm64 support", "commit_ref": null, "pull_url": null, "state": "not-applicable", "archived": false, "hash": "a1b1256892919705d3b66dc2c38922bc84f8059d", "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-15-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/2195175/comments/", "check": "pending", "checks": "http://patchwork.ozlabs.org/api/patches/2195175/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=fdcfF5Re;\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 4f9NPW2bCWz1xtr\n\tfor <incoming@patchwork.ozlabs.org>; Wed, 11 Feb 2026 00:55:43 +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 1vpoAH-0002Bs-QC; Tue, 10 Feb 2026 08:52:29 -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 1vpoAG-0002Ah-73\n for qemu-devel@nongnu.org; Tue, 10 Feb 2026 08:52:28 -0500", "from mail-wm1-x332.google.com ([2a00:1450:4864:20::332])\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-0006Ll-A7\n for qemu-devel@nongnu.org; Tue, 10 Feb 2026 08:52:27 -0500", "by mail-wm1-x332.google.com with SMTP id\n 5b1f17b1804b1-4801eb2c0a5so53543395e9.3\n for <qemu-devel@nongnu.org>; Tue, 10 Feb 2026 05:52:21 -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.18\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=1770731540; x=1771336340; 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=+XOcY+AOu+OcMbkxBTIZN3ikLAl892hSxYanbSLcRcg=;\n b=fdcfF5RelNQ+39FGG0QB1Qb97q/hk7IduHRTOsneUqq4PxPB29xFNIuIGbtCNnvk5T\n oopT6zMOup3rhKfs1jwaEzEDVVrtzF75pZsfNZ3pg8HYViEUzpNpynrLS0R6gyzJLgut\n DoLFBliNmhvg6swf6GbxDtu8JWSxiscvIya6CFQZn4FpkjEbdoorXo7y2FjV1twNWGal\n iW75UvhKFNKWjlqpt8SUHY1zvi4QR+9RKuP7z/C+FoukEiVMLvjD/lbTvMEcS/jXx8jX\n UXDhnZhwTPGsbRrzTadSVtZby2mZjC3ERtZH1kO+52CgC4e9Z6wS5Rn1PqfNFGzuHInh\n xCXg==", "X-Google-DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=1e100.net; s=20230601; t=1770731540; x=1771336340;\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=+XOcY+AOu+OcMbkxBTIZN3ikLAl892hSxYanbSLcRcg=;\n b=FS8TBlT7fC+7Rc/05uo3NOXeMtUsmG4By+OyVpSM8d4K8vM4R4U2sYkgLjiEcItOdV\n +vXrbD2wMOBQn3LOqEnlLCUA/zQ4EKBRkeIBx8OJUljuonMs+Foyttyh7pNxQI6eHorW\n tM2k9OVJhOaVqOfmQdCnsxwKDddUPTFRSugjjRpERTW7HvYaWK9pmKwQjmVgGna3r5N8\n xhJN5pFrS4kuViiDYENUf+Jrq/L0nTU2jX29OH5PaTSbr0GTkE2SCSXIV3Kg8HS/2tWi\n oGDmxh4hXKcqojjkfoIWPlWgf7qtplFQzvxiZu791moL+I9+AsNr9w0MJTiOlJsJyVJ4\n k2aQ==", "X-Gm-Message-State": "AOJu0YwArxM+VZZbR4PTEWc0WTv6A8kfu6RcY7IsgHf7HO5ABkogVWOD\n O7lP2BY2Ti8o/2p2P2+5EWypT9Ema4D6w0XzthrTNYnYaVLuFDlb8C/KMl2iRxnWotwjowadocs\n TdQuy", "X-Gm-Gg": "AZuq6aKqwEs++E/MHTDOnuHwjk5rcAjn4wZJS+JQ/7eTZ2yPZzeD0WBFDKBJjcWZVnH\n WhxjwTIuUT0tmNBzxA0/BNn9YiGylpMshbf871NIP/piklUqMxzMMUSUTnnc54TLGBc+JUgDk45\n WUP3XSGyvnZCEibb2P2y7iTy9ZMOaT3F0zH2TVLX6cIj0UgLbbv0nKyAQHDyApxWf7Zcyr6Cqr1\n ab5+rLyd2uDVJu1EUCx9njy3o8puEec9YpaZq9E0IL/L4sCiTgAcoMPcf21AbPhScMb/S2xdnY7\n VTr/viz7AKsgvFaOZEf4GcXIiOp1o13I3WZYEXYoyDzT8MX9py9WqBr8ZWFJewlybpP8TTw+dxh\n 0j02B2d0PFQnyd3JP3KLH4BcHRQrJ3WJBa6mDTUs/CfdKbe6qXtGzAXLr4iMtehW4Bkkn78s5g6\n /Diwujyc348Bxr3iww7r5lVZHtX/kxPNG6OxghILqV3FvhXadpq/17CMmA4gDHS+guLfhSJJj5J\n kv8p/e1RatPJjeEblZ4PISOByb41VQ=", "X-Received": "by 2002:a05:600c:3b1e:b0:483:3380:ca0c with SMTP id\n 5b1f17b1804b1-4835083456cmr33318915e9.35.1770731539716;\n Tue, 10 Feb 2026 05:52:19 -0800 (PST)", "From": "Peter Maydell <peter.maydell@linaro.org>", "To": "qemu-devel@nongnu.org", "Subject": "[PULL 14/26] whpx: add arm64 support", "Date": "Tue, 10 Feb 2026 13:51:54 +0000", "Message-ID": "<20260210135206.229528-15-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-Type": "text/plain; charset=UTF-8", "Content-Transfer-Encoding": "8bit", "Received-SPF": "pass client-ip=2a00:1450:4864:20::332;\n envelope-from=peter.maydell@linaro.org; helo=mail-wm1-x332.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\nSigned-off-by: Mohamed Mediouni <mohamed@unpredictable.fr>\nReviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>\nSigned-off-by: Peter Maydell <peter.maydell@linaro.org>\n---\n MAINTAINERS | 1 +\n accel/whpx/whpx-common.c | 1 +\n target/arm/meson.build | 1 +\n target/arm/whpx/meson.build | 3 +\n target/arm/whpx/whpx-all.c | 810 ++++++++++++++++++++++++++++++++++++\n 5 files changed, 816 insertions(+)\n create mode 100644 target/arm/whpx/meson.build\n create mode 100644 target/arm/whpx/whpx-all.c", "diff": "diff --git a/MAINTAINERS b/MAINTAINERS\nindex c6af6e10bb..5cdfea7e11 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: target/arm/whpx/\n F: hw/intc/arm_gicv3_whpx.c\n F: accel/stubs/whpx-stub.c\n F: include/system/whpx.h\ndiff --git a/accel/whpx/whpx-common.c b/accel/whpx/whpx-common.c\nindex 05f9e520b7..827f50f3e0 100644\n--- a/accel/whpx/whpx-common.c\n+++ b/accel/whpx/whpx-common.c\n@@ -12,6 +12,7 @@\n #include \"gdbstub/helpers.h\"\n #include \"qemu/accel.h\"\n #include \"accel/accel-ops.h\"\n+#include \"system/memory.h\"\n #include \"system/whpx.h\"\n #include \"system/cpus.h\"\n #include \"system/runstate.h\"\ndiff --git a/target/arm/meson.build b/target/arm/meson.build\nindex 1a1bcde260..fe396c4318 100644\n--- a/target/arm/meson.build\n+++ b/target/arm/meson.build\n@@ -59,6 +59,7 @@ arm_common_system_ss.add(files(\n ))\n \n subdir('hvf')\n+subdir('whpx')\n \n if 'CONFIG_TCG' in config_all_accel\n subdir('tcg')\ndiff --git a/target/arm/whpx/meson.build b/target/arm/whpx/meson.build\nnew file mode 100644\nindex 0000000000..1de2ef0283\n--- /dev/null\n+++ b/target/arm/whpx/meson.build\n@@ -0,0 +1,3 @@\n+arm_system_ss.add(when: 'CONFIG_WHPX', if_true: files(\n+ 'whpx-all.c',\n+))\ndiff --git a/target/arm/whpx/whpx-all.c b/target/arm/whpx/whpx-all.c\nnew file mode 100644\nindex 0000000000..192d7ec7a8\n--- /dev/null\n+++ b/target/arm/whpx/whpx-all.c\n@@ -0,0 +1,810 @@\n+/* SPDX-License-Identifier: GPL-2.0-or-later */\n+/*\n+ * QEMU Windows Hypervisor Platform accelerator (WHPX)\n+ *\n+ * Copyright (c) 2025 Mohamed Mediouni\n+ *\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 \"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 \"syndrome.h\"\n+#include \"cpu.h\"\n+#include \"target/arm/cpregs.h\"\n+#include \"internals.h\"\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+#include \"hw/arm/bsa.h\"\n+#include \"arm-powerctl.h\"\n+\n+#include <winhvplatform.h>\n+#include <winhvplatformdefs.h>\n+\n+typedef struct WHPXRegMatch {\n+ WHV_REGISTER_NAME reg;\n+ uint64_t offset;\n+} WHPXRegMatch;\n+\n+static const WHPXRegMatch whpx_reg_match[] = {\n+ { WHvArm64RegisterX0, offsetof(CPUARMState, xregs[0]) },\n+ { WHvArm64RegisterX1, offsetof(CPUARMState, xregs[1]) },\n+ { WHvArm64RegisterX2, offsetof(CPUARMState, xregs[2]) },\n+ { WHvArm64RegisterX3, offsetof(CPUARMState, xregs[3]) },\n+ { WHvArm64RegisterX4, offsetof(CPUARMState, xregs[4]) },\n+ { WHvArm64RegisterX5, offsetof(CPUARMState, xregs[5]) },\n+ { WHvArm64RegisterX6, offsetof(CPUARMState, xregs[6]) },\n+ { WHvArm64RegisterX7, offsetof(CPUARMState, xregs[7]) },\n+ { WHvArm64RegisterX8, offsetof(CPUARMState, xregs[8]) },\n+ { WHvArm64RegisterX9, offsetof(CPUARMState, xregs[9]) },\n+ { WHvArm64RegisterX10, offsetof(CPUARMState, xregs[10]) },\n+ { WHvArm64RegisterX11, offsetof(CPUARMState, xregs[11]) },\n+ { WHvArm64RegisterX12, offsetof(CPUARMState, xregs[12]) },\n+ { WHvArm64RegisterX13, offsetof(CPUARMState, xregs[13]) },\n+ { WHvArm64RegisterX14, offsetof(CPUARMState, xregs[14]) },\n+ { WHvArm64RegisterX15, offsetof(CPUARMState, xregs[15]) },\n+ { WHvArm64RegisterX16, offsetof(CPUARMState, xregs[16]) },\n+ { WHvArm64RegisterX17, offsetof(CPUARMState, xregs[17]) },\n+ { WHvArm64RegisterX18, offsetof(CPUARMState, xregs[18]) },\n+ { WHvArm64RegisterX19, offsetof(CPUARMState, xregs[19]) },\n+ { WHvArm64RegisterX20, offsetof(CPUARMState, xregs[20]) },\n+ { WHvArm64RegisterX21, offsetof(CPUARMState, xregs[21]) },\n+ { WHvArm64RegisterX22, offsetof(CPUARMState, xregs[22]) },\n+ { WHvArm64RegisterX23, offsetof(CPUARMState, xregs[23]) },\n+ { WHvArm64RegisterX24, offsetof(CPUARMState, xregs[24]) },\n+ { WHvArm64RegisterX25, offsetof(CPUARMState, xregs[25]) },\n+ { WHvArm64RegisterX26, offsetof(CPUARMState, xregs[26]) },\n+ { WHvArm64RegisterX27, offsetof(CPUARMState, xregs[27]) },\n+ { WHvArm64RegisterX28, offsetof(CPUARMState, xregs[28]) },\n+ { WHvArm64RegisterFp, offsetof(CPUARMState, xregs[29]) },\n+ { WHvArm64RegisterLr, offsetof(CPUARMState, xregs[30]) },\n+ { WHvArm64RegisterPc, offsetof(CPUARMState, pc) },\n+};\n+\n+static const WHPXRegMatch whpx_fpreg_match[] = {\n+ { WHvArm64RegisterQ0, offsetof(CPUARMState, vfp.zregs[0]) },\n+ { WHvArm64RegisterQ1, offsetof(CPUARMState, vfp.zregs[1]) },\n+ { WHvArm64RegisterQ2, offsetof(CPUARMState, vfp.zregs[2]) },\n+ { WHvArm64RegisterQ3, offsetof(CPUARMState, vfp.zregs[3]) },\n+ { WHvArm64RegisterQ4, offsetof(CPUARMState, vfp.zregs[4]) },\n+ { WHvArm64RegisterQ5, offsetof(CPUARMState, vfp.zregs[5]) },\n+ { WHvArm64RegisterQ6, offsetof(CPUARMState, vfp.zregs[6]) },\n+ { WHvArm64RegisterQ7, offsetof(CPUARMState, vfp.zregs[7]) },\n+ { WHvArm64RegisterQ8, offsetof(CPUARMState, vfp.zregs[8]) },\n+ { WHvArm64RegisterQ9, offsetof(CPUARMState, vfp.zregs[9]) },\n+ { WHvArm64RegisterQ10, offsetof(CPUARMState, vfp.zregs[10]) },\n+ { WHvArm64RegisterQ11, offsetof(CPUARMState, vfp.zregs[11]) },\n+ { WHvArm64RegisterQ12, offsetof(CPUARMState, vfp.zregs[12]) },\n+ { WHvArm64RegisterQ13, offsetof(CPUARMState, vfp.zregs[13]) },\n+ { WHvArm64RegisterQ14, offsetof(CPUARMState, vfp.zregs[14]) },\n+ { WHvArm64RegisterQ15, offsetof(CPUARMState, vfp.zregs[15]) },\n+ { WHvArm64RegisterQ16, offsetof(CPUARMState, vfp.zregs[16]) },\n+ { WHvArm64RegisterQ17, offsetof(CPUARMState, vfp.zregs[17]) },\n+ { WHvArm64RegisterQ18, offsetof(CPUARMState, vfp.zregs[18]) },\n+ { WHvArm64RegisterQ19, offsetof(CPUARMState, vfp.zregs[19]) },\n+ { WHvArm64RegisterQ20, offsetof(CPUARMState, vfp.zregs[20]) },\n+ { WHvArm64RegisterQ21, offsetof(CPUARMState, vfp.zregs[21]) },\n+ { WHvArm64RegisterQ22, offsetof(CPUARMState, vfp.zregs[22]) },\n+ { WHvArm64RegisterQ23, offsetof(CPUARMState, vfp.zregs[23]) },\n+ { WHvArm64RegisterQ24, offsetof(CPUARMState, vfp.zregs[24]) },\n+ { WHvArm64RegisterQ25, offsetof(CPUARMState, vfp.zregs[25]) },\n+ { WHvArm64RegisterQ26, offsetof(CPUARMState, vfp.zregs[26]) },\n+ { WHvArm64RegisterQ27, offsetof(CPUARMState, vfp.zregs[27]) },\n+ { WHvArm64RegisterQ28, offsetof(CPUARMState, vfp.zregs[28]) },\n+ { WHvArm64RegisterQ29, offsetof(CPUARMState, vfp.zregs[29]) },\n+ { WHvArm64RegisterQ30, offsetof(CPUARMState, vfp.zregs[30]) },\n+ { WHvArm64RegisterQ31, offsetof(CPUARMState, vfp.zregs[31]) },\n+};\n+\n+struct whpx_sreg_match {\n+ WHV_REGISTER_NAME reg;\n+ uint32_t key;\n+ bool global;\n+ uint32_t cp_idx;\n+};\n+\n+static struct whpx_sreg_match whpx_sreg_match[] = {\n+ { WHvArm64RegisterDbgbvr0El1, ENCODE_AA64_CP_REG(0, 0, 2, 0, 4) },\n+ { WHvArm64RegisterDbgbcr0El1, ENCODE_AA64_CP_REG(0, 0, 2, 0, 5) },\n+ { WHvArm64RegisterDbgwvr0El1, ENCODE_AA64_CP_REG(0, 0, 2, 0, 6) },\n+ { WHvArm64RegisterDbgwcr0El1, ENCODE_AA64_CP_REG(0, 0, 2, 0, 7) },\n+\n+ { WHvArm64RegisterDbgbvr0El1, ENCODE_AA64_CP_REG(0, 1, 2, 0, 4) },\n+ { WHvArm64RegisterDbgbcr0El1, ENCODE_AA64_CP_REG(0, 1, 2, 0, 5) },\n+ { WHvArm64RegisterDbgwvr0El1, ENCODE_AA64_CP_REG(0, 1, 2, 0, 6) },\n+ { WHvArm64RegisterDbgwcr0El1, ENCODE_AA64_CP_REG(0, 1, 2, 0, 7) },\n+\n+ { WHvArm64RegisterDbgbvr2El1, ENCODE_AA64_CP_REG(0, 2, 2, 0, 4) },\n+ { WHvArm64RegisterDbgbcr2El1, ENCODE_AA64_CP_REG(0, 2, 2, 0, 5) },\n+ { WHvArm64RegisterDbgwvr2El1, ENCODE_AA64_CP_REG(0, 2, 2, 0, 6) },\n+ { WHvArm64RegisterDbgwcr2El1, ENCODE_AA64_CP_REG(0, 2, 2, 0, 7) },\n+\n+ { WHvArm64RegisterDbgbvr3El1, ENCODE_AA64_CP_REG(0, 3, 2, 0, 4) },\n+ { WHvArm64RegisterDbgbcr3El1, ENCODE_AA64_CP_REG(0, 3, 2, 0, 5) },\n+ { WHvArm64RegisterDbgwvr3El1, ENCODE_AA64_CP_REG(0, 3, 2, 0, 6) },\n+ { WHvArm64RegisterDbgwcr3El1, ENCODE_AA64_CP_REG(0, 3, 2, 0, 7) },\n+\n+ { WHvArm64RegisterDbgbvr4El1, ENCODE_AA64_CP_REG(0, 4, 2, 0, 4) },\n+ { WHvArm64RegisterDbgbcr4El1, ENCODE_AA64_CP_REG(0, 4, 2, 0, 5) },\n+ { WHvArm64RegisterDbgwvr4El1, ENCODE_AA64_CP_REG(0, 4, 2, 0, 6) },\n+ { WHvArm64RegisterDbgwcr4El1, ENCODE_AA64_CP_REG(0, 4, 2, 0, 7) },\n+\n+ { WHvArm64RegisterDbgbvr5El1, ENCODE_AA64_CP_REG(0, 5, 2, 0, 4) },\n+ { WHvArm64RegisterDbgbcr5El1, ENCODE_AA64_CP_REG(0, 5, 2, 0, 5) },\n+ { WHvArm64RegisterDbgwvr5El1, ENCODE_AA64_CP_REG(0, 5, 2, 0, 6) },\n+ { WHvArm64RegisterDbgwcr5El1, ENCODE_AA64_CP_REG(0, 5, 2, 0, 7) },\n+\n+ { WHvArm64RegisterDbgbvr6El1, ENCODE_AA64_CP_REG(0, 6, 2, 0, 4) },\n+ { WHvArm64RegisterDbgbcr6El1, ENCODE_AA64_CP_REG(0, 6, 2, 0, 5) },\n+ { WHvArm64RegisterDbgwvr6El1, ENCODE_AA64_CP_REG(0, 6, 2, 0, 6) },\n+ { WHvArm64RegisterDbgwcr6El1, ENCODE_AA64_CP_REG(0, 6, 2, 0, 7) },\n+\n+ { WHvArm64RegisterDbgbvr7El1, ENCODE_AA64_CP_REG(0, 7, 2, 0, 4) },\n+ { WHvArm64RegisterDbgbcr7El1, ENCODE_AA64_CP_REG(0, 7, 2, 0, 5) },\n+ { WHvArm64RegisterDbgwvr7El1, ENCODE_AA64_CP_REG(0, 7, 2, 0, 6) },\n+ { WHvArm64RegisterDbgwcr7El1, ENCODE_AA64_CP_REG(0, 7, 2, 0, 7) },\n+\n+ { WHvArm64RegisterDbgbvr8El1, ENCODE_AA64_CP_REG(0, 8, 2, 0, 4) },\n+ { WHvArm64RegisterDbgbcr8El1, ENCODE_AA64_CP_REG(0, 8, 2, 0, 5) },\n+ { WHvArm64RegisterDbgwvr8El1, ENCODE_AA64_CP_REG(0, 8, 2, 0, 6) },\n+ { WHvArm64RegisterDbgwcr8El1, ENCODE_AA64_CP_REG(0, 8, 2, 0, 7) },\n+\n+ { WHvArm64RegisterDbgbvr9El1, ENCODE_AA64_CP_REG(0, 9, 2, 0, 4) },\n+ { WHvArm64RegisterDbgbcr9El1, ENCODE_AA64_CP_REG(0, 9, 2, 0, 5) },\n+ { WHvArm64RegisterDbgwvr9El1, ENCODE_AA64_CP_REG(0, 9, 2, 0, 6) },\n+ { WHvArm64RegisterDbgwcr9El1, ENCODE_AA64_CP_REG(0, 9, 2, 0, 7) },\n+\n+ { WHvArm64RegisterDbgbvr10El1, ENCODE_AA64_CP_REG(0, 10, 2, 0, 4) },\n+ { WHvArm64RegisterDbgbcr10El1, ENCODE_AA64_CP_REG(0, 10, 2, 0, 5) },\n+ { WHvArm64RegisterDbgwvr10El1, ENCODE_AA64_CP_REG(0, 10, 2, 0, 6) },\n+ { WHvArm64RegisterDbgwcr10El1, ENCODE_AA64_CP_REG(0, 10, 2, 0, 7) },\n+\n+ { WHvArm64RegisterDbgbvr11El1, ENCODE_AA64_CP_REG(0, 11, 2, 0, 4) },\n+ { WHvArm64RegisterDbgbcr11El1, ENCODE_AA64_CP_REG(0, 11, 2, 0, 5) },\n+ { WHvArm64RegisterDbgwvr11El1, ENCODE_AA64_CP_REG(0, 11, 2, 0, 6) },\n+ { WHvArm64RegisterDbgwcr11El1, ENCODE_AA64_CP_REG(0, 11, 2, 0, 7) },\n+\n+ { WHvArm64RegisterDbgbvr12El1, ENCODE_AA64_CP_REG(0, 12, 2, 0, 4) },\n+ { WHvArm64RegisterDbgbcr12El1, ENCODE_AA64_CP_REG(0, 12, 2, 0, 5) },\n+ { WHvArm64RegisterDbgwvr12El1, ENCODE_AA64_CP_REG(0, 12, 2, 0, 6) },\n+ { WHvArm64RegisterDbgwcr12El1, ENCODE_AA64_CP_REG(0, 12, 2, 0, 7) },\n+\n+ { WHvArm64RegisterDbgbvr13El1, ENCODE_AA64_CP_REG(0, 13, 2, 0, 4) },\n+ { WHvArm64RegisterDbgbcr13El1, ENCODE_AA64_CP_REG(0, 13, 2, 0, 5) },\n+ { WHvArm64RegisterDbgwvr13El1, ENCODE_AA64_CP_REG(0, 13, 2, 0, 6) },\n+ { WHvArm64RegisterDbgwcr13El1, ENCODE_AA64_CP_REG(0, 13, 2, 0, 7) },\n+\n+ { WHvArm64RegisterDbgbvr14El1, ENCODE_AA64_CP_REG(0, 14, 2, 0, 4) },\n+ { WHvArm64RegisterDbgbcr14El1, ENCODE_AA64_CP_REG(0, 14, 2, 0, 5) },\n+ { WHvArm64RegisterDbgwvr14El1, ENCODE_AA64_CP_REG(0, 14, 2, 0, 6) },\n+ { WHvArm64RegisterDbgwcr14El1, ENCODE_AA64_CP_REG(0, 14, 2, 0, 7) },\n+\n+ { WHvArm64RegisterDbgbvr15El1, ENCODE_AA64_CP_REG(0, 15, 2, 0, 4) },\n+ { WHvArm64RegisterDbgbcr15El1, ENCODE_AA64_CP_REG(0, 15, 2, 0, 5) },\n+ { WHvArm64RegisterDbgwvr15El1, ENCODE_AA64_CP_REG(0, 15, 2, 0, 6) },\n+ { WHvArm64RegisterDbgwcr15El1, ENCODE_AA64_CP_REG(0, 15, 2, 0, 7) },\n+#ifdef SYNC_NO_RAW_REGS\n+ /*\n+ * The registers below are manually synced on init because they are\n+ * marked as NO_RAW. We still list them to make number space sync easier.\n+ */\n+ { WHvArm64RegisterMidrEl1, ENCODE_AA64_CP_REG(0, 0, 3, 0, 0) },\n+ { WHvArm64RegisterMpidrEl1, ENCODE_AA64_CP_REG(0, 0, 3, 0, 5) },\n+ { WHvArm64RegisterIdPfr0El1, ENCODE_AA64_CP_REG(0, 4, 3, 0, 0) },\n+#endif\n+ { WHvArm64RegisterIdAa64Pfr1El1, ENCODE_AA64_CP_REG(0, 4, 3, 0, 1), true },\n+ { WHvArm64RegisterIdAa64Dfr0El1, ENCODE_AA64_CP_REG(0, 5, 3, 0, 0), true },\n+ { WHvArm64RegisterIdAa64Dfr1El1, ENCODE_AA64_CP_REG(0, 5, 3, 0, 1), true },\n+ { WHvArm64RegisterIdAa64Isar0El1, ENCODE_AA64_CP_REG(0, 6, 3, 0, 0), true },\n+ { WHvArm64RegisterIdAa64Isar1El1, ENCODE_AA64_CP_REG(0, 6, 3, 0, 1), true },\n+#ifdef SYNC_NO_MMFR0\n+ /* We keep the hardware MMFR0 around. HW limits are there anyway */\n+ { WHvArm64RegisterIdAa64Mmfr0El1, ENCODE_AA64_CP_REG(0, 7, 3, 0, 0) },\n+#endif\n+ { WHvArm64RegisterIdAa64Mmfr1El1, ENCODE_AA64_CP_REG(0, 7, 3, 0, 1), true },\n+ { WHvArm64RegisterIdAa64Mmfr2El1, ENCODE_AA64_CP_REG(0, 7, 3, 0, 2), true },\n+ { WHvArm64RegisterIdAa64Mmfr3El1, ENCODE_AA64_CP_REG(0, 7, 3, 0, 3), true },\n+\n+ { WHvArm64RegisterMdscrEl1, ENCODE_AA64_CP_REG(0, 2, 2, 0, 2) },\n+ { WHvArm64RegisterSctlrEl1, ENCODE_AA64_CP_REG(1, 0, 3, 0, 0) },\n+ { WHvArm64RegisterCpacrEl1, ENCODE_AA64_CP_REG(1, 0, 3, 0, 2) },\n+ { WHvArm64RegisterTtbr0El1, ENCODE_AA64_CP_REG(2, 0, 3, 0, 0) },\n+ { WHvArm64RegisterTtbr1El1, ENCODE_AA64_CP_REG(2, 0, 3, 0, 1) },\n+ { WHvArm64RegisterTcrEl1, ENCODE_AA64_CP_REG(2, 0, 3, 0, 2) },\n+\n+ { WHvArm64RegisterApiAKeyLoEl1, ENCODE_AA64_CP_REG(2, 1, 3, 0, 0) },\n+ { WHvArm64RegisterApiAKeyHiEl1, ENCODE_AA64_CP_REG(2, 1, 3, 0, 1) },\n+ { WHvArm64RegisterApiBKeyLoEl1, ENCODE_AA64_CP_REG(2, 1, 3, 0, 2) },\n+ { WHvArm64RegisterApiBKeyHiEl1, ENCODE_AA64_CP_REG(2, 1, 3, 0, 3) },\n+ { WHvArm64RegisterApdAKeyLoEl1, ENCODE_AA64_CP_REG(2, 2, 3, 0, 0) },\n+ { WHvArm64RegisterApdAKeyHiEl1, ENCODE_AA64_CP_REG(2, 2, 3, 0, 1) },\n+ { WHvArm64RegisterApdBKeyLoEl1, ENCODE_AA64_CP_REG(2, 2, 3, 0, 2) },\n+ { WHvArm64RegisterApdBKeyHiEl1, ENCODE_AA64_CP_REG(2, 2, 3, 0, 3) },\n+ { WHvArm64RegisterApgAKeyLoEl1, ENCODE_AA64_CP_REG(2, 3, 3, 0, 0) },\n+ { WHvArm64RegisterApgAKeyHiEl1, ENCODE_AA64_CP_REG(2, 3, 3, 0, 1) },\n+\n+ { WHvArm64RegisterSpsrEl1, ENCODE_AA64_CP_REG(4, 0, 3, 0, 0) },\n+ { WHvArm64RegisterElrEl1, ENCODE_AA64_CP_REG(4, 0, 3, 0, 1) },\n+ { WHvArm64RegisterSpEl1, ENCODE_AA64_CP_REG(4, 1, 3, 0, 0) },\n+ { WHvArm64RegisterEsrEl1, ENCODE_AA64_CP_REG(5, 2, 3, 0, 0) },\n+ { WHvArm64RegisterFarEl1, ENCODE_AA64_CP_REG(6, 0, 3, 0, 0) },\n+ { WHvArm64RegisterParEl1, ENCODE_AA64_CP_REG(7, 4, 3, 0, 0) },\n+ { WHvArm64RegisterMairEl1, ENCODE_AA64_CP_REG(10, 2, 3, 0, 0) },\n+ { WHvArm64RegisterVbarEl1, ENCODE_AA64_CP_REG(12, 0, 3, 0, 0) },\n+ { WHvArm64RegisterContextidrEl1, ENCODE_AA64_CP_REG(13, 0, 3, 0, 1) },\n+ { WHvArm64RegisterTpidrEl1, ENCODE_AA64_CP_REG(13, 0, 3, 0, 4) },\n+ { WHvArm64RegisterCntkctlEl1, ENCODE_AA64_CP_REG(14, 1, 3, 0, 0) },\n+ { WHvArm64RegisterCsselrEl1, ENCODE_AA64_CP_REG(0, 0, 3, 2, 0) },\n+ { WHvArm64RegisterTpidrEl0, ENCODE_AA64_CP_REG(13, 0, 3, 3, 2) },\n+ { WHvArm64RegisterTpidrroEl0, ENCODE_AA64_CP_REG(13, 0, 3, 3, 3) },\n+ { WHvArm64RegisterCntvCtlEl0, ENCODE_AA64_CP_REG(14, 3, 3, 3, 1) },\n+ { WHvArm64RegisterCntvCvalEl0, ENCODE_AA64_CP_REG(14, 3, 3, 3, 2) },\n+ { WHvArm64RegisterSpEl1, ENCODE_AA64_CP_REG(4, 1, 3, 4, 0) },\n+};\n+\n+static void flush_cpu_state(CPUState *cpu)\n+{\n+ if (cpu->vcpu_dirty) {\n+ whpx_set_registers(cpu, WHPX_SET_RUNTIME_STATE);\n+ cpu->vcpu_dirty = false;\n+ }\n+}\n+\n+HRESULT whpx_set_exception_exit_bitmap(UINT64 exceptions)\n+{\n+ if (exceptions != 0) {\n+ return E_NOTIMPL;\n+ }\n+ return ERROR_SUCCESS;\n+}\n+void whpx_apply_breakpoints(\n+ struct whpx_breakpoint_collection *breakpoints,\n+ CPUState *cpu,\n+ bool resuming)\n+{\n+ /* Breakpoints aren’t supported on this platform */\n+}\n+void whpx_translate_cpu_breakpoints(\n+ struct whpx_breakpoints *breakpoints,\n+ CPUState *cpu,\n+ int cpu_breakpoint_count)\n+{\n+ /* Breakpoints aren’t supported on this platform */\n+}\n+\n+static void whpx_get_reg(CPUState *cpu, WHV_REGISTER_NAME reg, WHV_REGISTER_VALUE* val)\n+{\n+ struct whpx_state *whpx = &whpx_global;\n+ HRESULT hr;\n+\n+ flush_cpu_state(cpu);\n+\n+ hr = whp_dispatch.WHvGetVirtualProcessorRegisters(whpx->partition, cpu->cpu_index,\n+ ®, 1, val);\n+\n+ if (FAILED(hr)) {\n+ error_report(\"WHPX: Failed to get register %08x, hr=%08lx\", reg, hr);\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+ 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_get_global_reg(WHV_REGISTER_NAME reg, WHV_REGISTER_VALUE *val)\n+{\n+ struct whpx_state *whpx = &whpx_global;\n+ HRESULT hr;\n+\n+ hr = whp_dispatch.WHvGetVirtualProcessorRegisters(whpx->partition, WHV_ANY_VP,\n+ ®, 1, val);\n+\n+ if (FAILED(hr)) {\n+ error_report(\"WHPX: Failed to get register %08x, hr=%08lx\", reg, hr);\n+ }\n+}\n+\n+static void whpx_set_global_reg(WHV_REGISTER_NAME reg, WHV_REGISTER_VALUE val)\n+{\n+ struct whpx_state *whpx = &whpx_global;\n+ HRESULT hr;\n+ hr = whp_dispatch.WHvSetVirtualProcessorRegisters(whpx->partition, WHV_ANY_VP,\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 uint64_t whpx_get_gp_reg(CPUState *cpu, int rt)\n+{\n+ assert(rt <= 31);\n+ if (rt == 31) {\n+ return 0;\n+ }\n+ WHV_REGISTER_NAME reg = WHvArm64RegisterX0 + rt;\n+ WHV_REGISTER_VALUE val;\n+ whpx_get_reg(cpu, reg, &val);\n+\n+ return val.Reg64;\n+}\n+\n+static void whpx_set_gp_reg(CPUState *cpu, int rt, uint64_t val)\n+{\n+ assert(rt < 31);\n+ WHV_REGISTER_NAME reg = WHvArm64RegisterX0 + rt;\n+ WHV_REGISTER_VALUE reg_val = {.Reg64 = val};\n+\n+ whpx_set_reg(cpu, reg, reg_val);\n+}\n+\n+static int whpx_handle_mmio(CPUState *cpu, WHV_MEMORY_ACCESS_CONTEXT *ctx)\n+{\n+ uint64_t syndrome = ctx->Syndrome;\n+\n+ bool isv = syndrome & ARM_EL_ISV;\n+ bool iswrite = (syndrome >> 6) & 1;\n+ bool sse = (syndrome >> 21) & 1;\n+ uint32_t sas = (syndrome >> 22) & 3;\n+ uint32_t len = 1 << sas;\n+ uint32_t srt = (syndrome >> 16) & 0x1f;\n+ uint32_t cm = (syndrome >> 8) & 0x1;\n+ uint64_t val = 0;\n+\n+ assert(!cm);\n+ assert(isv);\n+\n+ if (iswrite) {\n+ val = whpx_get_gp_reg(cpu, srt);\n+ address_space_write(&address_space_memory,\n+ ctx->Gpa,\n+ MEMTXATTRS_UNSPECIFIED, &val, len);\n+ } else {\n+ address_space_read(&address_space_memory,\n+ ctx->Gpa,\n+ MEMTXATTRS_UNSPECIFIED, &val, len);\n+ if (sse) {\n+ val = sextract64(val, 0, len * 8);\n+ }\n+ whpx_set_gp_reg(cpu, srt, val);\n+ }\n+\n+ return 0;\n+}\n+\n+static void whpx_psci_cpu_off(ARMCPU *arm_cpu)\n+{\n+ int32_t ret = arm_set_cpu_off(arm_cpu_mp_affinity(arm_cpu));\n+ assert(ret == QEMU_ARM_POWERCTL_RET_SUCCESS);\n+}\n+\n+int whpx_vcpu_run(CPUState *cpu)\n+{\n+ HRESULT hr;\n+ struct whpx_state *whpx = &whpx_global;\n+ ARMCPU *arm_cpu = ARM_CPU(cpu);\n+ AccelCPUState *vcpu = cpu->accel;\n+ int ret;\n+\n+\n+ g_assert(bql_locked());\n+\n+ if (whpx->running_cpus++ == 0) {\n+ ret = whpx_first_vcpu_starting(cpu);\n+ if (ret != 0) {\n+ return ret;\n+ }\n+ }\n+\n+ bql_unlock();\n+\n+\n+ cpu_exec_start(cpu);\n+ do {\n+ bool advance_pc = false;\n+ if (cpu->vcpu_dirty) {\n+ whpx_set_registers(cpu, WHPX_SET_RUNTIME_STATE);\n+ cpu->vcpu_dirty = false;\n+ }\n+\n+ if (qatomic_read(&cpu->exit_request)) {\n+ whpx_vcpu_kick(cpu);\n+ }\n+\n+ hr = whp_dispatch.WHvRunVirtualProcessor(\n+ whpx->partition, cpu->cpu_index,\n+ &vcpu->exit_ctx, sizeof(vcpu->exit_ctx));\n+\n+ if (FAILED(hr)) {\n+ error_report(\"WHPX: Failed to exec a virtual processor,\"\n+ \" hr=%08lx\", hr);\n+ ret = -1;\n+ break;\n+ }\n+\n+ switch (vcpu->exit_ctx.ExitReason) {\n+ case WHvRunVpExitReasonGpaIntercept:\n+ case WHvRunVpExitReasonUnmappedGpa:\n+ advance_pc = true;\n+\n+ if (vcpu->exit_ctx.MemoryAccess.Syndrome & BIT(8)) {\n+ error_report(\"WHPX: cached access to unmapped memory\"\n+ \"Pc = 0x%llx Gva = 0x%llx Gpa = 0x%llx\",\n+ vcpu->exit_ctx.MemoryAccess.Header.Pc,\n+ vcpu->exit_ctx.MemoryAccess.Gpa,\n+ vcpu->exit_ctx.MemoryAccess.Gva);\n+ break;\n+ }\n+\n+ ret = whpx_handle_mmio(cpu, &vcpu->exit_ctx.MemoryAccess);\n+ break;\n+ case WHvRunVpExitReasonCanceled:\n+ cpu->exception_index = EXCP_INTERRUPT;\n+ ret = 1;\n+ break;\n+ case WHvRunVpExitReasonArm64Reset:\n+ switch (vcpu->exit_ctx.Arm64Reset.ResetType) {\n+ case WHvArm64ResetTypePowerOff:\n+ qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);\n+ break;\n+ case WHvArm64ResetTypeReboot:\n+ qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);\n+ break;\n+ default:\n+ g_assert_not_reached();\n+ }\n+ bql_lock();\n+ if (arm_cpu->power_state != PSCI_OFF) {\n+ whpx_psci_cpu_off(arm_cpu);\n+ }\n+ bql_unlock();\n+ break;\n+ case WHvRunVpExitReasonNone:\n+ case WHvRunVpExitReasonUnrecoverableException:\n+ case WHvRunVpExitReasonInvalidVpRegisterValue:\n+ case WHvRunVpExitReasonUnsupportedFeature:\n+ default:\n+ error_report(\"WHPX: Unexpected VP exit code 0x%08x\",\n+ vcpu->exit_ctx.ExitReason);\n+ whpx_get_registers(cpu);\n+ bql_lock();\n+ qemu_system_guest_panicked(cpu_get_crash_info(cpu));\n+ bql_unlock();\n+ break;\n+ }\n+ if (advance_pc) {\n+ WHV_REGISTER_VALUE pc;\n+\n+ flush_cpu_state(cpu);\n+ pc.Reg64 = vcpu->exit_ctx.MemoryAccess.Header.Pc + 4;\n+ whpx_set_reg(cpu, WHvArm64RegisterPc, pc);\n+ }\n+ } while (!ret);\n+\n+ cpu_exec_end(cpu);\n+\n+ bql_lock();\n+ current_cpu = cpu;\n+\n+ if (--whpx->running_cpus == 0) {\n+ whpx_last_vcpu_stopping(cpu);\n+ }\n+\n+ qatomic_set(&cpu->exit_request, false);\n+\n+ return ret < 0;\n+}\n+\n+static void clean_whv_register_value(WHV_REGISTER_VALUE *val)\n+{\n+ memset(val, 0, sizeof(WHV_REGISTER_VALUE));\n+}\n+\n+void whpx_get_registers(CPUState *cpu)\n+{\n+ ARMCPU *arm_cpu = ARM_CPU(cpu);\n+ CPUARMState *env = &arm_cpu->env;\n+ WHV_REGISTER_VALUE val;\n+ int i;\n+\n+ for (i = 0; i < ARRAY_SIZE(whpx_reg_match); i++) {\n+ whpx_get_reg(cpu, whpx_reg_match[i].reg, &val);\n+ *(uint64_t *)((char *)env + whpx_reg_match[i].offset) = val.Reg64;\n+ }\n+\n+ for (i = 0; i < ARRAY_SIZE(whpx_fpreg_match); i++) {\n+ whpx_get_reg(cpu, whpx_reg_match[i].reg, &val);\n+ memcpy((char *)env + whpx_fpreg_match[i].offset, &val, sizeof(val.Reg128));\n+ }\n+\n+ whpx_get_reg(cpu, WHvArm64RegisterPc, &val);\n+ env->pc = val.Reg64;\n+\n+ whpx_get_reg(cpu, WHvArm64RegisterFpcr, &val);\n+ vfp_set_fpcr(env, val.Reg32);\n+\n+ whpx_get_reg(cpu, WHvArm64RegisterFpsr, &val);\n+ vfp_set_fpsr(env, val.Reg32);\n+\n+ whpx_get_reg(cpu, WHvArm64RegisterPstate, &val);\n+ pstate_write(env, val.Reg32);\n+\n+ for (i = 0; i < ARRAY_SIZE(whpx_sreg_match); i++) {\n+ if (whpx_sreg_match[i].cp_idx == -1) {\n+ continue;\n+ }\n+\n+ if (whpx_sreg_match[i].global) {\n+ /* WHP disallows us from accessing global regs as a vCPU */\n+ whpx_get_global_reg(whpx_sreg_match[i].reg, &val);\n+ } else {\n+ whpx_get_reg(cpu, whpx_sreg_match[i].reg, &val);\n+ }\n+ arm_cpu->cpreg_values[whpx_sreg_match[i].cp_idx] = val.Reg64;\n+ }\n+\n+ assert(write_list_to_cpustate(arm_cpu));\n+ aarch64_restore_sp(env, arm_current_el(env));\n+}\n+\n+void whpx_set_registers(CPUState *cpu, int level)\n+{\n+ ARMCPU *arm_cpu = ARM_CPU(cpu);\n+ CPUARMState *env = &arm_cpu->env;\n+ WHV_REGISTER_VALUE val;\n+ clean_whv_register_value(&val);\n+ int i;\n+\n+ assert(cpu_is_stopped(cpu) || qemu_cpu_is_self(cpu));\n+\n+ for (i = 0; i < ARRAY_SIZE(whpx_reg_match); i++) {\n+ val.Reg64 = *(uint64_t *)((char *)env + whpx_reg_match[i].offset);\n+ whpx_set_reg(cpu, whpx_reg_match[i].reg, val);\n+ }\n+\n+ for (i = 0; i < ARRAY_SIZE(whpx_fpreg_match); i++) {\n+ memcpy(&val.Reg128, (char *)env + whpx_fpreg_match[i].offset, sizeof(val.Reg128));\n+ whpx_set_reg(cpu, whpx_reg_match[i].reg, val);\n+ }\n+\n+ clean_whv_register_value(&val);\n+ val.Reg64 = env->pc;\n+ whpx_set_reg(cpu, WHvArm64RegisterPc, val);\n+\n+ clean_whv_register_value(&val);\n+ val.Reg32 = vfp_get_fpcr(env);\n+ whpx_set_reg(cpu, WHvArm64RegisterFpcr, val);\n+ val.Reg32 = vfp_get_fpsr(env);\n+ whpx_set_reg(cpu, WHvArm64RegisterFpsr, val);\n+ val.Reg32 = pstate_read(env);\n+ whpx_set_reg(cpu, WHvArm64RegisterPstate, val);\n+\n+ aarch64_save_sp(env, arm_current_el(env));\n+\n+ assert(write_cpustate_to_list(arm_cpu, false));\n+\n+ /* Currently set global regs every time. */\n+ for (i = 0; i < ARRAY_SIZE(whpx_sreg_match); i++) {\n+ if (whpx_sreg_match[i].cp_idx == -1) {\n+ continue;\n+ }\n+\n+ val.Reg64 = arm_cpu->cpreg_values[whpx_sreg_match[i].cp_idx];\n+ if (whpx_sreg_match[i].global) {\n+ /* WHP disallows us from accessing global regs as a vCPU */\n+ whpx_set_global_reg(whpx_sreg_match[i].reg, val);\n+ } else {\n+ whpx_set_reg(cpu, whpx_sreg_match[i].reg, val);\n+ }\n+ }\n+}\n+\n+static uint32_t max_vcpu_index;\n+\n+static void whpx_cpu_update_state(void *opaque, bool running, RunState state)\n+{\n+}\n+\n+int whpx_init_vcpu(CPUState *cpu)\n+{\n+ HRESULT hr;\n+ struct whpx_state *whpx = &whpx_global;\n+ ARMCPU *arm_cpu = ARM_CPU(cpu);\n+ CPUARMState *env = &arm_cpu->env;\n+\n+ uint32_t sregs_match_len = ARRAY_SIZE(whpx_sreg_match);\n+ uint32_t sregs_cnt = 0;\n+ WHV_REGISTER_VALUE val;\n+ int i;\n+\n+ hr = whp_dispatch.WHvCreateVirtualProcessor(\n+ whpx->partition, cpu->cpu_index, 0);\n+ if (FAILED(hr)) {\n+ error_report(\"WHPX: Failed to create a virtual processor,\"\n+ \" hr=%08lx\", hr);\n+ return -EINVAL;\n+ }\n+\n+ /* Assumption that CNTFRQ_EL0 is the same between the VMM and the partition. */\n+ asm volatile(\"mrs %0, cntfrq_el0\" : \"=r\"(arm_cpu->gt_cntfrq_hz));\n+\n+ cpu->vcpu_dirty = true;\n+ cpu->accel = g_new0(AccelCPUState, 1);\n+ max_vcpu_index = MAX(max_vcpu_index, cpu->cpu_index);\n+ qemu_add_vm_change_state_handler(whpx_cpu_update_state, env);\n+\n+ env->aarch64 = true;\n+\n+ /* Allocate enough space for our sysreg sync */\n+ arm_cpu->cpreg_indexes = g_renew(uint64_t, arm_cpu->cpreg_indexes,\n+ sregs_match_len);\n+ arm_cpu->cpreg_values = g_renew(uint64_t, arm_cpu->cpreg_values,\n+ sregs_match_len);\n+ arm_cpu->cpreg_vmstate_indexes = g_renew(uint64_t,\n+ arm_cpu->cpreg_vmstate_indexes,\n+ sregs_match_len);\n+ arm_cpu->cpreg_vmstate_values = g_renew(uint64_t,\n+ arm_cpu->cpreg_vmstate_values,\n+ sregs_match_len);\n+\n+ memset(arm_cpu->cpreg_values, 0, sregs_match_len * sizeof(uint64_t));\n+\n+ /* Populate cp list for all known sysregs */\n+ for (i = 0; i < sregs_match_len; i++) {\n+ const ARMCPRegInfo *ri;\n+ uint32_t key = whpx_sreg_match[i].key;\n+\n+ ri = get_arm_cp_reginfo(arm_cpu->cp_regs, key);\n+ if (ri) {\n+ assert(!(ri->type & ARM_CP_NO_RAW));\n+ whpx_sreg_match[i].cp_idx = sregs_cnt;\n+ arm_cpu->cpreg_indexes[sregs_cnt++] = cpreg_to_kvm_id(key);\n+ } else {\n+ whpx_sreg_match[i].cp_idx = -1;\n+ }\n+ }\n+ arm_cpu->cpreg_array_len = sregs_cnt;\n+ arm_cpu->cpreg_vmstate_array_len = sregs_cnt;\n+\n+ assert(write_cpustate_to_list(arm_cpu, false));\n+\n+ /* Set CP_NO_RAW system registers on init */\n+ val.Reg64 = arm_cpu->midr;\n+ whpx_set_reg(cpu, WHvArm64RegisterMidrEl1,\n+ val);\n+\n+ clean_whv_register_value(&val);\n+\n+ val.Reg64 = deposit64(arm_cpu->mp_affinity, 31, 1, 1 /* RES1 */);\n+ whpx_set_reg(cpu, WHvArm64RegisterMpidrEl1, val);\n+\n+ return 0;\n+}\n+\n+void whpx_cpu_instance_init(CPUState *cs)\n+{\n+}\n+\n+int whpx_accel_init(AccelState *as, MachineState *ms)\n+{\n+ struct whpx_state *whpx;\n+ int ret;\n+ HRESULT hr;\n+ WHV_CAPABILITY whpx_cap;\n+ UINT32 whpx_cap_size;\n+ WHV_PARTITION_PROPERTY prop;\n+ WHV_CAPABILITY_FEATURES features;\n+\n+ whpx = &whpx_global;\n+ /* on arm64 Windows Hypervisor Platform, vGICv3 always used */\n+ whpx_irqchip_in_kernel = true;\n+\n+ if (!init_whp_dispatch()) {\n+ ret = -ENOSYS;\n+ goto error;\n+ }\n+\n+ whpx->mem_quota = ms->ram_size;\n+\n+ hr = whp_dispatch.WHvGetCapability(\n+ WHvCapabilityCodeHypervisorPresent, &whpx_cap,\n+ sizeof(whpx_cap), &whpx_cap_size);\n+ if (FAILED(hr) || !whpx_cap.HypervisorPresent) {\n+ error_report(\"WHPX: No accelerator found, hr=%08lx\", hr);\n+ ret = -ENOSPC;\n+ goto error;\n+ }\n+\n+ memset(&features, 0, sizeof(features));\n+ hr = whp_dispatch.WHvGetCapability(\n+ WHvCapabilityCodeFeatures, &features, sizeof(features), NULL);\n+ if (FAILED(hr)) {\n+ error_report(\"WHPX: Failed to query capabilities, hr=%08lx\", hr);\n+ ret = -EINVAL;\n+ goto error;\n+ }\n+\n+ if (!features.Arm64Support) {\n+ error_report(\"WHPX: host OS exposing pre-release WHPX implementation. \"\n+ \"Please update your operating system to at least build 26100.3915\");\n+ ret = -EINVAL;\n+ goto error;\n+ }\n+\n+ hr = whp_dispatch.WHvCreatePartition(&whpx->partition);\n+ if (FAILED(hr)) {\n+ error_report(\"WHPX: Failed to create partition, hr=%08lx\", hr);\n+ ret = -EINVAL;\n+ goto error;\n+ }\n+\n+ memset(&prop, 0, sizeof(prop));\n+ prop.ProcessorCount = ms->smp.cpus;\n+ hr = whp_dispatch.WHvSetPartitionProperty(\n+ whpx->partition,\n+ WHvPartitionPropertyCodeProcessorCount,\n+ &prop,\n+ sizeof(prop));\n+\n+ if (FAILED(hr)) {\n+ error_report(\"WHPX: Failed to set partition processor count to %u,\"\n+ \" hr=%08lx\", prop.ProcessorCount, hr);\n+ ret = -EINVAL;\n+ goto error;\n+ }\n+\n+ if (!whpx->kernel_irqchip_allowed) {\n+ error_report(\"WHPX: on Arm, only kernel-irqchip=on is currently supported\");\n+ ret = -EINVAL;\n+ goto error;\n+ }\n+\n+ memset(&prop, 0, sizeof(prop));\n+\n+ hr = whp_dispatch.WHvSetupPartition(whpx->partition);\n+ if (FAILED(hr)) {\n+ error_report(\"WHPX: Failed to setup partition, hr=%08lx\", hr);\n+ ret = -EINVAL;\n+ goto error;\n+ }\n+\n+ whpx_memory_init();\n+\n+ return 0;\n+\n+error:\n+ if (whpx->partition != NULL) {\n+ whp_dispatch.WHvDeletePartition(whpx->partition);\n+ whpx->partition = NULL;\n+ }\n+\n+ return ret;\n+}\n", "prefixes": [ "PULL", "14/26" ] }