From nobody Fri Nov 14 18:05:09 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=reject dis=none) header.from=unpredictable.fr ARC-Seal: i=1; a=rsa-sha256; t=1760636488; cv=none; d=zohomail.com; s=zohoarc; b=KpZbblRFeeTpIHVncLcxh3TOySEqtu/9WB9/LKslltf4pxpsDvJT7mQqj8Z6aRIrQFFjP+z29bZ2RqCZHHIT5756Xv71pekyfWbO7+gvRP2vn8gV7p159KjyFfVF1mEesTlnHvEwrq0hbMBOZoCHFWvZtZEM+zBdkRBK+vK9uWQ= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1760636488; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=KS1drIzDSxivmOt789wl2SZJxZmlGZDJzXCWJBUlG48=; b=OvJP0PMWYQsiOEivBrkJbv49iPjXHB2VsmZQHBlbyQcMgcNiVtBlXlZoN//PhaTYM2bLbtysmCVix1TTz5Jn7rxyawgo7LwLY7y6T6pIxEzhggJZ/TvKR4WkL/7oJJ/YqHVPBf5MWzG6V1ZpZFR1Ku2t4gG6M+I+2pE5I89E/tc= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=reject dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1760636488792255.51423377196727; Thu, 16 Oct 2025 10:41:28 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1v9RwW-0006j5-H8; Thu, 16 Oct 2025 13:39:12 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1v9RwS-0006h0-Ce for qemu-devel@nongnu.org; Thu, 16 Oct 2025 13:39:09 -0400 Received: from p-east2-cluster4-host10-snip4-6.eps.apple.com ([57.103.78.227] helo=outbound.st.icloud.com) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1v9RwH-0007iJ-1T for qemu-devel@nongnu.org; Thu, 16 Oct 2025 13:39:08 -0400 Received: from outbound.st.icloud.com (unknown [127.0.0.2]) by p00-icloudmta-asmtp-us-east-1a-100-percent-6 (Postfix) with ESMTPS id 3E2E31800113; Thu, 16 Oct 2025 17:38:50 +0000 (UTC) Received: from localhost.localdomain (unknown [17.42.251.67]) by p00-icloudmta-asmtp-us-east-1a-100-percent-6 (Postfix) with ESMTPSA id 349B71800133; Thu, 16 Oct 2025 17:38:46 +0000 (UTC) Dkim-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=unpredictable.fr; s=sig1; bh=KS1drIzDSxivmOt789wl2SZJxZmlGZDJzXCWJBUlG48=; h=From:To:Subject:Date:Message-ID:MIME-Version:x-icloud-hme; b=Qpu0Gebod03/1Ns7C+eImTlAJIGOAAWMiNBK+zhOojKfIcrVcXZbBBRvUxl92bPahpB0oiWQkpQ+poV74a/QLbpOzgWrnnF19rvM7o2v/xL2BcIqNMRGTmEWcNrZeBQXBQ4c88PfQYY2MCkGYs4Qe33wV88YdjU6sBThjM0P8fpBdw8rY/tPfFRN39AednJe75NJUwTlcj0ZxMSPCzq13AoQRstlLhYhx7kdu2ABO7Y98a9Je90V7zG/yjQ+LpFOAglhiz3QSyxMURH3GpWOqV1hU6OxoZ5tsttF5itA6rKb2EpcwC3rOLvAVWeBrHreO8QSaMr8wKKFc8CokeetXg== mail-alias-created-date: 1752046281608 From: Mohamed Mediouni To: qemu-devel@nongnu.org Cc: qemu-arm@nongnu.org, kvm@vger.kernel.org, Richard Henderson , Sunil Muthuswamy , "Michael S. Tsirkin" , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= , Eduardo Habkost , Igor Mammedov , Yanan Wang , Ani Sinha , Shannon Zhao , Cameron Esfahani , Mads Ynddal , Zhao Liu , Phil Dennis-Jordan , Roman Bolshakov , Peter Maydell , Marcel Apfelbaum , Mohamed Mediouni , Paolo Bonzini , Alexander Graf , =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= , Pedro Barbuda , Pierrick Bouvier Subject: [PATCH v8 12/24] whpx: add arm64 support Date: Thu, 16 Oct 2025 19:37:51 +0200 Message-ID: <20251016173803.65764-13-mohamed@unpredictable.fr> X-Mailer: git-send-email 2.50.1 In-Reply-To: <20251016173803.65764-1-mohamed@unpredictable.fr> References: <20251016173803.65764-1-mohamed@unpredictable.fr> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Proofpoint-Spam-Details-Enc: AW1haW4tMjUxMDE2MDEyOCBTYWx0ZWRfX0LmAAwuAIO+m r2FAeRTDB5EUdFC5lKwRcItJHulwLZCBl9khJRU9CrtSaMcvsIDrZGJ7KaRoGxpHSy6bNRtJV7d He5BMO6c/ZiVHhFreXCEAMvpLQiuSatL6wSHTxFrnKMYu+Ra2wCPT3mEC4M8aFfF4jIcUAzSZVH 2rnq0a925kYyji9baCtNCgaMhGd+AVdlxj12EIvBWWA5LNZ5XG9cfmENS4W0RTpaiTIbK8+j4Po o1HS0WUw80r+SqSUjBmyhmlfHJ7veSEmeb+vuGrErQmHxn6ZA/8tlh9TQtWm8xFAoH+wxoYdk= X-Proofpoint-GUID: 7QYb6AjW0IrUiYzGfmeJDtkn8cms-Nbl X-Proofpoint-ORIG-GUID: 7QYb6AjW0IrUiYzGfmeJDtkn8cms-Nbl X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1121,Hydra:6.1.9,FMLib:17.12.80.40 definitions=2025-10-16_03,2025-10-13_01,2025-03-28_01 X-Proofpoint-Spam-Details: rule=notspam policy=default score=0 phishscore=0 suspectscore=0 clxscore=1030 bulkscore=0 mlxscore=0 malwarescore=0 spamscore=0 mlxlogscore=999 adultscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.22.0-2506270000 definitions=main-2510160128 X-JNJ: AAAAAAABa4T1ioKbrCPJesvNvzDQg6NW4C/Ls7XyJMsAREGQ10TfH1sLoiJfnM11/T6QBxFTD7pxvtRJ1Ep0evEtG1y4vfjAMySO5KY00l9hlEHep4HcBVFDi61rneOBVwU0eIJp10xRgSJVKNvN04xlit6mJffNkxPQwE3pfu8cVEwyJqus2Ac3CHyW1JlLASIXY5dSz8oJi8tuzIEYP5tLRF3condVIPUWQfqUioXGBIkkIk3LpQT9upYwaEf1KauLz8EGMcskVXNmFPTJvvAv/2ZoAZvhgUG/n+whir+CWc6gTwJo7Br5NNCWtoOjVsiom529zfLgHsUMtFFlyq3TUIXt0xqfmeofjSMd6pAj1cQTdXNR6Em0r36KfIzVx9rYhUWXt1JqTVIuIF4e2DUdUdNiwbEUJrmaOUGyif7azl7tdxCvlTksTlAthpJSFL6lCrUT5SHb3jpeOenkU2H3k8yJxNOcD/GvZaJNQUoYr/T1tq7pBODF1y9g7tVQQPaFvneWfcmtNIlfsPp0v49MCA6jnk7Unv1fpfW4RP5p7cPfF3bfD4gOPsSOJxx+cN02KWaLJWhhux4kAv9nKvp/Lmwp1YVk1dgicqGWlmYAtsFFTf/kQm3Ven5oTVQXheJWWK5Toz7olDEXzhcgpNdZ7tROVErdr+Oq4acpq/fT+/Kc4jgSkxM5R7xUndE/YHReYMiKjdyOrBfPNu8iPs85HRMI4lEzRvWqDkkaVs0lGnsygZhH1oK18L0pi83dNc5oU1/AbyTBWrPDRcInXN8aanVS4Y4YvFGdTxIpPx6KH69n6q+fMcA7K5ZToTiOcLvx8FZCDVXXziPcCFZoRhQbc64miFQrA+2uuD/PMRVWDsv9f64ghyS9765mdrKKiWRgHVysi9ul6ntdMr21LjELZgFuTfv54JtS Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=57.103.78.227; envelope-from=mohamed@unpredictable.fr; helo=outbound.st.icloud.com X-Spam_score_int: -10 X-Spam_score: -1.1 X-Spam_bar: - X-Spam_report: (-1.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FORGED_SPF_HELO=1, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, SPF_HELO_PASS=-0.001, T_SPF_TEMPERROR=0.01 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: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @unpredictable.fr) X-ZM-MESSAGEID: 1760636490259158500 Content-Type: text/plain; charset="utf-8" Signed-off-by: Mohamed Mediouni Reviewed-by: Pierrick Bouvier --- accel/whpx/whpx-common.c | 1 + target/arm/meson.build | 1 + target/arm/whpx/meson.build | 3 + target/arm/whpx/whpx-all.c | 845 ++++++++++++++++++++++++++++++++++++ 4 files changed, 850 insertions(+) create mode 100644 target/arm/whpx/meson.build create mode 100644 target/arm/whpx/whpx-all.c diff --git a/accel/whpx/whpx-common.c b/accel/whpx/whpx-common.c index 18d93225c1..c69792e638 100644 --- a/accel/whpx/whpx-common.c +++ b/accel/whpx/whpx-common.c @@ -16,6 +16,7 @@ #include "gdbstub/helpers.h" #include "qemu/accel.h" #include "accel/accel-ops.h" +#include "system/memory.h" #include "system/whpx.h" #include "system/cpus.h" #include "system/runstate.h" diff --git a/target/arm/meson.build b/target/arm/meson.build index 3df7e03654..61277a627c 100644 --- a/target/arm/meson.build +++ b/target/arm/meson.build @@ -59,6 +59,7 @@ arm_common_system_ss.add(files( )) =20 subdir('hvf') +subdir('whpx') =20 if 'CONFIG_TCG' in config_all_accel subdir('tcg') diff --git a/target/arm/whpx/meson.build b/target/arm/whpx/meson.build new file mode 100644 index 0000000000..1de2ef0283 --- /dev/null +++ b/target/arm/whpx/meson.build @@ -0,0 +1,3 @@ +arm_system_ss.add(when: 'CONFIG_WHPX', if_true: files( + 'whpx-all.c', +)) diff --git a/target/arm/whpx/whpx-all.c b/target/arm/whpx/whpx-all.c new file mode 100644 index 0000000000..8c34650765 --- /dev/null +++ b/target/arm/whpx/whpx-all.c @@ -0,0 +1,845 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * QEMU Windows Hypervisor Platform accelerator (WHPX) + * + * Copyright (c) 2025 Mohamed Mediouni + * + */ + +#include "qemu/osdep.h" +#include "cpu.h" +#include "system/address-spaces.h" +#include "system/ioport.h" +#include "gdbstub/helpers.h" +#include "qemu/accel.h" +#include "accel/accel-ops.h" +#include "system/whpx.h" +#include "system/cpus.h" +#include "system/runstate.h" +#include "qemu/main-loop.h" +#include "hw/boards.h" +#include "qemu/error-report.h" +#include "qapi/error.h" +#include "qapi/qapi-types-common.h" +#include "qapi/qapi-visit-common.h" +#include "migration/blocker.h" +#include "accel/accel-cpu-target.h" +#include + +#include "syndrome.h" +#include "cpu.h" +#include "target/arm/cpregs.h" +#include "internals.h" + +#include "system/whpx-internal.h" +#include "system/whpx-accel-ops.h" +#include "system/whpx-all.h" +#include "system/whpx-common.h" +#include "hw/arm/bsa.h" +#include "arm-powerctl.h" + +#include +#include + +struct whpx_reg_match { + WHV_REGISTER_NAME reg; + uint64_t offset; +}; + +static const struct whpx_reg_match whpx_reg_match[] =3D { + { WHvArm64RegisterX0, offsetof(CPUARMState, xregs[0]) }, + { WHvArm64RegisterX1, offsetof(CPUARMState, xregs[1]) }, + { WHvArm64RegisterX2, offsetof(CPUARMState, xregs[2]) }, + { WHvArm64RegisterX3, offsetof(CPUARMState, xregs[3]) }, + { WHvArm64RegisterX4, offsetof(CPUARMState, xregs[4]) }, + { WHvArm64RegisterX5, offsetof(CPUARMState, xregs[5]) }, + { WHvArm64RegisterX6, offsetof(CPUARMState, xregs[6]) }, + { WHvArm64RegisterX7, offsetof(CPUARMState, xregs[7]) }, + { WHvArm64RegisterX8, offsetof(CPUARMState, xregs[8]) }, + { WHvArm64RegisterX9, offsetof(CPUARMState, xregs[9]) }, + { WHvArm64RegisterX10, offsetof(CPUARMState, xregs[10]) }, + { WHvArm64RegisterX11, offsetof(CPUARMState, xregs[11]) }, + { WHvArm64RegisterX12, offsetof(CPUARMState, xregs[12]) }, + { WHvArm64RegisterX13, offsetof(CPUARMState, xregs[13]) }, + { WHvArm64RegisterX14, offsetof(CPUARMState, xregs[14]) }, + { WHvArm64RegisterX15, offsetof(CPUARMState, xregs[15]) }, + { WHvArm64RegisterX16, offsetof(CPUARMState, xregs[16]) }, + { WHvArm64RegisterX17, offsetof(CPUARMState, xregs[17]) }, + { WHvArm64RegisterX18, offsetof(CPUARMState, xregs[18]) }, + { WHvArm64RegisterX19, offsetof(CPUARMState, xregs[19]) }, + { WHvArm64RegisterX20, offsetof(CPUARMState, xregs[20]) }, + { WHvArm64RegisterX21, offsetof(CPUARMState, xregs[21]) }, + { WHvArm64RegisterX22, offsetof(CPUARMState, xregs[22]) }, + { WHvArm64RegisterX23, offsetof(CPUARMState, xregs[23]) }, + { WHvArm64RegisterX24, offsetof(CPUARMState, xregs[24]) }, + { WHvArm64RegisterX25, offsetof(CPUARMState, xregs[25]) }, + { WHvArm64RegisterX26, offsetof(CPUARMState, xregs[26]) }, + { WHvArm64RegisterX27, offsetof(CPUARMState, xregs[27]) }, + { WHvArm64RegisterX28, offsetof(CPUARMState, xregs[28]) }, + { WHvArm64RegisterFp, offsetof(CPUARMState, xregs[29]) }, + { WHvArm64RegisterLr, offsetof(CPUARMState, xregs[30]) }, + { WHvArm64RegisterPc, offsetof(CPUARMState, pc) }, +}; + +static const struct whpx_reg_match whpx_fpreg_match[] =3D { + { WHvArm64RegisterQ0, offsetof(CPUARMState, vfp.zregs[0]) }, + { WHvArm64RegisterQ1, offsetof(CPUARMState, vfp.zregs[1]) }, + { WHvArm64RegisterQ2, offsetof(CPUARMState, vfp.zregs[2]) }, + { WHvArm64RegisterQ3, offsetof(CPUARMState, vfp.zregs[3]) }, + { WHvArm64RegisterQ4, offsetof(CPUARMState, vfp.zregs[4]) }, + { WHvArm64RegisterQ5, offsetof(CPUARMState, vfp.zregs[5]) }, + { WHvArm64RegisterQ6, offsetof(CPUARMState, vfp.zregs[6]) }, + { WHvArm64RegisterQ7, offsetof(CPUARMState, vfp.zregs[7]) }, + { WHvArm64RegisterQ8, offsetof(CPUARMState, vfp.zregs[8]) }, + { WHvArm64RegisterQ9, offsetof(CPUARMState, vfp.zregs[9]) }, + { WHvArm64RegisterQ10, offsetof(CPUARMState, vfp.zregs[10]) }, + { WHvArm64RegisterQ11, offsetof(CPUARMState, vfp.zregs[11]) }, + { WHvArm64RegisterQ12, offsetof(CPUARMState, vfp.zregs[12]) }, + { WHvArm64RegisterQ13, offsetof(CPUARMState, vfp.zregs[13]) }, + { WHvArm64RegisterQ14, offsetof(CPUARMState, vfp.zregs[14]) }, + { WHvArm64RegisterQ15, offsetof(CPUARMState, vfp.zregs[15]) }, + { WHvArm64RegisterQ16, offsetof(CPUARMState, vfp.zregs[16]) }, + { WHvArm64RegisterQ17, offsetof(CPUARMState, vfp.zregs[17]) }, + { WHvArm64RegisterQ18, offsetof(CPUARMState, vfp.zregs[18]) }, + { WHvArm64RegisterQ19, offsetof(CPUARMState, vfp.zregs[19]) }, + { WHvArm64RegisterQ20, offsetof(CPUARMState, vfp.zregs[20]) }, + { WHvArm64RegisterQ21, offsetof(CPUARMState, vfp.zregs[21]) }, + { WHvArm64RegisterQ22, offsetof(CPUARMState, vfp.zregs[22]) }, + { WHvArm64RegisterQ23, offsetof(CPUARMState, vfp.zregs[23]) }, + { WHvArm64RegisterQ24, offsetof(CPUARMState, vfp.zregs[24]) }, + { WHvArm64RegisterQ25, offsetof(CPUARMState, vfp.zregs[25]) }, + { WHvArm64RegisterQ26, offsetof(CPUARMState, vfp.zregs[26]) }, + { WHvArm64RegisterQ27, offsetof(CPUARMState, vfp.zregs[27]) }, + { WHvArm64RegisterQ28, offsetof(CPUARMState, vfp.zregs[28]) }, + { WHvArm64RegisterQ29, offsetof(CPUARMState, vfp.zregs[29]) }, + { WHvArm64RegisterQ30, offsetof(CPUARMState, vfp.zregs[30]) }, + { WHvArm64RegisterQ31, offsetof(CPUARMState, vfp.zregs[31]) }, +}; + +struct whpx_sreg_match { + WHV_REGISTER_NAME reg; + uint32_t key; + bool global; + uint32_t cp_idx; +}; + +static struct whpx_sreg_match whpx_sreg_match[] =3D { + { WHvArm64RegisterDbgbvr0El1, ENCODE_AA64_CP_REG(0, 0, 2, 0, 4) }, + { WHvArm64RegisterDbgbcr0El1, ENCODE_AA64_CP_REG(0, 0, 2, 0, 5) }, + { WHvArm64RegisterDbgwvr0El1, ENCODE_AA64_CP_REG(0, 0, 2, 0, 6) }, + { WHvArm64RegisterDbgwcr0El1, ENCODE_AA64_CP_REG(0, 0, 2, 0, 7) }, + + { WHvArm64RegisterDbgbvr0El1, ENCODE_AA64_CP_REG(0, 1, 2, 0, 4) }, + { WHvArm64RegisterDbgbcr0El1, ENCODE_AA64_CP_REG(0, 1, 2, 0, 5) }, + { WHvArm64RegisterDbgwvr0El1, ENCODE_AA64_CP_REG(0, 1, 2, 0, 6) }, + { WHvArm64RegisterDbgwcr0El1, ENCODE_AA64_CP_REG(0, 1, 2, 0, 7) }, + + { WHvArm64RegisterDbgbvr2El1, ENCODE_AA64_CP_REG(0, 2, 2, 0, 4) }, + { WHvArm64RegisterDbgbcr2El1, ENCODE_AA64_CP_REG(0, 2, 2, 0, 5) }, + { WHvArm64RegisterDbgwvr2El1, ENCODE_AA64_CP_REG(0, 2, 2, 0, 6) }, + { WHvArm64RegisterDbgwcr2El1, ENCODE_AA64_CP_REG(0, 2, 2, 0, 7) }, + + { WHvArm64RegisterDbgbvr3El1, ENCODE_AA64_CP_REG(0, 3, 2, 0, 4) }, + { WHvArm64RegisterDbgbcr3El1, ENCODE_AA64_CP_REG(0, 3, 2, 0, 5) }, + { WHvArm64RegisterDbgwvr3El1, ENCODE_AA64_CP_REG(0, 3, 2, 0, 6) }, + { WHvArm64RegisterDbgwcr3El1, ENCODE_AA64_CP_REG(0, 3, 2, 0, 7) }, + + { WHvArm64RegisterDbgbvr4El1, ENCODE_AA64_CP_REG(0, 4, 2, 0, 4) }, + { WHvArm64RegisterDbgbcr4El1, ENCODE_AA64_CP_REG(0, 4, 2, 0, 5) }, + { WHvArm64RegisterDbgwvr4El1, ENCODE_AA64_CP_REG(0, 4, 2, 0, 6) }, + { WHvArm64RegisterDbgwcr4El1, ENCODE_AA64_CP_REG(0, 4, 2, 0, 7) }, + + { WHvArm64RegisterDbgbvr5El1, ENCODE_AA64_CP_REG(0, 5, 2, 0, 4) }, + { WHvArm64RegisterDbgbcr5El1, ENCODE_AA64_CP_REG(0, 5, 2, 0, 5) }, + { WHvArm64RegisterDbgwvr5El1, ENCODE_AA64_CP_REG(0, 5, 2, 0, 6) }, + { WHvArm64RegisterDbgwcr5El1, ENCODE_AA64_CP_REG(0, 5, 2, 0, 7) }, + + { WHvArm64RegisterDbgbvr6El1, ENCODE_AA64_CP_REG(0, 6, 2, 0, 4) }, + { WHvArm64RegisterDbgbcr6El1, ENCODE_AA64_CP_REG(0, 6, 2, 0, 5) }, + { WHvArm64RegisterDbgwvr6El1, ENCODE_AA64_CP_REG(0, 6, 2, 0, 6) }, + { WHvArm64RegisterDbgwcr6El1, ENCODE_AA64_CP_REG(0, 6, 2, 0, 7) }, + + { WHvArm64RegisterDbgbvr7El1, ENCODE_AA64_CP_REG(0, 7, 2, 0, 4) }, + { WHvArm64RegisterDbgbcr7El1, ENCODE_AA64_CP_REG(0, 7, 2, 0, 5) }, + { WHvArm64RegisterDbgwvr7El1, ENCODE_AA64_CP_REG(0, 7, 2, 0, 6) }, + { WHvArm64RegisterDbgwcr7El1, ENCODE_AA64_CP_REG(0, 7, 2, 0, 7) }, + + { WHvArm64RegisterDbgbvr8El1, ENCODE_AA64_CP_REG(0, 8, 2, 0, 4) }, + { WHvArm64RegisterDbgbcr8El1, ENCODE_AA64_CP_REG(0, 8, 2, 0, 5) }, + { WHvArm64RegisterDbgwvr8El1, ENCODE_AA64_CP_REG(0, 8, 2, 0, 6) }, + { WHvArm64RegisterDbgwcr8El1, ENCODE_AA64_CP_REG(0, 8, 2, 0, 7) }, + + { WHvArm64RegisterDbgbvr9El1, ENCODE_AA64_CP_REG(0, 9, 2, 0, 4) }, + { WHvArm64RegisterDbgbcr9El1, ENCODE_AA64_CP_REG(0, 9, 2, 0, 5) }, + { WHvArm64RegisterDbgwvr9El1, ENCODE_AA64_CP_REG(0, 9, 2, 0, 6) }, + { WHvArm64RegisterDbgwcr9El1, ENCODE_AA64_CP_REG(0, 9, 2, 0, 7) }, + + { WHvArm64RegisterDbgbvr10El1, ENCODE_AA64_CP_REG(0, 10, 2, 0, 4) }, + { WHvArm64RegisterDbgbcr10El1, ENCODE_AA64_CP_REG(0, 10, 2, 0, 5) }, + { WHvArm64RegisterDbgwvr10El1, ENCODE_AA64_CP_REG(0, 10, 2, 0, 6) }, + { WHvArm64RegisterDbgwcr10El1, ENCODE_AA64_CP_REG(0, 10, 2, 0, 7) }, + + { WHvArm64RegisterDbgbvr11El1, ENCODE_AA64_CP_REG(0, 11, 2, 0, 4) }, + { WHvArm64RegisterDbgbcr11El1, ENCODE_AA64_CP_REG(0, 11, 2, 0, 5) }, + { WHvArm64RegisterDbgwvr11El1, ENCODE_AA64_CP_REG(0, 11, 2, 0, 6) }, + { WHvArm64RegisterDbgwcr11El1, ENCODE_AA64_CP_REG(0, 11, 2, 0, 7) }, + + { WHvArm64RegisterDbgbvr12El1, ENCODE_AA64_CP_REG(0, 12, 2, 0, 4) }, + { WHvArm64RegisterDbgbcr12El1, ENCODE_AA64_CP_REG(0, 12, 2, 0, 5) }, + { WHvArm64RegisterDbgwvr12El1, ENCODE_AA64_CP_REG(0, 12, 2, 0, 6) }, + { WHvArm64RegisterDbgwcr12El1, ENCODE_AA64_CP_REG(0, 12, 2, 0, 7) }, + + { WHvArm64RegisterDbgbvr13El1, ENCODE_AA64_CP_REG(0, 13, 2, 0, 4) }, + { WHvArm64RegisterDbgbcr13El1, ENCODE_AA64_CP_REG(0, 13, 2, 0, 5) }, + { WHvArm64RegisterDbgwvr13El1, ENCODE_AA64_CP_REG(0, 13, 2, 0, 6) }, + { WHvArm64RegisterDbgwcr13El1, ENCODE_AA64_CP_REG(0, 13, 2, 0, 7) }, + + { WHvArm64RegisterDbgbvr14El1, ENCODE_AA64_CP_REG(0, 14, 2, 0, 4) }, + { WHvArm64RegisterDbgbcr14El1, ENCODE_AA64_CP_REG(0, 14, 2, 0, 5) }, + { WHvArm64RegisterDbgwvr14El1, ENCODE_AA64_CP_REG(0, 14, 2, 0, 6) }, + { WHvArm64RegisterDbgwcr14El1, ENCODE_AA64_CP_REG(0, 14, 2, 0, 7) }, + + { WHvArm64RegisterDbgbvr15El1, ENCODE_AA64_CP_REG(0, 15, 2, 0, 4) }, + { WHvArm64RegisterDbgbcr15El1, ENCODE_AA64_CP_REG(0, 15, 2, 0, 5) }, + { WHvArm64RegisterDbgwvr15El1, ENCODE_AA64_CP_REG(0, 15, 2, 0, 6) }, + { WHvArm64RegisterDbgwcr15El1, ENCODE_AA64_CP_REG(0, 15, 2, 0, 7) }, +#ifdef SYNC_NO_RAW_REGS + /* + * The registers below are manually synced on init because they are + * marked as NO_RAW. We still list them to make number space sync easi= er. + */ + { WHvArm64RegisterMidrEl1, ENCODE_AA64_CP_REG(0, 0, 3, 0, 0) }, + { WHvArm64RegisterMpidrEl1, ENCODE_AA64_CP_REG(0, 0, 3, 0, 5) }, + { WHvArm64RegisterIdPfr0El1, ENCODE_AA64_CP_REG(0, 4, 3, 0, 0) }, +#endif + { WHvArm64RegisterIdAa64Pfr1El1, ENCODE_AA64_CP_REG(0, 4, 3, 0, 1), tr= ue }, + { WHvArm64RegisterIdAa64Dfr0El1, ENCODE_AA64_CP_REG(0, 5, 3, 0, 0), tr= ue }, + { WHvArm64RegisterIdAa64Dfr1El1, ENCODE_AA64_CP_REG(0, 5, 3, 0, 1), tr= ue }, + { WHvArm64RegisterIdAa64Isar0El1, ENCODE_AA64_CP_REG(0, 6, 3, 0, 0), t= rue }, + { WHvArm64RegisterIdAa64Isar1El1, ENCODE_AA64_CP_REG(0, 6, 3, 0, 1), t= rue }, +#ifdef SYNC_NO_MMFR0 + /* We keep the hardware MMFR0 around. HW limits are there anyway */ + { WHvArm64RegisterIdAa64Mmfr0El1, ENCODE_AA64_CP_REG(0, 7, 3, 0, 0) }, +#endif + { WHvArm64RegisterIdAa64Mmfr1El1, ENCODE_AA64_CP_REG(0, 7, 3, 0, 1), t= rue }, + { WHvArm64RegisterIdAa64Mmfr2El1, ENCODE_AA64_CP_REG(0, 7, 3, 0, 2), t= rue }, + { WHvArm64RegisterIdAa64Mmfr3El1, ENCODE_AA64_CP_REG(0, 7, 3, 0, 3), t= rue }, + + { WHvArm64RegisterMdscrEl1, ENCODE_AA64_CP_REG(0, 2, 2, 0, 2) }, + { WHvArm64RegisterSctlrEl1, ENCODE_AA64_CP_REG(1, 0, 3, 0, 0) }, + { WHvArm64RegisterCpacrEl1, ENCODE_AA64_CP_REG(1, 0, 3, 0, 2) }, + { WHvArm64RegisterTtbr0El1, ENCODE_AA64_CP_REG(2, 0, 3, 0, 0) }, + { WHvArm64RegisterTtbr1El1, ENCODE_AA64_CP_REG(2, 0, 3, 0, 1) }, + { WHvArm64RegisterTcrEl1, ENCODE_AA64_CP_REG(2, 0, 3, 0, 2) }, + + { WHvArm64RegisterApiAKeyLoEl1, ENCODE_AA64_CP_REG(2, 1, 3, 0, 0) }, + { WHvArm64RegisterApiAKeyHiEl1, ENCODE_AA64_CP_REG(2, 1, 3, 0, 1) }, + { WHvArm64RegisterApiBKeyLoEl1, ENCODE_AA64_CP_REG(2, 1, 3, 0, 2) }, + { WHvArm64RegisterApiBKeyHiEl1, ENCODE_AA64_CP_REG(2, 1, 3, 0, 3) }, + { WHvArm64RegisterApdAKeyLoEl1, ENCODE_AA64_CP_REG(2, 2, 3, 0, 0) }, + { WHvArm64RegisterApdAKeyHiEl1, ENCODE_AA64_CP_REG(2, 2, 3, 0, 1) }, + { WHvArm64RegisterApdBKeyLoEl1, ENCODE_AA64_CP_REG(2, 2, 3, 0, 2) }, + { WHvArm64RegisterApdBKeyHiEl1, ENCODE_AA64_CP_REG(2, 2, 3, 0, 3) }, + { WHvArm64RegisterApgAKeyLoEl1, ENCODE_AA64_CP_REG(2, 3, 3, 0, 0) }, + { WHvArm64RegisterApgAKeyHiEl1, ENCODE_AA64_CP_REG(2, 3, 3, 0, 1) }, + + { WHvArm64RegisterSpsrEl1, ENCODE_AA64_CP_REG(4, 0, 3, 0, 0) }, + { WHvArm64RegisterElrEl1, ENCODE_AA64_CP_REG(4, 0, 3, 0, 1) }, + { WHvArm64RegisterSpEl1, ENCODE_AA64_CP_REG(4, 1, 3, 0, 0) }, + { WHvArm64RegisterEsrEl1, ENCODE_AA64_CP_REG(5, 2, 3, 0, 0) }, + { WHvArm64RegisterFarEl1, ENCODE_AA64_CP_REG(6, 0, 3, 0, 0) }, + { WHvArm64RegisterParEl1, ENCODE_AA64_CP_REG(7, 4, 3, 0, 0) }, + { WHvArm64RegisterMairEl1, ENCODE_AA64_CP_REG(10, 2, 3, 0, 0) }, + { WHvArm64RegisterVbarEl1, ENCODE_AA64_CP_REG(12, 0, 3, 0, 0) }, + { WHvArm64RegisterContextidrEl1, ENCODE_AA64_CP_REG(13, 0, 3, 0, 1) }, + { WHvArm64RegisterTpidrEl1, ENCODE_AA64_CP_REG(13, 0, 3, 0, 4) }, + { WHvArm64RegisterCntkctlEl1, ENCODE_AA64_CP_REG(14, 1, 3, 0, 0) }, + { WHvArm64RegisterCsselrEl1, ENCODE_AA64_CP_REG(0, 0, 3, 2, 0) }, + { WHvArm64RegisterTpidrEl0, ENCODE_AA64_CP_REG(13, 0, 3, 3, 2) }, + { WHvArm64RegisterTpidrroEl0, ENCODE_AA64_CP_REG(13, 0, 3, 3, 3) }, + { WHvArm64RegisterCntvCtlEl0, ENCODE_AA64_CP_REG(14, 3, 3, 3, 1) }, + { WHvArm64RegisterCntvCvalEl0, ENCODE_AA64_CP_REG(14, 3, 3, 3, 2) }, + { WHvArm64RegisterSpEl1, ENCODE_AA64_CP_REG(4, 1, 3, 4, 0) }, +}; + +static void flush_cpu_state(CPUState *cpu) +{ + if (cpu->vcpu_dirty) { + whpx_set_registers(cpu, WHPX_SET_RUNTIME_STATE); + cpu->vcpu_dirty =3D false; + } +} + +HRESULT whpx_set_exception_exit_bitmap(UINT64 exceptions) +{ + if (exceptions !=3D 0) { + return E_NOTIMPL; + } + return ERROR_SUCCESS; +} +void whpx_apply_breakpoints( +struct whpx_breakpoint_collection *breakpoints, + CPUState *cpu, + bool resuming) +{ + +} +void whpx_translate_cpu_breakpoints( + struct whpx_breakpoints *breakpoints, + CPUState *cpu, + int cpu_breakpoint_count) +{ + +} + +static void whpx_get_reg(CPUState *cpu, WHV_REGISTER_NAME reg, WHV_REGISTE= R_VALUE* val) +{ + struct whpx_state *whpx =3D &whpx_global; + HRESULT hr; + + flush_cpu_state(cpu); + + hr =3D whp_dispatch.WHvGetVirtualProcessorRegisters(whpx->partition, c= pu->cpu_index, + ®, 1, val); + + if (FAILED(hr)) { + error_report("WHPX: Failed to get register %08x, hr=3D%08lx", reg,= hr); + } +} + +static void whpx_set_reg(CPUState *cpu, WHV_REGISTER_NAME reg, WHV_REGISTE= R_VALUE val) +{ + struct whpx_state *whpx =3D &whpx_global; + HRESULT hr; + hr =3D whp_dispatch.WHvSetVirtualProcessorRegisters(whpx->partition, c= pu->cpu_index, + ®, 1, &val); + + if (FAILED(hr)) { + error_report("WHPX: Failed to set register %08x, hr=3D%08lx", reg,= hr); + } +} + +static void whpx_get_global_reg(WHV_REGISTER_NAME reg, WHV_REGISTER_VALUE = *val) +{ + struct whpx_state *whpx =3D &whpx_global; + HRESULT hr; + + hr =3D whp_dispatch.WHvGetVirtualProcessorRegisters(whpx->partition, W= HV_ANY_VP, + ®, 1, val); + + if (FAILED(hr)) { + error_report("WHPX: Failed to get register %08x, hr=3D%08lx", reg,= hr); + } +} + +static void whpx_set_global_reg(WHV_REGISTER_NAME reg, WHV_REGISTER_VALUE = val) +{ + struct whpx_state *whpx =3D &whpx_global; + HRESULT hr; + hr =3D whp_dispatch.WHvSetVirtualProcessorRegisters(whpx->partition, W= HV_ANY_VP, + ®, 1, &val); + + if (FAILED(hr)) { + error_report("WHPX: Failed to set register %08x, hr=3D%08lx", reg,= hr); + } +} + +static uint64_t whpx_get_gp_reg(CPUState *cpu, int rt) +{ + assert(rt <=3D 31); + if (rt =3D=3D 31) { + return 0; + } + WHV_REGISTER_NAME reg =3D WHvArm64RegisterX0 + rt; + WHV_REGISTER_VALUE val; + whpx_get_reg(cpu, reg, &val); + + return val.Reg64; +} + +static void whpx_set_gp_reg(CPUState *cpu, int rt, uint64_t val) +{ + assert(rt < 31); + WHV_REGISTER_NAME reg =3D WHvArm64RegisterX0 + rt; + WHV_REGISTER_VALUE reg_val =3D {.Reg64 =3D val}; + + whpx_set_reg(cpu, reg, reg_val); +} + +static int whpx_handle_mmio(CPUState *cpu, WHV_MEMORY_ACCESS_CONTEXT *ctx) +{ + uint64_t syndrome =3D ctx->Syndrome; + + bool isv =3D syndrome & ARM_EL_ISV; + bool iswrite =3D (syndrome >> 6) & 1; + bool sse =3D (syndrome >> 21) & 1; + uint32_t sas =3D (syndrome >> 22) & 3; + uint32_t len =3D 1 << sas; + uint32_t srt =3D (syndrome >> 16) & 0x1f; + uint32_t cm =3D (syndrome >> 8) & 0x1; + uint64_t val =3D 0; + + assert(!cm); + assert(isv); + + if (iswrite) { + val =3D whpx_get_gp_reg(cpu, srt); + address_space_write(&address_space_memory, + ctx->Gpa, + MEMTXATTRS_UNSPECIFIED, &val, len); + } else { + address_space_read(&address_space_memory, + ctx->Gpa, + MEMTXATTRS_UNSPECIFIED, &val, len); + if (sse) { + val =3D sextract64(val, 0, len * 8); + } + whpx_set_gp_reg(cpu, srt, val); + } + + return 0; +} + +static void whpx_psci_cpu_off(ARMCPU *arm_cpu) +{ + int32_t ret =3D arm_set_cpu_off(arm_cpu_mp_affinity(arm_cpu)); + assert(ret =3D=3D QEMU_ARM_POWERCTL_RET_SUCCESS); +} + +int whpx_vcpu_run(CPUState *cpu) +{ + HRESULT hr; + struct whpx_state *whpx =3D &whpx_global; + ARMCPU *arm_cpu =3D ARM_CPU(cpu); + AccelCPUState *vcpu =3D cpu->accel; + int ret; + + + g_assert(bql_locked()); + + if (whpx->running_cpus++ =3D=3D 0) { + ret =3D whpx_first_vcpu_starting(cpu); + if (ret !=3D 0) { + return ret; + } + } + + bql_unlock(); + + + cpu_exec_start(cpu); + do { + bool advance_pc =3D false; + if (cpu->vcpu_dirty) { + whpx_set_registers(cpu, WHPX_SET_RUNTIME_STATE); + cpu->vcpu_dirty =3D false; + } + + if (qatomic_read(&cpu->exit_request)) { + whpx_vcpu_kick(cpu); + } + + hr =3D whp_dispatch.WHvRunVirtualProcessor( + whpx->partition, cpu->cpu_index, + &vcpu->exit_ctx, sizeof(vcpu->exit_ctx)); + + if (FAILED(hr)) { + error_report("WHPX: Failed to exec a virtual processor," + " hr=3D%08lx", hr); + ret =3D -1; + break; + } + + switch (vcpu->exit_ctx.ExitReason) { + case WHvRunVpExitReasonGpaIntercept: + case WHvRunVpExitReasonUnmappedGpa: + advance_pc =3D true; + + if (vcpu->exit_ctx.MemoryAccess.Syndrome >> 8 & 0x1) { + error_report("WHPX: cached access to unmapped memory" + "Pc =3D 0x%llx Gva =3D 0x%llx Gpa =3D 0x%llx", + vcpu->exit_ctx.MemoryAccess.Header.Pc, + vcpu->exit_ctx.MemoryAccess.Gpa, + vcpu->exit_ctx.MemoryAccess.Gva); + break; + } + + ret =3D whpx_handle_mmio(cpu, &vcpu->exit_ctx.MemoryAccess); + break; + case WHvRunVpExitReasonCanceled: + cpu->exception_index =3D EXCP_INTERRUPT; + ret =3D 1; + break; + case WHvRunVpExitReasonArm64Reset: + switch (vcpu->exit_ctx.Arm64Reset.ResetType) { + case WHvArm64ResetTypePowerOff: + qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN= ); + break; + case WHvArm64ResetTypeReboot: + qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET); + break; + default: + g_assert_not_reached(); + } + bql_lock(); + if (arm_cpu->power_state !=3D PSCI_OFF) { + whpx_psci_cpu_off(arm_cpu); + } + bql_unlock(); + break; + case WHvRunVpExitReasonNone: + case WHvRunVpExitReasonUnrecoverableException: + case WHvRunVpExitReasonInvalidVpRegisterValue: + case WHvRunVpExitReasonUnsupportedFeature: + default: + error_report("WHPX: Unexpected VP exit code 0x%08x", + vcpu->exit_ctx.ExitReason); + whpx_get_registers(cpu); + bql_lock(); + qemu_system_guest_panicked(cpu_get_crash_info(cpu)); + bql_unlock(); + break; + } + if (advance_pc) { + WHV_REGISTER_VALUE pc; + + flush_cpu_state(cpu); + pc.Reg64 =3D vcpu->exit_ctx.MemoryAccess.Header.Pc + 4; + whpx_set_reg(cpu, WHvArm64RegisterPc, pc); + } + } while (!ret); + + cpu_exec_end(cpu); + + bql_lock(); + current_cpu =3D cpu; + + if (--whpx->running_cpus =3D=3D 0) { + whpx_last_vcpu_stopping(cpu); + } + + qatomic_set(&cpu->exit_request, false); + + return ret < 0; +} + +static void clean_whv_register_value(WHV_REGISTER_VALUE *val) +{ + memset(val, 0, sizeof(WHV_REGISTER_VALUE)); +} + +void whpx_get_registers(CPUState *cpu) +{ + ARMCPU *arm_cpu =3D ARM_CPU(cpu); + CPUARMState *env =3D &arm_cpu->env; + WHV_REGISTER_VALUE val; + int i; + + for (i =3D 0; i < ARRAY_SIZE(whpx_reg_match); i++) { + whpx_get_reg(cpu, whpx_reg_match[i].reg, &val); + *(uint64_t *)((void *)env + whpx_reg_match[i].offset) =3D val.Reg6= 4; + } + + for (i =3D 0; i < ARRAY_SIZE(whpx_fpreg_match); i++) { + whpx_get_reg(cpu, whpx_reg_match[i].reg, &val); + memcpy((void *)env + whpx_fpreg_match[i].offset, &val, sizeof(val.= Reg128)); + } + + whpx_get_reg(cpu, WHvArm64RegisterPc, &val); + env->pc =3D val.Reg64; + + whpx_get_reg(cpu, WHvArm64RegisterFpcr, &val); + vfp_set_fpcr(env, val.Reg32); + + whpx_get_reg(cpu, WHvArm64RegisterFpsr, &val); + vfp_set_fpsr(env, val.Reg32); + + whpx_get_reg(cpu, WHvArm64RegisterPstate, &val); + pstate_write(env, val.Reg32); + + for (i =3D 0; i < ARRAY_SIZE(whpx_sreg_match); i++) { + if (whpx_sreg_match[i].global =3D=3D true) { + continue; + } + if (whpx_sreg_match[i].cp_idx =3D=3D -1) { + continue; + } + + whpx_get_reg(cpu, whpx_sreg_match[i].reg, &val); + + arm_cpu->cpreg_values[whpx_sreg_match[i].cp_idx] =3D val.Reg64; + } + + /* WHP disallows us from reading global regs as a vCPU */ + for (i =3D 0; i < ARRAY_SIZE(whpx_sreg_match); i++) { + if (whpx_sreg_match[i].global =3D=3D false) { + continue; + } + if (whpx_sreg_match[i].cp_idx =3D=3D -1) { + continue; + } + + whpx_get_global_reg(whpx_sreg_match[i].reg, &val); + + arm_cpu->cpreg_values[whpx_sreg_match[i].cp_idx] =3D val.Reg64; + } + assert(write_list_to_cpustate(arm_cpu)); + + aarch64_restore_sp(env, arm_current_el(env)); +} + +void whpx_set_registers(CPUState *cpu, int level) +{ + ARMCPU *arm_cpu =3D ARM_CPU(cpu); + CPUARMState *env =3D &arm_cpu->env; + WHV_REGISTER_VALUE val; + clean_whv_register_value(&val); + int i; + + assert(cpu_is_stopped(cpu) || qemu_cpu_is_self(cpu)); + + for (i =3D 0; i < ARRAY_SIZE(whpx_reg_match); i++) { + val.Reg64 =3D *(uint64_t *)((void *)env + whpx_reg_match[i].offset= ); + whpx_set_reg(cpu, whpx_reg_match[i].reg, val); + } + + for (i =3D 0; i < ARRAY_SIZE(whpx_fpreg_match); i++) { + memcpy(&val.Reg128, (void *)env + whpx_fpreg_match[i].offset, size= of(val.Reg128)); + whpx_set_reg(cpu, whpx_reg_match[i].reg, val); + } + + clean_whv_register_value(&val); + val.Reg64 =3D env->pc; + whpx_set_reg(cpu, WHvArm64RegisterPc, val); + + clean_whv_register_value(&val); + val.Reg32 =3D vfp_get_fpcr(env); + whpx_set_reg(cpu, WHvArm64RegisterFpcr, val); + val.Reg32 =3D vfp_get_fpsr(env); + whpx_set_reg(cpu, WHvArm64RegisterFpsr, val); + val.Reg32 =3D pstate_read(env); + whpx_set_reg(cpu, WHvArm64RegisterPstate, val); + + aarch64_save_sp(env, arm_current_el(env)); + + assert(write_cpustate_to_list(arm_cpu, false)); + for (i =3D 0; i < ARRAY_SIZE(whpx_sreg_match); i++) { + if (whpx_sreg_match[i].global =3D=3D true) { + continue; + } + + if (whpx_sreg_match[i].cp_idx =3D=3D -1) { + continue; + } + clean_whv_register_value(&val); + val.Reg64 =3D arm_cpu->cpreg_values[whpx_sreg_match[i].cp_idx]; + whpx_set_reg(cpu, whpx_sreg_match[i].reg, val); + } + + /* Currently set global regs every time. */ + for (i =3D 0; i < ARRAY_SIZE(whpx_sreg_match); i++) { + if (whpx_sreg_match[i].global =3D=3D false) { + continue; + } + + if (whpx_sreg_match[i].cp_idx =3D=3D -1) { + continue; + } + clean_whv_register_value(&val); + val.Reg64 =3D arm_cpu->cpreg_values[whpx_sreg_match[i].cp_idx]; + whpx_set_global_reg(whpx_sreg_match[i].reg, val); + } +} + +static uint32_t max_vcpu_index; + +static void whpx_cpu_update_state(void *opaque, bool running, RunState sta= te) +{ +} + +int whpx_init_vcpu(CPUState *cpu) +{ + HRESULT hr; + struct whpx_state *whpx =3D &whpx_global; + AccelCPUState *vcpu =3D NULL; + ARMCPU *arm_cpu =3D ARM_CPU(cpu); + CPUARMState *env =3D &arm_cpu->env; + int ret; + + uint32_t sregs_match_len =3D ARRAY_SIZE(whpx_sreg_match); + uint32_t sregs_cnt =3D 0; + WHV_REGISTER_VALUE val; + int i; + + vcpu =3D g_new0(AccelCPUState, 1); + + hr =3D whp_dispatch.WHvCreateVirtualProcessor( + whpx->partition, cpu->cpu_index, 0); + if (FAILED(hr)) { + error_report("WHPX: Failed to create a virtual processor," + " hr=3D%08lx", hr); + ret =3D -EINVAL; + goto error; + } + + /* Assumption that CNTFRQ_EL0 is the same between the VMM and the part= ition. */ + asm volatile("mrs %0, cntfrq_el0" : "=3Dr"(arm_cpu->gt_cntfrq_hz)); + + cpu->vcpu_dirty =3D true; + cpu->accel =3D vcpu; + max_vcpu_index =3D max(max_vcpu_index, cpu->cpu_index); + qemu_add_vm_change_state_handler(whpx_cpu_update_state, env); + + env->aarch64 =3D true; + + /* Allocate enough space for our sysreg sync */ + arm_cpu->cpreg_indexes =3D g_renew(uint64_t, arm_cpu->cpreg_indexes, + sregs_match_len); + arm_cpu->cpreg_values =3D g_renew(uint64_t, arm_cpu->cpreg_values, + sregs_match_len); + arm_cpu->cpreg_vmstate_indexes =3D g_renew(uint64_t, + arm_cpu->cpreg_vmstate_indexe= s, + sregs_match_len); + arm_cpu->cpreg_vmstate_values =3D g_renew(uint64_t, + arm_cpu->cpreg_vmstate_values, + sregs_match_len); + + memset(arm_cpu->cpreg_values, 0, sregs_match_len * sizeof(uint64_t)); + + /* Populate cp list for all known sysregs */ + for (i =3D 0; i < sregs_match_len; i++) { + const ARMCPRegInfo *ri; + uint32_t key =3D whpx_sreg_match[i].key; + + ri =3D get_arm_cp_reginfo(arm_cpu->cp_regs, key); + if (ri) { + assert(!(ri->type & ARM_CP_NO_RAW)); + whpx_sreg_match[i].cp_idx =3D sregs_cnt; + arm_cpu->cpreg_indexes[sregs_cnt++] =3D cpreg_to_kvm_id(key); + } else { + whpx_sreg_match[i].cp_idx =3D -1; + } + } + arm_cpu->cpreg_array_len =3D sregs_cnt; + arm_cpu->cpreg_vmstate_array_len =3D sregs_cnt; + + assert(write_cpustate_to_list(arm_cpu, false)); + + /* Set CP_NO_RAW system registers on init */ + val.Reg64 =3D arm_cpu->midr; + whpx_set_reg(cpu, WHvArm64RegisterMidrEl1, + val); + + clean_whv_register_value(&val); + + val.Reg64 =3D deposit64(arm_cpu->mp_affinity, 31, 1, 1 /* RES1 */); + whpx_set_reg(cpu, WHvArm64RegisterMpidrEl1, val); + + return 0; + +error: + g_free(vcpu); + + return ret; + +} + +void whpx_cpu_instance_init(CPUState *cs) +{ +} + +int whpx_accel_init(AccelState *as, MachineState *ms) +{ + struct whpx_state *whpx; + int ret; + HRESULT hr; + WHV_CAPABILITY whpx_cap; + UINT32 whpx_cap_size; + WHV_PARTITION_PROPERTY prop; + WHV_CAPABILITY_FEATURES features =3D {0}; + + whpx =3D &whpx_global; + /* on arm64 Windows Hypervisor Platform, vGICv3 always used */ + whpx->kernel_irqchip =3D true; + + if (!init_whp_dispatch()) { + ret =3D -ENOSYS; + goto error; + } + + whpx->mem_quota =3D ms->ram_size; + + hr =3D whp_dispatch.WHvGetCapability( + WHvCapabilityCodeHypervisorPresent, &whpx_cap, + sizeof(whpx_cap), &whpx_cap_size); + if (FAILED(hr) || !whpx_cap.HypervisorPresent) { + error_report("WHPX: No accelerator found, hr=3D%08lx", hr); + ret =3D -ENOSPC; + goto error; + } + + hr =3D whp_dispatch.WHvGetCapability( + WHvCapabilityCodeFeatures, &features, sizeof(features), NULL); + if (FAILED(hr)) { + error_report("WHPX: Failed to query capabilities, hr=3D%08lx", hr); + ret =3D -EINVAL; + goto error; + } + + if (!features.Arm64Support) { + error_report("WHPX: host OS exposing pre-release WHPX implementati= on. " + "Please update your operating system to at least build 26100.3= 915"); + ret =3D -EINVAL; + goto error; + } + + hr =3D whp_dispatch.WHvCreatePartition(&whpx->partition); + if (FAILED(hr)) { + error_report("WHPX: Failed to create partition, hr=3D%08lx", hr); + ret =3D -EINVAL; + goto error; + } + + memset(&prop, 0, sizeof(WHV_PARTITION_PROPERTY)); + prop.ProcessorCount =3D ms->smp.cpus; + hr =3D whp_dispatch.WHvSetPartitionProperty( + whpx->partition, + WHvPartitionPropertyCodeProcessorCount, + &prop, + sizeof(WHV_PARTITION_PROPERTY)); + + if (FAILED(hr)) { + error_report("WHPX: Failed to set partition processor count to %u," + " hr=3D%08lx", prop.ProcessorCount, hr); + ret =3D -EINVAL; + goto error; + } + + if (!whpx->kernel_irqchip_allowed) { + error_report("WHPX: on Arm, only kernel-irqchip=3Don is currently = supported"); + ret =3D -EINVAL; + goto error; + } + + memset(&prop, 0, sizeof(WHV_PARTITION_PROPERTY)); + + hr =3D whp_dispatch.WHvSetupPartition(whpx->partition); + if (FAILED(hr)) { + error_report("WHPX: Failed to setup partition, hr=3D%08lx", hr); + ret =3D -EINVAL; + goto error; + } + + whpx_memory_init(); + + return 0; + +error: + + if (NULL !=3D whpx->partition) { + whp_dispatch.WHvDeletePartition(whpx->partition); + whpx->partition =3D NULL; + } + + return ret; +} --=20 2.50.1 (Apple Git-155)