From nobody Mon Sep 28 02:13:38 2026 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; arc=pass (i=1 dmarc=pass fromdomain=nutanix.com); dmarc=pass(p=none dis=none) header.from=nutanix.com ARC-Seal: i=2; a=rsa-sha256; t=1785491529; cv=pass; d=zohomail.com; s=zohoarc; b=JYy8hfQib6CCtV2/6Ohe0sZ7K2/VpTjidwnoW9rG4t/aNDF3M7xebXdo9ZC2g7palPNmnRAAIe4i7o6OyyjtxYnBBTs2voqQ+qtWoe1DLw20U8gzLqkKORHGcpUuhmmhF6Pboy/NznbTKHgPv91H/2UOEJwxyuUeIlLa6CZy3ss= ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1785491529; h=Content-Type: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=43m1k8CtLU4o9/62AmIm7vcfO1VgHTpynnj3cCg9LV4=; b=VL128KN1SBXyc8ol8zsESmDsZsMt7AsJrUsA/1CnxLxj+sEZf6AKr4JeNPSmDNxa8tUr3JXOMz8nxhiLSgU8aCw/bQ5GhHlj5ZprjYPcxLhzkX7eqgERz+CEpZ5DF1hgVQHIWtw4GZdgEoKuPDWsTald7DtJy8Ajl2TYVLACYTk= ARC-Authentication-Results: i=2; 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; arc=pass (i=1 dmarc=pass fromdomain=nutanix.com); dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 178549152957582.90138962438994; Fri, 31 Jul 2026 02:52:09 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1wpju6-0002M8-LH; Fri, 31 Jul 2026 05:51:46 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1wpju4-0002LU-Kg for qemu-devel@nongnu.org; Fri, 31 Jul 2026 05:51:45 -0400 Received: from mx0a-002c1b01.pphosted.com ([148.163.151.68]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1wpju2-0004sz-G5 for qemu-devel@nongnu.org; Fri, 31 Jul 2026 05:51:44 -0400 Received: from pps.filterd (m0127837.ppops.net [127.0.0.1]) by mx0a-002c1b01.pphosted.com (8.18.1.11/8.18.1.11) with ESMTP id 66V983BD417415; Fri, 31 Jul 2026 02:51:37 -0700 Received: from ph7pr06cu001.outbound.protection.outlook.com (mail-westus3azon11020140.outbound.protection.outlook.com [52.101.201.140]) by mx0a-002c1b01.pphosted.com (PPS) with ESMTPS id 4frrt9g2gf-1 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384 bits=256 verify=NOT); Fri, 31 Jul 2026 02:51:36 -0700 (PDT) Received: from CH2PR02MB6197.namprd02.prod.outlook.com (2603:10b6:610:4::25) by CO6PR02MB7842.namprd02.prod.outlook.com (2603:10b6:303:ad::24) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.21.270.16; Fri, 31 Jul 2026 09:51:35 +0000 Received: from CH2PR02MB6197.namprd02.prod.outlook.com ([fe80::90e9:29cb:631d:9ab]) by CH2PR02MB6197.namprd02.prod.outlook.com ([fe80::90e9:29cb:631d:9ab%4]) with mapi id 15.21.0270.012; Fri, 31 Jul 2026 09:51:35 +0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=nutanix.com; h= cc:content-transfer-encoding:content-type:date:from:in-reply-to :message-id:mime-version:references:subject:to; s= proofpoint20171006; bh=43m1k8CtLU4o9/62AmIm7vcfO1VgHTpynnj3cCg9L V4=; b=aRE9NV6rd8rdc8QRq3zuFTMLYrjX/stgrxhiuwjkLI224TK5ZHqS48o80 HXGgn5VBr87xoKwHLng7FK2tJ1v99+Wrs5FdnnS6Zlh6XjIo8MjRvwrr4kCG2Jat 4ul/HBxzP1SVUCqSt43JDaq+IUyF4GXmg0DQ0BY6UWEAKMWn0ID/tdB9geGmLair TqubI7HwnsPhvtU9NymhfVeHTPHaJ3o19Ll77QXbYCU+QRv92+keI7/Df3leAIBJ QCYE9eM2RgNDM/8JkOqLCA6Bw0mtbMZKk4/HRYOupqmuHmc3RVEkk0Q7Pnm5Jkzh SzkllpV3nNumrQynFcswjY3GN94SQ== ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=FXrC4UqTpdtDwAODl1w1ko8AjtIWbXBXuGRuhJNN6tqVhUUqyqa/ROUZm+EEuCDwklH/Ib+9oBO6pbf3rvnksSCMQo+/SjTglvRCroVpLnwDUkZh91nrn1RkN/jHLFrM5aVEOWyux3zu27O0ydFFgwPtpUDaeiy9AwZjPzQMDRD27NTztzop4yTqwxkrezWMbM6O1KC4ocB2ZNaK6dqRlmuwmOocY8XiQREpJLThtm84R9mGpnggyOBSpr3DkbOOlyw5eRBXeFg8uYrTowOVwUvc9Suk8HRdhDAmJuBpndXGyVLggELwXZKVkgmTrH8acLUacr3MMATl0JjtHkSMjQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=43m1k8CtLU4o9/62AmIm7vcfO1VgHTpynnj3cCg9LV4=; b=InXeh2OTUs1j24VDF9JMyD8W2Lvn2W4CqvNdnTH51Z3xr78wBTqI0R0PuNOUmdz+iw2jHR+Zo8t8c5oPi7dda/fCdiKXN8ADG+xMy0j1CJnp0GNHIMsenRnM22B69nZU3tk+PR3fSubnXqUL9hv+ow3C9Oh7ZaRu0gMXvCpwI4d0znr2ZroBfnn6MzNsmF+V8bFfu3bdqeszzxuzxgJygX1+XGDabEH8deZAvO19wOWbmbkrCXNYPIQj9IZ6ziSRMPfC0vUZkAbTAYe6LRTBn1VLeTuqnzC50DHSfxoWpy4dZnJUaYdNWvAd7g1hI7DNAzSRfdjxNeuJ6SxbJhG/ZA== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=nutanix.com; dmarc=pass action=none header.from=nutanix.com; dkim=pass header.d=nutanix.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=nutanix.com; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=43m1k8CtLU4o9/62AmIm7vcfO1VgHTpynnj3cCg9LV4=; b=Bl/QknQM+qfhzOU5ilBp1elOj13VVV8fnq52xSvnyWEZygzOLocqVTrkNxv11UGl9ESN55tArJsSX2mjuqcMPuV7XuUu46o1FaU8Zr5Ka1hvxznXN0X+UE93N4IcnyHmsmT0ilPNjVqDeVW5CeLzgnXuCZIRgt8ODV8hwtSsmp905VfprFgQP1Wfw3msaBe+sNjvAPdM6G/BaKJHGpuVXqimepvlqV8QwLrGBSBa9bRYv0WAGL6vedZakwuclndQLbsM1k7OrhV9KLJX/FQ3uig9tfvBDfNBQ3YNU4Uy2uQBM/V6WC7KcmheqEip5lUMBMNbNY0B2Ea9kl8lLmXCPQ== From: Florian Schmidt To: Cornelia Huck , Marcelo Tosatti , "Michael S. Tsirkin" , Paolo Bonzini , Peter Xu , Pierrick Bouvier Cc: kvm@vger.kernel.org, =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , qemu-devel@nongnu.org, Zhao Liu , Florian Schmidt Subject: [PATCH 1/2] Add HvExtCallQueryCapabilities Date: Fri, 31 Jul 2026 09:51:11 +0000 Message-ID: <20260731095112.2975175-2-flosch@nutanix.com> X-Mailer: git-send-email 2.54.0 In-Reply-To: <20260731095112.2975175-1-flosch@nutanix.com> References: <20260731095112.2975175-1-flosch@nutanix.com> Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: PH8P221CA0057.NAMP221.PROD.OUTLOOK.COM (2603:10b6:510:349::12) To CH2PR02MB6197.namprd02.prod.outlook.com (2603:10b6:610:4::25) MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: CH2PR02MB6197:EE_|CO6PR02MB7842:EE_ X-MS-Office365-Filtering-Correlation-Id: 3dd95ae6-cf90-42cd-758a-08deeee94ee6 x-proofpoint-crosstenant: true X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; ARA:13230040|7416014|376014|52116014|23010399003|1800799024|366016|38350700014|6133799003|10067099003|18002099003|22082099003|56012099006; X-Microsoft-Antispam-Message-Info: +Rj7L0nUevUq2/Ch1dotYgUBVAr339BkoCNrtJNDtL3wW0hVEsVccQT3KQvwKwk31B4HPcJNthSm/nPjWrGvkBshJRaCxbYNAi/VpblYJ8c5eqpW/71VWjPt0nMMOvc4/NndwCpEKTMctqZ+eWEW34vshgTg+f7Hoh/aKpvP19ggoCSC7FZkUvkeDUq0zV03geHDjLZL1J1tsyU154r8MPBkZhth0Dn5QQLuOF343nqoy8Bjh3Um0TSFePY9nVLjc1/lUTCiya3iqMJimwHSzKVui9AXPA1o0aKikCI7pBKFYLMu5yTx+vTxlQADoIIQb2Eskr44EAamCe9wuRgX/6lhMZ7VQjQ3J7TfZSf3UaKG5ho9Dk8KgAReuIR0rou+HDisqScvfifMtjApmQCna7udHFt8UBiq9hz2vR+gtlu+k/o+sUToxkiIUPJ2haIQ+f34SABJ4v4jZRNEga3Qu5LGGonwYXAh35Y4u3X9byY3e3X2lKO5k7bcXUFdYkqJVg4DZpnGTuVCnlvz4MAdCUOlfQzWk/lLLaBnRyKd/ZqDoILM6aXHaiWI3A4KElLTSXpcKBKwQBLU9NpgoON2RLp1Vpl7/Llwr0D325nJjVLIH3ZCJjqIDfHQhWa0hGtEXwDZs7ik8imerpYSTRIGs3C6EL0k1gVSP/GbB8Pp0mYdy5xbMMFgSExYwJcCKUhbSGL7gJP/J+i2NycuuwAUxnKTZSiHbTk8bAfu2O02wmQ= X-Forefront-Antispam-Report: CIP:255.255.255.255; CTRY:; LANG:en; SCL:1; SRV:; IPV:NLI; SFV:NSPM; H:CH2PR02MB6197.namprd02.prod.outlook.com; PTR:; CAT:NONE; SFS:(13230040)(7416014)(376014)(52116014)(23010399003)(1800799024)(366016)(38350700014)(6133799003)(10067099003)(18002099003)(22082099003)(56012099006); DIR:OUT; SFP:1102; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?us-ascii?Q?eW9KOXf25OV2XXn9WdkzNksAffBUD9GjMqComjVMRIkwmC4ibo274/ejNGCZ?= =?us-ascii?Q?IPGM/x775XiaciesJ0M16XxYHQjar3kanmt3EjlZ4tkmDWjpFOrV8WSVAujL?= =?us-ascii?Q?Rfw78NdttvXj/yWdnyrnfbjOfqcD/VTbdCmJ6nDH+NH2PxkZJh/umEo6GyRd?= =?us-ascii?Q?0FRVdtlca80sND3INgjnUanQz/WBtuudRHB5F78tTi2JvYiabibMY7sk3/QI?= =?us-ascii?Q?jv0wXP/8CdiWTAI3C7vEL3p1/6S/a3DTVAkMBZFQEoNrWJhoq9FjGizCzYag?= =?us-ascii?Q?7TrGmzY7hN6DkcsTSsLJ1LuTardzyCoLokvVsDZe0bLTwnjEH7ZxRIhowFSu?= =?us-ascii?Q?j9dr2fEKHCcJnuqBMX/aqXyaw/rC3XGC0X35u7dpEQX58nq6rmPSKRSKWgFg?= =?us-ascii?Q?6K0QmiSUl1KVPzyUFtNMxGWLTVkx3ftXhDeRqqdyS+vsckhMJkx4GdBFpyOj?= =?us-ascii?Q?odCSKPKPSC5VvhJ7sOZauhGcQGoOgYpPHNhh4gXSQgbeakV6ButLRUIdA6GT?= =?us-ascii?Q?005dlDaTx0ht9ePCmw3y4SsOJbrvsmf4OJlMjFozQ4EeHq+yYYXVWSyPCWWO?= =?us-ascii?Q?RvrMustDOtV5wscBaFYQesI1RFbq14W6sMnObn6ryFY4tlC0JNoQa7tq/G/p?= =?us-ascii?Q?EST1hN+ZC8osAUvfOsDIUOQadiUcfjdfxHrXFx0qwfQzLFd8yEtD7+4HkOel?= =?us-ascii?Q?7rr1tEhK453OaYtlskqpP4mKO7gxi2sZcO+XURfwRKLfDNPjqHlSzKtkQ/zI?= =?us-ascii?Q?wGyG5SqeRlZrlgAY4zqVJFTnrTIFWavTJiY/sk1pc44/D/XNMwCGVJAK0Vr3?= =?us-ascii?Q?L03gqzh2qUb9s9FlPHDn2BEcWos+y8/Pdyw5QRifoUfCEMXfhi7rZRwZp5Nc?= =?us-ascii?Q?xwXZGf7ykgx02JZDGPrds5Mmj9H0Rfwbb3WGT4clZ+HpnzRxosbD8PzldO/I?= =?us-ascii?Q?SncFuXP0YkGYxMv0FN1yjeyKddipe9J1sGz0TH53yjSC3ZyYzVLuRwr/tvaB?= =?us-ascii?Q?oKYpXoUL51M1pdO3xgu85bokgSm910MCoK0p0HNkCbuSqY2E9xtxxsVPv+dk?= =?us-ascii?Q?LAcWVclFxfY4l8GFsBClMUNfBVVX+sf+MLnOfACaomIEwwhWOa0qSh1iBWkd?= =?us-ascii?Q?VVIFEExSHSFJg6hYFIayjKmHMGlKmf5aWiiaNq6izrD31mco7vsMExAnMULE?= =?us-ascii?Q?IG91YuNfv/rFCXlo0Dn7Dwz03EH9RDowtWro6zZlJEjYLWKtFF24GaFHd/OO?= =?us-ascii?Q?ozHLsAuX59M4o7Fm+N+sNBQhg7J6b8fB49aSZWihiWQ580LdaqQKJ7np2hgz?= =?us-ascii?Q?i7lpY/RnLzxVJPA/RgCEIDcc5h0ufCloQmesz+ox4het/+z4WGY7gTzLwDUI?= =?us-ascii?Q?gPR/AbyEOk/J2ZP6J8uzdjSklKR0vDVbvkMhN8EwVmKF96jkOjiZnpERrASO?= =?us-ascii?Q?8ZIZp9hDqo4380tuwRdeUCPgZEsnmIWk1FplmcWNQSuRclM4a/pC9S2eYSrH?= =?us-ascii?Q?fSrPp/CIgVrJ8aYO8om8DU97YMbHg+sa6UdmePiBE5Hc8PZQM+1YmbCU51Bm?= =?us-ascii?Q?YjKcQhexTQy5PYKwkOZfM2BLqFG2pgOJdefOifL7aB3e1mCF6k5lR+o2U6vM?= =?us-ascii?Q?vADQaXi7G9+TqiYQ0As6lDIs2KnepJq+fLOAt8eXMJUbv9qjBU1zWfLo+hiV?= =?us-ascii?Q?qH/28iZ7lQqPYpiuc0P++eiQ1E6b6myfNPp2QtfwPj5hkDJjVQH27z8Fnera?= =?us-ascii?Q?cx5EoBsRv7qZUQdar90Q7ppktz7cJB4=3D?= X-Exchange-RoutingPolicyChecked: VtQ0gc2c0YspzAdaoppIGWXtZUFbtWyM1W9IWW3dezpD1cXjIXJQTnjzb8aOG5FC/8KTwGfqrkGoK9EofHb5Cdog5tWrcCpqMf9nrnppr/gopoTnLShCJMclSxnHOcGHgpdlvBIle+X3LDBRWL6ap5Jsk7LLhk83qIEibglCAxxJJw8h3hoJyKHViuJ/WOYExB/RaFzrL/5dKtD7tlfecf3+JvPPZlescnHYFx8HwRu9OvMtta4N4lMGLT8onWHLo+TIE8aAVmJUBcKVvnPS248lNgOV43kKZDyzZDPTq2iqwjZtRDIF34kr1U9kBS9ZeopK3rfx7GLk8N0fRsVj7A== X-OriginatorOrg: nutanix.com X-MS-Exchange-CrossTenant-Network-Message-Id: 3dd95ae6-cf90-42cd-758a-08deeee94ee6 X-MS-Exchange-CrossTenant-AuthSource: CH2PR02MB6197.namprd02.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 31 Jul 2026 09:51:35.2782 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: bb047546-786f-4de1-bd75-24e5b6f79043 X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: r7j1MXf1bxgi34+mk+XGqxXcWzXerKNvgnSWxtXMEdzwgxmaIWorWbse5oXS3TlHgmeuxeGkv69P8Evi2MtuX+e8fUj4RuxRCPWRCblkVvE= X-MS-Exchange-Transport-CrossTenantHeadersStamped: CO6PR02MB7842 X-Proofpoint-Spam-Info: AW1haW4tMjYwNzMxMDA3MyBTYWx0ZWRfX/NUJoHPcZb6e j2aWsIdYv8bJiOge+dcFChAholMmGpos/m8A+IhPtF1FnJX46cPCz2I949ikKrMVErR0dKy+eAX W1492dq9UKD5zpGD87k7GyPRGeWVZHw= X-Proofpoint-ORIG-GUID: OPIGTPYG_VN8c0Uc_enTZ3HzbG0V2pIN X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwNzMxMDA3MyBTYWx0ZWRfXxrhaN7GlFUrl zpiNZ/rMgYE/w0gDJnltek7BVMuhO08juHlHqQn1+yN04Fgkasz/yGiaIrBgkgFOPKHzR5Jso66 bvDHAuFRPQFcEw3dHGHlEnkR/su50XlPtKSO539++3R9NGk8Avjq9d4a+RMBUWy93CFxvO+pYvH zKSrNtQQ8M6zjqE1VJfNFhDeSMKT/Jd73dglnmMjkd8+8Um2ggl8YhPRmjJrwSNaWmN5m5/lXMi nqrCkmgX7HcD/2IAvW0kNIjVPoLewC3zRYe4BeMp+VwBUN2LanosymsFvzwwYENzcKH4G3Rfdou KLXrxhpVvzG6Kp5npwSF0P39Uipf2wSR6W1FbK/eO9WlPNgR3W2TLhj6NECeuVhQRi8zlGVgeD6 XQa1yWG6p19nGg4J/wowiWYN9o7z1yxnkCYBOk65rXAG8H7TjGgYoMrcQ0093uSrPgcXchBXyf/ nmkJ8NVXVAfKDOZ9hsA== X-Authority-Analysis: v=2.4 cv=N58Z0W9B c=1 sm=1 tr=0 ts=6a6c7028 cx=c_pps a=7xlfGB0ub5Zhz2aq4ZyXAQ==:117 a=6eWqkTHjU83fiwn7nKZWdM+Sl24=:19 a=z/mQ4Ysz8XfWz/Q5cLBRGdckG28=:19 a=lCpzRmAYbLLaTzLvsPZ7Mbvzbb8=:19 a=xqWC_Br6kY4A:10 a=RAioF0-LDSMA:10 a=0kUYKlekyDsA:10 a=VkNPw1HP01LnGYTKEx00:22 a=VofLwUrZ8Iiv6rRUPXIb:22 a=Ap8k9tRZuQ82DLYWQqG7:22 a=64Cc0HZtAAAA:8 a=C5gtayXK1LZycCbmP6EA:9 X-Proofpoint-GUID: OPIGTPYG_VN8c0Uc_enTZ3HzbG0V2pIN X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1143,Hydra:6.1.134,FMLib:17.12.100.49 definitions=2026-07-31_03,2026-07-30_01,2025-10-01_01 X-Proofpoint-Spam-Reason: safe 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=lists1p.gnu.org; Received-SPF: pass client-ip=148.163.151.68; envelope-from=flosch@nutanix.com; helo=mx0a-002c1b01.pphosted.com X-Spam_score_int: -43 X-Spam_score: -4.4 X-Spam_bar: ---- X-Spam_report: (-4.4 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-1.58, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_LOW=-0.7, SPF_HELO_NONE=0.001, 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 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 @nutanix.com) X-ZM-MESSAGEID: 1785491530977158500 Content-Type: text/plain; charset="utf-8" On CPUID leaf 0x40000003, EBX bit 20 signals that we support the HvExtCallQueryCapabilities hypercall. This returns a bit field which signals which further extended hypercalls are supported (as a way to conserve CPUID leaf bits). We'll track such capabilities in kvm_hyperv_properties like all the others, but they will have a ".reg" entry of 0, since they aren't returned via CPUID and so don't have a corresponding register. For now, we don't support any extended hypercalls, but we'll add HvExtCallGetBootZeroedMemory in a followup patch. Signed-off-by: Florian Schmidt --- docs/system/i386/hyperv.rst | 7 +++++++ hw/hyperv/hyperv.c | 28 ++++++++++++++++++++++++++++ include/hw/hyperv/hyperv-proto.h | 1 + include/hw/hyperv/hyperv.h | 5 +++++ target/i386/cpu.c | 2 ++ target/i386/cpu.h | 1 + target/i386/kvm/hyperv-proto.h | 1 + target/i386/kvm/hyperv.c | 6 ++++++ target/i386/kvm/kvm.c | 12 ++++++++++++ target/i386/kvm/kvm_i386.h | 2 ++ 10 files changed, 65 insertions(+) diff --git a/docs/system/i386/hyperv.rst b/docs/system/i386/hyperv.rst index e1babffb0f..a1985dc418 100644 --- a/docs/system/i386/hyperv.rst +++ b/docs/system/i386/hyperv.rst @@ -259,6 +259,13 @@ Existing enlightenments =20 Recommended: ``hv-evmcs`` (Intel) =20 +``hv-ext-query-caps`` + Certain "extended hypercalls" are not signaled to the guest directly via + CPUID bits, but use a separate hypercall that returns a bitfield to sign= al + support for them. This enables this hypercall. On its own, it does not + provide any useful new functionality, but it's required to be enabled to= use + any extended hypercalls. + Supplementary features ---------------------- =20 diff --git a/hw/hyperv/hyperv.c b/hw/hyperv/hyperv.c index 900ff80213..3dcf23ba53 100644 --- a/hw/hyperv/hyperv.c +++ b/hw/hyperv/hyperv.c @@ -702,6 +702,34 @@ int hyperv_set_event_flag_handler(uint32_t conn_id, Ev= entNotifier *notifier) return set_event_flag_handler(conn_id, notifier); } =20 +uint16_t hyperv_ext_hcall_query_caps(uint64_t sup, uint64_t outgpa, bool f= ast) +{ + uint16_t ret; + uint64_t *supported =3D NULL; + hwaddr len; + + if (fast) { + ret =3D HV_STATUS_INVALID_HYPERCALL_CODE; + goto cleanup; + } + + len =3D sizeof(*supported); + supported =3D cpu_physical_memory_map(outgpa, &len, 1); + if (!supported || len < sizeof(*supported)) { + ret =3D HV_STATUS_INSUFFICIENT_MEMORY; + goto cleanup; + } + + *supported =3D sup; + ret =3D HV_STATUS_SUCCESS; + +cleanup: + if (supported) { + cpu_physical_memory_unmap(supported, sizeof(*supported), 1, len); + } + return ret; +} + uint16_t hyperv_hcall_signal_event(uint64_t param, bool fast) { EventFlagHandler *handler; diff --git a/include/hw/hyperv/hyperv-proto.h b/include/hw/hyperv/hyperv-pr= oto.h index fffc5ce342..f1d1d2eb26 100644 --- a/include/hw/hyperv/hyperv-proto.h +++ b/include/hw/hyperv/hyperv-proto.h @@ -35,6 +35,7 @@ #define HV_POST_DEBUG_DATA 0x0069 #define HV_RETRIEVE_DEBUG_DATA 0x006a #define HV_RESET_DEBUG_SESSION 0x006b +#define HV_EXT_CALL_QUERY_CAPABILITIES 0x8001 #define HV_HYPERCALL_FAST (1u << 16) =20 /* diff --git a/include/hw/hyperv/hyperv.h b/include/hw/hyperv/hyperv.h index 23091301d0..e29d60f565 100644 --- a/include/hw/hyperv/hyperv.h +++ b/include/hw/hyperv/hyperv.h @@ -97,6 +97,11 @@ uint16_t hyperv_hcall_retreive_dbg_data(uint64_t ingpa, = uint64_t outgpa, */ uint16_t hyperv_hcall_post_dbg_data(uint64_t ingpa, uint64_t outgpa, bool = fast); =20 +/* + * Process HVCALL_EXT_QUERY_CAPABILITIES hypercall. + */ +uint16_t hyperv_ext_hcall_query_caps(uint64_t sup, uint64_t outgpa, bool f= ast); + uint32_t hyperv_syndbg_send(uint64_t ingpa, uint32_t count); uint32_t hyperv_syndbg_recv(uint64_t ingpa, uint32_t count); void hyperv_syndbg_set_pending_page(uint64_t ingpa); diff --git a/target/i386/cpu.c b/target/i386/cpu.c index 5805d33ab9..ed9773ac9e 100644 --- a/target/i386/cpu.c +++ b/target/i386/cpu.c @@ -10768,6 +10768,8 @@ static const Property x86_cpu_properties[] =3D { HYPERV_FEAT_TLBFLUSH_EXT, 0), DEFINE_PROP_BIT64("hv-tlbflush-direct", X86CPU, hyperv_features, HYPERV_FEAT_TLBFLUSH_DIRECT, 0), + DEFINE_PROP_BIT64("hv-ext-query-caps", X86CPU, hyperv_features, + HYPERV_FEAT_EXT_CALLS, 0), DEFINE_PROP_ON_OFF_AUTO("hv-no-nonarch-coresharing", X86CPU, hyperv_no_nonarch_cs, ON_OFF_AUTO_OFF), #ifdef CONFIG_SYNDBG diff --git a/target/i386/cpu.h b/target/i386/cpu.h index e6a197602d..6737340766 100644 --- a/target/i386/cpu.h +++ b/target/i386/cpu.h @@ -1480,6 +1480,7 @@ uint64_t x86_cpu_get_supported_feature_word(X86CPU *c= pu, FeatureWord w); #define HYPERV_FEAT_XMM_INPUT 18 #define HYPERV_FEAT_TLBFLUSH_EXT 19 #define HYPERV_FEAT_TLBFLUSH_DIRECT 20 +#define HYPERV_FEAT_EXT_CALLS 21 =20 #ifndef HYPERV_SPINLOCK_NEVER_NOTIFY #define HYPERV_SPINLOCK_NEVER_NOTIFY 0xFFFFFFFF diff --git a/target/i386/kvm/hyperv-proto.h b/target/i386/kvm/hyperv-proto.h index a9f056f2f3..4eb2955ac5 100644 --- a/target/i386/kvm/hyperv-proto.h +++ b/target/i386/kvm/hyperv-proto.h @@ -46,6 +46,7 @@ */ #define HV_POST_MESSAGES (1u << 4) #define HV_SIGNAL_EVENTS (1u << 5) +#define HV_ENABLE_EXT_HYPERCALLS (1u << 20) =20 /* * HV_CPUID_FEATURES.EDX bits diff --git a/target/i386/kvm/hyperv.c b/target/i386/kvm/hyperv.c index 420c76b5ff..807acaf6b1 100644 --- a/target/i386/kvm/hyperv.c +++ b/target/i386/kvm/hyperv.c @@ -17,6 +17,7 @@ #include "hyperv.h" #include "hw/hyperv/hyperv.h" #include "hyperv-proto.h" +#include "kvm_i386.h" =20 int hyperv_x86_synic_add(X86CPU *cpu) { @@ -117,6 +118,11 @@ int kvm_hv_handle_exit(X86CPU *cpu, struct kvm_hyperv_= exit *exit) exit->u.hcall.result =3D hyperv_hcall_reset_dbg_session(out_param); break; + case HV_EXT_CALL_QUERY_CAPABILITIES: + exit->u.hcall.result =3D + hyperv_ext_hcall_query_caps(hv_build_ext_call_caps(CPU(cpu= )), + out_param, fast); + break; default: exit->u.hcall.result =3D HV_STATUS_INVALID_HYPERCALL_CODE; } diff --git a/target/i386/kvm/kvm.c b/target/i386/kvm/kvm.c index 4272b6770c..bc1e44c33e 100644 --- a/target/i386/kvm/kvm.c +++ b/target/i386/kvm/kvm.c @@ -1137,6 +1137,13 @@ static struct { }, .dependencies =3D BIT(HYPERV_FEAT_VAPIC) }, + [HYPERV_FEAT_EXT_CALLS] =3D { + .desc =3D "query availability of extended hypercalls (hv-ext-query= -caps)", + .flags =3D { + {.func =3D HV_CPUID_FEATURES, .reg =3D R_EBX, + .bits =3D HV_ENABLE_EXT_HYPERCALLS} + } + }, }; =20 static struct kvm_cpuid2 *try_get_hv_cpuid(CPUState *cs, int max, @@ -1434,6 +1441,11 @@ static uint32_t hv_build_cpuid_leaf(CPUState *cs, ui= nt32_t func, int reg) return r; } =20 +uint64_t hv_build_ext_call_caps(CPUState *cs) +{ + return hv_build_cpuid_leaf(cs, HV_EXT_CALL_QUERY_CAPABILITIES, 0); +} + /* * Expand Hyper-V CPU features. In partucular, check that all the requested * features are supported by the host and the sanity of the configuration diff --git a/target/i386/kvm/kvm_i386.h b/target/i386/kvm/kvm_i386.h index 2b653442f4..8c71ad01af 100644 --- a/target/i386/kvm/kvm_i386.h +++ b/target/i386/kvm/kvm_i386.h @@ -72,6 +72,8 @@ struct kvm_cpuid_entry2 *cpuid_find_entry(struct kvm_cpui= d2 *cpuid, uint32_t cpuid_entry_get_reg(struct kvm_cpuid_entry2 *entry, int reg); uint32_t kvm_x86_build_cpuid(CPUX86State *env, struct kvm_cpuid_entry2 *en= tries, uint32_t cpuid_i); + +uint64_t hv_build_ext_call_caps(CPUState *cs); #endif /* CONFIG_KVM */ =20 void kvm_smm_cpu_address_space_init(X86CPU *cpu); --=20 2.47.3 From nobody Mon Sep 28 02:13:38 2026 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; arc=pass (i=1 dmarc=pass fromdomain=nutanix.com); dmarc=pass(p=none dis=none) header.from=nutanix.com ARC-Seal: i=2; a=rsa-sha256; t=1785491542; cv=pass; d=zohomail.com; s=zohoarc; b=TOde/WmOkvPVXKUh6T65cEskfofe+yI0/YpQEukLms9rzx7b/EVOjz/rRoX0KuSiJc5DVt6dXCS1vK0doaof+q1AOR0zU2l7J9C/mV+dzGU1HabWUJC8WPv5BSt7iUC2axwkVp/5F2IgR6lKlDME4T3WpkJflNFHzmYlOeg3JBI= ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1785491542; h=Content-Type: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=dDsz9oMPAPNcvlLjneLKE0U4q/x6XlO3TCMBCy/nOCw=; b=P8fMfl7XW1oIqGFF6bIGMUIqqCjaa0VHXgDb/2DAPwxFruzFfHaXLZvb1wWjMDhKJDMYoS+2WEa0sDEyzxuNlSd2h3OIYNJ525A6TOuDA9orwa0hcZP7i306UJjKxxuMY3qDcjmMhlabZQpGK9YogPt5bMlL7DwA9zz6Tc98VMo= ARC-Authentication-Results: i=2; 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; arc=pass (i=1 dmarc=pass fromdomain=nutanix.com); dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1785491542937178.08557295618994; Fri, 31 Jul 2026 02:52:22 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1wpjuA-0002Md-7w; Fri, 31 Jul 2026 05:51:50 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1wpju6-0002MA-Rk for qemu-devel@nongnu.org; Fri, 31 Jul 2026 05:51:47 -0400 Received: from mx0a-002c1b01.pphosted.com ([148.163.151.68]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1wpju3-0004tL-ID for qemu-devel@nongnu.org; Fri, 31 Jul 2026 05:51:46 -0400 Received: from pps.filterd (m0127839.ppops.net [127.0.0.1]) by mx0a-002c1b01.pphosted.com (8.18.1.11/8.18.1.11) with ESMTP id 66V7xPSX139274; Fri, 31 Jul 2026 02:51:39 -0700 Received: from ph7pr06cu001.outbound.protection.outlook.com (mail-westus3azon11020138.outbound.protection.outlook.com [52.101.201.138]) by mx0a-002c1b01.pphosted.com (PPS) with ESMTPS id 4frpcy0dqm-1 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384 bits=256 verify=NOT); Fri, 31 Jul 2026 02:51:39 -0700 (PDT) Received: from CH2PR02MB6197.namprd02.prod.outlook.com (2603:10b6:610:4::25) by CO6PR02MB7842.namprd02.prod.outlook.com (2603:10b6:303:ad::24) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.21.270.16; Fri, 31 Jul 2026 09:51:37 +0000 Received: from CH2PR02MB6197.namprd02.prod.outlook.com ([fe80::90e9:29cb:631d:9ab]) by CH2PR02MB6197.namprd02.prod.outlook.com ([fe80::90e9:29cb:631d:9ab%4]) with mapi id 15.21.0270.012; Fri, 31 Jul 2026 09:51:37 +0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=nutanix.com; h= cc:content-transfer-encoding:content-type:date:from:in-reply-to :message-id:mime-version:references:subject:to; s= proofpoint20171006; bh=dDsz9oMPAPNcvlLjneLKE0U4q/x6XlO3TCMBCy/nO Cw=; b=nkiMtReK8EjIDjWi4+5xLut6YUM+pxBg7d7xLpVr9oZbjbYCbX06hLkVb CJ3Auz2LmACqqvTD8lPx/1epDUBuJBwXZH+VpKBAU4eV/S8MZkyb2NoBcfMVJgu3 Zz8vYgnvW+nT895iSZlPBwxZB3yUFtuaHp8Ykd/fxwIb5sx43zOctOuadkA7OGf3 hMJjVvVymx06vGUnDqw3gxgjwzfPOVnvv1yH5X6/S+8w9uyISSYIv6QltQrkZr4C RaevDbL7Uc/x8VYR/6P/8hfiovXY1inYPd5VpbTEMKB5Nn+8mPMgdDDSJl3E1hbn sJjzr6XTYTbhsDlaknIej7ZjzhT6g== ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=mICYhSKzFiboKuOPmAhS3S+QEfKLQBSLyTQQqVm4MjqoUE2Zf0cMWe6wDaYe8UclEFkU6dLRT6adAUKex7jOxTUK5AcFZnJqQbmrXy6bk4YVngcq7o6i6GiVCCkMwI71ofZU/Fxa+lvRzkD0/e6l0p1nwqtu+Uab9i3ol+RPMjs91zESj5M5dQXohIls7X1xGoEPTwTVDv/mUyXwVoKBKHLtC6vPh0iYDfH820qUjbt0IKHoIIsvy8DDiZThesl+xx+OV4/me8KjsoLmoU/65kgyLyBn9qED28BhhOscPcOPUSNepSxXRZShBPVv7atF7U1n2X12asZpiKsWsf8tyA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=dDsz9oMPAPNcvlLjneLKE0U4q/x6XlO3TCMBCy/nOCw=; b=fgOybvDBLLGHp7TCtq6j1sonue6wJl3ZLDtXUc3vGcv/zk+lNO4wQEvk9fVC03aPHwV+/pKpX4FfOSwQKsI2ZpS1SCBB7djWRr1RvfyP8ut4ywSZKgom9lxrQrhQ0Nhv6UU45tsB4Pm0cibnLeXrtRn6IsFbqZg25eAj3budr0/78KpvbrJgJaaDQc2E6jzrFET9Gu4qVmKjLzZUaKvhhybaRYuBGvTGcC+uFwuzVp4kNmBqiuRPvReO+xwGcjqCYZY4dZCU6BNt/gXcUbW9mYw0D83n81H1woPYCNw5NRNlkzX6m4rAGLd5lTZuZGiVVE9JkQ5tJ9HVxUIJiSxFpA== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=nutanix.com; dmarc=pass action=none header.from=nutanix.com; dkim=pass header.d=nutanix.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=nutanix.com; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=dDsz9oMPAPNcvlLjneLKE0U4q/x6XlO3TCMBCy/nOCw=; b=a58OH1rwNSTV2RippMgbO4jEcj34vwaEtwA+p5oZDKUF/b2sT4FMvC2b6Q9DNd7kCjpVFd2GNLLa/QOzzjdJynnAAy7ZDphQQ8OSYnhYAOuIn/NQO3CkDm3r/t+VufvGwSU3gRWk0doVpWVQNefqXrifatpgaS3llW/EVCVqx8MHSGNNV9ICOBM6+s/X+KRaflZEhPKH1MA78uf5ihlzr9e/wM5aN2HBqufpEzRBG0tqQbc6ZUvvOrwR3e658VeLD8IEzsPhCiLjkc+WnFzmAv3LAokd8WPsVaz9fFg0LvY1NU83+L+NoOEyEid5UE6SJ9yWNYbx0TE+NhfvQgYDqQ== From: Florian Schmidt To: Cornelia Huck , Marcelo Tosatti , "Michael S. Tsirkin" , Paolo Bonzini , Peter Xu , Pierrick Bouvier Cc: kvm@vger.kernel.org, =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , qemu-devel@nongnu.org, Zhao Liu , Florian Schmidt Subject: [PATCH 2/2] Add HvExtCallGetBootZeroedMemory Date: Fri, 31 Jul 2026 09:51:12 +0000 Message-ID: <20260731095112.2975175-3-flosch@nutanix.com> X-Mailer: git-send-email 2.54.0 In-Reply-To: <20260731095112.2975175-1-flosch@nutanix.com> References: <20260731095112.2975175-1-flosch@nutanix.com> Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: PH8P221CA0057.NAMP221.PROD.OUTLOOK.COM (2603:10b6:510:349::12) To CH2PR02MB6197.namprd02.prod.outlook.com (2603:10b6:610:4::25) MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: CH2PR02MB6197:EE_|CO6PR02MB7842:EE_ X-MS-Office365-Filtering-Correlation-Id: 02ca9bfb-f0d3-41f6-b4d0-08deeee95017 x-proofpoint-crosstenant: true X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; ARA:13230040|7416014|376014|52116014|23010399003|1800799024|366016|38350700014|3023799007|6133799003|10067099003|18002099003|22082099003|56012099006; X-Microsoft-Antispam-Message-Info: BqiQiiRBuJKvvqjl3OzCi25RINsNvNrWamLO0TOmna9RXIe1XXmhpMwcPNtfM6x/CFkfHIHPM89ebQC//nnp2P6d8edNWXQtWzUDIkN4TMiOCyNDb2J3j8EGoZogD/9mCfYBjvhHFxX2/JYOIY1OSUN+r3I5Cfle9JJ8OMTpfOOBK2c6Kc4EXK1lFmihGcdKVzVLHm/3+8wnJv+pdTcOfIcMBMS/sAun2LO7bNsPIqP0Vxr2RckBOSxFxPxeePWpo3vNzMbsHwCqrnta+tc6d/En+JGO96VBMZc94AiSJxLO20vErbYgGrssKlmJ+qhQevpVBodTkTPkmJScMeNeJBKBOMx4CZu4NsBflc2MyMY6jyTkshiikiqEjy3j7u8BpjzkcQK3E39BWS/Zqs/pr+VA39TnDJi2ZLWT70xi7PpZ/cioRQKmeXAORwWHQh7NS6IG/Kr2Z47zQaZqz/ElrMj+Nl404PBoGnhlCrYW5NvFKHxumP8Y/StJpvfgJMOJgdTFVqdlV3jDciQelaHxYuzAVdAM8CpJE9jMM/ltOBzUw+Byws2RQjAdPvjyU/y1C/91OpVckMYROTPlXymBTB5goeMHkbHL4trVlc4DouzRJQgKhM+gAf8RXmyoKA3DCPoR6/OXrfV1A6/CZeu6EePL1oBEvoU3ZtvWYezRvuJ+55AgCA4zJxXIbSmYyXuLcVFma3afCI7p6dhLBv7v49XvL65IMt0D05CZlhz9bEo= X-Forefront-Antispam-Report: CIP:255.255.255.255; CTRY:; LANG:en; SCL:1; SRV:; IPV:NLI; SFV:NSPM; H:CH2PR02MB6197.namprd02.prod.outlook.com; PTR:; CAT:NONE; SFS:(13230040)(7416014)(376014)(52116014)(23010399003)(1800799024)(366016)(38350700014)(3023799007)(6133799003)(10067099003)(18002099003)(22082099003)(56012099006); DIR:OUT; SFP:1102; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?us-ascii?Q?A76Xq/sDT4YR86YQd9QtLnnsguWV6+jBmWpgV15kHhhQ1oydbgwCNBlk4yfV?= =?us-ascii?Q?C3pvtI977Zds0ufOizcSZb9K/qKc01oNi9xbMdhbnli8xn7PgY5JRJrWJHpB?= =?us-ascii?Q?X4LqAWijnIKISfvlmkFqKWAwUSEmCwxNZ6lUbQicB8mgakVAC3PMwn8f4wtw?= =?us-ascii?Q?NwgKRqM5XqX0P/pHJ47CWWaksw4wttjkth+N8wvpa+xvi65+b+DLPBn+/Dg4?= =?us-ascii?Q?3GmEdClfl7OA3OzAgob3GwUHlpVNc5fucb0xbznIlwcISVQ2hYGEYPevuy3Q?= =?us-ascii?Q?VQfHM9B1NSI8Nl9p8oOSuobmBjnzSw67DADb49TQNDHbW9BTdiUS8LGq2DfK?= =?us-ascii?Q?69Y2E8aQyBWSQ5HyPRVmFy/ZdvGlYeeoli7tnFdlUQM+Z5loR4Sn8OVfLrRL?= =?us-ascii?Q?+7D9GmpE+380gdJ0CEEEG9l22OlflEdnTfsyfwtAo0J8D1agperZZSmQmlwG?= =?us-ascii?Q?zwRnXWpg7JgOvDVBSQoy//f7egfHmsc5T1/RKYaRVioFTONrHjLrpFzIskYO?= =?us-ascii?Q?2MG+owS8jgKvXc8UoTwqUuRbDq5v0yQKtC8/+y/jZpUfV2gJ/d7OJTpczz9v?= =?us-ascii?Q?urlV25xUetqC9xpMGTvLxYjKx+1h7PcwMdV0PrFoeAttwtis/nkgZ/LzCzIf?= =?us-ascii?Q?9n4vM2vcDQsO2LSkZufThmVElcR6CbDJNNzyfpJnfMO1DJ1uSf4hyWa0GjYw?= =?us-ascii?Q?RWknqYRcsnM2UtCVTco07aGOOJMaW5vUGEpcaKML76X2fCa5mkKyg6aMIAWP?= =?us-ascii?Q?Nx/3ZOsnkVV5/9pePVF8weUhsKALxXr4ydrBB/v+NRLQijOra0qDitHbMNot?= =?us-ascii?Q?+osnlkW8wgZiUJrWvEbBORScaiD24dt7/KBkydl3qtzlsyk6Ukkrok+r0Y3m?= =?us-ascii?Q?4n7zUC4HPRhCITiz2fMxl8g7qA8c1pa0VPJveyRWpeWxLmv9RP6ltlvbuTnS?= =?us-ascii?Q?DBq9wDCxkKNnJhFhtzkc+B6ZkkuGpNIjGKVR3RKafWOayiuMpg55UE/R3jGV?= =?us-ascii?Q?Lsf/oKRVdVWx9st5W05ifUQWOD0zIRf/pGrKn4EeLAhcO8WCtXU8eV/UpEa1?= =?us-ascii?Q?1GE81JFprpIMY6W1Ck/sHLi4dukPxfIJETaUtD2tLY2SuYoHGom2QSVjm/ZF?= =?us-ascii?Q?XXmiDKH5CA1yjukKvSi4PmRHSghINpOW9OxNvaoiAEemikVl32nA255ze+zO?= =?us-ascii?Q?Kv1zMXBs8VTpbScoGSsJMZ9cUmrhztclQK3TBC4OVLP2iFRw6YJjg5XNfx4f?= =?us-ascii?Q?CKCNAuYIxcgyVfswhMrLukx0LZ1NzjjF+w1mSOm6xraz/qb0HGbfuUXRJ+o2?= =?us-ascii?Q?YD+5nfCCqp7c3nhyz7Avl7kUR/gCYN7q1pQMDOmJzpgMkPR5VCFsjWroI0pK?= =?us-ascii?Q?2U2WcQacakEaRHRwullett+E1+T4Kcmz/hwDqNG1K0Ny7u6whpaia9uxBUR1?= =?us-ascii?Q?h5ls3fXxbKa6zZz6GIABgVcIUwqpuQ66GiqMSVw/GUY+AfYMozsoEYCiFEwC?= =?us-ascii?Q?Bv85/VLkBlNP2KSbYIwibSgmu6GYsTnGwzEoFm/nMxkqQzJEXx8zhWzHLPnP?= =?us-ascii?Q?RQoZxzekrtqtIkm5ArPXp7LmX9Gy/gXIGZGe469AN9ojUg3oMpRA7b11ZZtw?= =?us-ascii?Q?3w7YUMrcI49soKiZhR6Dniu9wCeS+Kqab3Q3iKqHv/oCPmfXj2vk2H1fmQbz?= =?us-ascii?Q?3SqolIu5wls9FFtAaIZxKZab9JeaNRWztcLYRP8upf++OSJzmgryCfGVWTq7?= =?us-ascii?Q?GBzqlfcMxbMo7TJj2JbcrudLaJn3cdw=3D?= X-Exchange-RoutingPolicyChecked: M2gAjEV5Awd6XxO1uoBpM7+kkyyXu1IQOOtVWU82QuHzanwws3GYz5jSEnWg1NmmYVcJZIuB58QUuRc7qrH5syXOfnKkaERp1UgzqW/EOOI6GJUTsqXfrqNuwADgeaQ5SDyhUEARDwfz1XdHKTzbxCT30DbGVfF09CPN2d5bPCAsUuhVmyGfKdbEGHxQqquve0WSzQSUzCAbXywQVc8JsUqFDt6yy6AWgi5daIJACfyGONMRwsYN672ZzVomFb5NO0MgfWAJq2Bce3an7vsVEZGzi4DrnZ4RIE3nkaD73NEPJXN1PCngNPzHtXWSkmASAbEKPIVDL7f3kKQmqjB4hg== X-OriginatorOrg: nutanix.com X-MS-Exchange-CrossTenant-Network-Message-Id: 02ca9bfb-f0d3-41f6-b4d0-08deeee95017 X-MS-Exchange-CrossTenant-AuthSource: CH2PR02MB6197.namprd02.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 31 Jul 2026 09:51:37.3918 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: bb047546-786f-4de1-bd75-24e5b6f79043 X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: VhVnb+LIgj3nC5cLpG8MwqSjTC5yV2t1yCK4wmfYOE0kf3mX3W/7m2aye1DVzhm7ojGek5lz0fkaxs+xjHk+h15AkIMLMT6c/KR1lTm9mJM= X-MS-Exchange-Transport-CrossTenantHeadersStamped: CO6PR02MB7842 X-Proofpoint-GUID: erOHfRzg0A1Mo5yIZgP5Myqcj57mevo5 X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwNzMxMDA3MyBTYWx0ZWRfX4+x+QkCn1Nof NhfXZZx4nVxfJysyIaKSRBCNojqcQ+y0XZC+BmiTm2nEEwMdmNOQ5eGLdIyfmFobWB+5nM81Ks4 6oqilkGo3EvFOkMHKdwLhICdY+5MMnAKeexEcEglNJX/Ny3Uq8K5RKsn008dHGQ/5WTBXmQ6VPq ww92WyHfueegrteJ00DN+kF+c1L2Hgg/KCynAdLMn3wvqtc5Kd+7TnYN/gvVyvCiYNhHRs/ByFh Mv/xkhpRCx+xHsL8hObQyWVSGJE/Pj9f3tvYDqb1z2UsZ8PNSCLYxl1xe+vVXi36hNg5GXFwBMk 8D/8fH9SbNN8A1ujCu+m2p5N62oBbZboc7sI4L2h7Zsfjc3zVJ7I093VlLB1rQNOpp9eM8YSuUk r071cVS59M3hzZhK6MU3HjUxc30tEsbgvQAx0hv1k61jhfv/kArSCtXrktzO4spWEb6HQmSFLsK t7W5GsZTuk6g7R7lJ9g== X-Proofpoint-Spam-Info: AW1haW4tMjYwNzMxMDA3MyBTYWx0ZWRfX3I+O9XKiylCo If+iweuJGjRH3scmGg/n3XDiPL33IZVFjsZEFtbkP7mDIbV1T7t27jz4ZGS1eumU8YFzp1dhnuf 8jMw85oFFUS9r0gUX+7GSZ6LEVFWOjo= X-Proofpoint-ORIG-GUID: erOHfRzg0A1Mo5yIZgP5Myqcj57mevo5 X-Authority-Analysis: v=2.4 cv=DuhmPm/+ c=1 sm=1 tr=0 ts=6a6c702b cx=c_pps a=jcumTT0saVzx4HVuorHqQw==:117 a=6eWqkTHjU83fiwn7nKZWdM+Sl24=:19 a=z/mQ4Ysz8XfWz/Q5cLBRGdckG28=:19 a=lCpzRmAYbLLaTzLvsPZ7Mbvzbb8=:19 a=xqWC_Br6kY4A:10 a=RAioF0-LDSMA:10 a=0kUYKlekyDsA:10 a=VkNPw1HP01LnGYTKEx00:22 a=VofLwUrZ8Iiv6rRUPXIb:22 a=y4UcunY2MAxhM4LwGdWI:22 a=64Cc0HZtAAAA:8 a=P7j1cJWRIrBSRYB-Q1AA:9 X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1143,Hydra:6.1.134,FMLib:17.12.100.49 definitions=2026-07-31_03,2026-07-30_01,2025-10-01_01 X-Proofpoint-Spam-Reason: safe 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=lists1p.gnu.org; Received-SPF: pass client-ip=148.163.151.68; envelope-from=flosch@nutanix.com; helo=mx0a-002c1b01.pphosted.com X-Spam_score_int: -43 X-Spam_score: -4.4 X-Spam_bar: ---- X-Spam_report: (-4.4 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-1.58, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_LOW=-0.7, SPF_HELO_NONE=0.001, 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 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 @nutanix.com) X-ZM-MESSAGEID: 1785491544981158500 Content-Type: text/plain; charset="utf-8" This call allows a guest to ask the hypervisor which of its (guest physical) memory ranges were already zeroed out by the hypervisor, which means there's no need for the guest to zero them out again at boot. To do so, we have to track what memory is not zero any more. The conservative estimate for this is to consider all memory that we ever touched to not be zero any more. To track this, we introduce a new bitmap, independent of the existing dirty tracking maps. This is for several reasons: * Dirty memory tracking bitmaps are always allocated. This is wasteful when we only want this bitmap for one specific use case. * Dirty memory tracking is tightly aligned with target page sizes. We want to track at a much coarser granularity, which reduces the bitmap size, and will also make our hypercall reply have fewer fragmented areas, without losing too much of the benefit. Note that there are limitations of what we track: we only track initial memory. Memory hotplugged later will not be tracked, and so never reported as pre-zeroed. We also don't track non-zero memory over migrations. Both of these are fine with respect to the use case: Windows only enquires about zeroed memory relatively early during boot, where both of these operations are uncommon. For those cases, we simply report "memory is not pre-zeroed". Finally, we can't track memory that the VM itself touched. For this, we use a new KVM ioctl that tracks memory mapped in by the guest. This enlightnement depends on its availability, and returns areas marked as untouched by both QEMU and KVM. NOTE: the KVM capability and ioctl numbers may change until the KVM side is settled. Signed-off-by: Florian Schmidt --- docs/system/i386/hyperv.rst | 7 ++ hw/hyperv/hyperv.c | 178 ++++++++++++++++++++++++++++++- include/hw/hyperv/hyperv-proto.h | 11 ++ include/hw/hyperv/hyperv.h | 8 ++ include/system/physmem.h | 8 ++ linux-headers/linux/kvm.h | 15 +++ system/memory.c | 7 +- system/physmem.c | 50 +++++++++ target/i386/cpu.c | 2 + target/i386/cpu.h | 1 + target/i386/kvm/hyperv-proto.h | 5 + target/i386/kvm/hyperv.c | 8 ++ target/i386/kvm/kvm.c | 79 ++++++++++++++ 13 files changed, 375 insertions(+), 4 deletions(-) diff --git a/docs/system/i386/hyperv.rst b/docs/system/i386/hyperv.rst index a1985dc418..84b438ac8c 100644 --- a/docs/system/i386/hyperv.rst +++ b/docs/system/i386/hyperv.rst @@ -266,6 +266,13 @@ Existing enlightenments provide any useful new functionality, but it's required to be enabled to= use any extended hypercalls. =20 +``hv-boot-zeroed-mem`` + Enables the HvExtCallGetBootZeroedMemory hypercall. This allows a Windows + guest to inquire which memory has already been zeroed out by the host and + thus doesn't need to be zeroed out at boot again. + + Requires: ``hv-ext-query-caps`` + Supplementary features ---------------------- =20 diff --git a/hw/hyperv/hyperv.c b/hw/hyperv/hyperv.c index 3dcf23ba53..058c55eb4b 100644 --- a/hw/hyperv/hyperv.c +++ b/hw/hyperv/hyperv.c @@ -12,7 +12,10 @@ #include "qemu/module.h" #include "qapi/error.h" #include "system/address-spaces.h" +#include "system/kvm.h" #include "system/memory.h" +#include "system/physmem.h" +#include "system/runstate.h" #include "exec/target_page.h" #include "exec/cpu-common.h" #include "linux/kvm.h" @@ -24,10 +27,13 @@ #include "qemu/queue.h" #include "qemu/rcu.h" #include "qemu/rcu_queue.h" +#include "hw/core/boards.h" #include "hw/hyperv/hyperv.h" #include "qom/object.h" #include "target/i386/kvm/hyperv-proto.h" =20 +#define HV_BOOT_ZEROED_PAGE_SHIFT 9 + struct SynICState { DeviceState parent_obj; =20 @@ -714,7 +720,7 @@ uint16_t hyperv_ext_hcall_query_caps(uint64_t sup, uint= 64_t outgpa, bool fast) } =20 len =3D sizeof(*supported); - supported =3D cpu_physical_memory_map(outgpa, &len, 1); + supported =3D physical_memory_map(outgpa, &len, 1); if (!supported || len < sizeof(*supported)) { ret =3D HV_STATUS_INSUFFICIENT_MEMORY; goto cleanup; @@ -725,8 +731,151 @@ uint16_t hyperv_ext_hcall_query_caps(uint64_t sup, ui= nt64_t outgpa, bool fast) =20 cleanup: if (supported) { - cpu_physical_memory_unmap(supported, sizeof(*supported), 1, len); + physical_memory_unmap(supported, sizeof(*supported), 1, len); + } + return ret; +} + +struct boot_zero_opaque { + struct hyperv_get_boot_zeroed_memory_output *zr; + const unsigned long *zero_blocks; + const unsigned long *kvm_bitmap; + unsigned long num; + unsigned int order; + unsigned int count; +}; + +static uint64_t boot_zeroed_max_gpa; + +void hyperv_boot_zeroed_set_max_gpa(uint64_t max_gpa) +{ + boot_zeroed_max_gpa =3D max_gpa; +} + +static bool bootzero_mem_cb(Int128 istart, Int128 ilen, const MemoryRegion= *mr, + hwaddr offset_in_region, void *opaque) +{ + struct boot_zero_opaque *p =3D opaque; + uint64_t gpa_start, len; + ram_addr_t ram_start; + unsigned long ram_pfn_start, ram_pfn_end, gpa_ram_pfn_diff; + unsigned long gpa_bit_start, ram_bit_start, ram_bit_end, gpa_ram_bit_d= iff; + unsigned long idx, begin, pfn_start, pfn_end; + unsigned long full_shift =3D TARGET_PAGE_BITS + p->order; + + if (!memory_region_is_ram(mr) + || memory_region_is_rom(mr) + || memory_region_is_ram_device(mr) + || (int128_get64(ilen) =3D=3D 0)) { + return false; + } + + /* + * We iterate concurrently over p->zero_blocks, which is a ram_addr_t, + * and p->kvm_bitmap, which is indexed by GPA. Hence the various + * conversion gymnastics. + */ + gpa_start =3D int128_get64(istart); + ram_start =3D memory_region_get_ram_addr(mr) + offset_in_region; + len =3D int128_get64(ilen); + + ram_pfn_start =3D ram_start >> TARGET_PAGE_BITS; + ram_pfn_end =3D (ram_start + len - 1) >> TARGET_PAGE_BITS; + gpa_ram_pfn_diff =3D (gpa_start - ram_start) >> TARGET_PAGE_BITS; + + gpa_bit_start =3D gpa_start >> (full_shift); + ram_bit_start =3D ram_start >> (full_shift); + ram_bit_end =3D MIN(((ram_start + len - 1) >> full_shift) + 1, p->num); + gpa_ram_bit_diff =3D gpa_bit_start - ram_bit_start; + + idx =3D ram_bit_start; + while (idx < ram_bit_end && p->count < ARRAY_SIZE(p->zr->ranges)) { + while (idx < ram_bit_end && + (test_bit(idx, p->zero_blocks) || + test_bit(idx + gpa_ram_bit_diff, p->kvm_bitmap))) { + idx++; + } + if (idx =3D=3D ram_bit_end) { + break; + } + begin =3D idx; + while (idx < ram_bit_end && + !test_bit(idx, p->zero_blocks) && + !test_bit(idx + gpa_ram_bit_diff, p->kvm_bitmap)) { + idx++; + } + pfn_start =3D MAX(begin << p->order, ram_pfn_start); + pfn_end =3D MIN((idx << p->order) - 1, ram_pfn_end); + + p->zr->ranges[p->count].start_pfn =3D pfn_start + gpa_ram_pfn_diff; + p->zr->ranges[p->count].page_count =3D pfn_end - pfn_start + 1; + p->count++; + } + + return p->count =3D=3D ARRAY_SIZE(p->zr->ranges); +} + +uint16_t hyperv_ext_hcall_get_boot_zeroed_memory(uint64_t outgpa, bool fas= t) +{ + uint16_t ret; + hwaddr len; + struct boot_zero_opaque priv =3D { 0 }; + struct kvm_ever_mapped_log kvm_log =3D { 0 }; + hwaddr write_len =3D 0; + + if (fast) { + ret =3D HV_STATUS_INVALID_HYPERCALL_CODE; + goto cleanup; + } + + len =3D sizeof(*priv.zr); + priv.zr =3D physical_memory_map(outgpa, &len, 1); + if (!priv.zr || len < sizeof(*priv.zr)) { + ret =3D HV_STATUS_INSUFFICIENT_MEMORY; + goto cleanup; + } + + priv.zero_blocks =3D physical_memory_get_mapped_ranges(&priv.num, &pri= v.order); + priv.num *=3D BITS_PER_LONG; + + kvm_log.first_granule =3D 0; + kvm_log.granule_shift =3D priv.order + TARGET_PAGE_BITS; + kvm_log.num_granules =3D DIV_ROUND_UP(boot_zeroed_max_gpa, + 1ULL << kvm_log.granule_shift); + kvm_log.bitmap =3D g_malloc0(DIV_ROUND_UP(kvm_log.num_granules, BITS_P= ER_BYTE)); + priv.kvm_bitmap =3D kvm_log.bitmap; + if (kvm_vm_ioctl(kvm_state, KVM_GET_EVER_MAPPED_LOG, &kvm_log)) { + error_report("failed to get EVER_MAPPED_LOG from KVM, " + "first granule: 0x%" PRIx64 ", num_granules 0x%" PRIx= 64 ", " + "granule_shift: 0x%" PRIx32 ", error '%s'", + (uint64_t)kvm_log.first_granule, + (uint64_t)kvm_log.num_granules, + (uint32_t)kvm_log.granule_shift, strerror(errno)); + /* + * At this point, we haven't written anything to the return struct + * yet, so returning like this is the conservative way out. + * Though maybe we should use an error code here? But which one? + */ + ret =3D HV_STATUS_SUCCESS; + goto cleanup; + } + + priv.zr->range_count =3D 0; + if (priv.zero_blocks) { + RCU_READ_LOCK_GUARD(); + flatview_for_each_range(address_space_to_flatview(&address_space_m= emory), + bootzero_mem_cb, &priv); + priv.zr->range_count =3D priv.count; } + write_len =3D sizeof(priv.zr->range_count) + + priv.count * sizeof(priv.zr->ranges[0]); + ret =3D HV_STATUS_SUCCESS; + +cleanup: + if (priv.zr) { + physical_memory_unmap(priv.zr, len, 1, write_len); + } + g_free(kvm_log.bitmap); return ret; } =20 @@ -1013,6 +1162,31 @@ uint64_t hyperv_syndbg_query_options(void) return msg.u.query_options.options; } =20 +bool hyperv_boot_zeroed_setup(void) +{ + static bool initialized; + + if (initialized) { + return false; + } + + initialized =3D true; + + if (runstate_check(RUN_STATE_INMIGRATE)) { + /* + * We do not track zeroed memory across migrations. + * The hypercall is only issued early during boot, so we don't lose + * much by not dealing with the complication of moving the zeroed + * state of guest memory to the migrated instance. + */ + return false; + } + + physical_memory_init_mapped_tracker(current_machine->ram_size >> TARGE= T_PAGE_BITS, + HV_BOOT_ZEROED_PAGE_SHIFT); + return true; +} + static bool vmbus_recommended_features_enabled; =20 bool hyperv_are_vmbus_recommended_features_enabled(void) diff --git a/include/hw/hyperv/hyperv-proto.h b/include/hw/hyperv/hyperv-pr= oto.h index f1d1d2eb26..5bf5684d11 100644 --- a/include/hw/hyperv/hyperv-proto.h +++ b/include/hw/hyperv/hyperv-proto.h @@ -36,6 +36,7 @@ #define HV_RETRIEVE_DEBUG_DATA 0x006a #define HV_RESET_DEBUG_SESSION 0x006b #define HV_EXT_CALL_QUERY_CAPABILITIES 0x8001 +#define HV_EXT_CALL_GET_BOOT_ZEROED_MEMORY 0x8002 #define HV_HYPERCALL_FAST (1u << 16) =20 /* @@ -192,4 +193,14 @@ struct hyperv_retrieve_debug_data_output { uint32_t retrieved_count; uint32_t remaining_count; } __attribute__ ((__packed__)); + +struct hyperv_get_boot_zeroed_memory_range { + uint64_t start_pfn; + uint64_t page_count; +} __attribute__ ((__packed__)); + +struct hyperv_get_boot_zeroed_memory_output { + uint64_t range_count; + struct hyperv_get_boot_zeroed_memory_range ranges[255]; +} __attribute__ ((__packed__)); #endif diff --git a/include/hw/hyperv/hyperv.h b/include/hw/hyperv/hyperv.h index e29d60f565..2ab3943a03 100644 --- a/include/hw/hyperv/hyperv.h +++ b/include/hw/hyperv/hyperv.h @@ -102,11 +102,19 @@ uint16_t hyperv_hcall_post_dbg_data(uint64_t ingpa, u= int64_t outgpa, bool fast); */ uint16_t hyperv_ext_hcall_query_caps(uint64_t sup, uint64_t outgpa, bool f= ast); =20 +/* + * Process HVCALL_EXT_GET_BOOT_ZEROED_MEMORY hypercall. + */ +uint16_t hyperv_ext_hcall_get_boot_zeroed_memory(uint64_t outgpa, bool fas= t); + uint32_t hyperv_syndbg_send(uint64_t ingpa, uint32_t count); uint32_t hyperv_syndbg_recv(uint64_t ingpa, uint32_t count); void hyperv_syndbg_set_pending_page(uint64_t ingpa); uint64_t hyperv_syndbg_query_options(void); =20 +bool hyperv_boot_zeroed_setup(void); +void hyperv_boot_zeroed_set_max_gpa(uint64_t max_gpa); + typedef enum HvSynthDbgMsgType { HV_SYNDBG_MSG_CONNECTION_INFO, HV_SYNDBG_MSG_SEND, diff --git a/include/system/physmem.h b/include/system/physmem.h index c47b378025..924ae9f851 100644 --- a/include/system/physmem.h +++ b/include/system/physmem.h @@ -103,4 +103,12 @@ bool physical_memory_snapshot_get_dirty(DirtyBitmapSna= pshot *snap, ram_addr_t length); int ram_block_rebind(Error **errp); =20 +void physical_memory_init_mapped_tracker(unsigned long num_pages, + unsigned int order); + +void physical_memory_set_mapped_range(ram_addr_t addr, ram_addr_t length); + +const unsigned long *physical_memory_get_mapped_ranges(unsigned long *len, + unsigned int *order= ); + #endif diff --git a/linux-headers/linux/kvm.h b/linux-headers/linux/kvm.h index dd52e2a65b..7836514594 100644 --- a/linux-headers/linux/kvm.h +++ b/linux-headers/linux/kvm.h @@ -986,6 +986,7 @@ struct kvm_enable_cap { #define KVM_CAP_S390_KEYOP 247 #define KVM_CAP_S390_VSIE_ESAMODE 248 #define KVM_CAP_S390_HPAGE_2G 249 +#define KVM_CAP_EVER_MAPPED 250 =20 struct kvm_irq_routing_irqchip { __u32 irqchip; @@ -1655,4 +1656,18 @@ struct kvm_pre_fault_memory { __u64 padding[5]; }; =20 +#define KVM_GET_EVER_MAPPED_LOG _IOW(KVMIO, 0xd6, struct kvm_ever_mapped= _log) + +struct kvm_ever_mapped_log { + __u64 first_granule; + __u64 num_granules; + __u32 granule_shift; + __u32 flags; + union { + void *bitmap; + __u64 padding; + }; + __u64 reserved[4]; +}; + #endif /* __LINUX_KVM_H */ diff --git a/system/memory.c b/system/memory.c index 5fc36708ec..b0295f8bd9 100644 --- a/system/memory.c +++ b/system/memory.c @@ -2173,9 +2173,12 @@ void memory_region_set_log(MemoryRegion *mr, bool lo= g, unsigned client) void memory_region_set_dirty(MemoryRegion *mr, hwaddr addr, hwaddr size) { + ram_addr_t ramaddr; + assert(mr->ram_block); - physical_memory_set_dirty_range(memory_region_get_ram_addr(mr) + addr, - size, + ramaddr =3D memory_region_get_ram_addr(mr); + physical_memory_set_mapped_range(ramaddr + addr, size); + physical_memory_set_dirty_range(ramaddr + addr, size, memory_region_get_dirty_log_mask(m= r)); } =20 diff --git a/system/physmem.c b/system/physmem.c index c21ea92915..76820a2e84 100644 --- a/system/physmem.c +++ b/system/physmem.c @@ -180,6 +180,54 @@ struct DirtyBitmapSnapshot { unsigned long dirty[]; }; =20 +/** + * @mapped_blocks: pointer to the bitmap itself, may be NULL if no trackin= g. + * @mapped_blocks_num: the length of the bitmap, in sizeof(*mapped_blocks) + * @mapped_blocks_order: the order, in pages, i.e., 0 =3D 1 bit per page. + */ +static unsigned long *mapped_blocks; +static unsigned long mapped_blocks_num; +static unsigned int mapped_blocks_order; + +void physical_memory_init_mapped_tracker(unsigned long num_pages, + unsigned int order) +{ + mapped_blocks_order =3D order; + mapped_blocks_num =3D DIV_ROUND_UP(DIV_ROUND_UP(num_pages, 1ULL << ord= er), + BITS_PER_LONG); + mapped_blocks =3D g_malloc0(sizeof(*mapped_blocks) * mapped_blocks_num= ); +} + +void physical_memory_set_mapped_range(ram_addr_t addr, ram_addr_t length) +{ + unsigned long first_bit, last_bit; + unsigned long max_bits =3D mapped_blocks_num * BITS_PER_LONG; + + if (mapped_blocks =3D=3D NULL || length =3D=3D 0) { + return; + } + + /* + * Since we don't track hotplugged memory, we may get requests to + * (partially or fully) set a region we don't track. + */ + first_bit =3D addr >> (TARGET_PAGE_BITS + mapped_blocks_order); + if (first_bit >=3D max_bits) { + return; + } + last_bit =3D MIN((addr + length - 1) >> (TARGET_PAGE_BITS + mapped_blo= cks_order), + max_bits - 1); + bitmap_set_atomic(mapped_blocks, first_bit, last_bit - first_bit + 1); +} + +const unsigned long *physical_memory_get_mapped_ranges(unsigned long *len, + unsigned int *order) +{ + *len =3D mapped_blocks_num; + *order =3D mapped_blocks_order; + return mapped_blocks; +} + static void phys_map_node_reserve(PhysPageMap *map, unsigned nodes) { static unsigned alloc_hint =3D 16; @@ -3129,6 +3177,8 @@ static void invalidate_and_set_dirty(MemoryRegion *mr= , hwaddr addr, assert(ramaddr !=3D RAM_ADDR_INVALID); addr +=3D ramaddr; =20 + physical_memory_set_mapped_range(addr, length); + /* No early return if dirty_log_mask is or becomes 0, because * physical_memory_set_dirty_range will still call * xen_modified_memory. diff --git a/target/i386/cpu.c b/target/i386/cpu.c index ed9773ac9e..29564a3394 100644 --- a/target/i386/cpu.c +++ b/target/i386/cpu.c @@ -10770,6 +10770,8 @@ static const Property x86_cpu_properties[] =3D { HYPERV_FEAT_TLBFLUSH_DIRECT, 0), DEFINE_PROP_BIT64("hv-ext-query-caps", X86CPU, hyperv_features, HYPERV_FEAT_EXT_CALLS, 0), + DEFINE_PROP_BIT64("hv-boot-zeroed-mem", X86CPU, hyperv_features, + HYPERV_FEAT_BOOT_ZEROED_MEMORY, 0), DEFINE_PROP_ON_OFF_AUTO("hv-no-nonarch-coresharing", X86CPU, hyperv_no_nonarch_cs, ON_OFF_AUTO_OFF), #ifdef CONFIG_SYNDBG diff --git a/target/i386/cpu.h b/target/i386/cpu.h index 6737340766..67d569ee4d 100644 --- a/target/i386/cpu.h +++ b/target/i386/cpu.h @@ -1481,6 +1481,7 @@ uint64_t x86_cpu_get_supported_feature_word(X86CPU *c= pu, FeatureWord w); #define HYPERV_FEAT_TLBFLUSH_EXT 19 #define HYPERV_FEAT_TLBFLUSH_DIRECT 20 #define HYPERV_FEAT_EXT_CALLS 21 +#define HYPERV_FEAT_BOOT_ZEROED_MEMORY 22 =20 #ifndef HYPERV_SPINLOCK_NEVER_NOTIFY #define HYPERV_SPINLOCK_NEVER_NOTIFY 0xFFFFFFFF diff --git a/target/i386/kvm/hyperv-proto.h b/target/i386/kvm/hyperv-proto.h index 4eb2955ac5..ec38b717e4 100644 --- a/target/i386/kvm/hyperv-proto.h +++ b/target/i386/kvm/hyperv-proto.h @@ -94,6 +94,11 @@ #define HV_NESTED_DIRECT_FLUSH (1u << 17) #define HV_NESTED_MSR_BITMAP (1u << 19) =20 +/* + * HV_EXT_CALL_QUERY_CAPABILITIES bits + */ +#define HV_EXT_CAP_GET_BOOT_ZEROED_MEMORY (1u << 0) + /* * Basic virtualized MSRs */ diff --git a/target/i386/kvm/hyperv.c b/target/i386/kvm/hyperv.c index 807acaf6b1..dc226b4419 100644 --- a/target/i386/kvm/hyperv.c +++ b/target/i386/kvm/hyperv.c @@ -123,6 +123,14 @@ int kvm_hv_handle_exit(X86CPU *cpu, struct kvm_hyperv_= exit *exit) hyperv_ext_hcall_query_caps(hv_build_ext_call_caps(CPU(cpu= )), out_param, fast); break; + case HV_EXT_CALL_GET_BOOT_ZEROED_MEMORY: + if (!hyperv_feat_enabled(cpu, HYPERV_FEAT_BOOT_ZEROED_MEMORY))= { + exit->u.hcall.result =3D HV_STATUS_INVALID_HYPERCALL_CODE; + } else { + exit->u.hcall.result =3D + hyperv_ext_hcall_get_boot_zeroed_memory(out_param, fas= t); + } + break; default: exit->u.hcall.result =3D HV_STATUS_INVALID_HYPERCALL_CODE; } diff --git a/target/i386/kvm/kvm.c b/target/i386/kvm/kvm.c index bc1e44c33e..1b0e0bd61e 100644 --- a/target/i386/kvm/kvm.c +++ b/target/i386/kvm/kvm.c @@ -965,6 +965,36 @@ static bool tsc_is_stable_and_known(CPUX86State *env) || env->user_tsc_khz; } =20 +static bool find_max_gpa_cb(Int128 istart, Int128 ilen, const MemoryRegion= *mr, + hwaddr offset_in_region, void *opaque) +{ + uint64_t *max =3D opaque; + uint64_t end; + + if (!memory_region_is_ram(mr) + || memory_region_is_rom(mr) + || memory_region_is_ram_device(mr) + || (int128_get64(ilen) =3D=3D 0)) { + return false; + } + + end =3D int128_get64(istart) + int128_get64(ilen); + if (end > *max) { + *max =3D end; + } + return false; +} + +static uint64_t find_max_gpa(void) +{ + uint64_t max =3D 0; + + RCU_READ_LOCK_GUARD(); + flatview_for_each_range(address_space_to_flatview(&address_space_memor= y), + find_max_gpa_cb, &max); + return max; +} + #define DEFAULT_EVMCS_VERSION ((1 << 8) | 1) =20 static struct { @@ -1144,6 +1174,14 @@ static struct { .bits =3D HV_ENABLE_EXT_HYPERCALLS} } }, + [HYPERV_FEAT_BOOT_ZEROED_MEMORY] =3D { + .desc =3D "enlighten guest about pre-zeroed memory (hv-boot-zeroed= -mem)", + .flags =3D { + {.func =3D HV_EXT_CALL_QUERY_CAPABILITIES, .reg =3D 0, + .bits =3D HV_EXT_CAP_GET_BOOT_ZEROED_MEMORY} + }, + .dependencies =3D BIT(HYPERV_FEAT_EXT_CALLS) + }, }; =20 static struct kvm_cpuid2 *try_get_hv_cpuid(CPUState *cs, int max, @@ -1379,6 +1417,11 @@ static bool hyperv_feature_supported(CPUState *cs, i= nt feature) continue; } =20 + if (func =3D=3D HV_EXT_CALL_QUERY_CAPABILITIES) { + /* These do not correspond to host CPUID feature bits. */ + return true; + } + if ((hv_cpuid_get_host(cs, func, reg) & bits) !=3D bits) { return false; } @@ -1710,6 +1753,20 @@ static bool evmcs_version_supported(uint16_t evmcs_v= ersion, (max_version <=3D max_supported_version); } =20 +static Notifier kvm_init_ever_mapped; + +static void kvm_enable_ever_mapped(Notifier *notifier, void *unused) +{ + uint64_t max_gpa =3D find_max_gpa(); + + if (kvm_vm_enable_cap(kvm_state, KVM_CAP_EVER_MAPPED, 0, max_gpa)) { + error_report("Failed to enable KVM_CAP_EVER_MAPPED, max GPA: 0x%lx= , " + "error '%s'", max_gpa, strerror(errno)); + exit(1); + } + hyperv_boot_zeroed_set_max_gpa(max_gpa); +} + static int hyperv_init_vcpu(X86CPU *cpu) { CPUState *cs =3D CPU(cpu); @@ -1820,6 +1877,28 @@ static int hyperv_init_vcpu(X86CPU *cpu) hyperv_x86_set_vmbus_recommended_features_enabled(); } =20 + if (cs->cpu_index =3D=3D 0 && + hyperv_feat_enabled(cpu, HYPERV_FEAT_BOOT_ZEROED_MEMORY)) { + /* + * This is not per-CPU, so only run it for vCPU #0. + * We do it here instead of earlier during general setup, since we + * need to know CPU features for this. + */ + if (kvm_check_extension(kvm_state, KVM_CAP_EVER_MAPPED) <=3D 0) { + error_report("Can't use hv-boot-zeroed-mem without KVM-side " + "support for KVM_CAP_EVER_MAPPED."); + return -ENOTSUP; + } + if (hyperv_boot_zeroed_setup()) { + /* + * This part, we have to defer even further, until memory is + * set up, but (crucially!) vCPUs have not started yet. + */ + kvm_init_ever_mapped.notify =3D kvm_enable_ever_mapped; + qemu_add_machine_init_done_notifier(&kvm_init_ever_mapped); + } + } + return 0; } =20 --=20 2.47.3