From nobody Sun Feb 8 16:12:31 2026 Received: from mx0b-002c1b01.pphosted.com (mx0b-002c1b01.pphosted.com [148.163.155.12]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 4C95427CB02; Mon, 29 Dec 2025 11:18:38 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=148.163.155.12 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1767007120; cv=fail; b=PKzZNSRKl77hLErFvRzw2aQ5rC1So1BWMp8vSVD0g8X5BzGAKkVWC22Frw2IRpF1uxmLFuJ24iIQVWYEFc4ZORX7cOxqYNk3fXuzgMMrJXNKn9rPX5bXrVyEA2bkefUIXfopvuLwLCTS0Rvg6GivolTRnoF54mgVEB0kpdIYgK4= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1767007120; c=relaxed/simple; bh=+fZdLv1dsMonEs2fIqj97fM+pm/NpuNSunLTh7LopqI=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: Content-Type:MIME-Version; b=OY4V5vV0L4+mdybebPXDwI5EbtaWiu+aG+dEo4GnezTgarDCumg6HxS1am8zFOUW0iZJaZu+5xfxe/GUkR/mxiILgFY4LL0k7snJuSQFFztKPj2MiXDmBeB61CXKhL9MgyEYtBp6FPREmd5ksQTlawVUegYJJPZYtsyjUYgdo3Q= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=nutanix.com; spf=pass smtp.mailfrom=nutanix.com; dkim=pass (2048-bit key) header.d=nutanix.com header.i=@nutanix.com header.b=VYo17e3u; dkim=pass (2048-bit key) header.d=nutanix.com header.i=@nutanix.com header.b=LNZwkCYy; arc=fail smtp.client-ip=148.163.155.12 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=nutanix.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=nutanix.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=nutanix.com header.i=@nutanix.com header.b="VYo17e3u"; dkim=pass (2048-bit key) header.d=nutanix.com header.i=@nutanix.com header.b="LNZwkCYy" Received: from pps.filterd (m0127842.ppops.net [127.0.0.1]) by mx0b-002c1b01.pphosted.com (8.18.1.11/8.18.1.11) with ESMTP id 5BSL0cZ51186992; Mon, 29 Dec 2025 03:17:49 -0800 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=CXLjSgYA7ZebJnwwUPuvS7D0Kkd2WWyxb9yLE0XvG Vo=; b=VYo17e3uAdf6qyQsckr3OU73Op7OGdlZ4BNYp3adpww0r1w8n2+s8lrZL ORLZ9hndEx72PcjQr8vvHSSdFyNdNuJ/hu63JgW/QYBa5rJlW1sZouahjZ9WBoOU +o6K2Vq3MqEeM6MVkHqtU8lwIjytgUNI3mtjMZ6LCT71tAm1Wq6mSaV71ml1UFLJ vdGcD4tUWut9A4wal4daPWPQjMRRTpLJ+t5gOW0j5j7Ug/+CIoLJsWS10P5XV7rn wFY/aLINi3UsZzRIG24k+2lsEadYyw6xbh9JN8GUnKrQcmK76vKjPv5ZrniG2CKj yWyz636I/rKyN/KEOLjHdLarlKi3w== Received: from sn4pr0501cu005.outbound.protection.outlook.com (mail-southcentralusazon11021083.outbound.protection.outlook.com [40.93.194.83]) by mx0b-002c1b01.pphosted.com (PPS) with ESMTPS id 4bafnejj8n-1 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384 bits=256 verify=NOT); Mon, 29 Dec 2025 03:17:49 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=x/YB8moJwySLV5j7X2KF8pGsyhJoURIdygrOvTOxyd7fiPTmXnxBfD9y51uz6F8z7dGPTG0D444qvu3h9XJgby2Mq0pA0TfGOSCmjLPP4QJc/1y9vIwdxLyJmic8WQKYERdK/2JumqzqQi9NkzCX27RJupeVylMxalQTobX/hnIIV9EcSo0N8wvEkivWUJqc2jsujiEFtJDjXr+fn9oI4DwMLFytChZMX3+Zrhw5592iNKdci1l/LhkbP755gW437FSSJbMCh+IxcKoIHzWP9+Gfe7cInzfSXAg7HGBsdVD4lEz4gurMHLmwt6dRxM1HyHzTZBScEqEFijYcBZ/NNQ== 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=CXLjSgYA7ZebJnwwUPuvS7D0Kkd2WWyxb9yLE0XvGVo=; b=ihCPvBJlCTuLBeCJXNPiGCJce/ST7FvvsMdhFhcFNHimAfDjEdR/sn059p600/J4Kf52yD3tDTpxE3MKjpuGXsNywD/aYlYLjyX7giDzzdaR5DTIhBSa2KUMw610S3kvreOwBrUGS/V2sG2HQcVPB3xtw97VYyd80iOdnRJpOHFDgJz4j7mhaxrF+X0gfaWUdMsVLIEzNRRih5dQlnPYoI2K1BmfsShcWaZaiBU4EpH8GgwuiB6wxOPqA7rGY/EuCjY1QKecs0+18dIyG+J//bKRdkLau0cVLEpstfdd4yquHIzGBxp3FYiFVREpLAxpEHrpQbnLYEUm053kzFXFnA== 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=CXLjSgYA7ZebJnwwUPuvS7D0Kkd2WWyxb9yLE0XvGVo=; b=LNZwkCYyhvUuKZ3BTvCmhl/GDAd+dhW5GPFH8RMvwdt25Fy74koAIT5MdDuFu/zQ9oB7jqOCyYfo3iWEPnxn1GTYA3sj774naTCoy/RQSk6tiA3/4SUyehesClgLWwQV6NsV0VB4wLy3xsVGY6GK9F3vKYu/FrZ8lNNCmRb0JIsLiBaxQ+qw4SvIF4J6rytzQp2JAqyxt7ncrqIhxgZCvWSVa29DrhSTZtbnnEOLJV2CtPNQ0xLyTk/nPmcnxrihMoj5pfcN0oIn+cYqG8wOP5Y97YfvZVjPbwUYPHupt3c+LxqbRFXA81v+gWyQvMY4G8rLYspOVC/1Dmu8YP5qoQ== Received: from PH0PR02MB7557.namprd02.prod.outlook.com (2603:10b6:510:54::17) by PH7PR02MB9965.namprd02.prod.outlook.com (2603:10b6:510:2f9::19) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.9456.14; Mon, 29 Dec 2025 11:17:47 +0000 Received: from PH0PR02MB7557.namprd02.prod.outlook.com ([fe80::4917:bc05:4373:6bef]) by PH0PR02MB7557.namprd02.prod.outlook.com ([fe80::4917:bc05:4373:6bef%5]) with mapi id 15.20.9456.013; Mon, 29 Dec 2025 11:17:47 +0000 From: Khushit Shah To: seanjc@google.com, pbonzini@redhat.com, kai.huang@intel.com, dwmw2@infradead.org Cc: mingo@redhat.com, x86@kernel.org, bp@alien8.de, hpa@zytor.com, linux-kernel@vger.kernel.org, kvm@vger.kernel.org, dave.hansen@linux.intel.com, tglx@linutronix.de, jon@nutanix.com, shaju.abraham@nutanix.com, Khushit Shah Subject: [PATCH v5 1/3] KVM: x86: Refactor suppress EOI broadcast logic Date: Mon, 29 Dec 2025 11:17:06 +0000 Message-ID: <20251229111708.59402-2-khushit.shah@nutanix.com> X-Mailer: git-send-email 2.43.7 In-Reply-To: <20251229111708.59402-1-khushit.shah@nutanix.com> References: <20251229111708.59402-1-khushit.shah@nutanix.com> Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: PH5P220CA0011.NAMP220.PROD.OUTLOOK.COM (2603:10b6:510:34a::11) To PH0PR02MB7557.namprd02.prod.outlook.com (2603:10b6:510:54::17) Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: PH0PR02MB7557:EE_|PH7PR02MB9965:EE_ X-MS-Office365-Filtering-Correlation-Id: fb0ef918-2a68-44e0-923f-08de46cbe55c x-proofpoint-crosstenant: true X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|366016|376014|7416014|1800799024; X-Microsoft-Antispam-Message-Info: =?us-ascii?Q?62RTifGFu8/iY1s2UO+UGnrZJWl7VtCx2zfSj08HRIbqg79LY2MiD7UsMYn/?= =?us-ascii?Q?sU7Vp/DvoqIT9xG4xmK2NTPxLy+/YxxHgdetggPanSt4t6WqgPyFV+OqWSBX?= =?us-ascii?Q?mZOslWBusS+2BVQ+MMkKKqR6QSDjvOkihtJ8b3+F1qs+JtngoGPMzcUt8+8/?= =?us-ascii?Q?N8ykuxMS9UfsZMAAeCM9nUlrpsbOqZhpn3dPknJhIeDYFhV+mtKa1QfjhWMk?= =?us-ascii?Q?unYao2s1k0NuqcIi0ol/B/ODoLraO5qcobxIokh1tHVYpD4kSyStY7BLDEPH?= =?us-ascii?Q?6cvNjMkA4ULWc7yr0DDjh4/Ccgp0qJ9OvnsQu4bjZ4nq+CAOhBR21vGfTYle?= =?us-ascii?Q?TsLxIe4/FgyLrLLGc7QzdlNc81Cewpl1Ak7JmC/vxRyUCBDep4E2Uj1oJhBa?= =?us-ascii?Q?IJ4rT1RhgUJuLpQgtnovniDOpcgawqz/Qr3PfZnRdEaNAt08GyYGX4L17Ufp?= =?us-ascii?Q?gXNM9mE3v2oowglslSnjfjXOX26MVdRnk6yTJbKD8D0QJJZuy690SSrbqLyQ?= =?us-ascii?Q?0ZctF7tE5DzFm8sAm14i4zaSIORZLae8wuL145X0Kv5SPvVSdMzWzeqkDywh?= =?us-ascii?Q?ckSdpH5ux4f5KE6xpetsL/GRYey1IQz7ziD8yA1m4gDY7hay0De4zL/MPEr/?= =?us-ascii?Q?wcDjMJEnF3BA+W2A48+KqUeInemqriE+jkdivUn58iZdKmuwQpO4ldzxyifJ?= =?us-ascii?Q?r9QP4pc9Xm6p/+hZx7asZsuuAg/M9H7xO9FKe2sccHhNYuoEBkptR3q8IrKm?= =?us-ascii?Q?2zlEjDnv+GNBMHu916cCvB7uBamOyDG3jbmBzBmX81CPI50ICzk9FWG9k+3Z?= =?us-ascii?Q?dSr+Hs2Snj8P77irr0BYfqYeck649YQdRoneeMCZWaEy2DECjEF9sM1u01mr?= =?us-ascii?Q?LjLyqsO8ksEDkuVuK6WVQt/OCQqP/Al+IYgCMqsJFnVnATDDjw7fSXPw2Nu9?= =?us-ascii?Q?i03IHaJlMlAZrJ/QGsN775Iut/Gnw8mr3BFt+FjCylRkqg1uyLdiXla0J0ej?= =?us-ascii?Q?eWNFco/V1TMfp8EvDajnpVoVOz5sQo7JuDKsxCqooWoaBj5Byz49ECUf3Qck?= =?us-ascii?Q?VUqjxEEO/REmyK4k94c/XIULTGnygDcpvTMkQh4wS+Iys+kd71ZGsMUfyD7/?= =?us-ascii?Q?jTtjvwC4Pd9k3sD8C8yDn/3JErM+0823M7k5voovmBK594Rt79QJ3vfL3OhP?= =?us-ascii?Q?xmjcZGt2DtrQi/EnsfbZ0SSqC5m3ixkHhUOym241tL9SMq291aI/EQcJZcp5?= =?us-ascii?Q?s5DY6GaQo++XzJLj+X2KTEyJwMppuPEcklC2SXGowhm7hau9Twol2xcrsW4d?= =?us-ascii?Q?NcFD+SAezoinB1TWovQIZ6mG3KhExowp98rvuieRTTtHzB8Pv0macRPs45Mr?= =?us-ascii?Q?KO6vyJpQiP1M/bbRoqL2aItt9nmlhTHRrlevBOHBSYmbHXX2VbK27CVF09HG?= =?us-ascii?Q?7mPqIO2FeNyqvLt5OysIJdlNPgq4BwG7?= X-Forefront-Antispam-Report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:PH0PR02MB7557.namprd02.prod.outlook.com;PTR:;CAT:NONE;SFS:(13230040)(366016)(376014)(7416014)(1800799024);DIR:OUT;SFP:1102; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?us-ascii?Q?f7l4/od9M6aO9YixTQPgvW3XrrE6jhlmtRB+NBjNu5VjdVVzkiIZzVNyDWAh?= =?us-ascii?Q?pzxNmjRJQrhAcQpbHqnf16OEbtuuS+vDavpDzUgL34Cyud9/ODZXQ5dADOCc?= =?us-ascii?Q?NdcZaaY3ie2IKoftm4U4dAQVCIl6HdTKnMle3v27n5I8h6DWGqGLtoFN159N?= =?us-ascii?Q?1wwDIdVEcssjpXsplrzHNx8YOTAWMlM9muCKO1BB+ClZQRUFLlLRfSFiPEhx?= =?us-ascii?Q?AF3EfkdCFOUdqRKY9LI8U2MGbqj6OiBzcXSHWQMyCEqKS1zVCM7tinaqUQ4n?= =?us-ascii?Q?mSI88GnGuuRDEOhm/3rSEDegZp1GriZp9D/mipy6q8xJb6lMA/Vq82Voh/5s?= =?us-ascii?Q?3Gd3EIOTCu1aXCuiaksrnAH6MAFx0j6b3oWr5xfL4yVyVSjaWiezRHvnvg4E?= =?us-ascii?Q?3qAblWXjpxZtoRlDsXmy3GEZn3OAMFwuSTtI1iVaoBNujKqoie7up7UQ9Nud?= =?us-ascii?Q?P/Ou/puYWcEHnqssPICiwgMFtrOzN3Dj8w8A/uO9SsNEryHmUjQ4XyUtVJPj?= =?us-ascii?Q?81KMELhuAwO27WVHHPlfpPGthxirn912Bq6W+eUWJagDlZ/5g1ZWsl8COYL3?= =?us-ascii?Q?6MbH0NVn/EC8MtlUCxd3/BgZt+0pMjFJMz1Zb7r6TzHFsow+blsLm+O5paW9?= =?us-ascii?Q?94FZYGlOWBIb+u87m7kQtCFhd6aGAo9rShhedkDvImsx3CDpjV5l+nOdog09?= =?us-ascii?Q?JCQMHUDuWpwTFU3OOPTTmUoMZpyj1mcuoaGobZZ2Rz+k7G/U+m3QnQ3TsE8T?= =?us-ascii?Q?+vpGc4k3wgVCKJWbDFjkjyrAuGnwDm+S5TI/+twT03TLgnM6FxhFJbyWsezl?= =?us-ascii?Q?LquhX39R7ZAhbDOG2dXYadeAyTugEQ+kOgVSN0obkUePQPNVfZ3sYkWHZrIC?= =?us-ascii?Q?FbtbnGOqrwmnfrvO0qzmMYIBcOmUtf2mKZDMiAFb1nMC6H9e9ml7bVCOXGZY?= =?us-ascii?Q?d6ark0c8JC7wpA7SbyJT+6IednP5ILoD6Jk5GRBr2PVAH1kkORZOGOzr4oRv?= =?us-ascii?Q?mQzjbkpkMIzEzQmKUqfd7aGjcmfRnOweqkZxe/19Xs77irJGAL27cSkuf314?= =?us-ascii?Q?YR74YI9OhGW+gN96EExYuZYcHJFG/cCWIWWXPRKVu/kwgC9cL0qL6glpsuoA?= =?us-ascii?Q?OhfTTpj0NuInCbOB/XKXf0AaQFKlneLHAnWdxsCeCPupKOMXCXn6ihDiVZtl?= =?us-ascii?Q?oSuJEIKIn4s2aTKcoWmKIV3r+QSLvqQi+s/xoM/55Cn9Zx17IxTd2aM54ph4?= =?us-ascii?Q?c+r3lnfxBE33vzaZGok6PRPseamqiRdOB3TdCQs5TzV9KdhrbkmUHdVtZsnf?= =?us-ascii?Q?pUuJ7HN3cQKKejGVlIbNDpaJSh9yJ82Sjp59PLKHkexZUwREm6aPKi8KWh4s?= =?us-ascii?Q?odQY02C4gwPFnO1rbntMcfrgWk1PqsFyeCRqcBQ8UqspITBoWbYUw2jo4XZn?= =?us-ascii?Q?zu+zMb221kyg/T2vB6nekVCe4RApC2hAJu9JPljc7ShwR2+cAmnr0K9pPv2Q?= =?us-ascii?Q?ubRr7OXNkagNiEu67aus7r6jyJDgcvWcCEg5Rls+QONbudCtRQ/1qnCHoG0U?= =?us-ascii?Q?JNzHBacLHAbDJ2YZlOf6dhur9msVcfS/qGIJQIB/V+LkAj3KCIZwGLVMDK5G?= =?us-ascii?Q?uuBcoE4x32iHDNN68mwAp5V6g+hIp0Dj4K56Lbb3j/HLue35MEL2cDntPlVq?= =?us-ascii?Q?Hqn9pM3UwNsQrJnjcjbwXNxSitUfr6/Avkftz1S1rUw3C+CRXl7imm8RWR+T?= =?us-ascii?Q?sK49DnurX526aMFogT6PYTewHYTamNE=3D?= X-OriginatorOrg: nutanix.com X-MS-Exchange-CrossTenant-Network-Message-Id: fb0ef918-2a68-44e0-923f-08de46cbe55c X-MS-Exchange-CrossTenant-AuthSource: PH0PR02MB7557.namprd02.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 29 Dec 2025 11:17:47.4625 (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: A8nNf2l3Jya3K8SEHeRLnbmd52zyYnLgGb1HEmnpdfSuBQitCmu1S9c7MfKX4R13oxwThOtsAieMAAT+c3utvdI3EbLpGS7vWb8SGsWtMEM= X-MS-Exchange-Transport-CrossTenantHeadersStamped: PH7PR02MB9965 X-Authority-Analysis: v=2.4 cv=P5c3RyAu c=1 sm=1 tr=0 ts=6952635d cx=c_pps a=IDYaL8Jh3K30OkZprGHyjg==:117 a=6eWqkTHjU83fiwn7nKZWdM+Sl24=:19 a=z/mQ4Ysz8XfWz/Q5cLBRGdckG28=:19 a=lCpzRmAYbLLaTzLvsPZ7Mbvzbb8=:19 a=xqWC_Br6kY4A:10 a=wP3pNCr1ah4A:10 a=0kUYKlekyDsA:10 a=VkNPw1HP01LnGYTKEx00:22 a=64Cc0HZtAAAA:8 a=D1or6okRyu1H9lat9IUA:9 X-Proofpoint-ORIG-GUID: FoW8LSAJpQL99nE-koJ_xzdgxbjlB30B X-Proofpoint-GUID: FoW8LSAJpQL99nE-koJ_xzdgxbjlB30B X-Proofpoint-Spam-Details-Enc: AW1haW4tMjUxMjI5MDEwNSBTYWx0ZWRfX60kJWkPKT/p2 cKxrgBN2cD+oCkh2QcNU3JQbALNMBDXms/VgG7Cbx7EodE2i5/hSO0IpT7KRghV+pSuG9tqn/iU tGmzbKGAcrpWqSkYI0FbWat4BGJg7DYmsz7z7XeJZ2V9gOZrt8TNL58vuLU60AT6IJHNdNCdRxI veWzYatJ/MI9vr/3vLHcnbOJGoWYhNGRPcQCRBJTz12Ej68Jj10csbQklbSzdSovPuzsZIv9JXN 2ib2AEr84/LRMVC2NWmsiUhjC7/YYoV6vMBlAgCwYmZ0FXo7SMjiCF+WPftL4nBEp7SMC0Z0Px9 5tGwCjcNw6eVfi7BukLwC/hQIoqLcy/aIZFurv+6ipno01Q0lhcoFpg7mOZ4YDecxcOsHnKRiek ueJbZrhl3dWli8qVqi4gCYXoYwVQ9moeUzR4SWUq+LNJDbnSgGF2EymP5X+TbAzVGq5XnhbmWhT wnfoFCkG5HLpP2IzhKw== X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1121,Hydra:6.1.9,FMLib:17.12.100.49 definitions=2025-12-29_03,2025-12-29_01,2025-10-01_01 X-Proofpoint-Spam-Reason: safe Content-Type: text/plain; charset="utf-8" Extract the suppress EOI broadcast (Directed EOI) logic into helper functions and move the check from kvm_ioapic_update_eoi_one() to kvm_ioapic_update_eoi() (required for a later patch). Prepare kvm_ioapic_send_eoi() to honor Suppress EOI Broadcast in split IRQCHIP mode. Introduce two helper functions: - kvm_lapic_advertise_suppress_eoi_broadcast(): determines whether KVM should advertise Suppress EOI Broadcast support to the guest - kvm_lapic_respect_suppress_eoi_broadcast(): determines whether KVM should honor the guest's request to suppress EOI broadcasts This refactoring prepares for I/O APIC version 0x20 support and userspace control of suppress EOI broadcast behavior. Signed-off-by: Khushit Shah Reviewed-by: David Woodhouse Suggested-by: David Woodhouse --- arch/x86/kvm/ioapic.c | 12 +++++++--- arch/x86/kvm/lapic.c | 53 ++++++++++++++++++++++++++++++++++++------- arch/x86/kvm/lapic.h | 3 +++ 3 files changed, 57 insertions(+), 11 deletions(-) diff --git a/arch/x86/kvm/ioapic.c b/arch/x86/kvm/ioapic.c index 2c2783296aed..6bf8d110aece 100644 --- a/arch/x86/kvm/ioapic.c +++ b/arch/x86/kvm/ioapic.c @@ -545,7 +545,6 @@ static void kvm_ioapic_update_eoi_one(struct kvm_vcpu *= vcpu, int trigger_mode, int pin) { - struct kvm_lapic *apic =3D vcpu->arch.apic; union kvm_ioapic_redirect_entry *ent =3D &ioapic->redirtbl[pin]; =20 /* @@ -560,8 +559,7 @@ static void kvm_ioapic_update_eoi_one(struct kvm_vcpu *= vcpu, kvm_notify_acked_irq(ioapic->kvm, KVM_IRQCHIP_IOAPIC, pin); spin_lock(&ioapic->lock); =20 - if (trigger_mode !=3D IOAPIC_LEVEL_TRIG || - kvm_lapic_get_reg(apic, APIC_SPIV) & APIC_SPIV_DIRECTED_EOI) + if (trigger_mode !=3D IOAPIC_LEVEL_TRIG) return; =20 ASSERT(ent->fields.trig_mode =3D=3D IOAPIC_LEVEL_TRIG); @@ -591,10 +589,16 @@ static void kvm_ioapic_update_eoi_one(struct kvm_vcpu= *vcpu, void kvm_ioapic_update_eoi(struct kvm_vcpu *vcpu, int vector, int trigger_= mode) { int i; + struct kvm_lapic *apic =3D vcpu->arch.apic; struct kvm_ioapic *ioapic =3D vcpu->kvm->arch.vioapic; =20 spin_lock(&ioapic->lock); rtc_irq_eoi(ioapic, vcpu, vector); + + if ((kvm_lapic_get_reg(apic, APIC_SPIV) & APIC_SPIV_DIRECTED_EOI) && + kvm_lapic_respect_suppress_eoi_broadcast(ioapic->kvm)) + goto out; + for (i =3D 0; i < IOAPIC_NUM_PINS; i++) { union kvm_ioapic_redirect_entry *ent =3D &ioapic->redirtbl[i]; =20 @@ -602,6 +606,8 @@ void kvm_ioapic_update_eoi(struct kvm_vcpu *vcpu, int v= ector, int trigger_mode) continue; kvm_ioapic_update_eoi_one(vcpu, ioapic, trigger_mode, i); } + +out: spin_unlock(&ioapic->lock); } =20 diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c index 0ae7f913d782..2c24fd8d815f 100644 --- a/arch/x86/kvm/lapic.c +++ b/arch/x86/kvm/lapic.c @@ -105,6 +105,39 @@ bool kvm_apic_pending_eoi(struct kvm_vcpu *vcpu, int v= ector) apic_test_vector(vector, apic->regs + APIC_IRR); } =20 +bool kvm_lapic_advertise_suppress_eoi_broadcast(struct kvm *kvm) +{ + /* + * The default in-kernel I/O APIC emulates the 82093AA and does not + * implement an EOI register. Some guests (e.g. Windows with the + * Hyper-V role enabled) disable LAPIC EOI broadcast without checking + * the I/O APIC version, which can cause level-triggered interrupts to + * never be EOI'd. + * + * To avoid this, KVM must not advertise Suppress EOI Broadcast support + * when using the default in-kernel I/O APIC. + * + * Historically, in split IRQCHIP mode, KVM always advertised Suppress + * EOI Broadcast support but did not actually suppress EOIs, resulting + * in quirky behavior. + */ + return !ioapic_in_kernel(kvm); +} + +bool kvm_lapic_respect_suppress_eoi_broadcast(struct kvm *kvm) +{ + /* + * Returns true if KVM should honor the guest's request to suppress EOI + * broadcasts, i.e. actually implement Suppress EOI Broadcast. + * + * Historically, in split IRQCHIP mode, KVM ignored the suppress EOI + * broadcast bit set by the guest and broadcasts EOIs to the userspace + * I/O APIC. For In-kernel I/O APIC, the support itself is not + * advertised, but if bit was set by the guest, it was respected. + */ + return ioapic_in_kernel(kvm); +} + __read_mostly DEFINE_STATIC_KEY_FALSE(kvm_has_noapic_vcpu); EXPORT_SYMBOL_FOR_KVM_INTERNAL(kvm_has_noapic_vcpu); =20 @@ -554,15 +587,9 @@ void kvm_apic_set_version(struct kvm_vcpu *vcpu) =20 v =3D APIC_VERSION | ((apic->nr_lvt_entries - 1) << 16); =20 - /* - * KVM emulates 82093AA datasheet (with in-kernel IOAPIC implementation) - * which doesn't have EOI register; Some buggy OSes (e.g. Windows with - * Hyper-V role) disable EOI broadcast in lapic not checking for IOAPIC - * version first and level-triggered interrupts never get EOIed in - * IOAPIC. - */ + if (guest_cpu_cap_has(vcpu, X86_FEATURE_X2APIC) && - !ioapic_in_kernel(vcpu->kvm)) + kvm_lapic_advertise_suppress_eoi_broadcast(vcpu->kvm)) v |=3D APIC_LVR_DIRECTED_EOI; kvm_lapic_set_reg(apic, APIC_LVR, v); } @@ -1517,6 +1544,16 @@ static void kvm_ioapic_send_eoi(struct kvm_lapic *ap= ic, int vector) =20 /* Request a KVM exit to inform the userspace IOAPIC. */ if (irqchip_split(apic->vcpu->kvm)) { + /* + * Don't exit to userspace if the guest has enabled Directed + * EOI, a.k.a. Suppress EOI Broadcasts, in which case the local + * APIC doesn't broadcast EOIs (the guest must EOI the target + * I/O APIC(s) directly). + */ + if ((kvm_lapic_get_reg(apic, APIC_SPIV) & APIC_SPIV_DIRECTED_EOI) && + kvm_lapic_respect_suppress_eoi_broadcast(apic->vcpu->kvm)) + return; + apic->vcpu->arch.pending_ioapic_eoi =3D vector; kvm_make_request(KVM_REQ_IOAPIC_EOI_EXIT, apic->vcpu); return; diff --git a/arch/x86/kvm/lapic.h b/arch/x86/kvm/lapic.h index 282b9b7da98c..fe2db0f1d190 100644 --- a/arch/x86/kvm/lapic.h +++ b/arch/x86/kvm/lapic.h @@ -231,6 +231,9 @@ static inline int kvm_lapic_latched_init(struct kvm_vcp= u *vcpu) =20 bool kvm_apic_pending_eoi(struct kvm_vcpu *vcpu, int vector); =20 +bool kvm_lapic_advertise_suppress_eoi_broadcast(struct kvm *kvm); +bool kvm_lapic_respect_suppress_eoi_broadcast(struct kvm *kvm); + void kvm_wait_lapic_expire(struct kvm_vcpu *vcpu); =20 void kvm_bitmap_or_dest_vcpus(struct kvm *kvm, struct kvm_lapic_irq *irq, --=20 2.39.3 From nobody Sun Feb 8 16:12:31 2026 Received: from mx0a-002c1b01.pphosted.com (mx0a-002c1b01.pphosted.com [148.163.151.68]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 6DCFA237180; Mon, 29 Dec 2025 11:18:51 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=148.163.151.68 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1767007133; cv=fail; b=t7RRLCMzZ1i3SQkuLoTvk/dt9CC7UiAlJuH6js6gDoEOovqDWD51uyO25mal+7Xmk+quwX/uoUcB68XSs7zrarPjW0r2qKFXZ3uKDwVcM/Y+cv+aYw3Hy/BiJsjH//cM22W3iCYiD5/7VdDaVKFusz8Eoj3zQXZOB964Gin8Kp8= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1767007133; c=relaxed/simple; bh=5S5fdNSj1Ag1F4fksqEm4GWMwd3obM5IrzXEeHtHbrc=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: Content-Type:MIME-Version; b=uGDy9DMUAeiHCcqCNG1PRlhKJuCW99vJiLfGwaGUyfc0J4l1wVr4cDs+/HB9v+KtIzV739FAZanDzx8SQY0Oj3Oxn7lQZ3WTVaK6JvsS8tQB2cI4DVmCdPFqp6iLn/FAszuwPCy0SCvDY+qBVk6rkNTLPgwEPAJWYE/vCEWVx1o= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=nutanix.com; spf=pass smtp.mailfrom=nutanix.com; dkim=pass (2048-bit key) header.d=nutanix.com header.i=@nutanix.com header.b=KIX+X084; dkim=pass (2048-bit key) header.d=nutanix.com header.i=@nutanix.com header.b=I3vblus2; arc=fail smtp.client-ip=148.163.151.68 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=nutanix.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=nutanix.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=nutanix.com header.i=@nutanix.com header.b="KIX+X084"; dkim=pass (2048-bit key) header.d=nutanix.com header.i=@nutanix.com header.b="I3vblus2" Received: from pps.filterd (m0127840.ppops.net [127.0.0.1]) by mx0a-002c1b01.pphosted.com (8.18.1.11/8.18.1.11) with ESMTP id 5BSMIcA01210614; Mon, 29 Dec 2025 03:17:51 -0800 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=Vilz5b85wH9tw+0GiYvZ5ZQ9xPnq2jHC9cqsDxd7a Jc=; b=KIX+X084lxfcM7Okw9WKDLlsDVXctoYHAG1F60kD/8fTCZvstmpsRJSuA IeUp3NeNuyr5Yc4jQdnX5/9a6EoGEXyH8T5rihdjnV9FnX+wOj65WqE9j7roY/Z3 k+rpkbR1DkQ3F9O3N1L0Om9sd9atGzWAegsxRcKv1qa4rWmd64FJ34YS8QzMbnYS lqdGck+eehg07+I0bsfLIyorA0ssXcn59xgmxjOofLbNVOtJU3n3BbUmG81XkIV/ So6fK77pGCW4Bit+uoS04MPO2iPdOtSuBRMZo9AvEgqlFEctnR2zChEsJ3dj4x/M 04308IHdhmgV3XFNC18SSMJmX+8Dg== Received: from sn4pr0501cu005.outbound.protection.outlook.com (mail-southcentralusazon11021096.outbound.protection.outlook.com [40.93.194.96]) by mx0a-002c1b01.pphosted.com (PPS) with ESMTPS id 4bacns2pwd-1 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384 bits=256 verify=NOT); Mon, 29 Dec 2025 03:17:50 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=fHqTBse/GxwcLpUL8uq/aTdBW8R04oqaR3ZVL3HNcLESpxf7bvrRrECYmqDkmno9OylwqFL3uLEP14C2aZzSfjZQK6dPwhS35iypJMBK5ch20XHSZDSntaOp4xyWwxO9E9yye4W/1XSOjQq4QaeduYDfuCqMmLppJEq6IS/RXLrNRImL1+Ppd+/epZRz13HWvDh+da1wR5rebrOxd/woi6kuJIdt//bqXPOSESrmKIQmcuNNTnO532SX2Zy8jfM1UE2aMookVy7SIp7G6DiVTjLSNA7TW10hsfBJe2vOElGoysH3jZeu3PFDQGdUcQBhS/GmEnNUQR2Cw3MDLw3hdQ== 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=Vilz5b85wH9tw+0GiYvZ5ZQ9xPnq2jHC9cqsDxd7aJc=; b=IVqJxoeqbHm5oZ5IM0UvZM198kmjPEpoMzd7nVuvPmddG7KczFWyLtHhhlycGzu8PSdX3sR6dD0Sk2Cp2bT1COWmg6kRn6FRlX5YkMlXh2eLShzOSp/KWxZQsH7kCi3ZanWwHAMoS8i3XXvyWpWkeJXdmyRUI+Bgm3Vda9B5eDPKHfVEZ6T/omp588hUzWxXHGXXhJLLPHP16ENUckr0ccq5bBCuzYhdJ5fbDr1WAhnpRjcFthdHw524BobNXRDygsGnoGlCZbEXFVdDMEL7c0p7JcG8qDDXEY6gQv+N3gaUCA/iG99ycfwMkJNrmKDx/iT7z1zc98tVMi8PaD3wsA== 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=Vilz5b85wH9tw+0GiYvZ5ZQ9xPnq2jHC9cqsDxd7aJc=; b=I3vblus2wUkvyPThb+SsyeLaf9hXdjJ1wbyEgLbLt4CqNhvmHLaFhkL6y9QvOVOWohslj9ku+mbxh0RswVEcMceQylk+WcIB75vhkIAwFpeSlN48MAdbhxOQiDlXt4X30aRD2L5jcrjnPilNVe5dG3nTQr5LXy3zoCLTogjtzpCi3uxPse8cN8dvq0PpoM3x/oOqTrHgVZf73bPDq2Lp0UyeFtn9yAtW1WA2Yc5tsw9WGX0xQTzIxGxxS1IvS1742/1VKpPqgVnnvdX+zuJ0GgpyXcMgmN0Epc0hRSN4nFVbJAnTuisB/eMvPIhVZWfeX0tQESCp6LBZBUqzoH1Gpg== Received: from PH0PR02MB7557.namprd02.prod.outlook.com (2603:10b6:510:54::17) by PH7PR02MB9965.namprd02.prod.outlook.com (2603:10b6:510:2f9::19) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.9456.14; Mon, 29 Dec 2025 11:17:49 +0000 Received: from PH0PR02MB7557.namprd02.prod.outlook.com ([fe80::4917:bc05:4373:6bef]) by PH0PR02MB7557.namprd02.prod.outlook.com ([fe80::4917:bc05:4373:6bef%5]) with mapi id 15.20.9456.013; Mon, 29 Dec 2025 11:17:49 +0000 From: Khushit Shah To: seanjc@google.com, pbonzini@redhat.com, kai.huang@intel.com, dwmw2@infradead.org Cc: mingo@redhat.com, x86@kernel.org, bp@alien8.de, hpa@zytor.com, linux-kernel@vger.kernel.org, kvm@vger.kernel.org, dave.hansen@linux.intel.com, tglx@linutronix.de, jon@nutanix.com, shaju.abraham@nutanix.com, David Woodhouse , Khushit Shah Subject: [PATCH v5 2/3] KVM: x86/ioapic: Implement support for I/O APIC version 0x20 with EOIR Date: Mon, 29 Dec 2025 11:17:07 +0000 Message-ID: <20251229111708.59402-3-khushit.shah@nutanix.com> X-Mailer: git-send-email 2.43.7 In-Reply-To: <20251229111708.59402-1-khushit.shah@nutanix.com> References: <20251229111708.59402-1-khushit.shah@nutanix.com> Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: PH5P220CA0011.NAMP220.PROD.OUTLOOK.COM (2603:10b6:510:34a::11) To PH0PR02MB7557.namprd02.prod.outlook.com (2603:10b6:510:54::17) Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: PH0PR02MB7557:EE_|PH7PR02MB9965:EE_ X-MS-Office365-Filtering-Correlation-Id: 264e9027-48ff-4450-ad4f-08de46cbe66d x-proofpoint-crosstenant: true X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|366016|376014|7416014|1800799024; X-Microsoft-Antispam-Message-Info: =?us-ascii?Q?7ZHaQIqUOsLv/Fc0wtZfVyLqLlUBDHXHyp/22tMFa1GMzNa85VrEm9fszuUr?= =?us-ascii?Q?ymjguQpK89JZGHNwFe54NwGb7fOrWmrRiNFeTDUks6rnVeyFvEtiNoobRa4e?= =?us-ascii?Q?Dl67Q5mLiO7yaXjWhYeikJDFJaPuPiYzRAciHGoCIsNZVzVB1islOy2/B4i1?= =?us-ascii?Q?vtm+XKX0/BYWdyrBr1Mmmzc4OSHh4AO+pTyIaRX1hu8R1EGG7eTcIrLxtMYa?= =?us-ascii?Q?wc3EWZ5SG+t/JbryXH8aVM9eEYm+FE7T0+4Xq69HmFbcWceKJ1uFgHe9iC4t?= =?us-ascii?Q?ZS0XFSlLJXG7E60nVuAGenQZanzb6Xuc+y+zM17z6u502VbkCPCogqWOXD+/?= =?us-ascii?Q?LmGzBqwevyYBbcFfEzODbZ5JfwzLILE3x2M4JYp2pmlIcMjfdUxVsRNKLOtk?= =?us-ascii?Q?6DbOd51AFq7ZT5zxtJ3X6krxlimTxEPqiviu7kvzeLRvDIqjKwChjmJ3nT1f?= =?us-ascii?Q?Tp6X5f75nE/ZSdmT2Qqycjp0I0cKxIDDSacPR45mQIu1G5aoVQDIZzbA7Wv9?= =?us-ascii?Q?YRaFLvic7cspgwJhYDfzIkNbIqwD7Yy+vCR8+lbs0MBmtnrUzmh3tu7ySeQY?= =?us-ascii?Q?7ZJKcldbhEpN7pmfVA3DLcfrKAv0Rj+3DWUrKObdGsD63dRlN4TM7SsAJfDk?= =?us-ascii?Q?NqUSngxe0msDF51K/qvRDa/W/z6HFI7367g0GDKi+iePMjfk41b2lHW4CHAm?= =?us-ascii?Q?vWtAQw4neq3Z0HYtRcOeRzcfXvXPZl+tfUfpfxakvyu/KjkikhxwkILiYKCo?= =?us-ascii?Q?eppTSYVKlM7K4gx9TYT5WbZbS56ramOi9/dEBobD/SRG0k7RI2u4J0LeQTT9?= =?us-ascii?Q?gVMb7dGr6cBwkK8Nd4jV0uy2djuOKAd9XZAqzmGCNf5AYbHioqYev2ZcQ6Hf?= =?us-ascii?Q?RexTFDTopdzO/3+QON1Zn7GUINfJcv8h+AQUxFkFg1iRUE6eraMBxpLMcHhu?= =?us-ascii?Q?xaH4TG11cnVQjdIZz625IKNQfVcOGUe7G0sb/coXqiDUpkRXbZ6NCLIN3fWf?= =?us-ascii?Q?KXo96kBLOh4ceb/UIYyap+UpO138knYQhZ/+oj9MKha395vfkhtZ8cwaGI2+?= =?us-ascii?Q?Y8FbUkMrmd9DLScrmGVAs+92ZpET37sdkRdSYYJRqRirXc1ZWCOl1IYcsUJ9?= =?us-ascii?Q?gO1/B8DG665xGFrmlQGvaT5UPvBmqDURAErTaPvcmry01HKSyqrV+sGhtP3K?= =?us-ascii?Q?LNdLiF8qS2bEV0gxAjk6GgdMQf1yTGVUy5Pbioc/kTAvuGrj7DW6aPvzCygv?= =?us-ascii?Q?XU12/SmuApUf+LqMWy39kdMCo7Vtb8aXFO0Q5CYEgInLMCvrDLgHVWJSzBSk?= =?us-ascii?Q?CWdEh6VfXnglVREqR/mOm7dGaXO27nwuqd4p9ok3Qnx98FgtJb9553jGl5P6?= =?us-ascii?Q?pvfBWXM+v6x66/NovDpHdJBoPK5mo4X3MOvgxvm56ObSN60ujRf87j1lwyfv?= =?us-ascii?Q?fkRVfqpz35c14xMu8e2JaM+NrRAHaThv?= X-Forefront-Antispam-Report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:PH0PR02MB7557.namprd02.prod.outlook.com;PTR:;CAT:NONE;SFS:(13230040)(366016)(376014)(7416014)(1800799024);DIR:OUT;SFP:1102; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?us-ascii?Q?EZBQecMKdiOp4uqtV8X9faoZL/rl70fhde/sPqv79b6JcbPa4KHbn9cXZi7D?= =?us-ascii?Q?+muLoohzrydF7lyj5FpQ67g3z+6jaKkQ7+3VTlEpgK+OUDm/EG+mYMBC86Me?= =?us-ascii?Q?SvXddMpOmduRd3Fr5PZ7cnBRTs9sUR6966Hk7bA9xTWZFxLU/da5PQYPYOkc?= =?us-ascii?Q?4vKItD6Zu/5zGOnzZizbjAgoKde/nH59IpzMLjH1yzANOiAsJlNGSlqh+HFd?= =?us-ascii?Q?rJ5AB3LidFN1rDQKYFYu+cAATnASdc1ySPyWivXaW747T1+6JwQjwmd+W66r?= =?us-ascii?Q?dm2K+PURPPWRTiY30HL24v+1V1OWkmQlXNkGWabx9v3+fB60VYipxaaNkaGw?= =?us-ascii?Q?Kj5KTCrak3lATwwNREj41h1uTnZ6oy5AvNksGUhDs7p7Tyz5ti9Xb28vE9vV?= =?us-ascii?Q?RWCy7TGznmhKhl3bgUqCrn64KEx1lPWho84iw4EH7tv2fXbn5rO6oXkYx3M7?= =?us-ascii?Q?4hVK+wR46muyyu7XH5pZq+F8YERkBigCQEP9UXCH03KoQMO04SaKkNNUH/G+?= =?us-ascii?Q?ttydBZHAxu/ItEHwj4+jRfNbjO0G0wwnQxtHktgGfG/YtCZzdRb+owzyY5jv?= =?us-ascii?Q?sGknMnJwvBGVPj5EUHcYk5ONca0kcUnbj4N2l83ReGqcK+jCehj3mrgQxiCA?= =?us-ascii?Q?qWR3sqzaoevLM5VrhW5I//ctIl2oypNwpmdWL8aUmrrgws8cqBJ4zCHHJvIa?= =?us-ascii?Q?LFY59ShvmWZnLtqq1qKW6jeq2Gs4/MYv2WzexeGvQ4qg8vfcnlTqD73BHLe3?= =?us-ascii?Q?ofD01jrcu6xB0KQ6ZH//HlDWGR4zgdB4mf6LGB2EgKOmd7MvfRhGZr8WTL0B?= =?us-ascii?Q?M1QNbfZFqCzZzD0W9E9EalMmGAcDMKYnq4f5CCHSFWs2cx7g4pXO5DsUQ7Z2?= =?us-ascii?Q?wegF1myfjkKo7DO0Nq1zx0m97kN8g1DIo00nHk3g+bJ3sgaPXXvOPp133Mmg?= =?us-ascii?Q?pt9J8huFY2pF+TWLcIj8zKw5LFLINDw/Xe57jOqGHvnhJHvQtyNZNNgxHAhE?= =?us-ascii?Q?ebV1iJh1crW/vKYMV5dwPIaTCm9ZC7F7QjFa0f8tL2z240ZaqTrIK3/QYaSa?= =?us-ascii?Q?bSKvpPMGgPSNf6pN85abaSeIXm9FmuDkeSreawsQTNPS+MjbHoqcZAo9xW5/?= =?us-ascii?Q?Ez7EFBxKl7SzjcGj/ob1H/iD/1HiSni39s3EOoAf5ZYQefBZUgv5BQAOzgWB?= =?us-ascii?Q?yFoBnf9NDc6ig/s3Xzd27fW7SyjEwGmNILZ6gsAOExRq/tcqckeSfnke373E?= =?us-ascii?Q?JnHX4ANdjWzGC3v2U0rsJAGILRXaRxMSau9AJHoYat+uSjqYL42ShP1dliyi?= =?us-ascii?Q?UwHFRNJEufqv1/XiEFt9e6mjgG+hT9H1nn/3MzH3AhMuR4mdhJQXSaZ+jUkd?= =?us-ascii?Q?7xjUTLbJgdQZBufmJYShhQ/xo5wscg3P7nz99tUC5TDy03qAmAOij+txdsL9?= =?us-ascii?Q?A4JvRIVOQpigwdnriatvVv3IsXfn/ip7ufBeuiyeyC+vNOgpA3MZnB36pipk?= =?us-ascii?Q?LirDjHZLvz4+dxC9+hoziWvqhsfcGtGsptaCYhES97BelctHMuLKC1qFsnj8?= =?us-ascii?Q?enTqCwy8VQ8hBqzgJGeTG/Rmw2oVaR77fAfJf52wNVs1tFC0culEYKcGCaLw?= =?us-ascii?Q?4+M36PMdzPG4g3IQ77ciZ7G/L9CnPGAm1Mn+l+HoSLUz4VRl5qJUa3BImdQh?= =?us-ascii?Q?VgTG2D8OND7rgpmLpaAgWfgyxCwHQ2v1643xTgNbRESFbxrfnNf6Wsc1kND+?= =?us-ascii?Q?DuuYEYgEKLi84M3M8eSaCuSGYYm/q9s=3D?= X-OriginatorOrg: nutanix.com X-MS-Exchange-CrossTenant-Network-Message-Id: 264e9027-48ff-4450-ad4f-08de46cbe66d X-MS-Exchange-CrossTenant-AuthSource: PH0PR02MB7557.namprd02.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 29 Dec 2025 11:17:49.2646 (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: 8/KbRBazdf4Mup2LfT9SP3k3j0RFc8TxdQXfDuVPHmkxuE21sQpZPUDMCzLD1hLAUC+6kpEg2bqA8bJfGetDfzfplJ8BucHT1pqaVVvuzhk= X-MS-Exchange-Transport-CrossTenantHeadersStamped: PH7PR02MB9965 X-Authority-Analysis: v=2.4 cv=MMptWcZl c=1 sm=1 tr=0 ts=6952635f cx=c_pps a=Y5OhYnybWnDos8loL9/x+g==:117 a=6eWqkTHjU83fiwn7nKZWdM+Sl24=:19 a=z/mQ4Ysz8XfWz/Q5cLBRGdckG28=:19 a=lCpzRmAYbLLaTzLvsPZ7Mbvzbb8=:19 a=xqWC_Br6kY4A:10 a=wP3pNCr1ah4A:10 a=0kUYKlekyDsA:10 a=VkNPw1HP01LnGYTKEx00:22 a=pBOR-ozoAAAA:8 a=64Cc0HZtAAAA:8 a=ZJXzLAxtXV6UqsjHDPUA:9 X-Proofpoint-GUID: Ht4ARm4LLHLCo0pvsDREii7O7uJfFak3 X-Proofpoint-ORIG-GUID: Ht4ARm4LLHLCo0pvsDREii7O7uJfFak3 X-Proofpoint-Spam-Details-Enc: AW1haW4tMjUxMjI5MDEwNSBTYWx0ZWRfX3WA84gj2Eg2D sDIs4bgDnTOCbqyOmj1uPr4W34J/KIDWUDHy6zWBEjYrUTO2Rr1B3DulOSMmSOD33Rh7gSe/bgh yiJbjuCirl1pnsC/I9GJFIVP8SPThA5U1L+OnmRtIQVdrgV6AwrX8Qcsxx+83OrtLCXNx9sfKfL XQTSUW1F2hpWMoqG3aXREdtbfQQMLHB5vPcR/T4HZVvb4TEskZdakcfbemfezaml5g6U8UKbSfJ QT+3Qjm9O+LsYgfuVobdSVekSV+HkzZ09eZetPx/lweS+u2HToglos92jXZaF2Kci3SxYIhjomD u05Z1nQwl59KaWxA7BYI22tIro3Z+aOtGzSDmaPb+uS5PDD1ZiwOqtpYwXCjwNLcCq8yqO64cVe GnjRADefwM4wr0sEtJWVE11nh3Ev9FJhCYQ5hMiNt3+IRUfbg6J2TGJyDzG1lWyd7wyJHELzH5U WJVJ11cMqwZLwddFlwA== X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1121,Hydra:6.1.9,FMLib:17.12.100.49 definitions=2025-12-29_03,2025-12-29_01,2025-10-01_01 X-Proofpoint-Spam-Reason: safe Content-Type: text/plain; charset="utf-8" From: David Woodhouse Introduce support for I/O APIC version 0x20, which includes the EOI Register (EOIR) for directed EOI. The EOI register allows guests to perform EOIs to individual I/O APICs instead of relying on broadcast EOIs from the local APIC. When Suppress EOI Broadcast (SEOIB) capability is advertised to the guest, guests that enable it will EOI individual I/O APICs by writing to their EOI register instead of relying on broadcast EOIs from the LAPIC. Hence, when SEOIB is advertised (so that guests can use it if they choose), use I/O APIC version 0x20 to provide the EOI register. This prepares for a userspace API that will allow explicit control of SEOIB support, providing a consistent interface for both in-kernel and split IRQCHIP mode. Add a tracepoint (kvm_ioapic_directed_eoi) to track directed EOIs for debugging and observability. Signed-off-by: David Woodhouse Signed-off-by: Khushit Shah --- arch/x86/kvm/ioapic.c | 31 +++++++++++++++++++++++++++++-- arch/x86/kvm/ioapic.h | 19 +++++++++++-------- arch/x86/kvm/trace.h | 17 +++++++++++++++++ 3 files changed, 57 insertions(+), 10 deletions(-) diff --git a/arch/x86/kvm/ioapic.c b/arch/x86/kvm/ioapic.c index 6bf8d110aece..eea1eb7845c4 100644 --- a/arch/x86/kvm/ioapic.c +++ b/arch/x86/kvm/ioapic.c @@ -48,8 +48,11 @@ static unsigned long ioapic_read_indirect(struct kvm_ioa= pic *ioapic) =20 switch (ioapic->ioregsel) { case IOAPIC_REG_VERSION: - result =3D ((((IOAPIC_NUM_PINS - 1) & 0xff) << 16) - | (IOAPIC_VERSION_ID & 0xff)); + if (kvm_lapic_advertise_suppress_eoi_broadcast(ioapic->kvm)) + result =3D IOAPIC_VERSION_ID_EOIR; + else + result =3D IOAPIC_VERSION_ID; + result |=3D ((IOAPIC_NUM_PINS - 1) & 0xff) << 16; break; =20 case IOAPIC_REG_APIC_ID: @@ -57,6 +60,10 @@ static unsigned long ioapic_read_indirect(struct kvm_ioa= pic *ioapic) result =3D ((ioapic->id & 0xf) << 24); break; =20 + case IOAPIC_REG_BOOT_CONFIG: + result =3D 0x01; /* Processor bus */ + break; + default: { u32 redir_index =3D (ioapic->ioregsel - 0x10) >> 1; @@ -701,6 +708,26 @@ static int ioapic_mmio_write(struct kvm_vcpu *vcpu, st= ruct kvm_io_device *this, ioapic_write_indirect(ioapic, data); break; =20 + case IOAPIC_REG_EOIR: + /* + * The EOI register is supported (and version 0x20 advertised) + * when userspace explicitly enables suppress EOI broadcast. + */ + if (kvm_lapic_advertise_suppress_eoi_broadcast(vcpu->kvm)) { + u8 vector =3D data & 0xff; + int i; + + trace_kvm_ioapic_directed_eoi(vcpu, vector); + rtc_irq_eoi(ioapic, vcpu, vector); + for (i =3D 0; i < IOAPIC_NUM_PINS; i++) { + union kvm_ioapic_redirect_entry *ent =3D &ioapic->redirtbl[i]; + + if (ent->fields.vector !=3D vector) + continue; + kvm_ioapic_update_eoi_one(vcpu, ioapic, ent->fields.trig_mode, i); + } + } + break; default: break; } diff --git a/arch/x86/kvm/ioapic.h b/arch/x86/kvm/ioapic.h index bf28dbc11ff6..f219577f738c 100644 --- a/arch/x86/kvm/ioapic.h +++ b/arch/x86/kvm/ioapic.h @@ -11,7 +11,8 @@ struct kvm_vcpu; =20 #define IOAPIC_NUM_PINS KVM_IOAPIC_NUM_PINS #define MAX_NR_RESERVED_IOAPIC_PINS KVM_MAX_IRQ_ROUTES -#define IOAPIC_VERSION_ID 0x11 /* IOAPIC version */ +#define IOAPIC_VERSION_ID 0x11 /* Default IOAPIC version */ +#define IOAPIC_VERSION_ID_EOIR 0x20 /* IOAPIC version with EOIR support */ #define IOAPIC_EDGE_TRIG 0 #define IOAPIC_LEVEL_TRIG 1 =20 @@ -19,13 +20,15 @@ struct kvm_vcpu; #define IOAPIC_MEM_LENGTH 0x100 =20 /* Direct registers. */ -#define IOAPIC_REG_SELECT 0x00 -#define IOAPIC_REG_WINDOW 0x10 - -/* Indirect registers. */ -#define IOAPIC_REG_APIC_ID 0x00 /* x86 IOAPIC only */ -#define IOAPIC_REG_VERSION 0x01 -#define IOAPIC_REG_ARB_ID 0x02 /* x86 IOAPIC only */ +#define IOAPIC_REG_SELECT 0x00 +#define IOAPIC_REG_WINDOW 0x10 +#define IOAPIC_REG_EOIR 0x40 /* version 0x20+ only */ + +/* INDIRECT registers. */ +#define IOAPIC_REG_APIC_ID 0x00 /* x86 IOAPIC only */ +#define IOAPIC_REG_VERSION 0x01 +#define IOAPIC_REG_ARB_ID 0x02 /* x86 IOAPIC only */ +#define IOAPIC_REG_BOOT_CONFIG 0x03 /* x86 IOAPIC only */ =20 /*ioapic delivery mode*/ #define IOAPIC_FIXED 0x0 diff --git a/arch/x86/kvm/trace.h b/arch/x86/kvm/trace.h index e79bc9cb7162..6902758353a9 100644 --- a/arch/x86/kvm/trace.h +++ b/arch/x86/kvm/trace.h @@ -315,6 +315,23 @@ TRACE_EVENT(kvm_ioapic_delayed_eoi_inj, (__entry->e & (1<<15)) ? "level" : "edge", (__entry->e & (1<<16)) ? "|masked" : "") ); + +TRACE_EVENT(kvm_ioapic_directed_eoi, + TP_PROTO(struct kvm_vcpu *vcpu, u8 vector), + TP_ARGS(vcpu, vector), + + TP_STRUCT__entry( + __field( __u32, apicid ) + __field( __u8, vector ) + ), + + TP_fast_assign( + __entry->apicid =3D vcpu->vcpu_id; + __entry->vector =3D vector; + ), + + TP_printk("apicid %x vector %u", __entry->apicid, __entry->vector) +); #endif =20 TRACE_EVENT(kvm_msi_set_irq, --=20 2.39.3 From nobody Sun Feb 8 16:12:31 2026 Received: from mx0a-002c1b01.pphosted.com (mx0a-002c1b01.pphosted.com [148.163.151.68]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 6DD6A2749CF; Mon, 29 Dec 2025 11:18:51 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=148.163.151.68 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1767007133; cv=fail; b=AaJ5D0ggZuC0+VA5IZik3yW0NOi52gc0bkP4W6fZkX4NCtZKvbAO54ueypLqNAw2/Tqj6dJ15+BLbD3ho2bsCr0ajxmbRt+S/et++p5F0t0AjOtdUyQ0mE9I9+7BMZdD8pI/26MFZVRcAsFUOkteLB+6zHdlYv/OCTvCxPuv5wA= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1767007133; c=relaxed/simple; bh=0ckZh+U2ZL8M9I3VjroGyIKzW3oWA9Q0cT5aBYbWyqY=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: Content-Type:MIME-Version; b=NmYKkOJWY7CrV4uw9qJfFhC1U4POvp2u6bccO0oWtU4FfE0Iv/xrT0LZeywRNtO6zBKMzpTkVRpGDyG4h+w40YZ8q51VVLoxOie9jJxXYkz1FSuVzOLOP0dpoChktiCow3FLEqsko9+7x5uEd+427c82RZGvW9KY/Vs7stlwtrs= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=nutanix.com; spf=pass smtp.mailfrom=nutanix.com; dkim=pass (2048-bit key) header.d=nutanix.com header.i=@nutanix.com header.b=TIiq9XJv; dkim=pass (2048-bit key) header.d=nutanix.com header.i=@nutanix.com header.b=FkT5gIbW; arc=fail smtp.client-ip=148.163.151.68 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=nutanix.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=nutanix.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=nutanix.com header.i=@nutanix.com header.b="TIiq9XJv"; dkim=pass (2048-bit key) header.d=nutanix.com header.i=@nutanix.com header.b="FkT5gIbW" 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 5BSJAfQX391541; Mon, 29 Dec 2025 03:17:52 -0800 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=0k8jVzDofFiCi3C8z7kcsl4kgBU8KbWUee//pe3Et jg=; b=TIiq9XJvlYsMbZ87uw24P6tez41icOc0+Mu0CoI7wLNZ3fn/ZD0iILNkB yOeLD0G2cKjooZLH6pOm4k8eWGiFrd20oGXYzXaj1k+yCOUT1tZdcrWBr7hOr3sS ba/ZO7qVF1c1TpokMvfrx0loqzAwsC07VFG/HcZG5U2xbWL8EznM3A7SDsRRyR1L 5xsBUJxBV2ulSXHTryou7ZxTFmxqtzYYeH6VnIydHCPz77PHBe89itci396vULpS A2Cr0IN6zX8gzHK1jef5xN6JPe1Y2/xCMe+bYjhjW1O7JtQauEB/KWWOwJXEM2Ii JM4W1FBgavTbPV5xtW+ToANnV1VSg== Received: from sn4pr0501cu005.outbound.protection.outlook.com (mail-southcentralusazon11021084.outbound.protection.outlook.com [40.93.194.84]) by mx0a-002c1b01.pphosted.com (PPS) with ESMTPS id 4bac87aqsy-1 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384 bits=256 verify=NOT); Mon, 29 Dec 2025 03:17:52 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=xhV4udKeizRDFD1ovi35Zr+zjZ/99l3mbFDTmFqFKMW0ZPgteLBZ3ylQLhHy5l3Tpley/7fAttbWrjykY2xLophQKMxz2HPONpET7N+fspYN2gW+oKi/fn+VM+l1JD8TQ7sqSaXUIbEnGqBa6ovHVXy5iKGyx6aMCQp92FC0K6qnWaWwa+HTvgSe7SH4BChfSJ7aTflATVcYZW9wm4KSKKqXDC8trtqc3ezxBmPNx1mnA2wVoE4T+6xOeFtclfLOzf0O4emxsxsEKk/EiHCC/+PedRqe0m6K/HVkOi/MLGrn5/6tF6H+stLKiF4QH8SFQblxbhRVIHPO7cX06w2RBw== 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=0k8jVzDofFiCi3C8z7kcsl4kgBU8KbWUee//pe3Etjg=; b=NsxwtGuL9VBHNgvdUw4Nc1mvMHWDEZXO45u5FRMrlXPeN1egKIxwvR8Bw3bQg6h8BcXpKePP1D6x2CXUlx7vIWkxUjGBuJSHCmtoPAFt66dKPz2tJdR6bxzzuugtSkTX7zmx45OEeCSB+mVMmyX+7bOZzQK/EQiDP0t7WTBeK3v8Flypit0QU8iL3hcTNeniSKBOVo2la3Yd+c5XmQSQndidnXO7rQXNEcfQNRQtrQGkKlWJHdURW8auOmvQJjjwgAEpK81rWitRpMz/3c6I9/uy3GaM8wr/HsIao7f8bpiGb35BkJhFpsG/65WyiKhTKUyWj8B9+KhPrk4cYQ45mw== 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=0k8jVzDofFiCi3C8z7kcsl4kgBU8KbWUee//pe3Etjg=; b=FkT5gIbWvjX3HHHBzU7y86C8hrMKOLP6yr3HIG5S0Rtf+wPbB5lJ00RwsrW8jIg43SeauECoHaamy+G1cpYdblDHDe0rxda0xnNNBh16d7RvWY8F7n94MDJDJP05JkhCnm/Olk8fjqh2Ov5GZ1JRBwjeQIDt6WdCkCNjofXew1pqYDigv9s+EaLrKsjvi7cbR56Gqx7euRRu4/UYbS0yAakSi39+uFnhvk4BleFsbzzIfUj6XOG7fBWhRaP7cSH9/yLI1koOpjGr1h1jkeY9gG0vi8wFXRL7Jhd7NAecOdwmRBAOZTU3y1okAeGMagF+tR2/IGoqeZ9OXQ+QCt7r8A== Received: from PH0PR02MB7557.namprd02.prod.outlook.com (2603:10b6:510:54::17) by PH7PR02MB9965.namprd02.prod.outlook.com (2603:10b6:510:2f9::19) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.9456.14; Mon, 29 Dec 2025 11:17:50 +0000 Received: from PH0PR02MB7557.namprd02.prod.outlook.com ([fe80::4917:bc05:4373:6bef]) by PH0PR02MB7557.namprd02.prod.outlook.com ([fe80::4917:bc05:4373:6bef%5]) with mapi id 15.20.9456.013; Mon, 29 Dec 2025 11:17:50 +0000 From: Khushit Shah To: seanjc@google.com, pbonzini@redhat.com, kai.huang@intel.com, dwmw2@infradead.org Cc: mingo@redhat.com, x86@kernel.org, bp@alien8.de, hpa@zytor.com, linux-kernel@vger.kernel.org, kvm@vger.kernel.org, dave.hansen@linux.intel.com, tglx@linutronix.de, jon@nutanix.com, shaju.abraham@nutanix.com, Khushit Shah , stable@vger.kernel.org Subject: [PATCH v5 3/3] KVM: x86: Add x2APIC "features" to control EOI broadcast suppression Date: Mon, 29 Dec 2025 11:17:08 +0000 Message-ID: <20251229111708.59402-4-khushit.shah@nutanix.com> X-Mailer: git-send-email 2.43.7 In-Reply-To: <20251229111708.59402-1-khushit.shah@nutanix.com> References: <20251229111708.59402-1-khushit.shah@nutanix.com> Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: PH5P220CA0011.NAMP220.PROD.OUTLOOK.COM (2603:10b6:510:34a::11) To PH0PR02MB7557.namprd02.prod.outlook.com (2603:10b6:510:54::17) Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: PH0PR02MB7557:EE_|PH7PR02MB9965:EE_ X-MS-Office365-Filtering-Correlation-Id: 2366ab6c-3731-4d82-123b-08de46cbe72c x-proofpoint-crosstenant: true X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|366016|376014|7416014|1800799024; X-Microsoft-Antispam-Message-Info: =?us-ascii?Q?OgvEkQI7vnNLHmANo0a6GjA8CgL4je+c4L+Tr9m/IcCji2eJqBK54z0gV9wu?= =?us-ascii?Q?D2OufXbPz/7bcmPgwlcbDpHtTJWTALwyq8Kbz+pl6jgECpbgjKKHW7PuLsXD?= =?us-ascii?Q?dNhtvKOJhsREYR9ZqDtHG3byeOKhlvjb5C99gO0qYg13GgfosJ8iay4d+Sph?= =?us-ascii?Q?oVERnCMXrRSlfogsfMy2fPhthRmjJ0phDbyZQkL+9vfRajFQRljUuPmcPEWE?= =?us-ascii?Q?+7kOLbIbSyYbRvBFfXlw4aP8TxF0aCPwDaH79Hw73OuRg8j2WQajNaWrwm/0?= =?us-ascii?Q?kX+pBN4hI0myiuYRRADfoAr6gOVADGWuk5AYZxB0P1vuy7dwhyk9nY8hFcgJ?= =?us-ascii?Q?trrWxQDihhz50hgioQ6f+47vJWEKlW/JRfF1D1yQI/ocY08b3WmZLzMCgmRV?= =?us-ascii?Q?AcPlJ3EehHxIxlPTPxvYZJHngTW7OZSrTiIJIjumyFQgIyYtH33W/bTSsW6Q?= =?us-ascii?Q?MfyxhHkWapHgq0FeDMZ0ziPlyTVu5qEHmwhowEkxbhMDjglvxQZDMAvHB0iD?= =?us-ascii?Q?TIqbt5ecAiDRkzYR6L+xcSB4eEJxIEqlOkFuQ6pofB9xQQMKmMpV6so3eO6l?= =?us-ascii?Q?rFneYmkronJiO7CfIDy0XuaXH5L71aR4tax3G83u3H4ExqZPd15ZY4/8GoiB?= =?us-ascii?Q?NmSq57YhBs3hDm17KRnCiw2dZ8lOHV5eVHb90p/AFaC4XNI5bqhMXCy9lPex?= =?us-ascii?Q?YTXbbUb/TEy1hDVlrApm247YuFhJRa7a7AmQtB4bfSgb8JlXnn/E5hHETgyh?= =?us-ascii?Q?B419EdQHHoWfrtSabiZju/810PF3Iff8R7q79essrPGdrQytxl+sHyd5kR5q?= =?us-ascii?Q?rRpcpaQf3DeUtByd5uZDE5YlAIsOOKCySsMrQdstYFuGzkCGIncVjVjhoiF/?= =?us-ascii?Q?qYrqSO1ViHZlzMsVqE7NhPJidU3nwgQR6KofISJB2PELrBiIM6yUZBUsXdr/?= =?us-ascii?Q?D/kL0pw3TzJzLJkFq5zkhOMdtVvHcco/hguXEVMvSZIeEg5plEz6p80eMdnG?= =?us-ascii?Q?a1ItjZMj4urRvmxwtzd0kCxi74E4MQtK9PHZgTyplpOdNNJNIfdmoyKGYqjw?= =?us-ascii?Q?DvDwjR5ZJQaHZLtvioGe2yedqPxGmiSo1YmVwRXKVYpBZVDZ3PJBuvsWa+9f?= =?us-ascii?Q?+elKHMlZZ+baoYeIBgj4oD5uhJLPa5shC2DaQo2DEd2I84ujV9AR3Pu2hsE1?= =?us-ascii?Q?ynhKMrh+GtpRGA15G3ZrC/g/zvfQj8rpseEng0iPx+M9oPDoVeTNaF8ZEjUx?= =?us-ascii?Q?/hNi1cIgm1Kb56KbttDiRWrPZk7CbRGqdnYPZMfe2DpMIuSyjLe3SEwerJmK?= =?us-ascii?Q?tZRwNQZrjxxUH6wLulfez21IqZ+tnmOoQVm36++2UWuJE4dogNoN+LP7gkmn?= =?us-ascii?Q?lAl0FBq9EXLEFMyD0zX8UUcQq1J3nsemY2pkH1lKzvFhFuM6RGjAKumL6gIy?= =?us-ascii?Q?GJpUmaxqu4xbsqLQ3OvTZ9qiwLxWSrclXt+fp4e7JP/2yui4aYSywQ=3D=3D?= X-Forefront-Antispam-Report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:PH0PR02MB7557.namprd02.prod.outlook.com;PTR:;CAT:NONE;SFS:(13230040)(366016)(376014)(7416014)(1800799024);DIR:OUT;SFP:1102; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?us-ascii?Q?SLxV7TJk8ALk+bb0YqwvKmr3n/mUx39tlvqKAVbCvhq3yIVu23ToAcddUT06?= =?us-ascii?Q?iEwgGf2an/DF6VG+Xm19TVUDtJEfqF+v3IEuHe6d5SX7Sj2jmtIE0PFYlmzx?= =?us-ascii?Q?Xh1vS8dWsu37KUnEfyt9l3i9UuyapufEDZGB+XWS0ORwo1hGRrx8knVcwJdl?= =?us-ascii?Q?sv3LUdRw2BMjD+m7S/NdJUV4BTmkbP2L8pnKxtpD34FrU7qazHARNgry7dn4?= =?us-ascii?Q?ToAKDO/In3x498Jh+tdyHF3+YHmNy//xDzcFTNmbpHn7wh5cm1vxa9pIRBO9?= =?us-ascii?Q?9yqGRwG0077z4JGgbsuN8psHDVOuxU7qXEaztfJM9KXdG7WZpt9h2qweLz+F?= =?us-ascii?Q?L164n69ZNZFEvFZnYcu9xE2zNlr2tJMd7E06AF5HJYF1NW8PFJBt/dLtiYlD?= =?us-ascii?Q?fh8i2T8isOBkWzLXJ8bbqHs8VfOADbfAJlJAG4QdlEfYbVF34B1rzFLJQL3T?= =?us-ascii?Q?6vxqKPXphaRXd3ja2YQIMJqVpXFwvBgULXUFE5/61cceblVL4EZ6h/UxKLfx?= =?us-ascii?Q?EqM5CU0noWqkC9qGWwGZQomVjCUMRqmDxq8OgwB0eTUQX+Aiz2GmOLUkELxy?= =?us-ascii?Q?0MuC0Ox7CDw5gKKy+hrYqFjN5TA9ZUfp76rcIHMOyTZyqG9yyOrbIY8BDGYG?= =?us-ascii?Q?0HIq1byFt3FxP0i68+yKh05RciK5BiQCkpLaF728Z1Yg4B9cv4/wGE80cV8d?= =?us-ascii?Q?L4h5dOrFFSSg71xz+X9GD7aE9LUoxtD3qk3fEU52oFb5HhZ/wK4HhSk6hrob?= =?us-ascii?Q?MFZ1jXvsIFeCzsoDrR2gdCVy/iPVOdxQ3P/Jk2NLghkb7i+fXw4v2MqjGFEq?= =?us-ascii?Q?0Le3PHujkGCaUvX6w4pNHD5mgR9mg2XzyKIPDKDt8EvPIHQgQxaQNpa5akDC?= =?us-ascii?Q?d1b5VrslN9Jl8pPccQzltU5BAsoInvzmtl1T5dLBQcRuiVo/GI7Fn2hKDeZt?= =?us-ascii?Q?pvmeKLZww+hvEabH72WP3Jlc2zKsX6n5nNaYW0FIM0W1dNl9oBvimI+rpuqR?= =?us-ascii?Q?WVytzVxQBQ6341RNUPPXF8VsAcDgtmlXmh70+E4e4iJm7KcbB2A4N0VOCmce?= =?us-ascii?Q?oAVIYr8rZFnPPwgTtssefMRCEqsw646otL1hRPY+18mxfX/zuZugHZ3j6kRq?= =?us-ascii?Q?9rvUiN+M5rtKzRewUQ/O2GSak0J+a02dRmIw+/ZrXmjYj5lQFUqAdW1cgSwv?= =?us-ascii?Q?7EmywI5MfZgKrdtz7LBJS5/h1GfM06M+wjSYLjIdZo7KcmMda4axbGc0/8ff?= =?us-ascii?Q?RHwdavu8REE3vncYT5u/vwEs6KBrTJWUWIN2Voo7dwr9pBCK8RDrnn42fABG?= =?us-ascii?Q?VRhdHP5jvWeT3mUZbDnHree4UN31rlU6mqtd6FA76N7M/z09JAyof51q+z4E?= =?us-ascii?Q?IzdDUBfy/FaBb9V1t3TEsuyapugfRupn2J4Es3n9kFPIU1YwX+O7heTZ3kVc?= =?us-ascii?Q?Cuc/6ZwHE3SDE3UQmfr/9tnouEnwoYVhmWL44LFqbNU7dre4QinLArhSCeWX?= =?us-ascii?Q?ibguN/v+C3MJW3P52WToUgvkCmGoTulctUstGdqnekZjaaFvfiVCMv28cOTx?= =?us-ascii?Q?NBUXZot3lSyjrd5SPfepRpr5i4spKwxDoJfLgiONKyN9Ipuzudym57kDKq1Q?= =?us-ascii?Q?hGTTzE7It13u1CesGB0/mHWHod+IKU4feIZpqkwmEJTDT8+ydTe/+4Q/+PN7?= =?us-ascii?Q?V5tiS1vbunS52mn4Tq7KEzkplwdUEDCp15aW/51X+kTCmeN3dcn4xmV3V6AV?= =?us-ascii?Q?UQhLaAZxlTUzJvhplgK6ynT3nxbG+w0=3D?= X-OriginatorOrg: nutanix.com X-MS-Exchange-CrossTenant-Network-Message-Id: 2366ab6c-3731-4d82-123b-08de46cbe72c X-MS-Exchange-CrossTenant-AuthSource: PH0PR02MB7557.namprd02.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 29 Dec 2025 11:17:50.5026 (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: +ys8BoknMnGIOZE3cMzm/uj4qlSwEd57ntJyKAWyPnMsVi/blc7VKSLzG0dWavYIbwZkiKCx+enjvh2aRyLHDgxBsBULyjmzyMgkqo4smys= X-MS-Exchange-Transport-CrossTenantHeadersStamped: PH7PR02MB9965 X-Proofpoint-Spam-Details-Enc: AW1haW4tMjUxMjI5MDEwNSBTYWx0ZWRfXwflnDv2vzq3x +5lU0rrRW8LGsYPqdHIC+doqclJvM+zueJ+11a8fRSHXLsxDdLPQb6Vtc4xBzOb3lpburtMm6+h pI1d8iGFq6cIE5lP5rt3/vGXoV6NNyF0gzjD11jML7ja5fZhtUdUZwDSngWc/Jy4VfS43n7ZQpl KmwXrSsYQsBijK9O79dKWDmCBwuds242wxDfcq+JuLlCbZCZ0GK7Xen6pihvrreAOfbra9btD8i nJTYIXiLIogSVJyB1TNuo/lTIX4hL6/+AO9t1DZRZdxuixSzRvqOtl8VjoN8oTMw8AZqim5dUtB rNu+gDjeqH+6vxe+jruBdF9du9p4sICiht0DnmmWYIkJ9CRHfK74bs/kU715ev5tE8NDdeNVUjR i1iZnAilf+fZSEpCoeEMbzjnVm3zJtGQPMlJQFBMbn/TxzmcW0ugM3W1eIGesDnFdr4VrjdI65b XkcQGti9f3c0UO4x4yw== X-Proofpoint-ORIG-GUID: BieFc68Y4BgF0dM2mXSpexq2AqOFA_Il X-Proofpoint-GUID: BieFc68Y4BgF0dM2mXSpexq2AqOFA_Il X-Authority-Analysis: v=2.4 cv=L+YQguT8 c=1 sm=1 tr=0 ts=69526360 cx=c_pps a=FdfMFdOEn1VR10XCui1xPA==:117 a=6eWqkTHjU83fiwn7nKZWdM+Sl24=:19 a=z/mQ4Ysz8XfWz/Q5cLBRGdckG28=:19 a=lCpzRmAYbLLaTzLvsPZ7Mbvzbb8=:19 a=xqWC_Br6kY4A:10 a=wP3pNCr1ah4A:10 a=0kUYKlekyDsA:10 a=VkNPw1HP01LnGYTKEx00:22 a=VwQbUJbxAAAA:8 a=64Cc0HZtAAAA:8 a=JfrnYn6hAAAA:8 a=1XWaLZrsAAAA:8 a=3v8KogwRkgpbH0kN_DoA:9 a=1CNFftbPRP8L7MoqJWF3:22 X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1121,Hydra:6.1.9,FMLib:17.12.100.49 definitions=2025-12-29_03,2025-12-29_01,2025-10-01_01 X-Proofpoint-Spam-Reason: safe Content-Type: text/plain; charset="utf-8" Add two flags for KVM_CAP_X2APIC_API to allow userspace to control support for Suppress EOI Broadcasts, which KVM completely mishandles. When x2APIC support was first added, KVM incorrectly advertised and "enabled" Suppress EOI Broadcast, without fully supporting the I/O APIC side of the equation, i.e. without adding directed EOI to KVM's in-kernel I/O APIC. That flaw was carried over to split IRQCHIP support, i.e. KVM advertised support for Suppress EOI Broadcasts irrespective of whether or not the userspace I/O APIC implementation supported directed EOIs. Even worse, KVM didn't actually suppress EOI broadcasts, i.e. userspace VMMs without support for directed EOI came to rely on the "spurious" broadcasts. KVM "fixed" the in-kernel I/O APIC implementation by completely disabling support for Suppress EOI Broadcasts in commit 0bcc3fb95b97 ("KVM: lapic: stop advertising DIRECTED_EOI when in-kernel IOAPIC is in use"), but didn't do anything to remedy userspace I/O APIC implementations. KVM's bogus handling of Suppress EOI Broadcast is problematic when the guest relies on interrupts being masked in the I/O APIC until well after the initial local APIC EOI. E.g. Windows with Credential Guard enabled handles interrupts in the following order: 1. Interrupt for L2 arrives. 2. L1 APIC EOIs the interrupt. 3. L1 resumes L2 and injects the interrupt. 4. L2 EOIs after servicing. 5. L1 performs the I/O APIC EOI. Because KVM EOIs the I/O APIC at step #2, the guest can get an interrupt storm, e.g. if the IRQ line is still asserted and userspace reacts to the EOI by re-injecting the IRQ, because the guest doesn't de-assert the line until step #4, and doesn't expect the interrupt to be re-enabled until step #5. Unfortunately, simply "fixing" the bug isn't an option, as KVM has no way of knowing if the userspace I/O APIC supports directed EOIs, i.e. suppressing EOI broadcasts would result in interrupts being stuck masked in the userspace I/O APIC due to step #5 being ignored by userspace. And fully disabling support for Suppress EOI Broadcast is also undesirable, as picking up the fix would require a guest reboot, *and* more importantly would change the virtual CPU model exposed to the guest without any buy-in from userspace. Add KVM_X2APIC_ENABLE_SUPPRESS_EOI_BROADCAST and KVM_X2APIC_DISABLE_SUPPRESS_EOI_BROADCAST flags to allow userspace to explicitly enable or disable support for Suppress EOI Broadcasts. This gives userspace control over the virtual CPU model exposed to the guest, as KVM should never have enabled support for Suppress EOI Broadcast without userspace opt-in. Not setting either flag will result in legacy quirky behavior for backward compatibility. When KVM_X2APIC_ENABLE_SUPPRESS_EOI_BROADCAST is set and using in-kernel IRQCHIP mode, KVM will use I/O APIC version 0x20, which includes support for the EOI Register. Note, Suppress EOI Broadcasts is defined only in Intel's SDM, not in AMD's APM. But the bit is writable on some AMD CPUs, e.g. Turin, and KVM's ABI is to support Directed EOI (KVM's name) irrespective of guest CPU vendor. Fixes: 7543a635aa09 ("KVM: x86: Add KVM exit for IOAPIC EOIs") Closes: https://lore.kernel.org/kvm/7D497EF1-607D-4D37-98E7-DAF95F099342@nu= tanix.com Cc: stable@vger.kernel.org Suggested-by: David Woodhouse Co-developed-by: Sean Christopherson Signed-off-by: Sean Christopherson Signed-off-by: Khushit Shah Reviewed-by: David Woodhouse --- Documentation/virt/kvm/api.rst | 28 +++++++++++++-- arch/x86/include/asm/kvm_host.h | 7 ++++ arch/x86/include/uapi/asm/kvm.h | 6 ++-- arch/x86/kvm/lapic.c | 64 ++++++++++++++++++++++----------- arch/x86/kvm/x86.c | 15 ++++++-- 5 files changed, 93 insertions(+), 27 deletions(-) diff --git a/Documentation/virt/kvm/api.rst b/Documentation/virt/kvm/api.rst index 57061fa29e6a..ad15ca519afc 100644 --- a/Documentation/virt/kvm/api.rst +++ b/Documentation/virt/kvm/api.rst @@ -7800,8 +7800,10 @@ Will return -EBUSY if a VCPU has already been create= d. =20 Valid feature flags in args[0] are:: =20 - #define KVM_X2APIC_API_USE_32BIT_IDS (1ULL << 0) - #define KVM_X2APIC_API_DISABLE_BROADCAST_QUIRK (1ULL << 1) + #define KVM_X2APIC_API_USE_32BIT_IDS (1ULL << 0) + #define KVM_X2APIC_API_DISABLE_BROADCAST_QUIRK (1ULL << 1) + #define KVM_X2APIC_ENABLE_SUPPRESS_EOI_BROADCAST (1ULL << 2) + #define KVM_X2APIC_DISABLE_SUPPRESS_EOI_BROADCAST (1ULL << 3) =20 Enabling KVM_X2APIC_API_USE_32BIT_IDS changes the behavior of KVM_SET_GSI_ROUTING, KVM_SIGNAL_MSI, KVM_SET_LAPIC, and KVM_GET_LAPIC, @@ -7814,6 +7816,28 @@ as a broadcast even in x2APIC mode in order to suppo= rt physical x2APIC without interrupt remapping. This is undesirable in logical mode, where 0xff represents CPUs 0-7 in cluster 0. =20 +Setting KVM_X2APIC_ENABLE_SUPPRESS_EOI_BROADCAST instructs KVM to enable +Suppress EOI Broadcasts. KVM will advertise support for Suppress EOI +Broadcast to the guest and suppress LAPIC EOI broadcasts when the guest +sets the Suppress EOI Broadcast bit in the SPIV register. When using +in-kernel IRQCHIP mode, enabling this capability will cause KVM to use +I/O APIC version 0x20, which includes support for the EOI Register for +directed EOI. + +Setting KVM_X2APIC_DISABLE_SUPPRESS_EOI_BROADCAST disables support for +Suppress EOI Broadcasts entirely, i.e. instructs KVM to NOT advertise +support to the guest. + +Modern VMMs should either enable KVM_X2APIC_ENABLE_SUPPRESS_EOI_BROADCAST +or KVM_X2APIC_DISABLE_SUPPRESS_EOI_BROADCAST. If not, legacy quirky +behavior will be used by KVM: in split IRQCHIP mode, KVM will advertise +support for Suppress EOI Broadcasts but not actually suppress EOI +broadcasts; for in-kernel IRQCHIP mode, KVM will not advertise support for +Suppress EOI Broadcasts. + +Setting both KVM_X2APIC_ENABLE_SUPPRESS_EOI_BROADCAST and +KVM_X2APIC_DISABLE_SUPPRESS_EOI_BROADCAST will fail with an EINVAL error. + 7.8 KVM_CAP_S390_USER_INSTR0 ---------------------------- =20 diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_hos= t.h index 48598d017d6f..4a6d94dc7a2a 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h @@ -1229,6 +1229,12 @@ enum kvm_irqchip_mode { KVM_IRQCHIP_SPLIT, /* created with KVM_CAP_SPLIT_IRQCHIP */ }; =20 +enum kvm_suppress_eoi_broadcast_mode { + KVM_SUPPRESS_EOI_BROADCAST_QUIRKED, /* Legacy behavior */ + KVM_SUPPRESS_EOI_BROADCAST_ENABLED, /* Enable Suppress EOI broadcast */ + KVM_SUPPRESS_EOI_BROADCAST_DISABLED /* Disable Suppress EOI broadcast */ +}; + struct kvm_x86_msr_filter { u8 count; bool default_allow:1; @@ -1480,6 +1486,7 @@ struct kvm_arch { =20 bool x2apic_format; bool x2apic_broadcast_quirk_disabled; + enum kvm_suppress_eoi_broadcast_mode suppress_eoi_broadcast_mode; =20 bool has_mapped_host_mmio; bool guest_can_read_msr_platform_info; diff --git a/arch/x86/include/uapi/asm/kvm.h b/arch/x86/include/uapi/asm/kv= m.h index d420c9c066d4..d30241429fa8 100644 --- a/arch/x86/include/uapi/asm/kvm.h +++ b/arch/x86/include/uapi/asm/kvm.h @@ -913,8 +913,10 @@ struct kvm_sev_snp_launch_finish { __u64 pad1[4]; }; =20 -#define KVM_X2APIC_API_USE_32BIT_IDS (1ULL << 0) -#define KVM_X2APIC_API_DISABLE_BROADCAST_QUIRK (1ULL << 1) +#define KVM_X2APIC_API_USE_32BIT_IDS (_BITULL(0)) +#define KVM_X2APIC_API_DISABLE_BROADCAST_QUIRK (_BITULL(1)) +#define KVM_X2APIC_ENABLE_SUPPRESS_EOI_BROADCAST (_BITULL(2)) +#define KVM_X2APIC_DISABLE_SUPPRESS_EOI_BROADCAST (_BITULL(3)) =20 struct kvm_hyperv_eventfd { __u32 conn_id; diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c index 2c24fd8d815f..36a5af218802 100644 --- a/arch/x86/kvm/lapic.c +++ b/arch/x86/kvm/lapic.c @@ -107,21 +107,31 @@ bool kvm_apic_pending_eoi(struct kvm_vcpu *vcpu, int = vector) =20 bool kvm_lapic_advertise_suppress_eoi_broadcast(struct kvm *kvm) { - /* - * The default in-kernel I/O APIC emulates the 82093AA and does not - * implement an EOI register. Some guests (e.g. Windows with the - * Hyper-V role enabled) disable LAPIC EOI broadcast without checking - * the I/O APIC version, which can cause level-triggered interrupts to - * never be EOI'd. - * - * To avoid this, KVM must not advertise Suppress EOI Broadcast support - * when using the default in-kernel I/O APIC. - * - * Historically, in split IRQCHIP mode, KVM always advertised Suppress - * EOI Broadcast support but did not actually suppress EOIs, resulting - * in quirky behavior. - */ - return !ioapic_in_kernel(kvm); + switch (kvm->arch.suppress_eoi_broadcast_mode) { + case KVM_SUPPRESS_EOI_BROADCAST_ENABLED: + return true; + case KVM_SUPPRESS_EOI_BROADCAST_DISABLED: + return false; + case KVM_SUPPRESS_EOI_BROADCAST_QUIRKED: + /* + * The default in-kernel I/O APIC emulates the 82093AA and does not + * implement an EOI register. Some guests (e.g. Windows with the + * Hyper-V role enabled) disable LAPIC EOI broadcast without + * checking the I/O APIC version, which can cause level-triggered + * interrupts to never be EOI'd. + * + * To avoid this, KVM must not advertise Suppress EOI Broadcast + * support when using the default in-kernel I/O APIC. + * + * Historically, in split IRQCHIP mode, KVM always advertised + * Suppress EOI Broadcast support but did not actually suppress + * EOIs, resulting in quirky behavior. + */ + return !ioapic_in_kernel(kvm); + default: + WARN_ON_ONCE(1); + return false; + } } =20 bool kvm_lapic_respect_suppress_eoi_broadcast(struct kvm *kvm) @@ -129,13 +139,25 @@ bool kvm_lapic_respect_suppress_eoi_broadcast(struct = kvm *kvm) /* * Returns true if KVM should honor the guest's request to suppress EOI * broadcasts, i.e. actually implement Suppress EOI Broadcast. - * - * Historically, in split IRQCHIP mode, KVM ignored the suppress EOI - * broadcast bit set by the guest and broadcasts EOIs to the userspace - * I/O APIC. For In-kernel I/O APIC, the support itself is not - * advertised, but if bit was set by the guest, it was respected. */ - return ioapic_in_kernel(kvm); + switch (kvm->arch.suppress_eoi_broadcast_mode) { + case KVM_SUPPRESS_EOI_BROADCAST_ENABLED: + return true; + case KVM_SUPPRESS_EOI_BROADCAST_DISABLED: + return false; + case KVM_SUPPRESS_EOI_BROADCAST_QUIRKED: + /* + * Historically, in split IRQCHIP mode, KVM ignored the suppress + * EOI broadcast bit set by the guest and broadcasts EOIs to the + * userspace I/O APIC. For In-kernel I/O APIC, the support itself + * is not advertised, but if bit was set by the guest, it was + * respected. + */ + return ioapic_in_kernel(kvm); + default: + WARN_ON_ONCE(1); + return false; + } } =20 __read_mostly DEFINE_STATIC_KEY_FALSE(kvm_has_noapic_vcpu); diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index c9c2aa6f4705..5d56b0384dcc 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -121,8 +121,10 @@ static u64 __read_mostly efer_reserved_bits =3D ~((u64= )EFER_SCE); =20 #define KVM_CAP_PMU_VALID_MASK KVM_PMU_CAP_DISABLE =20 -#define KVM_X2APIC_API_VALID_FLAGS (KVM_X2APIC_API_USE_32BIT_IDS | \ - KVM_X2APIC_API_DISABLE_BROADCAST_QUIRK) +#define KVM_X2APIC_API_VALID_FLAGS (KVM_X2APIC_API_USE_32BIT_IDS | \ + KVM_X2APIC_API_DISABLE_BROADCAST_QUIRK | \ + KVM_X2APIC_ENABLE_SUPPRESS_EOI_BROADCAST | \ + KVM_X2APIC_DISABLE_SUPPRESS_EOI_BROADCAST) =20 static void update_cr8_intercept(struct kvm_vcpu *vcpu); static void process_nmi(struct kvm_vcpu *vcpu); @@ -6778,11 +6780,20 @@ int kvm_vm_ioctl_enable_cap(struct kvm *kvm, if (cap->args[0] & ~KVM_X2APIC_API_VALID_FLAGS) break; =20 + if ((cap->args[0] & KVM_X2APIC_ENABLE_SUPPRESS_EOI_BROADCAST) && + (cap->args[0] & KVM_X2APIC_DISABLE_SUPPRESS_EOI_BROADCAST)) + break; + if (cap->args[0] & KVM_X2APIC_API_USE_32BIT_IDS) kvm->arch.x2apic_format =3D true; if (cap->args[0] & KVM_X2APIC_API_DISABLE_BROADCAST_QUIRK) kvm->arch.x2apic_broadcast_quirk_disabled =3D true; =20 + if (cap->args[0] & KVM_X2APIC_ENABLE_SUPPRESS_EOI_BROADCAST) + kvm->arch.suppress_eoi_broadcast_mode =3D KVM_SUPPRESS_EOI_BROADCAST_EN= ABLED; + if (cap->args[0] & KVM_X2APIC_DISABLE_SUPPRESS_EOI_BROADCAST) + kvm->arch.suppress_eoi_broadcast_mode =3D KVM_SUPPRESS_EOI_BROADCAST_DI= SABLED; + r =3D 0; break; case KVM_CAP_X86_DISABLE_EXITS: --=20 2.39.3 From nobody Sun Feb 8 16:12:31 2026 Received: from desiato.infradead.org (desiato.infradead.org [90.155.92.199]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 24DDB1E5B63; Thu, 29 Jan 2026 04:49:41 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=90.155.92.199 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769662187; cv=none; b=n7wBrqsUNRLujWo+92cut4NlYAUd9KQCSoZl1BudjGwRqKwUlNKIXVuRs0QhUUkPTtCdUVHC0CldU2698fWT2ENFadpjzg6teuwc44JyOUyqxrRRVp0E2fjQvcECPrQrOo0h6ShDKC2KOOz4cJI1oRd0LDKSH9akWXAEXjfQahU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769662187; c=relaxed/simple; bh=xb1fwZd4ilqnTaBLLYUh8xH+V26qKIuPacDrWqOvWYY=; h=Message-ID:Subject:From:To:Cc:Date:In-Reply-To:References: Content-Type:MIME-Version; b=R36zkveOG300qfoPp/h5m0niTBXnHKLwmkpag7mWo9a8eQgLl8KXap4V2Hef+9Q3UoAYG64xOBSyNK9nvw1Kml3RW7ZxE3CvzBwmbT9K8zKD131nOsBlsJ2ikkbaova6HucflkTXsKc6FecTi5bxFk9pW197evwZxTOWw5F4ko0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=infradead.org; spf=none smtp.mailfrom=desiato.srs.infradead.org; dkim=pass (2048-bit key) header.d=infradead.org header.i=@infradead.org header.b=V69I6N/7; arc=none smtp.client-ip=90.155.92.199 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=infradead.org Authentication-Results: smtp.subspace.kernel.org; spf=none smtp.mailfrom=desiato.srs.infradead.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=infradead.org header.i=@infradead.org header.b="V69I6N/7" DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=desiato.20200630; h=MIME-Version:Content-Type:References: In-Reply-To:Date:Cc:To:From:Subject:Message-ID:Sender:Reply-To: Content-Transfer-Encoding:Content-ID:Content-Description; bh=yNr+14WAIKKE+qWrCubJeb4YGk57O/SiGwlTnAYtt50=; b=V69I6N/7y8SVqnglIXEqaSpbpk va4UYG1D6Bzn43JC7WXYga9mqPyGfv8OMy/eYrdZaxPt0jix/Ew0soUA4xYqdmb5MhbgmnvL/9jKB RcuBbH/3MzmzKIfP1KEnUKLvcQcgYJt/NCIMULIZqWbiEoKYbuu9Jwl3zvl+KI4ux6ohzZGB+Zhep r20H4BB4dvmFeTNaAi0bxAzVr7+jyyVX/gUOwQsyYkYp1O3zQB5C9iTGCPv7ZqvChmvm/Koqps2Nf mr3p7yZzgRk9+b61hvM6aSEL/E455IOQkugfmc2dZObh3n0PVtltW9H06wZhtlEQimBCYfqn0lTyh IASOSbeA==; Received: from [2001:8b0:10b::4] (helo=u09cd745991455d.ant.amazon.com) by desiato.infradead.org with esmtpsa (Exim 4.98.2 #2 (Red Hat Linux)) id 1vlJy3-00000009nr6-0eI2; Thu, 29 Jan 2026 04:49:27 +0000 Message-ID: <83f9b0a5dd0bc1de9d1e61954f6dd5211df45163.camel@infradead.org> Subject: [PATCH v5 4/3] KVM: selftests: Add test cases for EOI suppression modes From: David Woodhouse To: Khushit Shah , seanjc@google.com, pbonzini@redhat.com, kai.huang@intel.com Cc: mingo@redhat.com, x86@kernel.org, bp@alien8.de, hpa@zytor.com, linux-kernel@vger.kernel.org, kvm@vger.kernel.org, dave.hansen@linux.intel.com, tglx@linutronix.de, jon@nutanix.com, shaju.abraham@nutanix.com Date: Wed, 28 Jan 2026 20:49:12 -0800 In-Reply-To: <20251229111708.59402-1-khushit.shah@nutanix.com> References: <20251229111708.59402-1-khushit.shah@nutanix.com> Content-Type: multipart/signed; micalg="sha-256"; protocol="application/pkcs7-signature"; boundary="=-XM1aDuSYUJFjYLXU6f31" User-Agent: Evolution 3.52.3-0ubuntu1.1 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-SRS-Rewrite: SMTP reverse-path rewritten from by desiato.infradead.org. See http://www.infradead.org/rpr.html --=-XM1aDuSYUJFjYLXU6f31 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" From: David Woodhouse Rather than being frightened of doing the right thing for the in-kernel I/O APIC because "there might be bugs", let's add selftests for it to make sure it behaves correctly. For both in-kernel I/O APIC and userspace, exercise the following modes: =E2=80=A2 Legacy "quirk" behaviour (this test shows the same results on bo= th old kernels and on kernels with this patch series in default mode). =E2=80=A2 KVM_X2APIC_ENABLE_SUPPRESS_EOI_BROADCAST mode, both with the gue= st enabling APIC_SPIV_DIRECTED_EOI and without. =E2=80=A2 KVM_X2APIC_DISABLE_SUPPRESS_EOI_BROADCAST mode. Testing quirk mode (no flags)... IOAPIC v0x11, LVR directed_eoi=3D0, SPIV directed_eoi=3D0, remote_irr=3D0 Testing explicit enable... IOAPIC v0x20, LVR directed_eoi=3D1, SPIV directed_eoi=3D1, remote_irr=3D1 Testing explicit enable (guest doesn't use)... IOAPIC v0x20, LVR directed_eoi=3D1, SPIV directed_eoi=3D0, remote_irr=3D0 Testing explicit disable... IOAPIC v0x11, LVR directed_eoi=3D0, SPIV directed_eoi=3D0, remote_irr=3D0 All tests passed =3D=3D=3D Testing split IRQCHIP mode =3D=3D=3D Testing quirk mode (no flags)... Split IRQCHIP: LVR directed_eoi=3D1, SPIV directed_eoi=3D0, got_eoi_exit= =3D1 Testing explicit enable... Split IRQCHIP: LVR directed_eoi=3D1, SPIV directed_eoi=3D1, got_eoi_exit= =3D0 Testing explicit enable (guest doesn't use)... Split IRQCHIP: LVR directed_eoi=3D1, SPIV directed_eoi=3D0, got_eoi_exit= =3D1 Testing explicit disable... Split IRQCHIP: LVR directed_eoi=3D0, SPIV directed_eoi=3D0, got_eoi_exit= =3D1 All tests passed There didn't seem to be a way for selftests to use split irqchip mode until now, so this adds vm_irqchip_mode modelled on the existing vm_guest_mode enum. Signed-off-by: David Woodhouse --- diff --git a/tools/testing/selftests/kvm/Makefile.kvm b/tools/testing/selft= ests/kvm/Makefile.kvm index 148d427ff24b..01c59bf8b79f 100644 --- a/tools/testing/selftests/kvm/Makefile.kvm +++ b/tools/testing/selftests/kvm/Makefile.kvm @@ -122,6 +122,7 @@ TEST_GEN_PROGS_x86 +=3D x86/vmx_nested_tsc_scaling_test TEST_GEN_PROGS_x86 +=3D x86/apic_bus_clock_test TEST_GEN_PROGS_x86 +=3D x86/xapic_ipi_test TEST_GEN_PROGS_x86 +=3D x86/xapic_state_test +TEST_GEN_PROGS_x86 +=3D x86/suppress_eoi_test TEST_GEN_PROGS_x86 +=3D x86/xcr0_cpuid_test TEST_GEN_PROGS_x86 +=3D x86/xss_msr_test TEST_GEN_PROGS_x86 +=3D x86/debug_regs diff --git a/tools/testing/selftests/kvm/include/kvm_util.h b/tools/testing= /selftests/kvm/include/kvm_util.h index d3f3e455c031..c4eb0e95bae9 100644 --- a/tools/testing/selftests/kvm/include/kvm_util.h +++ b/tools/testing/selftests/kvm/include/kvm_util.h @@ -209,6 +209,14 @@ kvm_static_assert(sizeof(struct vm_shape) =3D=3D sizeo= f(uint64_t)); shape; \ }) =20 +enum vm_irqchip_mode { + VM_IRQCHIP_AUTO, + VM_IRQCHIP_KERNEL, + VM_IRQCHIP_SPLIT, +}; + +extern enum vm_irqchip_mode vm_irqchip_mode; + #if defined(__aarch64__) =20 extern enum vm_guest_mode vm_mode_default; diff --git a/tools/testing/selftests/kvm/lib/kvm_util.c b/tools/testing/sel= ftests/kvm/lib/kvm_util.c index 1a93d6361671..4858c10f7530 100644 --- a/tools/testing/selftests/kvm/lib/kvm_util.c +++ b/tools/testing/selftests/kvm/lib/kvm_util.c @@ -1687,21 +1687,34 @@ void *addr_gpa2alias(struct kvm_vm *vm, vm_paddr_t = gpa) return (void *) ((uintptr_t) region->host_alias + offset); } =20 +enum vm_irqchip_mode vm_irqchip_mode =3D VM_IRQCHIP_AUTO; + /* Create an interrupt controller chip for the specified VM. */ void vm_create_irqchip(struct kvm_vm *vm) { int r; =20 /* - * Allocate a fully in-kernel IRQ chip by default, but fall back to a - * split model (x86 only) if that fails (KVM x86 allows compiling out - * support for KVM_CREATE_IRQCHIP). + * Create IRQ chip based on vm_irqchip_mode: + * - VM_IRQCHIP_AUTO: Try in-kernel, fall back to split if not supported + * - VM_IRQCHIP_KERNEL: Force in-kernel IRQ chip + * - VM_IRQCHIP_SPLIT: Force split IRQ chip (x86 only) */ - r =3D __vm_ioctl(vm, KVM_CREATE_IRQCHIP, NULL); - if (r && errno =3D=3D ENOTTY && kvm_has_cap(KVM_CAP_SPLIT_IRQCHIP)) + if (vm_irqchip_mode =3D=3D VM_IRQCHIP_SPLIT) { + TEST_ASSERT(kvm_has_cap(KVM_CAP_SPLIT_IRQCHIP), + "Split IRQ chip not supported"); vm_enable_cap(vm, KVM_CAP_SPLIT_IRQCHIP, 24); - else + } else if (vm_irqchip_mode =3D=3D VM_IRQCHIP_KERNEL) { + r =3D __vm_ioctl(vm, KVM_CREATE_IRQCHIP, NULL); TEST_ASSERT_VM_VCPU_IOCTL(!r, KVM_CREATE_IRQCHIP, r, vm); + } else { + /* VM_IRQCHIP_AUTO */ + r =3D __vm_ioctl(vm, KVM_CREATE_IRQCHIP, NULL); + if (r && errno =3D=3D ENOTTY && kvm_has_cap(KVM_CAP_SPLIT_IRQCHIP)) + vm_enable_cap(vm, KVM_CAP_SPLIT_IRQCHIP, 24); + else + TEST_ASSERT_VM_VCPU_IOCTL(!r, KVM_CREATE_IRQCHIP, r, vm); + } =20 vm->has_irqchip =3D true; } diff --git a/tools/testing/selftests/kvm/x86/suppress_eoi_test.c b/tools/te= sting/selftests/kvm/x86/suppress_eoi_test.c new file mode 100644 index 000000000000..ea14690b3116 --- /dev/null +++ b/tools/testing/selftests/kvm/x86/suppress_eoi_test.c @@ -0,0 +1,441 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Test KVM's handling of Suppress EOI Broadcast in x2APIC mode. + */ +#include "kvm_util.h" +#include "processor.h" +#include "test_util.h" +#include "apic.h" + +#define TEST_VECTOR 0xa2 +#define TEST_IRQ 5 +#define APIC_LVR_DIRECTED_EOI (1 << 24) +#define APIC_SPIV_DIRECTED_EOI (1 << 12) + +#define APIC_ISR 0x100 +#define APIC_LVTPC 0x340 +#define APIC_LVT0 0x350 +#define APIC_LVT1 0x360 +#define APIC_LVTERR 0x370 + +#define IOAPIC_BASE_GPA 0xfec00000 +#define IOAPIC_REG_SELECT 0x00 +#define IOAPIC_REG_WINDOW 0x10 +#define IOAPIC_REG_VERSION 0x01 +#define IOAPIC_REG_EOI 0x40 + +static uint32_t ioapic_version; + +static void guest_irq_handler(struct ex_regs *regs) +{ +} + +static uint32_t ioapic_read_reg(uint32_t reg) +{ + volatile uint32_t *ioapic =3D (volatile uint32_t *)IOAPIC_BASE_GPA; + ioapic[0] =3D reg; + return ioapic[4]; +} + +static void ioapic_write_reg(uint32_t reg, uint32_t val) +{ + volatile uint32_t *ioapic =3D (volatile uint32_t *)IOAPIC_BASE_GPA; + ioapic[0] =3D reg; + ioapic[4] =3D val; +} + +static void guest_code(uint64_t use_directed) +{ + uint64_t apic_base; + uint32_t spiv; + + /* Enable x2APIC mode */ + apic_base =3D rdmsr(MSR_IA32_APICBASE); + wrmsr(MSR_IA32_APICBASE, apic_base | X2APIC_ENABLE); + + /* Mask all LVT entries to prevent spurious interrupts/NMIs */ + x2apic_write_reg(APIC_LVTT, APIC_LVT_MASKED); + x2apic_write_reg(APIC_LVTPC, APIC_LVT_MASKED); + x2apic_write_reg(APIC_LVT0, APIC_LVT_MASKED); + x2apic_write_reg(APIC_LVT1, APIC_LVT_MASKED); + x2apic_write_reg(APIC_LVTERR, APIC_LVT_MASKED); + + /* Enable APIC */ + x2apic_write_reg(APIC_SPIV, APIC_SPIV_APIC_ENABLED | TEST_VECTOR); + + /* Read IOAPIC version */ + ioapic_version =3D ioapic_read_reg(IOAPIC_REG_VERSION); + + /* Conditionally set APIC_SPIV_DIRECTED_EOI based on flag */ + if (use_directed) { + spiv =3D x2apic_read_reg(APIC_SPIV); + x2apic_write_reg(APIC_SPIV, spiv | APIC_SPIV_DIRECTED_EOI); + } + spiv =3D x2apic_read_reg(APIC_SPIV); + + GUEST_SYNC(ioapic_version | (spiv << 16)); + + /* Enable interrupts and wait for interrupt to be delivered */ + asm volatile("sti; hlt"); + + /* Write EOI to trigger broadcast (or not) */ + x2apic_write_reg(APIC_EOI, 0); + + GUEST_SYNC(0); + + /* If IOAPIC v0x20, write directed EOI to clear remote_irr */ + if ((ioapic_version & 0xff) =3D=3D 0x20) { + ioapic_write_reg(IOAPIC_REG_EOI, TEST_VECTOR); + GUEST_SYNC(1); + } + + GUEST_DONE(); +} + +static void test_suppress_eoi(uint64_t x2apic_flags, bool expect_advertise= d, bool expect_implemented, + bool use_directed) +{ + struct kvm_vcpu *vcpu; + struct kvm_vm *vm; + struct kvm_lapic_state lapic; + struct kvm_irqchip chip; + struct kvm_irq_level irq_level; + struct ucall uc; + uint32_t lvr, ioapic_ver, spiv_after; + bool remote_irr_set; + + use_directed =3D use_directed; + + vm =3D vm_create(1); + + if (x2apic_flags) + vm_enable_cap(vm, KVM_CAP_X2APIC_API, x2apic_flags); + + if (!vm->has_irqchip) + vm_create_irqchip(vm); + + vcpu =3D vm_vcpu_add(vm, 0, guest_code); + vcpu_args_set(vcpu, 1, use_directed); + + vm_install_exception_handler(vm, TEST_VECTOR, guest_irq_handler); + + /* Map IOAPIC for guest access */ + virt_map(vm, IOAPIC_BASE_GPA, IOAPIC_BASE_GPA, 1); + + /* Configure level-triggered interrupt in IOAPIC */ + chip.chip_id =3D KVM_IRQCHIP_IOAPIC; + vm_ioctl(vm, KVM_GET_IRQCHIP, &chip); + + chip.chip.ioapic.redirtbl[TEST_IRQ].fields.vector =3D TEST_VECTOR; + chip.chip.ioapic.redirtbl[TEST_IRQ].fields.delivery_mode =3D 0; /* fixed = */ + chip.chip.ioapic.redirtbl[TEST_IRQ].fields.dest_mode =3D 0; /* physical */ + chip.chip.ioapic.redirtbl[TEST_IRQ].fields.mask =3D 0; /* unmasked */ + chip.chip.ioapic.redirtbl[TEST_IRQ].fields.trig_mode =3D 1; /* level */ + chip.chip.ioapic.redirtbl[TEST_IRQ].fields.dest_id =3D vcpu->id; + + vm_ioctl(vm, KVM_SET_IRQCHIP, &chip); + + vcpu_run(vcpu); + TEST_ASSERT_EQ(get_ucall(vcpu, &uc), UCALL_SYNC); + ioapic_ver =3D uc.args[1] & 0xff; + spiv_after =3D (uc.args[1] >> 16) & 0xffff; + + /* Inject level-triggered interrupt */ + irq_level.irq =3D TEST_IRQ; + irq_level.level =3D 1; + vm_ioctl(vm, KVM_IRQ_LINE, &irq_level); + + /* De-assert immediately so we only get one interrupt */ + irq_level.level =3D 0; + vm_ioctl(vm, KVM_IRQ_LINE, &irq_level); + + /* Guest receives interrupt and writes EOI */ + vcpu_run(vcpu); + + /* Check what ucall we got */ + int ucall_type =3D get_ucall(vcpu, &uc); + + /* Handle guest completion based on what it did */ + if (ucall_type =3D=3D UCALL_SYNC) { + /* Guest has more to do */ + vcpu_run(vcpu); + ucall_type =3D get_ucall(vcpu, &uc); + + if (ucall_type =3D=3D UCALL_SYNC) { + /* Guest wrote EOIR */ + vcpu_run(vcpu); + TEST_ASSERT_EQ(get_ucall(vcpu, &uc), UCALL_DONE); + } else { + TEST_ASSERT_EQ(ucall_type, UCALL_DONE); + } + } else { + TEST_ASSERT_EQ(ucall_type, UCALL_DONE); + } + + /* Check remote_irr after all guest EOI activity */ + chip.chip_id =3D KVM_IRQCHIP_IOAPIC; + vm_ioctl(vm, KVM_GET_IRQCHIP, &chip); + remote_irr_set =3D chip.chip.ioapic.redirtbl[TEST_IRQ].fields.remote_irr; + + /* De-assert IRQ line */ + irq_level.level =3D 0; + vm_ioctl(vm, KVM_IRQ_LINE, &irq_level); + + /* Check LAPIC LVR */ + vcpu_ioctl(vcpu, KVM_GET_LAPIC, &lapic); + lvr =3D *(u32 *)&lapic.regs[APIC_LVR]; + + printf(" IOAPIC v0x%x, LVR directed_eoi=3D%d, SPIV directed_eoi=3D%d, re= mote_irr=3D%d\n", + ioapic_ver, !!(lvr & APIC_LVR_DIRECTED_EOI), + !!(spiv_after & APIC_SPIV_DIRECTED_EOI), remote_irr_set); + + if (expect_advertised) { + TEST_ASSERT(lvr & APIC_LVR_DIRECTED_EOI, + "Expected APIC_LVR_DIRECTED_EOI, got LVR=3D0x%x", lvr); + } else { + TEST_ASSERT(!(lvr & APIC_LVR_DIRECTED_EOI), + "Expected no APIC_LVR_DIRECTED_EOI, got LVR=3D0x%x", lvr); + } + + /* Check IOAPIC version */ + if (expect_implemented) { + TEST_ASSERT(ioapic_ver =3D=3D 0x20, + "Expected IOAPIC v0x20 (with EOIR), got 0x%x", ioapic_ver); + } else { + TEST_ASSERT(ioapic_ver =3D=3D 0x11, + "Expected IOAPIC v0x11 (no EOIR), got 0x%x", ioapic_ver); + } + + /* Check SPIV and remote_irr based on whether guest used directed EOI */ + if (use_directed) { + TEST_ASSERT(spiv_after & APIC_SPIV_DIRECTED_EOI, + "Expected APIC_SPIV_DIRECTED_EOI set, got SPIV=3D0x%x", spiv_after); + TEST_ASSERT(remote_irr_set, + "Expected remote_irr set (EOI suppressed), got cleared"); + } else { + TEST_ASSERT(!(spiv_after & APIC_SPIV_DIRECTED_EOI), + "Expected APIC_SPIV_DIRECTED_EOI clear, got SPIV=3D0x%x", spiv_afte= r); + TEST_ASSERT(!remote_irr_set, + "Expected remote_irr cleared (EOI broadcast), got set"); + } + + kvm_vm_free(vm); +} + +static void guest_code_split(uint64_t use_directed) +{ + uint64_t apic_base; + uint32_t spiv; + + /* Enable x2APIC mode */ + apic_base =3D rdmsr(MSR_IA32_APICBASE); + wrmsr(MSR_IA32_APICBASE, apic_base | X2APIC_ENABLE); + + /* Mask all LVT entries */ + x2apic_write_reg(APIC_LVTT, APIC_LVT_MASKED); + x2apic_write_reg(APIC_LVTPC, APIC_LVT_MASKED); + x2apic_write_reg(APIC_LVT0, APIC_LVT_MASKED); + x2apic_write_reg(APIC_LVT1, APIC_LVT_MASKED); + x2apic_write_reg(APIC_LVTERR, APIC_LVT_MASKED); + + /* Enable APIC */ + x2apic_write_reg(APIC_SPIV, APIC_SPIV_APIC_ENABLED | TEST_VECTOR); + + /* Conditionally set APIC_SPIV_DIRECTED_EOI */ + if (use_directed) { + spiv =3D x2apic_read_reg(APIC_SPIV); + x2apic_write_reg(APIC_SPIV, spiv | APIC_SPIV_DIRECTED_EOI); + } + spiv =3D x2apic_read_reg(APIC_SPIV); + + GUEST_SYNC(spiv); + + /* Enable interrupts and wait for interrupt */ + asm volatile("sti; hlt"); + + /* Write EOI */ + x2apic_write_reg(APIC_EOI, 0); + + GUEST_DONE(); +} + +static void test_suppress_eoi_split(uint64_t x2apic_flags, bool expect_adv= ertised, bool use_directed) +{ + struct kvm_vcpu *vcpu; + struct kvm_vm *vm; + struct kvm_lapic_state lapic; + struct ucall uc; + uint32_t lvr, spiv_after; + bool got_eoi_exit; + enum vm_irqchip_mode saved_mode =3D vm_irqchip_mode; + + vm_irqchip_mode =3D VM_IRQCHIP_SPLIT; + vm =3D vm_create(1); + vm_irqchip_mode =3D saved_mode; + + if (x2apic_flags) + vm_enable_cap(vm, KVM_CAP_X2APIC_API, x2apic_flags); + + vcpu =3D vm_vcpu_add(vm, 0, guest_code_split); + vcpu_args_set(vcpu, 1, use_directed); + + /* Set up IRQ routing so kernel knows userspace IOAPIC handles TEST_IRQ */ + struct kvm_irq_routing *routing =3D calloc(1, sizeof(*routing) + sizeof(r= outing->entries[0])); + routing->nr =3D 1; + routing->entries[0].gsi =3D TEST_IRQ; + routing->entries[0].type =3D KVM_IRQ_ROUTING_MSI; + routing->entries[0].u.msi.address_lo =3D 0xfee00000; /* Dest ID 0 */ + routing->entries[0].u.msi.address_hi =3D 0; + routing->entries[0].u.msi.data =3D TEST_VECTOR | (1 << 15); /* Level-tri= ggered */ + __vm_ioctl(vm, KVM_SET_GSI_ROUTING, routing); + free(routing); + + vm_install_exception_handler(vm, TEST_VECTOR, guest_irq_handler); + + vcpu_run(vcpu); + TEST_ASSERT_EQ(get_ucall(vcpu, &uc), UCALL_SYNC); + spiv_after =3D uc.args[1]; + + /* Inject via GSI (which routes to MSI) */ + struct kvm_irq_level irq_level =3D { + .irq =3D TEST_IRQ, + .level =3D 1, + }; + vm_ioctl(vm, KVM_IRQ_LINE, &irq_level); + irq_level.level =3D 0; + vm_ioctl(vm, KVM_IRQ_LINE, &irq_level); + + /* Guest receives interrupt and writes EOI */ + vcpu_run(vcpu); + + + /* Check if we got KVM_EXIT_IOAPIC_EOI */ + got_eoi_exit =3D (vcpu->run->exit_reason =3D=3D KVM_EXIT_IOAPIC_EOI && + vcpu->run->eoi.vector =3D=3D TEST_VECTOR); + + /* If we got EOI exit, continue guest to finish */ + if (got_eoi_exit) { + vcpu_run(vcpu); + } + + /* Let guest finish */ + int ucall_type =3D get_ucall(vcpu, &uc); + if (ucall_type =3D=3D UCALL_SYNC) { + vcpu_run(vcpu); + ucall_type =3D get_ucall(vcpu, &uc); + if (ucall_type =3D=3D UCALL_SYNC) { + vcpu_run(vcpu); + TEST_ASSERT_EQ(get_ucall(vcpu, &uc), UCALL_DONE); + } else { + TEST_ASSERT_EQ(ucall_type, UCALL_DONE); + } + } else { + TEST_ASSERT_EQ(ucall_type, UCALL_DONE); + } + + /* Check LAPIC LVR */ + vcpu_ioctl(vcpu, KVM_GET_LAPIC, &lapic); + lvr =3D *(u32 *)&lapic.regs[APIC_LVR]; + + printf(" Split IRQCHIP: LVR directed_eoi=3D%d, SPIV directed_eoi=3D%d, g= ot_eoi_exit=3D%d\n", + !!(lvr & APIC_LVR_DIRECTED_EOI), + !!(spiv_after & APIC_SPIV_DIRECTED_EOI), got_eoi_exit); + + if (expect_advertised) { + TEST_ASSERT(lvr & APIC_LVR_DIRECTED_EOI, + "Expected APIC_LVR_DIRECTED_EOI, got LVR=3D0x%x", lvr); + } else { + TEST_ASSERT(!(lvr & APIC_LVR_DIRECTED_EOI), + "Expected no APIC_LVR_DIRECTED_EOI, got LVR=3D0x%x", lvr); + } + + /* Check EOI exit based on whether guest used directed EOI */ + if (use_directed) { + TEST_ASSERT(spiv_after & APIC_SPIV_DIRECTED_EOI, + "Expected APIC_SPIV_DIRECTED_EOI set, got SPIV=3D0x%x", spiv_after); + TEST_ASSERT(!got_eoi_exit, + "Expected no EOI exit (suppressed), but got one"); + } else { + TEST_ASSERT(!(spiv_after & APIC_SPIV_DIRECTED_EOI), + "Expected APIC_SPIV_DIRECTED_EOI clear, got SPIV=3D0x%x", spiv_afte= r); + if (expect_advertised) { + /* Quirk mode: advertised but should still broadcast */ + if (!got_eoi_exit) { + printf(" Note: No EOI exit in quirk mode (old kernel behavior)\n"); + } + } else { + /* Feature not advertised, no EOI exits expected */ + } + } + + kvm_vm_free(vm); +} + +int main(void) +{ + int cap; + + TEST_REQUIRE(kvm_has_cap(KVM_CAP_X2APIC_API)); + TEST_REQUIRE(kvm_has_cap(KVM_CAP_IRQCHIP)); + + cap =3D kvm_check_cap(KVM_CAP_X2APIC_API); + + /* + * Test that KVM correctly handles the suppress EOI broadcast flags. + * Note: The actual behavior depends on the kernel implementation. + * This test documents the expected behavior per the commit messages. + * + * Quirk mode: Don't advertise or implement (legacy behavior) + * Explicit enable: Advertise and implement + * Explicit disable: Don't advertise or implement + */ + + printf("Testing quirk mode (no flags)...\n"); + test_suppress_eoi(0, false, false, false); + + if (cap & KVM_X2APIC_ENABLE_SUPPRESS_EOI_BROADCAST) { + printf("Testing explicit enable...\n"); + test_suppress_eoi(KVM_X2APIC_ENABLE_SUPPRESS_EOI_BROADCAST, true, true, = true); + + printf("Testing explicit enable (guest doesn't use)...\n"); + test_suppress_eoi(KVM_X2APIC_ENABLE_SUPPRESS_EOI_BROADCAST, true, true, = false); + } else { + printf("Skipping explicit enable (not supported)...\n"); + } + + if (cap & KVM_X2APIC_DISABLE_SUPPRESS_EOI_BROADCAST) { + printf("Testing explicit disable...\n"); + test_suppress_eoi(KVM_X2APIC_DISABLE_SUPPRESS_EOI_BROADCAST, false, fals= e, false); + } else { + printf("Skipping explicit disable (not supported)...\n"); + } + + printf("All tests passed\n"); + + /* Test split irqchip mode */ + printf("\n=3D=3D=3D Testing split IRQCHIP mode =3D=3D=3D\n"); + + printf("Testing quirk mode (no flags)...\n"); + test_suppress_eoi_split(0, true, false); /* Quirk: advertised in split m= ode */ + + if (cap & KVM_X2APIC_ENABLE_SUPPRESS_EOI_BROADCAST) { + printf("Testing explicit enable...\n"); + test_suppress_eoi_split(KVM_X2APIC_ENABLE_SUPPRESS_EOI_BROADCAST, true, = true); + + printf("Testing explicit enable (guest doesn't use)...\n"); + test_suppress_eoi_split(KVM_X2APIC_ENABLE_SUPPRESS_EOI_BROADCAST, true, = false); + } else { + printf("Skipping explicit enable (not supported)...\n"); + } + + if (cap & KVM_X2APIC_DISABLE_SUPPRESS_EOI_BROADCAST) { + printf("Testing explicit disable...\n"); + test_suppress_eoi_split(KVM_X2APIC_DISABLE_SUPPRESS_EOI_BROADCAST, false= , false); + } else { + printf("Skipping explicit disable (not supported)...\n"); + } + + printf("All tests passed\n"); + return 0; +} + --=-XM1aDuSYUJFjYLXU6f31 Content-Type: application/pkcs7-signature; name="smime.p7s" Content-Disposition: attachment; filename="smime.p7s" Content-Transfer-Encoding: base64 MIAGCSqGSIb3DQEHAqCAMIACAQExDzANBglghkgBZQMEAgEFADCABgkqhkiG9w0BBwEAAKCCD9Aw ggSOMIIDdqADAgECAhAOmiw0ECVD4cWj5DqVrT9PMA0GCSqGSIb3DQEBCwUAMGUxCzAJBgNVBAYT AlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xJDAi BgNVBAMTG0RpZ2lDZXJ0IEFzc3VyZWQgSUQgUm9vdCBDQTAeFw0yNDAxMzAwMDAwMDBaFw0zMTEx MDkyMzU5NTlaMEExCzAJBgNVBAYTAkFVMRAwDgYDVQQKEwdWZXJva2V5MSAwHgYDVQQDExdWZXJv a2V5IFNlY3VyZSBFbWFpbCBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMjvgLKj jfhCFqxYyRiW8g3cNFAvltDbK5AzcOaR7yVzVGadr4YcCVxjKrEJOgi7WEOH8rUgCNB5cTD8N/Et GfZI+LGqSv0YtNa54T9D1AWJy08ZKkWvfGGIXN9UFAPMJ6OLLH/UUEgFa+7KlrEvMUupDFGnnR06 aDJAwtycb8yXtILj+TvfhLFhafxroXrflspavejQkEiHjNjtHnwbZ+o43g0/yxjwnarGI3kgcak7 nnI9/8Lqpq79tLHYwLajotwLiGTB71AGN5xK+tzB+D4eN9lXayrjcszgbOv2ZCgzExQUAIt98mre 8EggKs9mwtEuKAhYBIP/0K6WsoMnQCcCAwEAAaOCAVwwggFYMBIGA1UdEwEB/wQIMAYBAf8CAQAw HQYDVR0OBBYEFIlICOogTndrhuWByNfhjWSEf/xwMB8GA1UdIwQYMBaAFEXroq/0ksuCMS1Ri6en IZ3zbcgPMA4GA1UdDwEB/wQEAwIBhjAdBgNVHSUEFjAUBggrBgEFBQcDBAYIKwYBBQUHAwIweQYI KwYBBQUHAQEEbTBrMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdpY2VydC5jb20wQwYIKwYB BQUHMAKGN2h0dHA6Ly9jYWNlcnRzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydEFzc3VyZWRJRFJvb3RD QS5jcnQwRQYDVR0fBD4wPDA6oDigNoY0aHR0cDovL2NybDMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0 QXNzdXJlZElEUm9vdENBLmNybDARBgNVHSAECjAIMAYGBFUdIAAwDQYJKoZIhvcNAQELBQADggEB ACiagCqvNVxOfSd0uYfJMiZsOEBXAKIR/kpqRp2YCfrP4Tz7fJogYN4fxNAw7iy/bPZcvpVCfe/H /CCcp3alXL0I8M/rnEnRlv8ItY4MEF+2T/MkdXI3u1vHy3ua8SxBM8eT9LBQokHZxGUX51cE0kwa uEOZ+PonVIOnMjuLp29kcNOVnzf8DGKiek+cT51FvGRjV6LbaxXOm2P47/aiaXrDD5O0RF5SiPo6 xD1/ClkCETyyEAE5LRJlXtx288R598koyFcwCSXijeVcRvBB1cNOLEbg7RMSw1AGq14fNe2cH1HG W7xyduY/ydQt6gv5r21mDOQ5SaZSWC/ZRfLDuEYwggWbMIIEg6ADAgECAhAH5JEPagNRXYDiRPdl c1vgMA0GCSqGSIb3DQEBCwUAMEExCzAJBgNVBAYTAkFVMRAwDgYDVQQKEwdWZXJva2V5MSAwHgYD VQQDExdWZXJva2V5IFNlY3VyZSBFbWFpbCBHMjAeFw0yNDEyMzAwMDAwMDBaFw0yODAxMDQyMzU5 NTlaMB4xHDAaBgNVBAMME2R3bXcyQGluZnJhZGVhZC5vcmcwggIiMA0GCSqGSIb3DQEBAQUAA4IC DwAwggIKAoICAQDali7HveR1thexYXx/W7oMk/3Wpyppl62zJ8+RmTQH4yZeYAS/SRV6zmfXlXaZ sNOE6emg8WXLRS6BA70liot+u0O0oPnIvnx+CsMH0PD4tCKSCsdp+XphIJ2zkC9S7/yHDYnqegqt w4smkqUqf0WX/ggH1Dckh0vHlpoS1OoxqUg+ocU6WCsnuz5q5rzFsHxhD1qGpgFdZEk2/c//ZvUN i12vPWipk8TcJwHw9zoZ/ZrVNybpMCC0THsJ/UEVyuyszPtNYeYZAhOJ41vav1RhZJzYan4a1gU0 kKBPQklcpQEhq48woEu15isvwWh9/+5jjh0L+YNaN0I//nHSp6U9COUG9Z0cvnO8FM6PTqsnSbcc 0j+GchwOHRC7aP2t5v2stVx3KbptaYEzi4MQHxm/0+HQpMEVLLUiizJqS4PWPU6zfQTOMZ9uLQRR ci+c5xhtMEBszlQDOvEQcyEG+hc++fH47K+MmZz21bFNfoBxLP6bjR6xtPXtREF5lLXxp+CJ6KKS blPKeVRg/UtyJHeFKAZXO8Zeco7TZUMVHmK0ZZ1EpnZbnAhKE19Z+FJrQPQrlR0gO3lBzuyPPArV hvWxjlO7S4DmaEhLzarWi/ze7EGwWSuI2eEa/8zU0INUsGI4ywe7vepQz7IqaAovAX0d+f1YjbmC VsAwjhLmveFjNwIDAQABo4IBsDCCAawwHwYDVR0jBBgwFoAUiUgI6iBOd2uG5YHI1+GNZIR//HAw HQYDVR0OBBYEFFxiGptwbOfWOtMk5loHw7uqWUOnMDAGA1UdEQQpMCeBE2R3bXcyQGluZnJhZGVh ZC5vcmeBEGRhdmlkQHdvb2Rob3Uuc2UwFAYDVR0gBA0wCzAJBgdngQwBBQEBMA4GA1UdDwEB/wQE AwIF4DAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwQwewYDVR0fBHQwcjA3oDWgM4YxaHR0 cDovL2NybDMuZGlnaWNlcnQuY29tL1Zlcm9rZXlTZWN1cmVFbWFpbEcyLmNybDA3oDWgM4YxaHR0 cDovL2NybDQuZGlnaWNlcnQuY29tL1Zlcm9rZXlTZWN1cmVFbWFpbEcyLmNybDB2BggrBgEFBQcB AQRqMGgwJAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmRpZ2ljZXJ0LmNvbTBABggrBgEFBQcwAoY0 aHR0cDovL2NhY2VydHMuZGlnaWNlcnQuY29tL1Zlcm9rZXlTZWN1cmVFbWFpbEcyLmNydDANBgkq hkiG9w0BAQsFAAOCAQEAQXc4FPiPLRnTDvmOABEzkIumojfZAe5SlnuQoeFUfi+LsWCKiB8Uextv iBAvboKhLuN6eG/NC6WOzOCppn4mkQxRkOdLNThwMHW0d19jrZFEKtEG/epZ/hw/DdScTuZ2m7im 8ppItAT6GXD3aPhXkXnJpC/zTs85uNSQR64cEcBFjjoQDuSsTeJ5DAWf8EMyhMuD8pcbqx5kRvyt JPsWBQzv1Dsdv2LDPLNd/JUKhHSgr7nbUr4+aAP2PHTXGcEBh8lTeYea9p4d5k969pe0OHYMV5aL xERqTagmSetuIwolkAuBCzA9vulg8Y49Nz2zrpUGfKGOD0FMqenYxdJHgDCCBZswggSDoAMCAQIC EAfkkQ9qA1FdgOJE92VzW+AwDQYJKoZIhvcNAQELBQAwQTELMAkGA1UEBhMCQVUxEDAOBgNVBAoT B1Zlcm9rZXkxIDAeBgNVBAMTF1Zlcm9rZXkgU2VjdXJlIEVtYWlsIEcyMB4XDTI0MTIzMDAwMDAw MFoXDTI4MDEwNDIzNTk1OVowHjEcMBoGA1UEAwwTZHdtdzJAaW5mcmFkZWFkLm9yZzCCAiIwDQYJ KoZIhvcNAQEBBQADggIPADCCAgoCggIBANqWLse95HW2F7FhfH9bugyT/danKmmXrbMnz5GZNAfj Jl5gBL9JFXrOZ9eVdpmw04Tp6aDxZctFLoEDvSWKi367Q7Sg+ci+fH4KwwfQ8Pi0IpIKx2n5emEg nbOQL1Lv/IcNiep6Cq3DiyaSpSp/RZf+CAfUNySHS8eWmhLU6jGpSD6hxTpYKye7PmrmvMWwfGEP WoamAV1kSTb9z/9m9Q2LXa89aKmTxNwnAfD3Ohn9mtU3JukwILRMewn9QRXK7KzM+01h5hkCE4nj W9q/VGFknNhqfhrWBTSQoE9CSVylASGrjzCgS7XmKy/BaH3/7mOOHQv5g1o3Qj/+cdKnpT0I5Qb1 nRy+c7wUzo9OqydJtxzSP4ZyHA4dELto/a3m/ay1XHcpum1pgTOLgxAfGb/T4dCkwRUstSKLMmpL g9Y9TrN9BM4xn24tBFFyL5znGG0wQGzOVAM68RBzIQb6Fz758fjsr4yZnPbVsU1+gHEs/puNHrG0 9e1EQXmUtfGn4InoopJuU8p5VGD9S3Ikd4UoBlc7xl5yjtNlQxUeYrRlnUSmdlucCEoTX1n4UmtA 9CuVHSA7eUHO7I88CtWG9bGOU7tLgOZoSEvNqtaL/N7sQbBZK4jZ4Rr/zNTQg1SwYjjLB7u96lDP sipoCi8BfR35/ViNuYJWwDCOEua94WM3AgMBAAGjggGwMIIBrDAfBgNVHSMEGDAWgBSJSAjqIE53 a4blgcjX4Y1khH/8cDAdBgNVHQ4EFgQUXGIam3Bs59Y60yTmWgfDu6pZQ6cwMAYDVR0RBCkwJ4ET ZHdtdzJAaW5mcmFkZWFkLm9yZ4EQZGF2aWRAd29vZGhvdS5zZTAUBgNVHSAEDTALMAkGB2eBDAEF AQEwDgYDVR0PAQH/BAQDAgXgMB0GA1UdJQQWMBQGCCsGAQUFBwMCBggrBgEFBQcDBDB7BgNVHR8E dDByMDegNaAzhjFodHRwOi8vY3JsMy5kaWdpY2VydC5jb20vVmVyb2tleVNlY3VyZUVtYWlsRzIu Y3JsMDegNaAzhjFodHRwOi8vY3JsNC5kaWdpY2VydC5jb20vVmVyb2tleVNlY3VyZUVtYWlsRzIu Y3JsMHYGCCsGAQUFBwEBBGowaDAkBggrBgEFBQcwAYYYaHR0cDovL29jc3AuZGlnaWNlcnQuY29t MEAGCCsGAQUFBzAChjRodHRwOi8vY2FjZXJ0cy5kaWdpY2VydC5jb20vVmVyb2tleVNlY3VyZUVt YWlsRzIuY3J0MA0GCSqGSIb3DQEBCwUAA4IBAQBBdzgU+I8tGdMO+Y4AETOQi6aiN9kB7lKWe5Ch 4VR+L4uxYIqIHxR7G2+IEC9ugqEu43p4b80LpY7M4KmmfiaRDFGQ50s1OHAwdbR3X2OtkUQq0Qb9 6ln+HD8N1JxO5nabuKbymki0BPoZcPdo+FeRecmkL/NOzzm41JBHrhwRwEWOOhAO5KxN4nkMBZ/w QzKEy4PylxurHmRG/K0k+xYFDO/UOx2/YsM8s138lQqEdKCvudtSvj5oA/Y8dNcZwQGHyVN5h5r2 nh3mT3r2l7Q4dgxXlovERGpNqCZJ624jCiWQC4ELMD2+6WDxjj03PbOulQZ8oY4PQUyp6djF0keA MYIDuzCCA7cCAQEwVTBBMQswCQYDVQQGEwJBVTEQMA4GA1UEChMHVmVyb2tleTEgMB4GA1UEAxMX VmVyb2tleSBTZWN1cmUgRW1haWwgRzICEAfkkQ9qA1FdgOJE92VzW+AwDQYJYIZIAWUDBAIBBQCg ggE3MBgGCSqGSIb3DQEJAzELBgkqhkiG9w0BBwEwHAYJKoZIhvcNAQkFMQ8XDTI2MDEyOTA0NDkx M1owLwYJKoZIhvcNAQkEMSIEIEE0SARrRzgx5rK+g2F6lxfptoX3QrCJAK1mCeSoGCJ5MGQGCSsG AQQBgjcQBDFXMFUwQTELMAkGA1UEBhMCQVUxEDAOBgNVBAoTB1Zlcm9rZXkxIDAeBgNVBAMTF1Zl cm9rZXkgU2VjdXJlIEVtYWlsIEcyAhAH5JEPagNRXYDiRPdlc1vgMGYGCyqGSIb3DQEJEAILMVeg VTBBMQswCQYDVQQGEwJBVTEQMA4GA1UEChMHVmVyb2tleTEgMB4GA1UEAxMXVmVyb2tleSBTZWN1 cmUgRW1haWwgRzICEAfkkQ9qA1FdgOJE92VzW+AwDQYJKoZIhvcNAQEBBQAEggIAbzw/sGzIoC+i qBOHIhLDQ97buWMIujP/XnP0k7frECp5em87FicOt58zNn/GzFJGoa2JIWGREN+va7/lmkV/4dSG Mc/wGQ7UxlnheUHqlnmgsJxkeS/f3HNMMCmN2LYjsz3z5H05iYRC9FS5Q/yis6yjE/SH0Ii85+jI ZRohz8QE4DJG+Kl/8PcqyNDN9h6YWdcAnRN6T5aXwTDfNEr/+5/1npu+feaXMhIT6dTUkVnuUHUT 07WP3vnmkVwtLp+kZQFkdfOilANLK1Dy4mr/2Bz808/7JRnyaT8iBK7o0cvOIB6fPnUWrN611WKe kP04MdxidiTcsyIQjAesOKsne83Sqq8FVuPmJKCp9vrpiutIO4mrkQ1aUCW8ViGDImlJ2jyagWDt cAlPk+K407dhVSZSekcndozX//mK/+YenNXHjfb/fC5WQkkpbkhiXLqHKIymjkx4kDYDLD390PvT SvkCdJp1j+2Au2tJ9y3q+0LGj+Lc1ZzhEtZERMIfp8/MX21X6dD3aZOgAka/7GV7jvTuuNeElxyI q4FJ/avdectDtAEpYGOTUHSO/O8mQm1DS5YwxpRUtBQJQErWfyLlWervnMkbMHjCZULnAqx7/Pxi 6iZBezxcKBFvyUd9WVu9Ch5G4y24Rugncu8zpEtkdOVaXbd6toL4LKxg4UOYiGIAAAAAAAA= --=-XM1aDuSYUJFjYLXU6f31--