From nobody Fri Oct 23 15:32:28 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) client-ip=192.237.175.120; envelope-from=xen-devel-bounces@lists.xenproject.org; helo=lists.xenproject.org; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=pass(p=none dis=none) header.from=gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1790785201; cv=none; d=zohomail.com; s=zohoarc; b=NZGE8Xb60ovlTDmspkjaq1Q6jsDDiEe76BKl0CCTqxyqBweZJ0AeRHnJIZgmpv1f57LOOab5Ir9P6mXxHTuu9u/cinL9RYdhP3Qt8Og/JBC389hWKT8K6PkzSR8G50dvP6VVUq/PS0S8Zr4kda4TIJNqERulOOemn3PSoO0JOYI= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1790785201; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=LrKFeRIoL8z7uYGXx6LOdIuYW20jZhQAIuucTzUA5hQ=; b=dGYq8r5JHtSRJoNY7o608+/eS4wjuZfj0XPiAuZB/tCPjiO3WHRyZQmxrc8IXR9Z+WyEYPe9tkIC32AXxDvM5a5vq/JSssql6/gQ2qsEl5k8cBjd/JVwLFfTLmsNNKhrheSfMsEwL33JaOEocpER3ntDSlPeH5CwHAVp13wUA88= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) by mx.zohomail.com with SMTPS id 1790785201610554.8198715500073; Wed, 30 Sep 2026 09:20:01 -0700 (PDT) Received: from list by lists.xenproject.org with outflank-mailman.1437471.1656351 (Exim 4.92) (envelope-from ) id 1xBx1v-0005T8-Pg; Wed, 30 Sep 2026 16:19:39 +0000 Received: by outflank-mailman (output) from mailman id 1437471.1656351; Wed, 30 Sep 2026 16:19:39 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1xBx1v-0005T1-Mq; Wed, 30 Sep 2026 16:19:39 +0000 Received: by outflank-mailman (input) for mailman id 1437471; Wed, 30 Sep 2026 16:19:38 +0000 Received: from mx.expurgate.net ([194.145.224.10]) by lists.xenproject.org with esmtp (Exim 4.92) id 1xBx1u-0005Sd-Jc for xen-devel@lists.xenproject.org; Wed, 30 Sep 2026 16:19:38 +0000 Received: from mx.expurgate.net (helo=localhost) by mx.expurgate.net with esmtp id 1xBx1u-00Ezzr-0T for xen-devel@lists.xenproject.org; Wed, 30 Sep 2026 18:19:38 +0200 Received: from [10.42.69.5] (helo=localhost) by localhost with ESMTP (eXpurgate MTA 0.9.1) (envelope-from ) id 6abd368a-bab6-0a2a0a5309dd-0a2a4505e51a-14 for ; Wed, 30 Sep 2026 18:19:37 +0200 Received: from [74.125.225.140] (helo=mail-wm2-f12.google.com) by tlsNG-c201ff.mxtls.expurgate.net with ESMTPS (eXpurgate 4.57.1) (envelope-from ) id 6abd3699-4cb1-0a2a45050019-4a7de18cc1a9-3 for ; Wed, 30 Sep 2026 18:19:37 +0200 Received: by mail-wm2-f12.google.com with SMTP id 5b1f17b1804b1-49ffde3cec6so24418535e9.3 for ; Wed, 30 Sep 2026 09:19:37 -0700 (PDT) Received: from fedora (user-109-243-71-234.play-internet.pl. [109.243.71.234]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-4a01eb60804sm2807245e9.1.2026.09.30.09.19.30 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 30 Sep 2026 09:19:31 -0700 (PDT) X-Outflank-Mailman: Message body and most headers restored to incoming version X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" Authentication-Results: eu.smtp.expurgate.cloud; dkim=pass header.s=20251104 header.d=gmail.com header.i="@gmail.com" header.h="Content-Transfer-Encoding:MIME-Version:References:In-Reply-To:Message-ID:Date:Subject:Cc:To:From" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1790785177; x=1791389977; darn=lists.xenproject.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=LrKFeRIoL8z7uYGXx6LOdIuYW20jZhQAIuucTzUA5hQ=; b=I67PpGE7RFLJXcRdAQFp+HlfFoJ4gMx6gdAWgUu3FsAPMUFTxYnMDTqM2NpRcvRNOh ZzoTjpcqexAE09BBKhBKG71TY4Cv4znvsRE9BLwg5bHJYBpuqLLe7laoKoK+gHuIemgD jBiprl7p32Ayf7fHwaLomLRCrQTPQhsyYA+yfG9EpGRh5ArvI8YfSUPWVeGznyC4QUWQ WLyCEpQoquF45EU/skecEhU8TTlG8WPvmru9uHUlb9jhetNAtVaRgote2KC1klr8h+tX 4KmpucXiPtMy3JOZHmg4nCy/nQeCCiTrI5H/RQVSTYJWBTl+2jRMVP/OMNXxIHQvTF6i Y2Iw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1790785177; x=1791389977; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=LrKFeRIoL8z7uYGXx6LOdIuYW20jZhQAIuucTzUA5hQ=; b=dff98/fCq75SoC6ECf+nxoRqWgHhkHauzFRCYqtnRYcfHpJJMnsg/odl3U8xfHDBhG qVM1CexGIjZKOp7HoGvogWQu89WkxOz+d/c0uh+eWdMeGLHRUDxgaFJyXqQ7ZNEhZbwx /Ofmh29yeOLP7QkSNLP3UNxJ/zIkt7JIVnzuJ+zjor8hGdJaBmcMUzeJ5K4umFJV653m zz6nE0ONpekf1tVOhmZ+WWSN/fY+khQoFp3lkHRBAx6HIfUw874TvEj7ZYLFS8weU0iV LWYEMp5KleVWxGrXvGtztMpYMLg+5O62VZDUD6WZCsitnRLqRzniT/CGmByqKt9uwWAE 2jNg== X-Gm-Message-State: AFuF++kHo4cTmEgYa7cmWRAonD2GzSmldo49B2Lq5Vl2/NpsPFh+QL3a 6aQobL1Es/7A4P2Q4xoPRcmwlTvr79Bf4/pGEPkx5/VUJw3GBYsoHWkGkanIYg== X-Gm-Gg: AYBFou398n2o/+lG+YeYLOCbaOFdVYCa7pULQNCG7k6x8DRbqwrjbvDlmxaCivh3ynO u/rswCmgCxe/gPkNOKM896GapT6rwJvhC7qjDTagRHSoQcnBw+mbPORb4gWkSUTYk0lVffFlKYw TZUpkNmzN2bLFLqTmXNC/MBtjWWGJCDPvaRifUylLhPWqrazGJQGAaBDKn8cUvKVHbM1CyUrpFy rcahH00Yhhcnn51VvtYWhC6dAlYjMFwA7uOyr+QDfYEc+34CvnA+PzwsgBHgt2FRY7KnvLFx31c Y61IWH6gVlW2rp4IntoUj/hFSG1IJ4wh3/alKjkhAHhqAjWB7+e8rcchT1+fYpgAtlTPYQVv8Ys 04uKAzjNGpLGlpI0dLBJffOkNTlP+TQK2N9N/eXa4gc8pvnyqajuquIiO5UHLYyr3UjKe4VlklF sZRaUftn4s8xh9vPyqyUmrC508v2PA8jRJde1aLR/otAWEdckqiFfyMopc3z8d5dDg/5RogLGjC 5T+ROKSHSLdj0QX53fg033ETJ0lZRlOL7ccpybXkKaULv4WONo= X-Received: by 2002:a05:600c:354e:b0:4a0:1eb1:133b with SMTP id 5b1f17b1804b1-4a01eb113acmr2588115e9.12.1790785177281; Wed, 30 Sep 2026 09:19:37 -0700 (PDT) From: Oleksii Kurochko To: xen-devel@lists.xenproject.org Cc: Romain Caritey , Baptiste Le Duc , Zheng Zhang , Oleksii Kurochko , Alistair Francis , Connor Davis , Andrew Cooper , Anthony PERARD , Michal Orzel , Jan Beulich , Julien Grall , =?UTF-8?q?Roger=20Pau=20Monn=C3=A9?= , Stefano Stabellini Subject: [PATCH v3 01/39] xen/riscv: drop INSN_{16,32}BIT_MASK and report unknown instruction lengths Date: Wed, 30 Sep 2026 18:18:43 +0200 Message-ID: X-Mailer: git-send-email 2.55.0 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-purgate-ID: tlsNG-c201ff/1790785177-73ABF2A1-8A07D0AD/10/78276251493 X-purgate-type: spam X-purgate-size: 2717 X-ZohoMail-DKIM: pass (identity @gmail.com) X-ZM-MESSAGEID: 1790785202139158500 Content-Type: text/plain; charset="utf-8" Both constants were inherited from OpenSBI and their names are misleading. The length of an instruction is encoded in its low bits: bits[1:0] !=3D 11 means 16 bits, otherwise bits[4:2] !=3D 111 means 32 bits, and anything else is 48 bits or wider. 0x3 and 0x1c are the patterns compared against in these two tests, not masks selecting a 16-bit or a 32-bit instruction. As each constant is needed in one place only, once INSN_IS_16BIT() and INSN_IS_32BIT() encapsulate the tests, drop them and spell the values out in those two macros instead. While at it, make INSN_LEN() cover the case both macros already knew about: an encoding of 48 bits or wider now yields 0 rather than being silently taken for a 32-bit instruction. No ratified extension defines an instruction of such a length, so rather than open-coding a decoder for encodings which cannot legitimately occur, leave it to the caller to treat the 0 as an illegal instruction. No functional change: the only present caller applies INSN_LEN() to a bug frame, i.e. to an instruction emitted by Xen itself, which is either 16 or 32 bits wide. Suggested-by: Jan Beulich Signed-off-by: Oleksii Kurochko Acked-by: Jan Beulich Reviewed-by: Baptiste Le Duc --- Changes in v3: - New patch. --- --- xen/arch/riscv/include/asm/riscv_encoding.h | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/xen/arch/riscv/include/asm/riscv_encoding.h b/xen/arch/riscv/i= nclude/asm/riscv_encoding.h index 03e186bcdb8c..647268e6d0d4 100644 --- a/xen/arch/riscv/include/asm/riscv_encoding.h +++ b/xen/arch/riscv/include/asm/riscv_encoding.h @@ -857,16 +857,18 @@ #error "Unexpected __riscv_xlen" #endif =20 -#define INSN_16BIT_MASK 0x3 -#define INSN_32BIT_MASK 0x1c +#define INSN_IS_16BIT(insn) (((insn) & 3) !=3D 3) +#define INSN_IS_32BIT(insn) (!INSN_IS_16BIT(insn) && ((insn) & 0x1c) !=3D = 0x1c) =20 -#define INSN_IS_16BIT(insn) \ - (((insn) & INSN_16BIT_MASK) !=3D INSN_16BIT_MASK) -#define INSN_IS_32BIT(insn) \ - (((insn) & INSN_16BIT_MASK) =3D=3D INSN_16BIT_MASK && \ - ((insn) & INSN_32BIT_MASK) !=3D INSN_32BIT_MASK) - -#define INSN_LEN(insn) (INSN_IS_16BIT(insn) ? 2 : 4) +/* + * Length in bytes of the instruction whose first parcel is @insn: 2 or 4,= or + * 0 when the encoding is 48 bits or wider. No ratified extension defines = an + * instruction of such a length, so rather than open-coding a decoder for + * encodings which cannot legitimately occur, leave it to the caller to tr= eat + * the 0 as an illegal instruction. + */ +#define INSN_LEN(insn) \ + (INSN_IS_16BIT(insn) ? 2 : (INSN_IS_32BIT(insn) ? 4 : 0)) =20 #if __riscv_xlen =3D=3D 64 #define LOG_REGBYTES 3 --=20 2.55.0 From nobody Fri Oct 23 15:32:28 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) client-ip=192.237.175.120; envelope-from=xen-devel-bounces@lists.xenproject.org; helo=lists.xenproject.org; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=pass(p=none dis=none) header.from=gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1790785205; cv=none; d=zohomail.com; s=zohoarc; b=cnxoMIcOEbBa7McAd8KFdVfFOz1lbB0DdrgFfyiFa02rHtM7yPkdaS8E8As8ZFpAJMJa6BQGRHjMSf5DhNXuRwQfefTQ3W9sD+KmQDs73t9FdgbjOXHQ4rhXn8WBvEMBvT0/DomQmp2FhEtxVWTgPWsbDx0goKWM1kzlHI7Ww14= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1790785205; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=4+PNt+3y/KK2OFRC3rLj+FscDUEuDZDVKtqoLnTNDd8=; b=A8j8OFs8EfQpqAju7RlyZlppLiIMaH6BZ8ty6DY+pVmSOwxFnkF7sdXIwGX0gEVLpH0UbhV8AyO9TtWsJhJ9rI3thQRCnk+5DfyWDfMkcaEVaJ7jwNcBPTtPWD4NsfD0sPAtzZ2AomVJaOvz/UvJdg0yyVLrThtGUH4GZWsMtuw= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) by mx.zohomail.com with SMTPS id 1790785205611627.4685077937745; Wed, 30 Sep 2026 09:20:05 -0700 (PDT) Received: from list by lists.xenproject.org with outflank-mailman.1437472.1656360 (Exim 4.92) (envelope-from ) id 1xBx1y-0005h9-0V; Wed, 30 Sep 2026 16:19:42 +0000 Received: by outflank-mailman (output) from mailman id 1437472.1656360; Wed, 30 Sep 2026 16:19:41 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1xBx1x-0005h0-U0; Wed, 30 Sep 2026 16:19:41 +0000 Received: by outflank-mailman (input) for mailman id 1437472; Wed, 30 Sep 2026 16:19:40 +0000 Received: from mx.expurgate.net ([195.190.135.20]) by lists.xenproject.org with esmtp (Exim 4.92) id 1xBx1w-0005eR-Os for xen-devel@lists.xenproject.org; Wed, 30 Sep 2026 16:19:40 +0000 Received: from mx.expurgate.net (helo=localhost) by mx.expurgate.net with esmtp id 1xBx1w-0008b7-5Y for xen-devel@lists.xenproject.org; Wed, 30 Sep 2026 18:19:40 +0200 Received: from [10.42.69.7] (helo=localhost) by localhost with ESMTP (eXpurgate MTA 0.9.1) (envelope-from ) id 6abd3681-8faa-0a2a0a5109dd-0a2a4507d690-26 for ; Wed, 30 Sep 2026 18:19:40 +0200 Received: from [74.125.225.141] (helo=mail-wm2-f13.google.com) by tlsNG-ef75cf.mxtls.expurgate.net with ESMTPS (eXpurgate 4.57.1) (envelope-from ) id 6abd369b-b4ea-0a2a45070019-4a7de18d9786-3 for ; Wed, 30 Sep 2026 18:19:40 +0200 Received: by mail-wm2-f13.google.com with SMTP id 5b1f17b1804b1-49e71cdb22bso40972675e9.2 for ; Wed, 30 Sep 2026 09:19:39 -0700 (PDT) Received: from fedora (user-109-243-71-234.play-internet.pl. [109.243.71.234]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-4a01eb60804sm2807245e9.1.2026.09.30.09.19.37 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 30 Sep 2026 09:19:38 -0700 (PDT) X-Outflank-Mailman: Message body and most headers restored to incoming version X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" Authentication-Results: eu.smtp.expurgate.cloud; dkim=pass header.s=20251104 header.d=gmail.com header.i="@gmail.com" header.h="Content-Transfer-Encoding:MIME-Version:References:In-Reply-To:Message-ID:Date:Subject:Cc:To:From" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1790785179; x=1791389979; darn=lists.xenproject.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=4+PNt+3y/KK2OFRC3rLj+FscDUEuDZDVKtqoLnTNDd8=; b=eJtCy719ZseeOFzPTJ+qSfYbGpetxFK0vOY2YLQFytrVHmna5RnZfYJwzyaUmMM36V MapKtDKpOYBPe0zL22Cr4cifmLlCJT3mRjjg8p8MhuVbvnRLzba6Q+EEYNPqp1KXVL5G MzEjaC2lfi724kZ7PodqWPc98sbIZX4iTHFphBwbFbhAUwyVrc44cpA6djIyuirsfA9C tHWJezUwBe5C6N6EHJMvBoJ9Whl9KVAJwuaelsujGyW3Qgr27rp662B9MKG9tndAaQD5 MOqIq3mu/RCmvrQ8L6LMFKbQOo3k0ztwfdfoz2hLR+COFENelAwpNuor9Vk0hnfwybPD QM8w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1790785179; x=1791389979; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=4+PNt+3y/KK2OFRC3rLj+FscDUEuDZDVKtqoLnTNDd8=; b=a+/ljGDiPcFil7Sm/rlKZj1NbXQBy4fzr7ZwY+bBDWEJR3JVfxqxdV6JUkAxf8hl1z E/CRlPMmVkOYCgF2T904p0aGJwqTJv2CTRkpTQ7l2cSV8nHmLlFrCT8G33lhYvtZGuoe huNl9B8sJq3yRITQcmWPMbs3siA8ckv5ZPTRE1d2hNcDVKUbMHpba7LlgE2Itamt8mj/ OeUEKD+Yi2/kNeBuZe+ePT9XjazB2BhlqirIgFrHksKnowXa++RmF9IFr2EDEdkKSSy3 fXv5dbI/wudJzt9iaxXQlW4JbuQHh9rK90zuEPQzAOqpKaPXsfejNbNZSZiuMCCuKqXy +hMA== X-Gm-Message-State: AFuF++m+PdfutTtCvV+vaw08GQq59TwaQXBcCD0FVn0fjEvQAH61m9Ng CzN9bxwkcU2eRWqN9CsZIAC34G9E5fesRVEBofQCodMubBvuKIqcPSs1rpiW+g== X-Gm-Gg: AYBFou1yeHKIwION5qxR4bKn9d1PwLbaede1I/xZ2yCpaJwiUzpSldiaw3FAjKZaY1k XNDN2ak6idChQC0V2V9sq6OXHB8i0+9D8xzrYYVZ8okEZcN6JUuRESieKPtFMBjTYIZE1+7ILel 5TfcYh4gHpj33J+zRxxJZEY8iHHXKE6aS7JyOKwThebeCREt2Wx4Mh/8AKKLOEM/WB+bJ5OFxPb euKSZNOupYdVl/AEhUsdxP/0YPP1iFYalgD+1PJ9EZqdvqWry51QA/sah94mBnCOpGygrDf3Yu9 x4K7uJgNo0Y0pNbzjRZ/DF34fHHLukZxuQTZ8bhNtlPXM5Vz6tePd/2ZCOTPgp/1n+hWfC13c3H u2wnY9tXBYbNE3EMMzQuC0YjqGaFSHD5kCNilVVPSNKIZixQr1xXgxf0c/UBAkw4xdIwD6mdf63 P4XKdGrEqRrpsPsLvkf/TkciezlddbhvYb/3KqjC0o3u8D+usyuzlQuHu+SFcX46oPmV236P07i 539hRHvTvZ2BE4gKtYGJmPZSnEZ1CuT/Rfvgoug X-Received: by 2002:a05:600c:45d3:b0:49b:d03:8d3a with SMTP id 5b1f17b1804b1-4a01aff2060mr27284845e9.11.1790785179254; Wed, 30 Sep 2026 09:19:39 -0700 (PDT) From: Oleksii Kurochko To: xen-devel@lists.xenproject.org Cc: Romain Caritey , Baptiste Le Duc , Zheng Zhang , Oleksii Kurochko , Alistair Francis , Connor Davis , Andrew Cooper , Anthony PERARD , Michal Orzel , Jan Beulich , Julien Grall , =?UTF-8?q?Roger=20Pau=20Monn=C3=A9?= , Stefano Stabellini Subject: [PATCH v3 02/39] xen/riscv: set the domain type for 64-bit kernel images Date: Wed, 30 Sep 2026 18:18:44 +0200 Message-ID: X-Mailer: git-send-email 2.55.0 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-purgate-ID: tlsNG-ef75cf/1790785180-A5CC7AE4-0F729281/10/73395122804 X-purgate-type: spam X-purgate-size: 1344 X-ZohoMail-DKIM: pass (identity @gmail.com) X-ZM-MESSAGEID: 1790785206040158500 Content-Type: text/plain; charset="utf-8" kernel_image64_probe() never set info->type, so every domain kept the DOMAIN_32BIT value a zeroed KERNEL_INFO_INIT leaves behind, even though Xen on RISC-V is only built for RV64 and accepts nothing but a 64-bit Image. Nothing consumes d->type on RISC-V yet, so there is no functional change. Fixes: f6a20eda9212 ("xen/riscv: add Linux kernel loading support") Signed-off-by: Oleksii Kurochko Acked-by: Jan Beulich Reviewed-by: Baptiste Le Duc --- d->type being left wrong is a bug on its own, whether or not anything consumes it yet. Its future user is "xen/riscv: set the guest's XLEN explicitly in hstatus.VSXL" in this series. The patch is placed ahead of that one, as it fixes an issue which already exists and doesn't depend on it. If preferred, the two can be merged. --- Changes in v3: - New patch. --- --- xen/arch/riscv/kernel.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/xen/arch/riscv/kernel.c b/xen/arch/riscv/kernel.c index 8580cdb32d7a..5601b2818b37 100644 --- a/xen/arch/riscv/kernel.c +++ b/xen/arch/riscv/kernel.c @@ -233,6 +233,8 @@ static int __init kernel_image64_probe(struct kernel_in= fo *info, info->image.text_offset =3D le64_to_cpu(image.text_offset); info->image.start =3D 0; =20 + info->type =3D DOMAIN_64BIT; + info->load =3D kernel_image_load; =20 return 0; --=20 2.55.0 From nobody Fri Oct 23 15:32:28 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) client-ip=192.237.175.120; envelope-from=xen-devel-bounces@lists.xenproject.org; helo=lists.xenproject.org; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=pass(p=none dis=none) header.from=gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1790785203; cv=none; d=zohomail.com; s=zohoarc; b=lnSF7lfTQNlYbYz/MOedDdcuKrLDpIQFcZHkwzw/3GJuZKS0W0Jb+yQ9Y1KJkil8uLb/zVJlGGvxYTtC8syt65Zxqmb7NTN/fDmmyBqipY6Ps6GolVkQqrTeI/b6Tb2mZsffahPYo4u+VsscQDE4080mKMPItEHWFEF5RtUhAhk= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1790785203; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=ndysInZFRd3KJAfO9tj2iTZ8cZtuOYLRyLiwdhRF1Ws=; b=cxpL4xrcrvJm4M93mHZB3XUb9LSBwxx8OXZw4VmcFvCEZmM1bzMXD2SAxJQuqRZuKAV9RMW9MDwB87tq+yOUkbVfpIZFhFEETlljFfD66hEsbFDCXGIhC0zdtuYiQhghhwkqJZNZjC1WlDnuzQrR2DVeYUyJiNY0y54H32gZz+0= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) by mx.zohomail.com with SMTPS id 1790785203853200.93853788620447; Wed, 30 Sep 2026 09:20:03 -0700 (PDT) Received: from list by lists.xenproject.org with outflank-mailman.1437473.1656369 (Exim 4.92) (envelope-from ) id 1xBx20-0005wB-CK; Wed, 30 Sep 2026 16:19:44 +0000 Received: by outflank-mailman (output) from mailman id 1437473.1656369; Wed, 30 Sep 2026 16:19:44 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1xBx20-0005w1-7a; Wed, 30 Sep 2026 16:19:44 +0000 Received: by outflank-mailman (input) for mailman id 1437473; Wed, 30 Sep 2026 16:19:43 +0000 Received: from mx.expurgate.net ([194.145.224.10]) by lists.xenproject.org with esmtp (Exim 4.92) id 1xBx1y-0005se-Vd for xen-devel@lists.xenproject.org; Wed, 30 Sep 2026 16:19:43 +0000 Received: from mx.expurgate.net (helo=localhost) by mx.expurgate.net with esmtp id 1xBx1y-00Ezzr-Ce for xen-devel@lists.xenproject.org; Wed, 30 Sep 2026 18:19:42 +0200 Received: from [10.42.69.4] (helo=localhost) by localhost with ESMTP (eXpurgate MTA 0.9.1) (envelope-from ) id 6abd3695-bab6-0a2a0a5309dd-0a2a4504a40e-6 for ; Wed, 30 Sep 2026 18:19:42 +0200 Received: from [74.125.225.76] (helo=mail-wr2-f12.google.com) by tlsNG-ebf023.mxtls.expurgate.net with ESMTPS (eXpurgate 4.57.1) (envelope-from ) id 6abd369e-b57f-0a2a45040019-4a7de14ca077-3 for ; Wed, 30 Sep 2026 18:19:42 +0200 Received: by mail-wr2-f12.google.com with SMTP id ffacd0b85a97d-482f6350f91so3275942f8f.1 for ; Wed, 30 Sep 2026 09:19:42 -0700 (PDT) Received: from fedora (user-109-243-71-234.play-internet.pl. [109.243.71.234]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-4a01eb60804sm2807245e9.1.2026.09.30.09.19.39 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 30 Sep 2026 09:19:40 -0700 (PDT) X-Outflank-Mailman: Message body and most headers restored to incoming version X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" Authentication-Results: eu.smtp.expurgate.cloud; dkim=pass header.s=20251104 header.d=gmail.com header.i="@gmail.com" header.h="Content-Transfer-Encoding:MIME-Version:References:In-Reply-To:Message-ID:Date:Subject:Cc:To:From" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1790785182; x=1791389982; darn=lists.xenproject.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=ndysInZFRd3KJAfO9tj2iTZ8cZtuOYLRyLiwdhRF1Ws=; b=i0n2+LqB9ipLcUCuj9QvswiknGlgxvl2/eQhgWcFZ89ORbTbxW+QegYpEXvGeQTxmT /THlwbHqXk2CjvteoEXMeTvlo6I3rAoNBwQYt+fQdFdOdqDa55JDDckwIgEBDAahnkJd NawKBUth/SDy84mwblmwYgIXH3BdKFAFoHJqxjH1Xq2mzsRO8iRSZIAvZochKDB/2nUE RXmWyZpAAYr/CtNPpqtnW8eQAomWN9nMA2CDnBaN2LVyLIYeeKGPoz5H6mrBpRLEYSVz ODExDz5jOLoZnpuGTv2BwR/aVRslR2f0m9QOqu95qjSUc6vTpFDf2TNLJyP2oqT5tRiM zxag== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1790785182; x=1791389982; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=ndysInZFRd3KJAfO9tj2iTZ8cZtuOYLRyLiwdhRF1Ws=; b=0jlHR58QwxePkr1NNdUfCt8TjRZyZMKNrZLCRcwnqJQlJWTk2dHKFEEmP07Kb/t8Cf +Gkeu5/iD57IGFUdad+4bcMTbrpSn3CKAGrhE21rJEgvI+FahzZ9GhXG9j1qRMFwr3T6 p/uo1cBTV+wciwZDLFKCnGFEvNYSaJaUwrqmlbZ9WqKTW/NWnsdkUmzqGr5S1XdJZ4sW qwSa6/RcAP3fP6cFGmo93B72A02/8PUWWyQHTnzTedW5lvNjvsEFzQP06fsUN2+pmrA9 3z0rRGWyM8veomGLVN+rIrVLrGhK/12Fm/KlZc8XDliG2Zz/8VbfuhW3nfWF8DB3trx4 ekUw== X-Gm-Message-State: AFuF++koxhfvyP5d8hKo4nv8j8st1pTSwJS6nPpHa9T/JFPy+hlHMU98 FrTEJTjiNKTZh21Gg+HgUEg/sG7Od7+++zJwtQJGyCiq/WU2CTgpL/kep/ZZHg== X-Gm-Gg: AYBFou2Bstr1PntaMEo1cmrg9lBPOtjlu6OheZEoE3Vk9BiGOj1P2QMc9ysQHYTRSuz nLEUvt77hxNFmuAXXxNpX2MbXA/j5ZSbclaLpbZrcNguEb1Ifd5R0HFgwcVEwQUml0OWLlPm0Vy UanXE9jXBv1F0BLQj8Zx207uZXxJVfu8ZzaX5a2kMyh3ID2EAGc5V3ulKJD52TaV05NL2s/bkfH dNOY6uSAyOKCwZ4AmsiXqySqNchQD9e7SrZssntszmkwWOt3ROK3UxYvwvwIgabsVSF1oEq7Non /jMpnzX6lVSaWDMEW//Er6+XFT3IWp8jqyBFhJ0iex7NiyDnM0ySfF8oakQtshTQVyHCYi1yyu1 R+hwSXbRvSow2lgIrPSdNvdPZYLNVJeukV4tn+9ow4ZSzHTH3bxf4LZ3+pRl0qrUZpTY4PEy4VT DbNcfsmTVo0kH5E3XPtkKHkInepnXqb+LLqeHPaZN8mkjQqvPaaOdvr1krr5cN7JfGRl4R699aR e+bYSuVXlVBgwPamv47lzmx9HjsFlLqxRInrAb6 X-Received: by 2002:a05:600c:a45:b0:49f:fd40:80fa with SMTP id 5b1f17b1804b1-4a01b11de2bmr30435415e9.34.1790785181650; Wed, 30 Sep 2026 09:19:41 -0700 (PDT) From: Oleksii Kurochko To: xen-devel@lists.xenproject.org Cc: Romain Caritey , Baptiste Le Duc , Zheng Zhang , Oleksii Kurochko , Alistair Francis , Connor Davis , Andrew Cooper , Anthony PERARD , Michal Orzel , Jan Beulich , Julien Grall , =?UTF-8?q?Roger=20Pau=20Monn=C3=A9?= , Stefano Stabellini Subject: [PATCH v3 03/39] xen/riscv: introduce csr_volatile_read64() Date: Wed, 30 Sep 2026 18:18:45 +0200 Message-ID: X-Mailer: git-send-email 2.55.0 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-purgate-ID: tlsNG-ebf023/1790785182-50CDFB50-BA9D4029/10/73395122804 X-purgate-type: spam X-purgate-size: 3798 X-ZohoMail-DKIM: pass (identity @gmail.com) X-ZM-MESSAGEID: 1790785206062158500 Content-Type: text/plain; charset="utf-8" On RV32 a 64-bit CSR is accessed as two halves, and H. Reading the halves with two separate instructions isn't always safe: for a CSR which hardware increments, a carry from the low half into the high one can happen in between, so a plain pair of reads can produce a value the CSR never held. Therefore the high half is re-read and the sequence retried if it changed in the meantime. Only CSRs which change under Xen's feet need that, hence the name. The majority can be read with a plain pair of csr_read()s, so no helper for those is introduced here as there would be no user for it. Use it for CSR_TIME, which is exactly such a counter, and widen cycles_t to uint64_t. Otherwise get_cycles() would still truncate the time counter to 32 bits on RV32. No functional change on RV64. Fixes: a541ddadec0a ("xen/riscv: introduce time.h") Signed-off-by: Oleksii Kurochko Reviewed-by: Jan Beulich --- Changes in v3: - Rename csr_read64() to csr_volatile_read64(): only CSRs which change under Xen's feet need the retry, the majority can be read with a plain split access, which isn't introduced here as it would have no user. - Carry the high half read at the end of an iteration over to the next one, instead of reading it twice per retry. - Update the commit message. --- Changes in v2: - New patch. --- --- xen/arch/riscv/include/asm/csr.h | 27 +++++++++++++++++++++++++++ xen/arch/riscv/include/asm/time.h | 4 ++-- 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/xen/arch/riscv/include/asm/csr.h b/xen/arch/riscv/include/asm/= csr.h index 888d6a2a86d6..a5cb24c863dd 100644 --- a/xen/arch/riscv/include/asm/csr.h +++ b/xen/arch/riscv/include/asm/csr.h @@ -39,12 +39,39 @@ csr_write(csr, v_); \ csr_write(csr ## H, v_ >> 32); \ }) + +/* + * The two halves are read by separate instructions, so a CSR which hardwa= re + * increments can carry from the low half into the high one in between, + * yielding a value the CSR never held. Re-read the high half and retry the + * sequence if it changed. + * + * Only needed for CSRs which change under Xen's feet. + */ +#define csr_volatile_read64(csr) \ +({ \ + uint32_t hi_, lo_, old_; \ + \ + hi_ =3D csr_read(csr ## H); \ + do { \ + old_ =3D hi_; \ + lo_ =3D csr_read(csr); \ + } while ( (hi_ =3D csr_read(csr ## H)) !=3D old_ ); \ + \ + ((uint64_t)hi_ << 32) | lo_; \ +}) #else #define csr_write64(csr, val) \ ({ \ csr_write(csr, val); \ (void)csr ## H; \ }) + +#define csr_volatile_read64(csr) \ +({ \ + (void)csr ## H; \ + csr_read(csr); \ +}) #endif =20 #define csr_swap(csr, val) \ diff --git a/xen/arch/riscv/include/asm/time.h b/xen/arch/riscv/include/asm= /time.h index 4d68900151a7..a7c9736ae719 100644 --- a/xen/arch/riscv/include/asm/time.h +++ b/xen/arch/riscv/include/asm/time.h @@ -18,11 +18,11 @@ static inline void force_update_vcpu_system_time(struct= vcpu *v) BUG_ON("unimplemented"); } =20 -typedef unsigned long cycles_t; +typedef uint64_t cycles_t; =20 static inline cycles_t get_cycles(void) { - return csr_read(CSR_TIME); + return csr_volatile_read64(CSR_TIME); } =20 void preinit_xen_time(void); --=20 2.55.0 From nobody Fri Oct 23 15:32:28 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) client-ip=192.237.175.120; envelope-from=xen-devel-bounces@lists.xenproject.org; helo=lists.xenproject.org; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=pass(p=none dis=none) header.from=gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1790785285; cv=none; d=zohomail.com; s=zohoarc; b=UABrqnkyhj3Lo3fcnqYPPhbS0rm6VQGKtTpX/8mWzBBrOsErOGW9B4tWIeRl1WwnnhCEyjw9m16Gfw6XLlZ+63F0Leyo98zCrbyEOYSv9woKih9Z8bg/cYjDckcmXQppttk1E96WyZHXsYqgVyS9riA1KvEcV1PcKAi7OD6AYBI= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1790785285; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=OFod2chJ8fMlZWxxt1ZDOupdRNyKNPgUaDsct9SpfCs=; b=Oh6zF6ywg9PEfmppVUmeOFdq+79H4m/DuHvUh2+GjGFgvx4LcB7BKVJA7uFcayGfFKTwliNi5TbY65B0HveK0bH4ja0UsL6sw5o+wjPeB1SRrrOmhoxGgXQV9fkfL3pPnMvFIORD69GQxIdXh76z0IOAaD7QWDsdzIGBrw1RUM8= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) by mx.zohomail.com with SMTPS id 179078528529975.19622621008114; Wed, 30 Sep 2026 09:21:25 -0700 (PDT) Received: from list by lists.xenproject.org with outflank-mailman.1437474.1656379 (Exim 4.92) (envelope-from ) id 1xBx21-0006Ab-L0; Wed, 30 Sep 2026 16:19:45 +0000 Received: by outflank-mailman (output) from mailman id 1437474.1656379; Wed, 30 Sep 2026 16:19:45 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1xBx21-0006AQ-GJ; Wed, 30 Sep 2026 16:19:45 +0000 Received: by outflank-mailman (input) for mailman id 1437474; Wed, 30 Sep 2026 16:19:44 +0000 Received: from mx.expurgate.net ([194.145.224.10]) by lists.xenproject.org with esmtp (Exim 4.92) id 1xBx20-0005vf-4F for xen-devel@lists.xenproject.org; Wed, 30 Sep 2026 16:19:44 +0000 Received: from mx.expurgate.net (helo=localhost) by mx.expurgate.net with esmtp id 1xBx1z-006NIu-HZ for xen-devel@lists.xenproject.org; Wed, 30 Sep 2026 18:19:43 +0200 Received: from [10.42.69.12] (helo=localhost) by localhost with ESMTP (eXpurgate MTA 0.9.1) (envelope-from ) id 6abd3692-2eae-0a2a0a5409dd-0a2a450ca994-30 for ; Wed, 30 Sep 2026 18:19:43 +0200 Received: from [74.125.225.141] (helo=mail-wm2-f13.google.com) by tlsNG-d25034.mxtls.expurgate.net with ESMTPS (eXpurgate 4.57.1) (envelope-from ) id 6abd369f-f479-0a2a450c0019-4a7de18dc38a-3 for ; Wed, 30 Sep 2026 18:19:43 +0200 Received: by mail-wm2-f13.google.com with SMTP id 5b1f17b1804b1-49b912d37b6so31226555e9.0 for ; Wed, 30 Sep 2026 09:19:43 -0700 (PDT) Received: from fedora (user-109-243-71-234.play-internet.pl. [109.243.71.234]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-4a01eb60804sm2807245e9.1.2026.09.30.09.19.41 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 30 Sep 2026 09:19:42 -0700 (PDT) X-Outflank-Mailman: Message body and most headers restored to incoming version X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" Authentication-Results: eu.smtp.expurgate.cloud; dkim=pass header.s=20251104 header.d=gmail.com header.i="@gmail.com" header.h="Content-Transfer-Encoding:MIME-Version:References:In-Reply-To:Message-ID:Date:Subject:Cc:To:From" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1790785183; x=1791389983; darn=lists.xenproject.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=OFod2chJ8fMlZWxxt1ZDOupdRNyKNPgUaDsct9SpfCs=; b=A907fe2pWlEcoleUDzAYBCUvS5im46UtIPRv9qusFK5SoOWulbJsb2m+Li2BnnFk9j VAHpLBvdWES+3n1gRVjQwETmzV8V//w73jXed/ln/MbesXc1agHYA8cBLXpo0F9NieRQ /SOhPLTZkp4y5NBfqknKEC2uXXl/1B75YpRJk6gkUCkx+UiKh2Ft2QHSqYWrYByNtkgw yrhtg8jaHRwAA+t3g0Ua3HBztJQEpLa3z+DmBneK7E42smCUq+8OFC2bnaipBaJiuOUY dvKfj+YatSvkqAmo+ssQiyDNydMEnMvGxsEcaIsqbI/dQ4rOdrskKQS6ams5VuUhnr9r 7Aew== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1790785183; x=1791389983; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=OFod2chJ8fMlZWxxt1ZDOupdRNyKNPgUaDsct9SpfCs=; b=FoisrMwodvO2MCU+38nXezqT6olBY3BVnkvdDHIGQFUCWGYI5AICZu54m13lRObhbU kLOlgOF9pnayFkn6S+gk5IlwqIVUanE2zrUVPz9EnfwNMRTnDuctfW+J1dK8iIpCiShL NMFpppuB+E/YDLd7RhCPnFoZMqh5nGBooffM5VmJ2YNAq44ndMZzNF3E+DFgeu95eVcQ MsVkn/kZUhTk0kC4YWPUT4vphPuE7QFRlrshDcJ+AVBqK92C49+t4LWy/HUDB4YJXKoF 7tzCkcZJ28j3wgJ/Fb3n9dNsQcfb2Ys65z1ql10ICQN9Gf1xtH7LAJV4tdzKflsMazdY rCiQ== X-Gm-Message-State: AFuF++nWZJfeMTVUCaQ0311TNsQI7A4tpO6nS+WKLk5ZOJ5lyMS7HLrW 7SVNrSSq4OUNk85P5ZOhuVvKyhQmFMNCxl5PpVRjRh4Ytr/VxPxYLvAJeHySaw== X-Gm-Gg: AYBFou35KSyQZUuA+jF2R8JvcInjvmoV0FrcX81HbEmbNJUmV7RrQdodZzW1aBZBxB+ OXQ4Qgyv3IdtA8W6ZoYVFMjc+30G82MPi/1QGQseGD9oAg/je++A0glotsa7EKcuLZqdydcqyue kNhhjX6h9kD1iHXVjqQT174onk/AajgygYQMnyi9Q7fCWGBOH8VJ7T/P/lMRdIJjxj5jqIIPvnI /yPvKGNkAgX5DYtn4IiZCEQHZUlZMTmXQFoSJ9BH5EBtYpedbnM7x3fCmo/PMQXcYwpYRuztEAG SkB4sltrOwEb8CzWxrWgzCnGkm0FXX3vzHqT2ZlpPapMQvm/N4e+WJKAEXtTnLlaD3do/VoeoNG b9UYR+UBoo3Li+LGow8jVNaMCX9VmCuYe2qSkWRybwq+WWOkDOtkkuZRpDOhT/sNBulUZ/Kqr8S IuC6twJgnbtASkDzIMGph8zeQ6NHHC2GXayNNp+g9Z26AuvHPOCKGZAY5Muma1v4szJYueFQn53 qPjLCym+wdp21UFABq6O8Zhdcw0gTsAkzoIdWE4W4wOdAmxLMg= X-Received: by 2002:a05:600c:1c28:b0:4a0:1d1a:6067 with SMTP id 5b1f17b1804b1-4a01d1a619amr15602695e9.34.1790785182845; Wed, 30 Sep 2026 09:19:42 -0700 (PDT) From: Oleksii Kurochko To: xen-devel@lists.xenproject.org Cc: Romain Caritey , Baptiste Le Duc , Zheng Zhang , Oleksii Kurochko , Alistair Francis , Connor Davis , Andrew Cooper , Anthony PERARD , Michal Orzel , Jan Beulich , Julien Grall , =?UTF-8?q?Roger=20Pau=20Monn=C3=A9?= , Stefano Stabellini Subject: [PATCH v3 04/39] xen/riscv: request a G-stage flush on vmenter when VMIDs are disabled Date: Wed, 30 Sep 2026 18:18:46 +0200 Message-ID: <7b3e9a486b348470b3c3b371b6a8d3f7afe0e53f.1790779209.git.oleksii.kurochko@gmail.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-purgate-ID: tlsNG-d25034/1790785183-776D6A5B-43E1CFB0/10/73395122804 X-purgate-type: spam X-purgate-size: 2388 X-ZohoMail-DKIM: pass (identity @gmail.com) X-ZM-MESSAGEID: 1790785286588158500 Content-Type: text/plain; charset="utf-8" vmid_handle_vmenter() reports that no flush is needed when VMIDs are unavailable (e.g. vmid=3Doff, or hardware with no more than one VMID bit). Every domain then runs under VMID 0 with nothing flushed in between, so as soon as a hart runs more than one domain, a domain entered there can use the G-stage translations left behind by the domain which ran before it. Report that a flush is needed on every entry instead. Update the comment in p2m_handle_vmenter() accordingly: without VMIDs the VS-stage TLB doesn't need a separate flush either, as the G-stage flush now done on every entry already covers it. While at it, spell the other early return as a bool literal. Fixes: bff3b9ea4696 ("xen/riscv: introduce VMID allocation and manegement") Signed-off-by: Oleksii Kurochko Acked-by: Jan Beulich Reviewed-by: Baptiste Le Duc --- Changes in v3: - Update the commit message. --- Changes in v2: - New patch. --- --- xen/arch/riscv/p2m.c | 4 +++- xen/arch/riscv/vmid.c | 4 ++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/xen/arch/riscv/p2m.c b/xen/arch/riscv/p2m.c index 1cea86512c8c..de25607247a6 100644 --- a/xen/arch/riscv/p2m.c +++ b/xen/arch/riscv/p2m.c @@ -1584,7 +1584,9 @@ void p2m_handle_vmenter(void) /* * There is also no need to flush the VS-stage TLB: even if speculation * occurs (VSATP + old HGATP were used), it will use the old VMID, whi= ch - * won't be reused until need_flush is set to true. + * won't be reused until need_flush is set to true. When VMIDs aren't + * available there is no old VMID to rely on, but then need_flush is s= et + * on every entry, so the flush above covers that case. */ } =20 diff --git a/xen/arch/riscv/vmid.c b/xen/arch/riscv/vmid.c index 11c7e9d6d6c8..93714b359534 100644 --- a/xen/arch/riscv/vmid.c +++ b/xen/arch/riscv/vmid.c @@ -141,7 +141,7 @@ bool vmid_handle_vmenter(struct vcpu_vmid *vmid) =20 /* Test if VCPU has valid VMID. */ if ( read_atomic(&vmid->generation) =3D=3D data->generation ) - return 0; + return false; =20 /* If there are no free VMIDs, need to go to a new generation. */ if ( unlikely(data->next_vmid > data->max_vmid) ) @@ -164,7 +164,7 @@ bool vmid_handle_vmenter(struct vcpu_vmid *vmid) =20 disabled: vmid->vmid =3D 0; - return 0; + return true; } =20 /* --=20 2.55.0 From nobody Fri Oct 23 15:32:28 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) client-ip=192.237.175.120; envelope-from=xen-devel-bounces@lists.xenproject.org; helo=lists.xenproject.org; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=pass(p=none dis=none) header.from=gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1790785218; cv=none; d=zohomail.com; s=zohoarc; b=j7Ar3UGbfWVuyJyTqyfHsPsx8XBHEwxDaU1fptXtnHvb/I57+/dSQ4Z+nThvXwqu+S78/Fr0gnj7LAdwBDJy3/DKIqmm0rcm4nr+sPT4S56FlB0Yan9ykn4MAtRkN63myHoYX6FV1X/xS7PHRvc1kKZEspDAOffSaHMA5CypfyA= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1790785218; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=0jP5teAbj/qkytYZEEH2E3nqfgZ1G5e5RzALaSNKJXI=; b=OmYnhJusXWwRcEnDVyE3+6glQgSZVwM17aUrrH8J73CsCnjbVAUr8F3TSdDKPGJ9ySk8biXki/2tg+C2Ke3ASizIgazNuIf1fxIxeCgSWSXR+PyFuO/5Pv+HJvXe9i07Fsoyx3z3gwxMfTneBUy9Zo7aVYVgzJHobu5TDL4b66I= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) by mx.zohomail.com with SMTPS id 1790785218083396.6192333176766; Wed, 30 Sep 2026 09:20:18 -0700 (PDT) Received: from list by lists.xenproject.org with outflank-mailman.1437475.1656387 (Exim 4.92) (envelope-from ) id 1xBx22-0006PK-Sj; Wed, 30 Sep 2026 16:19:46 +0000 Received: by outflank-mailman (output) from mailman id 1437475.1656387; Wed, 30 Sep 2026 16:19:46 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1xBx22-0006P6-OC; Wed, 30 Sep 2026 16:19:46 +0000 Received: by outflank-mailman (input) for mailman id 1437475; Wed, 30 Sep 2026 16:19:45 +0000 Received: from mx.expurgate.net ([195.190.135.20]) by lists.xenproject.org with esmtp (Exim 4.92) id 1xBx21-0006AA-Jc for xen-devel@lists.xenproject.org; Wed, 30 Sep 2026 16:19:45 +0000 Received: from mx.expurgate.net (helo=localhost) by mx.expurgate.net with esmtp id 1xBx21-0008es-0a for xen-devel@lists.xenproject.org; Wed, 30 Sep 2026 18:19:45 +0200 Received: from [10.42.69.7] (helo=localhost) by localhost with ESMTP (eXpurgate MTA 0.9.1) (envelope-from ) id 6abd3681-8faa-0a2a0a5109dd-0a2a4507d690-46 for ; Wed, 30 Sep 2026 18:19:44 +0200 Received: from [74.125.225.141] (helo=mail-wm2-f13.google.com) by tlsNG-ef75cf.mxtls.expurgate.net with ESMTPS (eXpurgate 4.57.1) (envelope-from ) id 6abd36a0-b4ea-0a2a45070019-4a7de18ddd8a-3 for ; Wed, 30 Sep 2026 18:19:44 +0200 Received: by mail-wm2-f13.google.com with SMTP id 5b1f17b1804b1-49e71cdb22bso40973325e9.2 for ; Wed, 30 Sep 2026 09:19:44 -0700 (PDT) Received: from fedora (user-109-243-71-234.play-internet.pl. [109.243.71.234]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-4a01eb60804sm2807245e9.1.2026.09.30.09.19.42 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 30 Sep 2026 09:19:43 -0700 (PDT) X-Outflank-Mailman: Message body and most headers restored to incoming version X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" Authentication-Results: eu.smtp.expurgate.cloud; dkim=pass header.s=20251104 header.d=gmail.com header.i="@gmail.com" header.h="Content-Transfer-Encoding:MIME-Version:References:In-Reply-To:Message-ID:Date:Subject:Cc:To:From" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1790785184; x=1791389984; darn=lists.xenproject.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=0jP5teAbj/qkytYZEEH2E3nqfgZ1G5e5RzALaSNKJXI=; b=s9LXGZOTTmuaYu+K0r+8N2bnzpKvpytCfrMaunqjdBAKlymZ8AK3U7Dvp2NfWq05Lc ybczYe1BsmpFlnRmyqIYAfk1jEwTYD+YRZ6C3lvUsK7TefmmsN25CPpDYXYYbiQk7nX+ X2tqKz8XLt+dYLVRE0kgfeU8VQBW1NCeDmDW95OwVfXY7xKcSreKOK340SnX3YQZ3vx9 RdOcj62g0pZmWgq2JLgaVaA93IPTIHXmCEUDEfeproIGQyyQ2pDotiJlJ5QF6W4sVOpC NLhqD6wy5BMbI542LTkLhkNof2dYTDnQW5GfLqJQRJ8Vu6Mk4+U46J4wJ8nMBbcZwpOD JwSg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1790785184; x=1791389984; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=0jP5teAbj/qkytYZEEH2E3nqfgZ1G5e5RzALaSNKJXI=; b=jnaAg9yofUlH9QWU+ip8Yu/v5qgUfupiLVhQj0aoCthFGNPdApfaobNxsrfxUBCuHV y8PfYp8b7x9rKISagklb89T5PVaFnGqpAu/KzoIX8KOJJMY/ahyzbdd/78NHxYFOWFRD i0hC2Dt7rWES7jpIAdNTYWxcTrC3FTlSO3lSJ4jWZwfWzS1XXqGuGTUUSIDxd9bb+WFY GgfzcSsE2L9pggtFzIVQYPhbhx5YSCA9TwlQvaZDGARuU0wZnuHO2hho2rDDy7/Q64Rz hEyG3hjPGdSHYFtbRRDKGqR5rSeNHA8RBk3HrIBUFAWyiDNTssgWlJnYEYzNzzzmk1V3 mebw== X-Gm-Message-State: AFuF++mPsJ5hAv7dRwG9DUMyNj2QWQraT/A2q4cuSQSaaaFPpL4KNJ9B 7RrO4nCrUaQlHvw4qNzUTN9Ci5pIfZZLymUiYbKJUxrw5lCobjR9lNy8N4rHNA== X-Gm-Gg: AYBFou2xI/Lm5Z4Y3tjfBbgZnpXGnPL650QFWpEw01KxMkJPa1O5SQtx2anJiNMFZQQ YxjebtVwuopEnmuL/stvXkzugsK3ZHtepeH6FxHpaHFJ85CVCFhYBTV9nKhsaDTCGqE2pqdgg8n 2EQRDoj8YYxav1cdsY9o24rjVRsfVFPYTqRd7RL4+LejAJH06ugM6bdM6et7w0JI5QFImpvA4Xx abBGP8V56qM+1Ctzhk30q4OJNCV+hvpw9nt9IZgzEgnHtKw5TzPEPeE0ZS/LW59XTh+2tl/TIR/ RkERcUWC+bGKNGbYyvUT3XtSDTfICkkFva8nEI7AJCuzzWF17IQPP8nNlWysOmYviQ0VYSXzNfj e6Q02lyZvMj/W/p4zapfLzf3TZBSkhh4GP7VWInjxjsZUyd7FC3PDXP6dqCmFp3Er9JQJ7VSdXn knglSEbTsPW13rE11IbzWGkveaGCaaDQZSvfYt3bSgJvGomHV8jCC3iqaq4gk339cmrZDj++lHH LBei7H6paUY50k6OJvAeRSUrJUfz9QacDkIP+El X-Received: by 2002:a05:600c:8a16:10b0:4a0:b9:21b5 with SMTP id 5b1f17b1804b1-4a01b12cbcemr27098005e9.30.1790785184065; Wed, 30 Sep 2026 09:19:44 -0700 (PDT) From: Oleksii Kurochko To: xen-devel@lists.xenproject.org Cc: Romain Caritey , Baptiste Le Duc , Zheng Zhang , Oleksii Kurochko , Alistair Francis , Connor Davis , Andrew Cooper , Anthony PERARD , Michal Orzel , Jan Beulich , Julien Grall , =?UTF-8?q?Roger=20Pau=20Monn=C3=A9?= , Stefano Stabellini Subject: [PATCH v3 05/39] xen/riscv: use ~0 instead of ULONG_MAX to disable the VS-timer Date: Wed, 30 Sep 2026 18:18:47 +0200 Message-ID: <96c87282b3c36e910f8d504a1c85e5802f75efad.1790779209.git.oleksii.kurochko@gmail.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-purgate-ID: tlsNG-ef75cf/1790785184-A50CDAE4-8CA6CDC5/10/73395122804 X-purgate-type: spam X-purgate-size: 1845 X-ZohoMail-DKIM: pass (identity @gmail.com) X-ZM-MESSAGEID: 1790785220415158500 Content-Type: text/plain; charset="utf-8" vstimecmp is a 64-bit CSR independently of XLEN, which is why it is written with csr_write64(). On RV32 that macro splits the value into the vstimecmp/vstimecmph pair, so passing ULONG_MAX (0xffffffff there) writes all ones to the low half and zero to the high half, leaving the CSR at 0x00000000ffffffff rather than at its maximum. A VS-timer irq would then become pending as soon as (time + htimedelta) reaches 2^32, which is exactly what the code is trying to avoid. Use ~0 instead: csr_write64() converts its argument to uint64_t, and the conversion of the signed -1 sign-extends to all ones, so both halves get 0xffffffff. On RV64 the result is equal to ULONG_MAX, so no functional change there. Fixes: 25e032730690 ("xen/riscv: allow Xen to use SSTC while hiding it from= guests") Signed-off-by: Oleksii Kurochko Reviewed-by: Baptiste Le Duc Acked-by: Jan Beulich --- Changes in v3: - Add Reviewed-by: Baptiste Le Duc . - Use ~0 instead of UINT64_MAX. - Update the subject and the commit message accordingly. --- Changes in v2: - New patch. --- --- xen/arch/riscv/time.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/xen/arch/riscv/time.c b/xen/arch/riscv/time.c index 602c029641b8..782d9cd450f3 100644 --- a/xen/arch/riscv/time.c +++ b/xen/arch/riscv/time.c @@ -101,8 +101,8 @@ void __init preinit_xen_time(void) * A VS-timer interrupt becomes pending whenever the value of * (time + htimedelta) is greater than or equal to vstimecmp CSR. * Thereby to avoid spurious VS-timer irqs set vstimecmp CSR to - * ULONG_MAX. + * ~0. */ - csr_write64(CSR_VSTIMECMP, ULONG_MAX); + csr_write64(CSR_VSTIMECMP, ~0); } } --=20 2.55.0 From nobody Fri Oct 23 15:32:28 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) client-ip=192.237.175.120; envelope-from=xen-devel-bounces@lists.xenproject.org; helo=lists.xenproject.org; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=pass(p=none dis=none) header.from=gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1790785219; cv=none; d=zohomail.com; s=zohoarc; b=nJq42X6+I72CZfoVuNCjKEyV+XMN2aYy9QtcAlLGyAeani0126xqkRWZ8qoLgaXVPPyJNBhN64XKDUapWSAm/BB0iHa6Wvb+0NVagTXsFjo4rSLmiawZqujFEvPX6KiY1OthA3cbDU9o5Th9T1tdxuYtGV6ZmgDn+yXh5nAO55Y= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1790785219; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=zSU4/LWkp/snZLor2J2IjSVQr3Wp7NAVAmray4t/CSM=; b=Y8EUR3xIY5YWpEgY1eryWc6OAckY9lSETnxNQ0Hmdfy7wNieiRPzQ9IusQTMOipYnZOXNVAdxCBE1arGQRxPP07bJXmMf1MxxpxFyZYmwgMe91YcMWbHXd4CJddXZ5WJKimIaJLWaNG1njGuyimrOz9t6mvGErfmwcuquRl9NG0= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) by mx.zohomail.com with SMTPS id 1790785219548130.91204891569646; Wed, 30 Sep 2026 09:20:19 -0700 (PDT) Received: from list by lists.xenproject.org with outflank-mailman.1437476.1656396 (Exim 4.92) (envelope-from ) id 1xBx25-0006gT-7y; Wed, 30 Sep 2026 16:19:49 +0000 Received: by outflank-mailman (output) from mailman id 1437476.1656396; Wed, 30 Sep 2026 16:19:49 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1xBx25-0006gK-22; Wed, 30 Sep 2026 16:19:49 +0000 Received: by outflank-mailman (input) for mailman id 1437476; Wed, 30 Sep 2026 16:19:46 +0000 Received: from mx.expurgate.net ([194.145.224.10]) by lists.xenproject.org with esmtp (Exim 4.92) id 1xBx22-0006O4-PV for xen-devel@lists.xenproject.org; Wed, 30 Sep 2026 16:19:46 +0000 Received: from mx.expurgate.net (helo=localhost) by mx.expurgate.net with esmtp id 1xBx22-006NIu-6c for xen-devel@lists.xenproject.org; Wed, 30 Sep 2026 18:19:46 +0200 Received: from [10.42.69.12] (helo=localhost) by localhost with ESMTP (eXpurgate MTA 0.9.1) (envelope-from ) id 6abd3692-2eae-0a2a0a5409dd-0a2a450ca994-40 for ; Wed, 30 Sep 2026 18:19:46 +0200 Received: from [74.125.225.141] (helo=mail-wm2-f13.google.com) by tlsNG-d25034.mxtls.expurgate.net with ESMTPS (eXpurgate 4.57.1) (envelope-from ) id 6abd36a2-f479-0a2a450c0019-4a7de18dcecb-3 for ; Wed, 30 Sep 2026 18:19:46 +0200 Received: by mail-wm2-f13.google.com with SMTP id 5b1f17b1804b1-49e7d2bb404so9224985e9.1 for ; Wed, 30 Sep 2026 09:19:46 -0700 (PDT) Received: from fedora (user-109-243-71-234.play-internet.pl. [109.243.71.234]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-4a01eb60804sm2807245e9.1.2026.09.30.09.19.44 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 30 Sep 2026 09:19:44 -0700 (PDT) X-Outflank-Mailman: Message body and most headers restored to incoming version X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" Authentication-Results: eu.smtp.expurgate.cloud; dkim=pass header.s=20251104 header.d=gmail.com header.i="@gmail.com" header.h="Content-Transfer-Encoding:MIME-Version:References:In-Reply-To:Message-ID:Date:Subject:Cc:To:From" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1790785186; x=1791389986; darn=lists.xenproject.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=zSU4/LWkp/snZLor2J2IjSVQr3Wp7NAVAmray4t/CSM=; b=UPhVFWROGj1NfHIebfaaGcQFwkGYKsc7w7Z5b2BZK9ApLt2RyHBU4YpdI8ydwtIg/Z Ag62HTIyKxlht3D83X6hgKOGA0WRzO4SdS0DYw9ml9S6W1i2qXmXIcQn1mQK3GGqmsxp KnXiQ2+Fg28UWzsTB35CqsaqdYuGhGlNoZbKzhEytbZiLRmRUQ+rxbM3HxYNTNsKrU2I XJROUvybX4ciCxqnsjz/UDe2vzhhjNZy6PPdfeDlj7GoXZsnEVV88m3VXtf+aHl/By6g vvVzJZ+Id3YhqBmqrH3wQ/Tz9gPZ6JV4evkU/a2TRZkuNNIGyk1StSd8Lum8SmUHJr9U JQPA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1790785186; x=1791389986; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=zSU4/LWkp/snZLor2J2IjSVQr3Wp7NAVAmray4t/CSM=; b=YgLRemy9erTEhNw/GQzyX8iScXFphrq27nl3hYO393tUOPHqnsSeL2qGyvoRtPr9bs M0okfqB33r8xZ72BLTwcFpk4bwYoqInBvSkhUSWwvIN+HMUVftD6FnXEJhTOb5SYuYMd Rtk7JFAfKq1ZDPDdn0i5mlBZsmSMSjr4mlBFPtkjb1M7D4MdfWoX1BUUNqo6+q3UN0QT LFWcpSwt7K/deYJ4nfyL9zi99AFa6AXe67y4jlERGOMp69cWTl1jT3ucIIuhrLgeE0tK MKZadAcz7cIwUS+PD0dnCrVUYZKFK/f3ijiI86bK3SwtORsN/QJ3+w19QJNU1+5VvUo/ QU9A== X-Gm-Message-State: AFuF++nKnrPAPWOudAS+fdsHYN4KcIwgj33Tup5jHcjpAZLem/buO0m+ NRlCyQXxShBRQI/5xXCliff9EHiflzjubvyymm1A0AA3zCwzpz1+qcZCwZnMaA== X-Gm-Gg: AYBFou1lpcvGkRRjJuai3T8QKJTeUlFnm7uuBq4kNkP8TboBitASIubQXhEV3J5XGpv ttiI0TVKh6rnMec6yfiqzZ7mnRf9pbv2kNFkDtTAQ5YjfqTuKH6RPIlHoSqG9HVr8Bqh2U+Q40E tNKmLn8EuL0PxFDRC7x4UugWHqeG2YGJhWKMT6g31bBKtzinsHYqpWpANgLgeVQfFKNFYlvejoY QJ+JWnl45aObLK7M6A9QKLbZCS4HYOCdoLv+ITZ1/lHNALxlsLti258JGwQGTxJ0lOxMwkc1Ud1 QFYKaxdDSJYpvg4TTLVGM/RD37swUdbxgF9J27vfbbnX92plyG7CrQG605rIjuSIP+COs9T+rjP WRhUnFbsecoPxNpmxPkvE07v3f5JhBzc6o7T/TVLDd0a7EyVMEZD6EKkWXnkO0zhR+w065Wdc9E KS8LWfR+bRz0Zqy078X2rcx6cadFE/IFoguufO3LqRp8YT6jzaLwVUZwmTKUO+UoxRF7V3a+/Vw ANb0Fx0PA5FahkDKYPtIoxFxAs5Zy2w2Gn22CAR X-Received: by 2002:a7b:ca5a:0:b0:49f:fbad:29ae with SMTP id 5b1f17b1804b1-4a01eb19ffdmr1883005e9.17.1790785185448; Wed, 30 Sep 2026 09:19:45 -0700 (PDT) From: Oleksii Kurochko To: xen-devel@lists.xenproject.org Cc: Romain Caritey , Baptiste Le Duc , Zheng Zhang , Oleksii Kurochko , Alistair Francis , Connor Davis , Andrew Cooper , Anthony PERARD , Michal Orzel , Jan Beulich , Julien Grall , =?UTF-8?q?Roger=20Pau=20Monn=C3=A9?= , Stefano Stabellini Subject: [PATCH v3 06/39] xen/riscv: introduce device-agnostic MMIO emulation dispatch Date: Wed, 30 Sep 2026 18:18:48 +0200 Message-ID: X-Mailer: git-send-email 2.55.0 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-purgate-ID: tlsNG-d25034/1790785186-03CD3A5B-F6925B72/10/73395122804 X-purgate-type: spam X-purgate-size: 12556 X-ZohoMail-DKIM: pass (identity @gmail.com) X-ZM-MESSAGEID: 1790785220493158500 Content-Type: text/plain; charset="utf-8" A RISC-V guest can be given several emulated devices at distinct GPA ranges; the virtual interrupt controllers alone account for vPLIC on legacy machines and vAPLIC together with vIMSIC on AIA-compliant ones. Routing MMIO faults via a per-device is_access() check in the trap handler would couple that handler to every device it must serve, requiring a new conditional branch in the fault path for each emulated device added. Introduce a per-domain MMIO handler registration table, modeled after the equivalent ARM framework, so that virtual devices self-register their GPA ranges and read/write callbacks at domain creation time. The MMIO fault path delegates to a single do_mmio() entry point and remains agnostic of which device owns a particular address. Nothing registers a handler and do_mmio() has no callers yet, so this patch is a no-op; the trap handler is left untouched. Signed-off-by: Oleksii Kurochko --- do_mmio() gets its first caller in "xen/riscv: add guest load emulation for trapped MMIO accesses" in this series. --- Changes in v3: - Update the commit message. - Capitalize the comments inside mmio_info_t and drop the list of access widths from the one on len, as it could go stale. - Drop the parentheses around the typedef names. - Reject an access width which isn't a power of 2 in do_mmio(). - Fold the !size check of register_mmio_handler() into end <=3D addr. - Return -EADDRINUSE instead of -EEXIST for an overlapping region. - Drop setting d->arch.vmmio.num_entries to 0, as struct domain starts out zero-filled. --- Changes in v2: - Drop copyright from mmio.c as it will go stale anyway as code moves around. - Drop the max_count parameter of domain_io_init() (MAX_IO_HANDLER is a global boundary) and embed the handler array directly in struct vmmio as struct mmio_handler handlers[MAX_IO_HANDLER]. This removes the xvzalloc_array() allocation, the max_num_entries field and domain_io_free() altogether; domain_io_init() consequently cannot fail any longer and now returns void. Note this goes slightly beyond the suggested variant in that max_num_entries is dropped as well, since ARRAY_SIZE(vmmio->handlers) serves the same purpose. - Drop the separate register_t argument of mmio_read_t/mmio_write_t; handlers now produce and consume the value through info->data. handle_read()/handle_write() are gone as a result, with try_handle_mmio() invoking ops->read()/ops->write() directly. - Turn mmio_read_t/mmio_write_t into function types rather than pointer-to-function types, so that pointer-ness is visible at the use sites in struct mmio_handler_ops. Constify the mmio_info_t * of the write callback, which has no reason to modify it any more. - register_mmio_handler() returns int instead of BUG_ON()ing on a full table: -ENOSPC now lets the caller fail domain creation. It also validates its inputs, rejecting a NULL ops (or one with a missing read/write callback) as well as zero-sized and address-wrapping regions with -EINVAL. - Guarantee the non-overlap property that cmp_mmio_handler() relies on: register_mmio_handler() checks the new region against both neighbours of its insertion slot and returns -EEXIST on overlap. - Replace the sort() call per registration with an insertion into the already sorted array: locate the slot and memmove() the tail up by one. sort(), swap_mmio_handler() and are gone. - Extend cmp_mmio_handler()'s comment to state that it is a bsearch() comparator and to explain the key/elem asymmetry; document why the neighbours' addr + size cannot overflow. - Fix over-long lines and a mis-indented label. --- --- xen/arch/riscv/Makefile | 1 + xen/arch/riscv/domain.c | 3 + xen/arch/riscv/include/asm/domain.h | 3 + xen/arch/riscv/include/asm/mmio.h | 63 ++++++++++ xen/arch/riscv/mmio.c | 175 ++++++++++++++++++++++++++++ 5 files changed, 245 insertions(+) create mode 100644 xen/arch/riscv/include/asm/mmio.h create mode 100644 xen/arch/riscv/mmio.c diff --git a/xen/arch/riscv/Makefile b/xen/arch/riscv/Makefile index 665ec2693335..5454517724bd 100644 --- a/xen/arch/riscv/Makefile +++ b/xen/arch/riscv/Makefile @@ -14,6 +14,7 @@ obj-y +=3D intc.o obj-y +=3D irq.o obj-y +=3D kernel.init.o obj-y +=3D mm.o +obj-y +=3D mmio.o obj-y +=3D p2m.o obj-y +=3D paging.o obj-y +=3D pt.o diff --git a/xen/arch/riscv/domain.c b/xen/arch/riscv/domain.c index d94652809e36..fd6229635627 100644 --- a/xen/arch/riscv/domain.c +++ b/xen/arch/riscv/domain.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include =20 @@ -310,6 +311,8 @@ int arch_domain_create(struct domain *d, if ( (rc =3D p2m_init(d, config)) !=3D 0) goto fail; =20 + domain_io_init(d); + if ( (rc =3D domain_vintc_init(d)) ) goto fail; =20 diff --git a/xen/arch/riscv/include/asm/domain.h b/xen/arch/riscv/include/a= sm/domain.h index e035b33ddfdc..15e8fa19685e 100644 --- a/xen/arch/riscv/include/asm/domain.h +++ b/xen/arch/riscv/include/asm/domain.h @@ -9,6 +9,7 @@ =20 #include #include +#include #include #include =20 @@ -101,6 +102,8 @@ struct arch_domain { const unsigned long *isa; =20 struct vintc *vintc; + + struct vmmio vmmio; }; =20 #include diff --git a/xen/arch/riscv/include/asm/mmio.h b/xen/arch/riscv/include/asm= /mmio.h new file mode 100644 index 000000000000..1bf48571a9f7 --- /dev/null +++ b/xen/arch/riscv/include/asm/mmio.h @@ -0,0 +1,63 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +#ifndef RISCV_MMIO_H +#define RISCV_MMIO_H + +#include +#include + +struct domain; +struct vcpu; + +#define MAX_IO_HANDLER 16 + +typedef struct { + paddr_t gpa; + unsigned int len; /* Access width in bytes */ + bool is_write; + /* Store: value to write; load: value read (set by handler) */ + register_t data; +} mmio_info_t; + +enum io_state +{ + IO_ABORT, /* The IO was handled and led to an abort. */ + IO_HANDLED, /* The IO was successfully handled. */ + IO_UNHANDLED, /* No handler found for the IO. */ +}; + +typedef enum io_state mmio_read_t(struct vcpu *v, mmio_info_t *info); +typedef enum io_state mmio_write_t(struct vcpu *v, const mmio_info_t *info= ); + +struct mmio_handler_ops { + mmio_read_t *read; + mmio_write_t *write; +}; + +struct mmio_handler { + paddr_t addr; + paddr_t size; + const struct mmio_handler_ops *ops; +}; + +struct vmmio { + unsigned int num_entries; + rwlock_t lock; + struct mmio_handler handlers[MAX_IO_HANDLER]; +}; + +int do_mmio(mmio_info_t *info, paddr_t fault_addr, unsigned int len); +int register_mmio_handler(struct domain *d, + const struct mmio_handler_ops *ops, + paddr_t addr, paddr_t size); +void domain_io_init(struct domain *d); + +#endif /* RISCV_MMIO_H */ + +/* + * Local variables: + * mode: C + * c-file-style: "BSD" + * c-basic-offset: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/xen/arch/riscv/mmio.c b/xen/arch/riscv/mmio.c new file mode 100644 index 000000000000..cf739a790afc --- /dev/null +++ b/xen/arch/riscv/mmio.c @@ -0,0 +1,175 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#include +#include +#include +#include +#include + +#include +#include + +/* + * bsearch() comparator: @key holds the address to look up in its addr fie= ld, + * @elem is an entry of vmmio->handlers. Relies on the regions not + * overlapping, which register_mmio_handler() enforces. + */ +static int cmp_mmio_handler(const void *key, const void *elem) +{ + const struct mmio_handler *handler0 =3D key; + const struct mmio_handler *handler1 =3D elem; + + if ( handler0->addr < handler1->addr ) + return -1; + + if ( handler0->addr >=3D (handler1->addr + handler1->size) ) + return 1; + + return 0; +} + +/* + * Return a copy of the matching handler rather than a pointer into + * vmmio->handlers: a concurrent register_mmio_handler() shifts entries + * up to keep the array sorted, so an escaped pointer could refer to a + * different (or torn) entry once the lock is dropped. The copy stays + * valid as the ops structures are never freed. + */ +static bool find_mmio_handler(struct domain *d, paddr_t gpa, + struct mmio_handler *out) +{ + struct vmmio *vmmio =3D &d->arch.vmmio; + struct mmio_handler key =3D { .addr =3D gpa }; + const struct mmio_handler *handler; + + read_lock(&vmmio->lock); + handler =3D bsearch(&key, vmmio->handlers, vmmio->num_entries, + sizeof(*handler), cmp_mmio_handler); + if ( handler ) + *out =3D *handler; + read_unlock(&vmmio->lock); + + return handler !=3D NULL; +} + +static enum io_state try_handle_mmio(mmio_info_t *info) +{ + struct vcpu *v =3D current; + struct mmio_handler handler =3D {}; + + if ( !find_mmio_handler(v->domain, info->gpa, &handler) ) + return IO_UNHANDLED; + + if ( info->is_write ) + return handler.ops->write(v, info); + else + return handler.ops->read(v, info); +} + +/* + * Check alignment and dispatch a decoded MMIO access to a registered + * handler. On success (0), info->data holds the read value for loads. + * + * There is no "retry" outcome to handle: find_mmio_handler() returns a + * copy of the matching handler taken under vmmio->lock and the ops + * structures are never freed, so the lookup result cannot go stale + * between finding the handler and invoking it. + */ +int do_mmio(mmio_info_t *info, paddr_t fault_addr, unsigned int len) +{ + /* Fault address should be aligned to length of MMIO */ + if ( (len & (len - 1)) || (fault_addr & (len - 1)) ) + return -EIO; + + info->gpa =3D fault_addr; + info->len =3D len; + + switch ( try_handle_mmio(info) ) + { + case IO_HANDLED: + return 0; + + case IO_ABORT: + return -EIO; + + default: + return -EOPNOTSUPP; + } +} + +int register_mmio_handler(struct domain *d, + const struct mmio_handler_ops *ops, + paddr_t addr, paddr_t size) +{ + struct vmmio *vmmio =3D &d->arch.vmmio; + struct mmio_handler *handlers =3D vmmio->handlers; + paddr_t end =3D addr + size; + unsigned int i; + int rc =3D 0; + bool overlap; + + if ( !ops || !ops->read || !ops->write || end <=3D addr ) + return -EINVAL; + + write_lock(&vmmio->lock); + + if ( vmmio->num_entries >=3D ARRAY_SIZE(vmmio->handlers) ) + { + rc =3D -ENOSPC; + goto out; + } + + /* + * The array is kept sorted by base address, so rather than appending = and + * re-sorting, find the slot the new region belongs to and shift the t= ail + * up by one. + */ + for ( i =3D vmmio->num_entries; + i > 0 && handlers[i - 1].addr > addr; + i-- ) + /* Nothing to do */; + + /* + * Regions are required not to overlap; check both neighbours. Their + * addr + size cannot overflow, as such regions are rejected above when + * they get registered. + */ + overlap =3D (i > 0 && handlers[i - 1].addr + handlers[i - 1].size > ad= dr) || + (i < vmmio->num_entries && end > handlers[i].addr); + + if ( overlap ) + { + rc =3D -EADDRINUSE; + goto out; + } + + memmove(&handlers[i + 1], &handlers[i], + (vmmio->num_entries - i) * sizeof(*handlers)); + + handlers[i] =3D (struct mmio_handler){ + .addr =3D addr, + .size =3D size, + .ops =3D ops, + }; + + vmmio->num_entries++; + + out: + write_unlock(&vmmio->lock); + + return rc; +} + +void domain_io_init(struct domain *d) +{ + rwlock_init(&d->arch.vmmio.lock); +} + +/* + * Local variables: + * mode: C + * c-file-style: "BSD" + * c-basic-offset: 4 + * indent-tabs-mode: nil + * End: + */ --=20 2.55.0 From nobody Fri Oct 23 15:32:28 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) client-ip=192.237.175.120; envelope-from=xen-devel-bounces@lists.xenproject.org; helo=lists.xenproject.org; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=pass(p=none dis=none) header.from=gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1790785222; cv=none; d=zohomail.com; s=zohoarc; b=G4o+hvNzcliLNIKAkl/BBX/WQSeh35e+2/n2ttz7cg7RSbhfe+T1MkP2F3SXiH49qyhH2+sLEYa3wXktH5S1swL3K7M/N6zhi9iVkHbAvfHr7VhevnIbFzRpwteq5KJ+WLubj4Q0QblNI+5trqqoRU8vghvsQGDcNi7Crl6weXY= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1790785222; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=lHdTYGi1Jbmw7kNLK7RacNslgvIwjTWakn7E42QVdOk=; b=UH36K2tCX5g/HKrfzJLMDanjpBbADRNzxOTkRUdXALCPsj4rNM2jqFOG8xOyjs0TXObgCN+Oj2+csRGMaUQr9Ae58tPqz9IqXp+VdQDMX4PccjQfJ0VjWg1RK6ZVEQqzUYNWb4RpG73BVITg8WdBQWU6r+/0Zh6diaSrGn7FKCc= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) by mx.zohomail.com with SMTPS id 1790785222529517.0255224301687; Wed, 30 Sep 2026 09:20:22 -0700 (PDT) Received: from list by lists.xenproject.org with outflank-mailman.1437478.1656402 (Exim 4.92) (envelope-from ) id 1xBx25-0006n9-SI; Wed, 30 Sep 2026 16:19:49 +0000 Received: by outflank-mailman (output) from mailman id 1437478.1656402; Wed, 30 Sep 2026 16:19:49 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1xBx25-0006kj-Iv; Wed, 30 Sep 2026 16:19:49 +0000 Received: by outflank-mailman (input) for mailman id 1437478; Wed, 30 Sep 2026 16:19:48 +0000 Received: from mx.expurgate.net ([195.190.135.10]) by lists.xenproject.org with esmtp (Exim 4.92) id 1xBx24-0006db-Iw for xen-devel@lists.xenproject.org; Wed, 30 Sep 2026 16:19:48 +0000 Received: from mx.expurgate.net (helo=localhost) by mx.expurgate.net with esmtp id 1xBx23-007398-H7 for xen-devel@lists.xenproject.org; Wed, 30 Sep 2026 18:19:47 +0200 Received: from [10.42.69.9] (helo=localhost) by localhost with ESMTP (eXpurgate MTA 0.9.1) (envelope-from ) id 6abd368b-e002-0a2a0a5209dd-0a2a4509baf2-44 for ; Wed, 30 Sep 2026 18:19:47 +0200 Received: from [74.125.225.99] (helo=mail-wr2-f35.google.com) by tlsNG-bad1c0.mxtls.expurgate.net with ESMTPS (eXpurgate 4.57.1) (envelope-from ) id 6abd36a3-be1a-0a2a45090019-4a7de1639a24-3 for ; Wed, 30 Sep 2026 18:19:47 +0200 Received: by mail-wr2-f35.google.com with SMTP id ffacd0b85a97d-4887840c529so1974070f8f.1 for ; Wed, 30 Sep 2026 09:19:47 -0700 (PDT) Received: from fedora (user-109-243-71-234.play-internet.pl. [109.243.71.234]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-4a01eb60804sm2807245e9.1.2026.09.30.09.19.45 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 30 Sep 2026 09:19:46 -0700 (PDT) X-Outflank-Mailman: Message body and most headers restored to incoming version X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" Authentication-Results: eu.smtp.expurgate.cloud; dkim=pass header.s=20251104 header.d=gmail.com header.i="@gmail.com" header.h="Content-Transfer-Encoding:MIME-Version:References:In-Reply-To:Message-ID:Date:Subject:Cc:To:From" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1790785187; x=1791389987; darn=lists.xenproject.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=lHdTYGi1Jbmw7kNLK7RacNslgvIwjTWakn7E42QVdOk=; b=l06lCOSV7EynRL12EhazaF+x2ynb4OfZQJ6dlteZsRumTf/UXcjibkKOtymWrGi+Ko h+RKx50KC67Qgwr1X591XSCbutUoDKNr9AUlGY+Wavv0Voqth12T217AvSUlKDO1Lhoa IXf9KqT/PXEDGVgxjskG60IoE/mKwbNl64x77uv3i+GdVZhKHWccqXBHwfBihCzFYs+1 wNrS+XAvUN0GtFRBZbuLhml1UVUEVWUuB1Sl8+xLoulb5WF03IjvbwDcFkFJIo+lFJiQ EqAq7pYyHwR/yKiLbPbR0NFXCr2sjW6DHqw/z1ONQF8G89y9ZIpJbP0QaRaVTVfKWglM GEKA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1790785187; x=1791389987; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=lHdTYGi1Jbmw7kNLK7RacNslgvIwjTWakn7E42QVdOk=; b=U9AjTDbidJK6IsrHH+82GQvaX4ta6QB1/E/bL2WdAnmLte2ENXtHfd0vwM4aPZ99US pJISPMnLM4rYNf6qX2ZR2mSLsvSVkdqTUE2lxdMcIVoHpt/szKJkVEgjKJnflrttG3Lv 0J+VUNnjxlToqvK1GvOZfV6yoUD4kB5Wn49cS7SRV9ra0VMbxgSoNa1vA1FOnIlVv0Gi peNgAHTr45FQA9skpnHAYmz01AT7PudL1+wSwCTbATo7AwN4yUvx4zsRr4LlSFyR61CL pXsf5Y/AygQT7PIjwLXkpInCIUxJ5bqTHySK5mRF4nT4CG9rhp3Vk+h38J9qwUJKWeVs s61g== X-Gm-Message-State: AFuF++nBnHGVVrXBA6esIcaPtLUyUdfyZYTOcgxu3hQhwTPkgrSerbj5 CUBol8c8er85jOIn0fuCvjBWVa14jN/Ul1uBvd2JT4oGA47unZEsCosvKqus7A== X-Gm-Gg: AYBFou2+uIUw251YUBvlka3ce99cIq5tbxFqJist2qatnVnER89fGsL40YueEDMDLET OsX9ynpc2N4H7vSQdMuqcFF1i+rfqxvo3PqyfPfyaobfHjkvNQ7jarLeXkzRKr6W1E7AtvGqCat YdIlPku+bygL7td/dAplttT2oQXDMYNYZOFl4cAGA6Fr0nvOxRlZHNf/mRHXB7nHDY6C+P2SrOx LClGT8ZNmHrmKaKkPR5JZybq7hNqwqKi2qYPbtRkZRPLzu89KFnq3mLb5MuHz9bFT6Z3uOS67PF 9rqgiOjqLejJVL4d6/aLhc3MNJsOWnwiNKKlZF4ULKyqSMg+WcSC15P1eoUD0EGqB+metuoapA8 Ny7YMfZHs4fGaESoe+Ss4+3n79Mv71LFYZt/9y8vvnHWkkhVqVJcls+bl9o8jwYkONmBtI9+9zX B1IJos0Kzypuvq/aD6b33OV8Lg9wRkXL2Jz9oLREB5QZJUDq2SUfxZB3sqSFdmx3tv61SCY0jKv LjuIdn8MH/Sus9PcPRIl7fOOYRIYOqbWoPLzekH X-Received: by 2002:a05:600c:5d0:b0:49e:715d:95ca with SMTP id 5b1f17b1804b1-4a01eb12cecmr1590275e9.13.1790785186884; Wed, 30 Sep 2026 09:19:46 -0700 (PDT) From: Oleksii Kurochko To: xen-devel@lists.xenproject.org Cc: Romain Caritey , Baptiste Le Duc , Zheng Zhang , Oleksii Kurochko , Alistair Francis , Connor Davis , Andrew Cooper , Anthony PERARD , Michal Orzel , Jan Beulich , Julien Grall , =?UTF-8?q?Roger=20Pau=20Monn=C3=A9?= , Stefano Stabellini Subject: [PATCH v3 07/39] xen/riscv: introduce CPU_NONE Date: Wed, 30 Sep 2026 18:18:49 +0200 Message-ID: X-Mailer: git-send-email 2.55.0 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-purgate-ID: tlsNG-bad1c0/1790785187-FD06B034-A5D6629D/10/73395122804 X-purgate-type: spam X-purgate-size: 3395 X-ZohoMail-DKIM: pass (identity @gmail.com) X-ZM-MESSAGEID: 1790785224060158500 Content-Type: text/plain; charset="utf-8" Introduce CPU_NONE, a CPU number which doesn't identify any physical CPU, to be used wherever a pCPU has to be recorded but there may be none. Its first user is vsfile_cpu in struct vimsic_state, which records the pCPU whose h/w guest interrupt file backs the vCPU's IMSIC VS-file. NR_CPUS has been used there as the value meaning that there is no such pCPU, i.e. that the s/w VS-file is in use. NR_CPUS is however an upper bound rather than a "no CPU" marker, and it already carries other meanings: hartid_to_cpuid() returns it for a hart Xen doesn't know, and pcpu_info[] uses it for an entry whose processor_id isn't valid yet. Use CPU_NONE for vsfile_cpu instead, so that the s/w VS-file case can't be mistaken for any of those. Signed-off-by: Oleksii Kurochko Reviewed-by: Baptiste Le Duc --- CPU_NONE is also used later in this series: - "xen/riscv: implement virtual APLIC MMIO emulation" checks vsfile_cpu against it to tell whether the target vCPU has a h/w guest interrupt file. - "xen/riscv: implement vCPU context switching" initialises the new arch_vcpu.last_cpu with it, and "xen/riscv: handle the case when no vCPU migration is needed" checks last_cpu against it. - "xen/riscv: remap interrupts to new IMSIC VS-file", "xen/riscv: save and clear the old IMSIC VS-file on vCPU migration" and "xen/riscv: introduce IMSIC h/w interrupt file attaching to vcpu" use it for vsfile_cpu of the s/w IMSIC VS-file. --- Changes in v3: - New patch. --- --- xen/arch/riscv/imsic.c | 4 ++-- xen/arch/riscv/include/asm/config.h | 3 +++ xen/arch/riscv/include/asm/imsic.h | 2 +- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/xen/arch/riscv/imsic.c b/xen/arch/riscv/imsic.c index 44b8640ea39a..402b2f14f591 100644 --- a/xen/arch/riscv/imsic.c +++ b/xen/arch/riscv/imsic.c @@ -357,9 +357,9 @@ int cf_check vcpu_imsic_init(struct vcpu *v) /* * xvzalloc() already cleared the context, so guest_file_id =3D=3D 0, = i.e. the * always-available s/w IMSIC VS-file. Only vsfile_cpu needs an explic= it - * initializer as its s/w VS-file value is NR_CPUS rather than 0. + * initializer as its s/w VS-file value is CPU_NONE rather than 0. */ - imsic_state->vsfile_cpu =3D NR_CPUS; + imsic_state->vsfile_cpu =3D CPU_NONE; =20 v->arch.vimsic_state =3D imsic_state; =20 diff --git a/xen/arch/riscv/include/asm/config.h b/xen/arch/riscv/include/a= sm/config.h index fd69057826e1..fb6203a7d502 100644 --- a/xen/arch/riscv/include/asm/config.h +++ b/xen/arch/riscv/include/asm/config.h @@ -136,6 +136,9 @@ #define OPT_CONSOLE_STR "dtuart" #define INVALID_VCPU_ID MAX_VIRT_CPUS =20 +/* A CPU number which doesn't identify any physical CPU. */ +#define CPU_NONE (~0U) + /* Linkage for RISCV */ #ifdef __ASSEMBLER__ #define CODE_FILL /* empty */ diff --git a/xen/arch/riscv/include/asm/imsic.h b/xen/arch/riscv/include/as= m/imsic.h index 2425430ed116..6baadc008d81 100644 --- a/xen/arch/riscv/include/asm/imsic.h +++ b/xen/arch/riscv/include/asm/imsic.h @@ -71,7 +71,7 @@ struct vimsic_state { */ unsigned int guest_file_id; /* - * s/w IMSIC VS-file -> vsfile_cpu =3D=3D NR_CPUS + * s/w IMSIC VS-file -> vsfile_cpu =3D=3D CPU_NONE * h/w IMSIC VS-file -> vsfile_cpu < NR_CPUS */ unsigned int vsfile_cpu; --=20 2.55.0 From nobody Fri Oct 23 15:32:28 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) client-ip=192.237.175.120; envelope-from=xen-devel-bounces@lists.xenproject.org; helo=lists.xenproject.org; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=pass(p=none dis=none) header.from=gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1790785236; cv=none; d=zohomail.com; s=zohoarc; b=Jb/KdXOVJgYZq60WUbzcuwSm/PFrnJIZNUw1QSkVc67ItgHxpLFpEvSgkBpWYeFd/ihGRBkGAz0Zc8jhaSxiTpHAIo0tDHV1fULpWssGALsu0WtTH03E4mD72h9Jm0cHhQ+HmILp0R973lT4i1/GTdnaBXP08/QBtUYZiO+PE8g= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1790785236; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=V5Kblt+ExtqVzVhNgKdvZ/dnVYhyUbnQhzyOxt3I4h8=; b=auG8KGcKSSzoe5cBN45TQDkTieOd7j3znRIOt87g9MnViqXhHWLIvBDBzEjR6vj0WUbVddSVTWmd6TKscSBQZ3LswqWI46ydzJd17MlMe+TAUmFQ7SxH6tsn3y8aVwMwvKs785bgA34+7Ib1nGjenhf9WNw4um0ljoSfJZzYGio= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) by mx.zohomail.com with SMTPS id 179078523600361.195535206121804; Wed, 30 Sep 2026 09:20:36 -0700 (PDT) Received: from list by lists.xenproject.org with outflank-mailman.1437479.1656414 (Exim 4.92) (envelope-from ) id 1xBx27-0007Db-VL; Wed, 30 Sep 2026 16:19:51 +0000 Received: by outflank-mailman (output) from mailman id 1437479.1656414; Wed, 30 Sep 2026 16:19:51 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1xBx27-0007DE-Rr; Wed, 30 Sep 2026 16:19:51 +0000 Received: by outflank-mailman (input) for mailman id 1437479; Wed, 30 Sep 2026 16:19:50 +0000 Received: from mx.expurgate.net ([195.190.135.10]) by lists.xenproject.org with esmtp (Exim 4.92) id 1xBx25-0006nb-U1 for xen-devel@lists.xenproject.org; Wed, 30 Sep 2026 16:19:50 +0000 Received: from mx.expurgate.net (helo=localhost) by mx.expurgate.net with esmtp id 1xBx25-007398-AS for xen-devel@lists.xenproject.org; Wed, 30 Sep 2026 18:19:49 +0200 Received: from [10.42.69.2] (helo=localhost) by localhost with ESMTP (eXpurgate MTA 0.9.1) (envelope-from ) id 6abd3695-e002-0a2a0a5209dd-0a2a45028710-12 for ; Wed, 30 Sep 2026 18:19:49 +0200 Received: from [74.125.225.141] (helo=mail-wm2-f13.google.com) by tlsNG-720697.mxtls.expurgate.net with ESMTPS (eXpurgate 4.57.1) (envelope-from ) id 6abd36a5-6ca4-0a2a45020019-4a7de18de71a-3 for ; Wed, 30 Sep 2026 18:19:49 +0200 Received: by mail-wm2-f13.google.com with SMTP id 5b1f17b1804b1-49ffbd83a92so35192395e9.0 for ; Wed, 30 Sep 2026 09:19:49 -0700 (PDT) Received: from fedora (user-109-243-71-234.play-internet.pl. [109.243.71.234]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-4a01eb60804sm2807245e9.1.2026.09.30.09.19.46 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 30 Sep 2026 09:19:47 -0700 (PDT) X-Outflank-Mailman: Message body and most headers restored to incoming version X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" Authentication-Results: eu.smtp.expurgate.cloud; dkim=pass header.s=20251104 header.d=gmail.com header.i="@gmail.com" header.h="Content-Transfer-Encoding:MIME-Version:References:In-Reply-To:Message-ID:Date:Subject:Cc:To:From" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1790785189; x=1791389989; darn=lists.xenproject.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=V5Kblt+ExtqVzVhNgKdvZ/dnVYhyUbnQhzyOxt3I4h8=; b=chi7TYEfMiXarZQ6ZcacKK+INvZp1KRhQqQ/ZWYRGkKq13V90jQhTB21oJyLU4D5N8 8WGNHUHGjtCNnvljwugjo2l3jRgGbuZkZndIzROAUX8OYowrRfu8NGxh6AZ6GMrNCqvu +QkBG+T0eWjOUe1JBFc5ZA6Vk8GA58jM45Yh3tIjZTM0Xl4mRNznIoJNW2buY4UA69jf sz3126m7Cjp2y94kXogHYGsO+AVnLOEPS4vHEQpJmiZlW/v2ErkezE8blbWIRz92m44B kzjoeg/JzJd+aVBqTz6Giu4yd9YH9QndGwjhuX0IbJiYNuisb26vA4C+GLcEC4tHhOeY 0boQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1790785189; x=1791389989; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=V5Kblt+ExtqVzVhNgKdvZ/dnVYhyUbnQhzyOxt3I4h8=; b=Yw6mcaP/YYtW7irQY91uy0zdkK3gX7cHgfg6PjHoBvyZGKquaQVzdbO/s+r/1g6BL1 Z2gBZaLtUuYxkJkXr4VfPuKDDDYjwErIINrXw/ljcjgRQ/EE+sfw7YF+UCcPEMG2tv5l X0tgFqftWkgzrYpizs/43bDSmURjueml2TdyeF7k5zf/+6aDqAzz9944ZcSj1BMoOx87 Au3IOvUkJW1Ic4gknuutxX3TJ+NYi3Ser+jCZMU29MWQf1TDOCnKNE+8k+6wUPk+JLmp l4xQb5V9kP48yIXq3NJ84DL7I0FaZk7E2DdpSRYCt6q8zAVsYloh9aXoh/ayRSTCa/yA aX3g== X-Gm-Message-State: AFuF++ngzFQ3GMpQxXdOOdZ5E8inlzbDTdbnVM2g6qdttrJba9UESgxU iPww4SRvx21ZDykgcZUAbiqc31+pECPOzL2kca1RIAByH+Gv+EdAdhs1FitpDA== X-Gm-Gg: AYBFou1kA8GOzFidV/Y2K2wnSa2Lvu95d+kkfYjSlu+L5YzRinrVudtRbAUi8TyVYID ypaIIn0bQUoQrd4ck5aAWMjYlevPi0Juc7/5+zn3FD+mlJcK0DWoLHpGxs3Vx/DLpY2wPjbRWS7 ryKon6I+bdYcw2YJpys6fx7p4vo6cqOrreBKf+IaOPvqlXbDGNP5z3ck0uKPMuI0UlKtGXdNFbt 9zD9Qjz93ocLP8ODjF0r6W5We/0TyBY35sf/u7hlbhIoPPdqq5NtaOeQRAzNTrovrcxnYMnIb2Q hJ7DcadDu8ppPkBnJlejgD0t3X1K0Le3naxWKYmg4ZG3VpG+dxeBgxLjJWsjc9VRoomuUS97OAR LWCMdlBQFSc0ND5QDG06t4vbqcR0XZi2bLubCCnWMPYD/cMJ6bZJuQrOyd5eLM5uxvRPBkdUe9P +Dh0dbDUckxYwBZWcCh/EnSRkQTeQTKrFvIvNtpd2ar8yX9xZw8hBFKtsa316TBsQjI3RHutoQL AISy98yvmsWl+1LBEP6b35ttXQPm8Z8KHNo++9y X-Received: by 2002:a05:600c:354e:b0:4a0:b6:460f with SMTP id 5b1f17b1804b1-4a01b132a27mr32980865e9.33.1790785188063; Wed, 30 Sep 2026 09:19:48 -0700 (PDT) From: Oleksii Kurochko To: xen-devel@lists.xenproject.org Cc: Romain Caritey , Baptiste Le Duc , Zheng Zhang , Oleksii Kurochko , Alistair Francis , Connor Davis , Andrew Cooper , Anthony PERARD , Michal Orzel , Jan Beulich , Julien Grall , =?UTF-8?q?Roger=20Pau=20Monn=C3=A9?= , Stefano Stabellini Subject: [PATCH v3 08/39] xen/riscv: implement virtual APLIC MMIO emulation Date: Wed, 30 Sep 2026 18:18:50 +0200 Message-ID: X-Mailer: git-send-email 2.55.0 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-purgate-ID: tlsNG-720697/1790785189-F3EBB2AC-3BBA4FEF/10/73395122804 X-purgate-type: spam X-purgate-size: 32595 X-ZohoMail-DKIM: pass (identity @gmail.com) X-ZM-MESSAGEID: 1790785236323158500 Content-Type: text/plain; charset="utf-8" Guests running under Xen program interrupt routing by writing to APLIC MMIO registers. Xen must intercept these accesses to enforce interrupt isolation between domains and to translate guest routing intent into the underlying physical MSI topology. Register the vAPLIC range with the MMIO dispatch and emulate the accesses: - reads and writes are masked with the domain's authorised interrupt bitmap, so that a guest can neither observe nor affect interrupts it does not own; - target registers are shadowed per source, so that a guest reads back what it wrote. The h/w register instead gets the hart index and guest interrupt file of the pCPU the target vCPU's interrupt file lives on, as the APLIC uses these fields directly to compute the MSI address. As long as the target vCPU has no h/w guest interrupt file, only the shadow copy is updated; - only MSI delivery mode is emulated: target writes made while the guest's domaincfg.DM is clear are ignored. Delegation (APLIC_SOURCECFG_D) is not yet supported. Co-developed-by: Romain Caritey Signed-off-by: Oleksii Kurochko --- Changes in v3: - sourcecfg store emulation: mask the guest value with the new APLIC_SOURCECFG_WMASK (D and SM are the only implemented fields, all the other bits are reserved and read as zero) instead of rejecting the write when the value is above APLIC_SOURCECFG_SM_LEVEL_LOW. The dropped check compared the whole value against 7 rather than the SM field, so a legal SM with anything set in the reserved bits 9:3 was rejected. SM is WARL and vAPLIC keeps no shadow copy of sourcecfg[], so a reserved SM value is left to the h/w to normalize; add a TODO covering what will have to be emulated here once sourcecfg[] is shadowed. - Introduce APLIC_SOURCECFG_WMASK in asm/aplic.h. - target store emulation: reword the comment about a non-zero guest index to say that such a write is illegal and is therefore ignored as a whole, that the shadow copy keeps the zero it was allocated with, and that aplic_msi_target_gen() overwrites the field with vcpu_guest_file_id() anyway. Drop the now-redundant "Ignore such writes ..." comment. - s/aplic_hart_field/aplic_hart_index/ (and the local variable with it): the value is the APLIC "Hart Index", not a field of it. - Clarify the MSI target address documentation above aplic_hart_index(): name the Guest Index in the address formula, say that the APLIC computes the MSI target address itself in MSI delivery mode, and label the two parts of the 14-bit Hart Index field as g and h to match the surrounding text. - Don't add the MSI target address scheme diagram to asm/imsic.h: it would duplicate the one documented above aplic_hart_index(). - Fix the comment on APLIC_TARGET_IPRIO: the field exists when the target is in direct delivery mode (domaincfg.DM =3D 0), not "in DM mode". - Rearrange the case blocks of vaplic_emulate_load() and vaplic_emulate_store() primarily by register offset: APLIC_DOMAINCFG comes first and APLIC_SOURCECFG handling directly follows it; the set/clr-num registers are also listed in offset order. No functional change. - Rename the first parameter of aplic_msi_target_gen() from target_vcpu to v. - Use a const-qualified pointer in aplic_hw_read_reg()'s cast to match readl()'s prototype. - Put APLIC_xMSICFGADDR_PPN_HHX_MASK(), APLIC_xMSICFGADDR_PPN_LHX_MASK() and APLIC_xMSICFGADDR_PPN_LHX_SHIFT() on a single line each. - Use gdprintk() instead of dprintk() for guest-triggered messages in vaplic.c and drop the redundant "is passed" from the word_idx message. - Call domain_vaplic_deinit() in both failure paths of domain_vaplic_init() instead of open-coding the clean-up. - aplic_msi_target_gen() takes the hart index from the pCPU the vCPU's interrupt file lives on (vsfile_cpu) instead of v->processor, which may already name the new pCPU while the vCPU is being migrated. Callers have to hold vsfile_lock until the value is written to the h/w, which the vAPLIC target write path now does. - A target register write for a vCPU which has no h/w guest interrupt file yet (its vsfile_cpu is CPU_NONE) only updates the stored copy; the h/w register isn't programmed, as there is neither a hart nor a guest interrupt file to point it at. Add a TODO about s/w guest interrupt files, for which the h/w register will have to be written too. - Turn vaplic_regs.target[] into vaplic_regs.sources[], an array of struct vaplic_source holding the guest's view of the target register together with a per-source lock which keeps the stored copy and the h/w target register updated as a pair. Document how many elements it holds and why index 0 is unused. - Drop the emulation of target register writes in direct delivery mode: such writes are ignored with a one-time warning. Resolve the target vCPU only in the MSI delivery mode path, where it is used. --- Changes in v2: - Shadow the guest-written target registers in a per-domain array and serve reads of APLIC_TARGET_* from it: the hardware register holds the value produced by aplic_msi_target_gen() (physical hart field, VS-file id), so reading it back would expose the host layout and return something the guest never wrote. A non-zero guest index is dropped with a one-time warning instead of being echoed back. - aplic_hart_field(): take a CPU id instead of a hartid and derive both the group and the hart index from msi->base_addr + msi->offset - the hart index bits are a part of that offset, so the hartid can't be used as the hart index. Add APLIC_xMSICFGADDR_PPN_LHX_{MASK,SHIFT} for that. - Document the IMSIC MSI target address layout and the APLIC hart index packing above aplic_hart_field(), and correct the corresponding diagram in asm/imsic.h. - Drop the mask parameter of aplic_hw_read_reg() and apply the authorization mask in vaplic_emulate_load() instead. - vaplic_emulate_{load,store}(): return bool instead of int, rename v/d to curr/currd and add ASSERT(curr =3D=3D current). - Use domain_vcpu() instead of open-coded d->vcpu[] indexing when resolving the target hart index. - s/APLIC_REG_OFFSET_MASK/APLIC_CTRL_REGION_OFFSET_MASK/. - Update store emulation handling for target register to be able to deal with target format in both cases (MSI and Direct). - Update store emulation handling of domaincfg. There is no need to force DM/IE mode here (it will be forced/checked on Xen irq handler side). - Rename APLIC_DEFAULT_PRIORITY and move to aplic.h as default prioity value is used in vaplic code too now. --- --- xen/arch/riscv/aplic-priv.h | 2 + xen/arch/riscv/aplic.c | 138 +++++++++- xen/arch/riscv/include/asm/aplic.h | 37 +++ xen/arch/riscv/include/asm/vaplic.h | 19 ++ xen/arch/riscv/vaplic.c | 384 +++++++++++++++++++++++++++- 5 files changed, 575 insertions(+), 5 deletions(-) diff --git a/xen/arch/riscv/aplic-priv.h b/xen/arch/riscv/aplic-priv.h index 35100d3a64fe..2245029b105d 100644 --- a/xen/arch/riscv/aplic-priv.h +++ b/xen/arch/riscv/aplic-priv.h @@ -47,4 +47,6 @@ struct aplic_priv { */ extern unsigned int guest_aplic_num_sources; =20 +uint32_t aplic_msi_target_gen(const struct vcpu *v, uint32_t base_val); + #endif /* ASM_RISCV_APLIC_PRIV_H */ diff --git a/xen/arch/riscv/aplic.c b/xen/arch/riscv/aplic.c index 17c96177a3b1..febc451760bf 100644 --- a/xen/arch/riscv/aplic.c +++ b/xen/arch/riscv/aplic.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -28,8 +29,6 @@ #include #include =20 -#define APLIC_DEFAULT_PRIORITY 1 - static struct aplic_priv aplic =3D { .lock =3D SPIN_LOCK_UNLOCKED, }; @@ -38,6 +37,137 @@ static struct intc_info __ro_after_init aplic_info =3D { .hw_variant =3D INTC_APLIC, }; =20 +/* + * The arrangement of IMSIC interrupt files in MMIO space follows a topolo= gy + * defined by the RISC-V AIA specification. An IMSIC group is a set of + * interrupt files (e.g., in a cluster or socket) co-located in memory. + * + * The physical address of an outgoing MSI is calculated by bitwise ORing a + * Base Physical Page Number (Base PPN) with the Group Index (g), the Hart + * Index (h) and, for a supervisor-level interrupt domain, the Guest Index: + * + * ( Base PPN | (g << (HHXS + 12)) | (h << LHXS) | Guest Index ) << 12 + * + * where Base PPN, HHXS, LHXS, HHXW and LHXW come from the {m,s}msiaddrcfg= [h] + * registers of the interrupt domain that sends the MSI: + * + * XLEN-1 HHXS+24 LHXS+12 12 0 + * | | | | | + * ------------------------------------------------------------ + * |xxxx| g |xxxxxxxx| h |xxxx|Guest Index| 0 | + * ------------------------------------------------------------ + * + * - g: group number. + * - h: hart number relative to the group. + * - xxxx: remaining Base PPN bits; each gap may be zero-width. + * - Guest Index: selects one of the 4 KiB pages right above the hart's own + * supervisor-level file, i.e. it starts at bit 12; LHXS must therefore = be + * at least as large as the number of guest index bits. + * - Bits 11:0: always zero because IMSIC files are 4 KiB page-aligned. + * + * For wired interrupts in MSI delivery mode (domaincfg.DM =3D 1), the APL= IC + * computes the MSI target address itself from the "Hart Index" field + * (bits 31:18) of the corresponding target[i] register. This 14-bit field + * holds both g and h: + * + * 13 lhxw+hhxw lhxw 0 + * | | | | + * ------------------------------------ + * | 0 | g | h | + * ------------------------------------ + * + * - lhxw (Low Hart Index Width): the number of bits used for the hart num= ber + * within a group. + * - hhxw (High Hart Index Width): the number of bits used for the group + * number; the remaining bits of the field must be zero. + * + * The Guest Index isn't a part of it: for a supervisor-level interrupt do= main + * it has its own field (bits 17:12) in target[i]. + * + * Because there are "xxxx" gaps (Base PPN bits) between the indices in the + * physical address (depending on HHXS and LHXS), software must extract the + * group and hart components separately and pack them into the APLIC-defin= ed + * Hart Index format to ensure correct MSI targeting. + */ +static unsigned long aplic_hart_index(unsigned int cpu) +{ + const struct imsic_config *imsic =3D imsic_get_config(); + const struct imsic_msi *msi =3D &imsic->msi[cpu]; + /* Low Hart Index Shift */ + unsigned int lhxs =3D imsic->guest_index_bits; + /* Low Hart Index Width */ + unsigned int lhxw =3D imsic->hart_index_bits; + /* High Hart Index Width */ + unsigned int hhxw =3D imsic->group_index_bits; + /* High Hart Index Shift */ + unsigned int hhxs =3D + imsic->group_index_shift - APLIC_xMSICFGADDR_PPN_SHIFT * 2; + /* + * msi->base_addr is the base of the MMIO regset this CPU's interrupt + * files live in, and one regset can cover several harts; msi->offset + * selects this CPU's block inside it. The hart index bits are part of + * that offset, so both indexes have to be derived from the full addre= ss. + */ + paddr_t target_addr =3D msi->base_addr + msi->offset; + unsigned long tppn =3D target_addr >> APLIC_xMSICFGADDR_PPN_SHIFT; + unsigned long g =3D + (tppn >> APLIC_xMSICFGADDR_PPN_HHX_SHIFT(hhxs)) & + APLIC_xMSICFGADDR_PPN_HHX_MASK(hhxw); + unsigned long h =3D + (tppn >> APLIC_xMSICFGADDR_PPN_LHX_SHIFT(lhxs)) & + APLIC_xMSICFGADDR_PPN_LHX_MASK(lhxw); + + return (g << lhxw) | h; +} + +/* + * v->processor can't be used here: during a migration it names the new pC= PU + * before the interrupt file is moved there. The caller has to hold + * vsfile_lock until the result is written to the h/w. + */ +uint32_t aplic_msi_target_gen(const struct vcpu *v, uint32_t base_val) +{ + const struct vimsic_state *vimsic_state =3D v->arch.vimsic_state; + unsigned int guest_id =3D vcpu_guest_file_id(v); + unsigned long hart_index; + + ASSERT(rw_is_locked(&vimsic_state->vsfile_lock)); + ASSERT(vimsic_state->vsfile_cpu < NR_CPUS); + + hart_index =3D aplic_hart_index(vimsic_state->vsfile_cpu); + + base_val &=3D APLIC_TARGET_EIID; + base_val |=3D MASK_INSR(guest_id, APLIC_TARGET_GUEST_IDX); + base_val |=3D MASK_INSR(hart_index, APLIC_TARGET_HART_IDX); + + return base_val; +} + +uint32_t aplic_hw_read_reg(unsigned int offset) +{ + unsigned long flags; + uint32_t val; + + ASSERT((offset < aplic.size) && IS_ALIGNED(offset, sizeof(uint32_t))); + + spin_lock_irqsave(&aplic.lock, flags); + val =3D readl((const volatile void __iomem *)aplic.regs + offset); + spin_unlock_irqrestore(&aplic.lock, flags); + + return val; +} + +void aplic_hw_write_reg(unsigned int offset, uint32_t value) +{ + unsigned long flags; + + ASSERT((offset < aplic.size) && IS_ALIGNED(offset, sizeof(uint32_t))); + + spin_lock_irqsave(&aplic.lock, flags); + writel(value, (volatile void __iomem *)aplic.regs + offset); + spin_unlock_irqrestore(&aplic.lock, flags); +} + static void __init aplic_init_hw_interrupts(void) { unsigned int i; @@ -53,9 +183,9 @@ static void __init aplic_init_hw_interrupts(void) /* * Low bits of target register contains Interrupt Priority bits wh= ich * can't be zero according to AIA spec. - * Thereby they are initialized to APLIC_DEFAULT_PRIORITY. + * Thereby they are initialized to APLIC_TARGET_IPRIO_DEFAULT. */ - writel(APLIC_DEFAULT_PRIORITY, &aplic.regs->target[i]); + writel(APLIC_TARGET_IPRIO_DEFAULT, &aplic.regs->target[i]); } =20 writel(APLIC_DOMAINCFG_IE | APLIC_DOMAINCFG_DM, &aplic.regs->domaincfg= ); diff --git a/xen/arch/riscv/include/asm/aplic.h b/xen/arch/riscv/include/as= m/aplic.h index a2af55d54fc0..664bda2cb7eb 100644 --- a/xen/arch/riscv/include/asm/aplic.h +++ b/xen/arch/riscv/include/asm/aplic.h @@ -39,6 +39,13 @@ #define APLIC_DOMAINCFG_IE BIT(8, U) #define APLIC_DOMAINCFG_DM BIT(2, U) #define APLIC_DOMAINCFG_BE BIT(0, U) +/* + * The bits a write may change. Everything else, including the read-only z= ero + * bit 7 and the reserved bits, has to read back as zero, and BE is WARL a= nd + * hardwired to 0 as Xen is little-endian only. + */ +#define APLIC_DOMAINCFG_WMASK (APLIC_DOMAINCFG_IE | \ + APLIC_DOMAINCFG_DM) =20 #define APLIC_SOURCECFG_BASE 0x0004 #define APLIC_SOURCECFG_LAST 0x0ffc @@ -58,6 +65,12 @@ #define APLIC_SOURCECFG_SM_EDGE_FALL 0x5 #define APLIC_SOURCECFG_SM_LEVEL_HIGH 0x6 #define APLIC_SOURCECFG_SM_LEVEL_LOW 0x7 +/* + * All other bits of sourcecfg[] are reserved and read as zero, so drop th= em + * on a write. + */ +#define APLIC_SOURCECFG_WMASK (APLIC_SOURCECFG_D | \ + APLIC_SOURCECFG_SM) =20 #define APLIC_SMSICFGADDR 0x1bc8 #define APLIC_SMSICFGADDRH 0x1bcc @@ -89,6 +102,9 @@ #define APLIC_TARGET_GUEST_IDX GENMASK(17, 12) /* Bit 11 is reserved and reads as zero */ #define APLIC_TARGET_EIID GENMASK(10, 0) +/* If target is in direct delivery mode (domaincfg.DM =3D 0) */ +#define APLIC_TARGET_IPRIO GENMASK(7, 0) +#define APLIC_TARGET_IPRIO_DEFAULT 1U =20 #define APLIC_IDC_SIZE 32 =20 @@ -98,6 +114,24 @@ #define APLIC_SIZE(nr_cpus) \ (APLIC_MIN_SIZE + APLIC_SIZE_ALIGN(APLIC_IDC_SIZE * (nr_cpus))) =20 +/* + * Using setip is fine here, as all SET* and CLR* register groups consist = of 32 + * registers and therefore have identical sizes. + * + * Lowest 2 bits are always zero for SET* and CLR* registers. + */ +#define APLIC_SETCLR_OFFSET_MASK \ + (sizeof_field(struct aplic_regs, setip) - sizeof(uint32_t)) + +#define APLIC_xMSICFGADDR_PPN_SHIFT IMSIC_MMIO_PAGE_SHIFT + +#define APLIC_xMSICFGADDR_PPN_HHX_MASK(hhxw) (BIT(hhxw, UL) - 1) +#define APLIC_xMSICFGADDR_PPN_HHX_SHIFT(hhxs) \ + ((hhxs) + APLIC_xMSICFGADDR_PPN_SHIFT) + +#define APLIC_xMSICFGADDR_PPN_LHX_MASK(lhxw) (BIT(lhxw, UL) - 1) +#define APLIC_xMSICFGADDR_PPN_LHX_SHIFT(lhxs) (lhxs) + struct aplic_regs { uint32_t domaincfg; /* 0x0000 */ uint32_t sourcecfg[1023]; /* 0x0004 */ @@ -141,4 +175,7 @@ struct aplic_regs { uint32_t target[1023]; /* 0x3004 */ }; =20 +uint32_t aplic_hw_read_reg(unsigned int offset); +void aplic_hw_write_reg(unsigned int offset, uint32_t value); + #endif /* ASM_RISCV_APLIC_H */ diff --git a/xen/arch/riscv/include/asm/vaplic.h b/xen/arch/riscv/include/a= sm/vaplic.h index 96080bfbc23b..3a555742bbe0 100644 --- a/xen/arch/riscv/include/asm/vaplic.h +++ b/xen/arch/riscv/include/asm/vaplic.h @@ -11,6 +11,7 @@ #define ASM__RISCV__VAPLIC_H =20 #include +#include #include =20 #include @@ -19,13 +20,31 @@ struct domain; =20 #define to_vaplic(d) container_of((d)->arch.vintc, struct vaplic, vintc) =20 +/* State of one vAPLIC interrupt source. */ +struct vaplic_source { + /* Protects target together with the h/w target register of the source= . */ + spinlock_t lock; + + /* Guest's view of the APLIC target register. */ + uint32_t target; +}; + struct vaplic_regs { uint32_t domaincfg; + + /* + * Indexed by source number. The array holds d->arch.vintc->nr_virqs + * elements; sources[0] is unused as APLIC interrupt sources start fro= m 1. + */ + struct vaplic_source *sources; }; =20 struct vaplic { struct vintc vintc; struct vaplic_regs regs; + + paddr_t regs_start; + unsigned int regs_size; }; =20 int domain_vaplic_init(struct domain *d); diff --git a/xen/arch/riscv/vaplic.c b/xen/arch/riscv/vaplic.c index 6fbdc07805fd..ea4b0dc88951 100644 --- a/xen/arch/riscv/vaplic.c +++ b/xen/arch/riscv/vaplic.c @@ -17,6 +17,7 @@ #include #include #include +#include #include =20 #include "aplic-priv.h" @@ -27,6 +28,313 @@ unsigned int __ro_after_init guest_aplic_num_sources; =20 #define FDT_VAPLIC_INT_CELLS 2 =20 +#define AUTH_IRQ_BIT(d, irqn) \ + (((irqn) < (d)->arch.vintc->nr_virqs) && \ + test_bit(irqn, (d)->arch.vintc->used_irqs)) + +/* + * Convert a byte offset (within a SETIP/CLRIP/SETIE/CLRIE register group)= to + * a 32-bit word index into the used_irqs bitmap. Each word covers 32 + * interrupt sources. For SOURCECFG and TARGET groups the same division al= so + * yields the interrupt number directly, because those arrays store one 32= -bit + * register per source. + */ +#define regoffset_to_word_idx(reg_val) ((reg_val) / sizeof(uint32_t)) + +static uint32_t vaplic_target_read(const struct domain *d, unsigned int ir= qn) +{ + const struct vaplic *vaplic =3D to_vaplic(d); + + /* target[0] doesn't exist so irqn =3D=3D 0 should be impossible */ + if ( !irqn || irqn >=3D vaplic->vintc.nr_virqs ) + return 0; + + return read_atomic(&vaplic->regs.sources[irqn].target); +} + +static inline uint32_t generate_auth_mask(const struct domain *currd, + unsigned int word_idx) +{ + unsigned int first_bit =3D word_idx * sizeof(uint32_t) * BITS_PER_BYTE; + + if ( word_idx >=3D DIV_ROUND_UP(currd->arch.vintc->nr_virqs, + sizeof(uint32_t) * BITS_PER_BYTE) ) + { + gdprintk(XENLOG_DEBUG, "incorrect word_idx(%u)\n", word_idx); + + return 0; + } + + return currd->arch.vintc->used_irqs[first_bit / BITS_PER_LONG] >> + (first_bit % BITS_PER_LONG); +} + +static bool vaplic_emulate_load(const struct vcpu *curr, paddr_t addr, + uint32_t *out) +{ + const struct domain *currd =3D curr->domain; + const struct vaplic *vaplic =3D to_vaplic(currd); + const unsigned int offset =3D addr & APLIC_CTRL_REGION_OFFSET_MASK; + uint32_t auth_mask; + unsigned int i; + + ASSERT(curr =3D=3D current); + + switch ( offset ) + { + case APLIC_DOMAINCFG: + *out =3D vaplic->regs.domaincfg; + + return true; + + case APLIC_SETIP_BASE ... APLIC_SETIP_LAST: + case APLIC_CLRIP_BASE ... APLIC_CLRIP_LAST: + case APLIC_SETIE_BASE ... APLIC_SETIE_LAST: + i =3D regoffset_to_word_idx(offset & APLIC_SETCLR_OFFSET_MASK); + auth_mask =3D generate_auth_mask(currd, i); + + break; + + case APLIC_SETIPNUM: + case APLIC_CLRIPNUM: + case APLIC_SETIENUM: + case APLIC_CLRIE_BASE ... APLIC_CLRIE_LAST: + case APLIC_CLRIENUM: + case APLIC_SETIPNUM_LE: + /* + * Based on the RISC-V AIA spec a read of these registers + * always returns zero + */ + *out =3D 0; + + return true; + + case APLIC_TARGET_BASE ... APLIC_TARGET_LAST: + /* + * As target registers start from 1: + * 0x3000 genmsi + * 0x3004 target[1] + * 0x3008 target[2] + * ... + * 0x3FFC target[1023] + * It is necessary to calculate an interrupt number by subtracting + * APLIC_GENMSI instead of APLIC_TARGET_BASE. + */ + i =3D regoffset_to_word_idx(offset - APLIC_GENMSI); + + *out =3D AUTH_IRQ_BIT(currd, i) ? vaplic_target_read(currd, i) : 0; + + return true; + + default: + gdprintk(XENLOG_WARNING, "Unhandled APLIC read at offset %#x\n", + offset); + + return false; + } + + *out =3D aplic_hw_read_reg(offset) & auth_mask; + + return true; +} + +static bool vaplic_emulate_store(const struct vcpu *curr, paddr_t addr, + uint32_t value) +{ + const struct domain *currd =3D curr->domain; + unsigned int offset =3D addr & APLIC_CTRL_REGION_OFFSET_MASK; + + ASSERT(curr =3D=3D current); + + switch ( offset ) + { + case APLIC_DOMAINCFG: + { + struct vaplic *vaplic =3D to_vaplic(currd); + + vaplic->regs.domaincfg =3D APLIC_DOMAINCFG_RO | + (value & APLIC_DOMAINCFG_WMASK); + + return true; + } + + case APLIC_SOURCECFG_BASE ... APLIC_SOURCECFG_LAST: + /* + * Only D (bit 10) and SM (bits 2:0) are implemented, the rest of = the + * bits are reserved and read as zero, so ignore what a guest writ= es + * to them. + */ + value &=3D APLIC_SOURCECFG_WMASK; + + if ( value & APLIC_SOURCECFG_D ) + { + gdprintk(XENLOG_ERR, "APLIC_SOURCECFG_D isn't supported\n"); + + goto fail; + } + + /* + * SM is WARL, so the reserved values 0x2 and 0x3 need no handling + * here: vAPLIC keeps no shadow copy of sourcecfg[], the value is + * written straight to the h/w register and is read back from it, = so + * it is the h/w which substitutes a legal value for an illegal on= e. + * + * TODO: when vAPLIC starts to shadow sourcecfg[], the WARL behavi= our + * will have to be emulated here instead, e.g.: + * if ( value =3D=3D 0x2 || value =3D=3D 0x3 ) + * value =3D APLIC_SOURCECFG_SM_INACTIVE; + */ + + /* + * As sourcecfg register starts from 1: + * 0x0000 domaincfg + * 0x0004 sourcecfg[1] + * 0x0008 sourcecfg[2] + * ... + * 0x0FFC sourcecfg[1023] + * It is necessary to calculate an interrupt number by subtracting + * APLIC_DOMAINCFG instead of APLIC_SOURCECFG_BASE. + */ + if ( !AUTH_IRQ_BIT(currd, + regoffset_to_word_idx(offset - APLIC_DOMAINCFG)= ) ) + /* Interrupt not enabled, ignore it */ + return true; + + break; + + case APLIC_SETIP_BASE ... APLIC_SETIP_LAST: + case APLIC_CLRIP_BASE ... APLIC_CLRIP_LAST: + case APLIC_SETIE_BASE ... APLIC_SETIE_LAST: + case APLIC_CLRIE_BASE ... APLIC_CLRIE_LAST: + { + unsigned int word_idx =3D + regoffset_to_word_idx(offset & APLIC_SETCLR_OFFSET_MASK); + + value &=3D generate_auth_mask(currd, word_idx); + + break; + } + + case APLIC_SETIPNUM: + case APLIC_CLRIPNUM: + case APLIC_SETIENUM: + case APLIC_CLRIENUM: + case APLIC_SETIPNUM_LE: + if ( !value || !AUTH_IRQ_BIT(currd, value) ) + return true; + + break; + + case APLIC_TARGET_BASE ... APLIC_TARGET_LAST: + { + struct vaplic *vaplic =3D to_vaplic(currd); + /* + * Look at vaplic_emulate_load() for explanation why APLIC_GENMSI = is + * subtracted. + */ + unsigned int srcn =3D regoffset_to_word_idx(offset - APLIC_GENMSI); + + if ( !AUTH_IRQ_BIT(currd, srcn) ) + /* Interrupt not enabled, ignore it */ + return true; + + if ( vaplic->regs.domaincfg & APLIC_DOMAINCFG_DM ) + { + struct vaplic_source *src =3D &vaplic->regs.sources[srcn]; + struct vcpu *target_vcpu; + unsigned int guest_hart_idx =3D + MASK_EXTR(value, APLIC_TARGET_HART_IDX); + unsigned long flags; + struct vimsic_state *vimsic_state; + + target_vcpu =3D domain_vcpu(currd, guest_hart_idx); + + if ( !target_vcpu ) + { + gdprintk(XENLOG_ERR, "Invalid vCPU id in target register\n= "); + + /* Ignore such writings */ + return true; + } + + vimsic_state =3D target_vcpu->arch.vimsic_state; + + /* + * A non-zero guest index asks for delivery to an interrupt fi= le + * of a nested guest. The vIMSIC node has no riscv,guest-index= -bits + * property, so a guest is told its harts have no guest interr= upt + * files and the field reads as zero for them. Such a write is + * illegal and is therefore ignored as a whole: the stored copy + * keeps the zero it was allocated with, so the field never ne= eds + * to be masked out here. + * What ends up in the h/w register is Xen's own value anyway: + * aplic_msi_target_gen() overwrites the field with + * vcpu_guest_file_id() of the target vCPU. + */ + if ( MASK_EXTR(value, APLIC_TARGET_GUEST_IDX) ) + { + printk_once(XENLOG_WARNING + "%pd: vAPLIC target guest index !=3D 0 is unsu= pported\n", + currd); + + return true; + } + + /* + * src->lock keeps the stored copy and the h/w register updated + * as a pair. + */ + spin_lock_irqsave(&src->lock, flags); + + write_atomic(&src->target, value); + + /* IRQs are already off under src->lock. */ + read_lock(&vimsic_state->vsfile_lock); + + /* + * The h/w register names the hart and the guest interrupt file + * MSIs are sent to, and there is none of either until the tar= get + * vCPU is given a h/w guest interrupt file. The stored copy + * reaches the h/w at that point. + * + * TODO: once s/w guest interrupt files are supported, a vCPU = using + * one still needs its MSIs, so the h/w register will have to = be + * written for it too, pointing at an interrupt file Xen recei= ves + * them in on the vCPU's behalf. + */ + if ( vimsic_state->vsfile_cpu !=3D CPU_NONE ) + aplic_hw_write_reg(offset, + aplic_msi_target_gen(target_vcpu, value= )); + + read_unlock(&vimsic_state->vsfile_lock); + + spin_unlock_irqrestore(&src->lock, flags); + + return true; + } + + /* printk_once(), as a guest could otherwise flood the log. */ + printk_once(XENLOG_WARNING + "%pd: vAPLIC direct delivery mode isn't supported\n", + currd); + + return true; + } + + default: + fail: + gdprintk(XENLOG_WARNING, + "Unhandled APLIC write at offset %#x (value %#x)\n", offs= et, + value); + + return false; + } + + aplic_hw_write_reg(offset, value); + + return true; +} + static int __init cf_check vaplic_make_domu_dt_node(struct kernel_info *ki= nfo) { struct domain *d =3D kinfo->bd.d; @@ -95,6 +403,56 @@ static const struct vintc_init_ops __initconstrel init_= ops =3D { .make_domu_dt_node =3D vaplic_make_domu_dt_node, }; =20 +static enum io_state cf_check vaplic_mmio_read(struct vcpu *v, + mmio_info_t *info) +{ + uint32_t val; + + ASSERT(v =3D=3D current); + + if ( info->len !=3D sizeof(uint32_t) || + !IS_ALIGNED(info->gpa, sizeof(uint32_t)) ) + { + gdprintk(XENLOG_DEBUG, + "VAPLIC: unaligned/wrong-width read gpa=3D%"PRIpaddr" len= =3D%u\n", + info->gpa, info->len); + return IO_ABORT; + } + + if ( !vaplic_emulate_load(v, info->gpa, &val) ) + return IO_ABORT; + + /* APLIC registers are 32-bit; zero-extend to the guest register width= . */ + info->data =3D val; + + return IO_HANDLED; +} + +static enum io_state cf_check vaplic_mmio_write(struct vcpu *v, + const mmio_info_t *info) +{ + ASSERT(v =3D=3D current); + + if ( info->len !=3D sizeof(uint32_t) || + !IS_ALIGNED(info->gpa, sizeof(uint32_t)) ) + { + gdprintk(XENLOG_DEBUG, + "VAPLIC: unaligned/wrong-width write gpa=3D%"PRIpaddr" le= n=3D%u\n", + info->gpa, info->len); + return IO_ABORT; + } + + if ( !vaplic_emulate_store(v, info->gpa, info->data) ) + return IO_ABORT; + + return IO_HANDLED; +} + +static const struct mmio_handler_ops vaplic_mmio_ops =3D { + .read =3D vaplic_mmio_read, + .write =3D vaplic_mmio_write, +}; + static const struct vintc_ops vintc_ops =3D { .vcpu_init =3D vcpu_imsic_init, .vcpu_deinit =3D vcpu_imsic_deinit, @@ -103,6 +461,8 @@ static const struct vintc_ops vintc_ops =3D { int domain_vaplic_init(struct domain *d) { struct vaplic *vaplic =3D xvzalloc(struct vaplic); + unsigned int i; + int rc; =20 if ( !vaplic ) return -ENOMEM; @@ -123,7 +483,28 @@ int domain_vaplic_init(struct domain *d) */ d->arch.vintc->nr_virqs =3D guest_aplic_num_sources + 1; =20 - return 0; + /* Slot 0 is unused: APLIC source numbering starts at 1 (see used_irqs= ). */ + vaplic->regs.sources =3D xvzalloc_array(struct vaplic_source, + d->arch.vintc->nr_virqs); + if ( !vaplic->regs.sources ) + { + domain_vaplic_deinit(d); + + return -ENOMEM; + } + + for ( i =3D 0; i < d->arch.vintc->nr_virqs; i++ ) + spin_lock_init(&vaplic->regs.sources[i].lock); + + vaplic->regs_start =3D GUEST_APLIC_S_BASE; + vaplic->regs_size =3D APLIC_SIZE(d->max_vcpus); + + rc =3D register_mmio_handler(d, &vaplic_mmio_ops, + vaplic->regs_start, vaplic->regs_size); + if ( rc ) + domain_vaplic_deinit(d); + + return rc; } =20 void domain_vaplic_deinit(struct domain *d) @@ -135,5 +516,6 @@ void domain_vaplic_deinit(struct domain *d) =20 vaplic =3D to_vaplic(d); d->arch.vintc =3D NULL; + xvfree(vaplic->regs.sources); xvfree(vaplic); } --=20 2.55.0 From nobody Fri Oct 23 15:32:28 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) client-ip=192.237.175.120; envelope-from=xen-devel-bounces@lists.xenproject.org; helo=lists.xenproject.org; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=pass(p=none dis=none) header.from=gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1790785229; cv=none; d=zohomail.com; s=zohoarc; b=DRD+Lu+HVTUaESM6NUCcPEUKdrtfhcqezsNuNV0/1Up6MmNdnYx1ucrWQoM+dRwr1ZYuNyy8U372mtSR8gJMp+5QPqC4oZDTYSixJ3V3UlCT1HFd/cfpchOzs/ZFoCMXKLFaQazpjLYGBaV8uwrO/C+Xnw2x/NN0jh4uhOQkpyQ= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1790785229; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=PlfN5CBy9cV3u57McoKXQYsgCREbvWm+6jvR2D7bz88=; b=HIMJuzIYwEPbicbg6UuHKP7b+6wgzMoVNqN3TrdVrfRHFDE+uLJmEWHvWRYjmUIukfVct7iqAcor1/mSsJHf85+QpnUALjVMcG1MpeVWMTvvUysxXh7ym3tvnTT+VsjKLOk6NGjVXgJP5veyxsfEOBfwGUIWSR14yV0cF/SFG0I= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) by mx.zohomail.com with SMTPS id 179078522984549.467944583026; Wed, 30 Sep 2026 09:20:29 -0700 (PDT) Received: from list by lists.xenproject.org with outflank-mailman.1437481.1656419 (Exim 4.92) (envelope-from ) id 1xBx28-0007HN-GE; Wed, 30 Sep 2026 16:19:52 +0000 Received: by outflank-mailman (output) from mailman id 1437481.1656419; Wed, 30 Sep 2026 16:19:52 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1xBx28-0007Gy-7L; Wed, 30 Sep 2026 16:19:52 +0000 Received: by outflank-mailman (input) for mailman id 1437481; Wed, 30 Sep 2026 16:19:50 +0000 Received: from mx.expurgate.net ([195.190.135.20]) by lists.xenproject.org with esmtp (Exim 4.92) id 1xBx26-0006xa-HT for xen-devel@lists.xenproject.org; Wed, 30 Sep 2026 16:19:50 +0000 Received: from mx.expurgate.net (helo=localhost) by mx.expurgate.net with esmtp id 1xBx25-0008es-UT for xen-devel@lists.xenproject.org; Wed, 30 Sep 2026 18:19:49 +0200 Received: from [10.42.69.7] (helo=localhost) by localhost with ESMTP (eXpurgate MTA 0.9.1) (envelope-from ) id 6abd36a3-8faa-0a2a0a5109dd-0a2a4507c56a-2 for ; Wed, 30 Sep 2026 18:19:49 +0200 Received: from [74.125.225.141] (helo=mail-wm2-f13.google.com) by tlsNG-ef75cf.mxtls.expurgate.net with ESMTPS (eXpurgate 4.57.1) (envelope-from ) id 6abd36a5-b4ea-0a2a45070019-4a7de18df63e-3 for ; Wed, 30 Sep 2026 18:19:49 +0200 Received: by mail-wm2-f13.google.com with SMTP id 5b1f17b1804b1-49ff9642c57so10087755e9.0 for ; Wed, 30 Sep 2026 09:19:49 -0700 (PDT) Received: from fedora (user-109-243-71-234.play-internet.pl. [109.243.71.234]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-4a01eb60804sm2807245e9.1.2026.09.30.09.19.48 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 30 Sep 2026 09:19:48 -0700 (PDT) X-Outflank-Mailman: Message body and most headers restored to incoming version X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" Authentication-Results: eu.smtp.expurgate.cloud; dkim=pass header.s=20251104 header.d=gmail.com header.i="@gmail.com" header.h="Content-Transfer-Encoding:MIME-Version:References:In-Reply-To:Message-ID:Date:Subject:Cc:To:From" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1790785189; x=1791389989; darn=lists.xenproject.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=PlfN5CBy9cV3u57McoKXQYsgCREbvWm+6jvR2D7bz88=; b=aMwZ+fAH8OdyTgiLvN+pwOp0tvkJ6xNdohBOzT6Z0vZmdP2IvLydmE5I9aYvdI0PsR ow1i2jxi1yExPV27a0Rx9aea5uVXlHZGC3TzmAPB3OQ9cnG15Nr6MwCQ9tCpxFnuk8yk t83ESck2reSP4gsMCYFk5IxMhpKttOMlGUeedAYhR5JvEAGb6Oe8M2yGjt4XnSPCbRg0 tznY9aGTGTSr9d5LaJeJMmemnoZRR6Y8158ION3vuvp35Nh3/H6pGEe9F3KiAV10/+Ut f5u3UNOyEnshDtTlqGbed3BiPqmEshojQMTE0NiAM4pu8wzB37WF50ZgMbeOtKgtrnyq 8TXg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1790785189; x=1791389989; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=PlfN5CBy9cV3u57McoKXQYsgCREbvWm+6jvR2D7bz88=; b=phxEcwBHdpcb70zPvHnsB5+SKWDJY5VKRGHVlw7bG90zoC5CYF7bGKR4o3nJ+6vPri Nr6kkqhTMFq2du3lk2ZXZnHp6gCUpPwy2F1BuaF5zIslvDQ6jl43BPhnkNyXTqoYw/0N CVcx7adWSI11gkg/lGEs/8c6ben1oVnot4EmUVMQLczWtGnhoqwLhmhlal1GK8GeRJJh um8uc7m1WmM4kEYzN9emoI+/26S+APs0GOj2SYlGgkTBEmiG1guW0jTiKZ12KO8FkW/K 2dcozqbOjdLKzHp0QAWnyVM+dBeu9j97Z4+SEEw3/SeTuskIBzQ4QphGjgPMK4F3OFmE EdBg== X-Gm-Message-State: AFuF++liX7+HW7ULQe+VMkPXyxmhgbNh0rSxv/P0/krOl+Yhr0uonlO3 9NEdZnNhJtYCh3QPgeF0Y9Gdp+irUKtpVLr8/7mgtz8u7lD6CSSkmCYzLTC7+Q== X-Gm-Gg: AYBFou2or+4zNKsYBfvYVe8xq7akKWr7++neSoYMNSEBPdiN/qcR86tUnpsF+3u76J+ g4l1YLIVRIG/O/QyHvKukPHSA/Fr+ynk3iJq0OwnOGG5v3D00yqW+NKx6C13LcRLmNJNX7RL9Vj XWI2ANkVCmiphF149KMyqTDEmakcjX5wa6lNe9VioNYmOmcXi/MAs+tUyFikkdpR7B1DMjhYx/X urg4INByss3Qe1WvN1K6vKgFV9987QiO5QvzvIj+3U4uHP0knLYC+ym/gmChx0WRYEY5m3Jg7rI kqG0/8V34znY17nvDm7nFLGLVYh1ZbPMLoYdq/4/kH8HGZOSXIs974kuMIQXYtu1avoRHXf8GzT M8bEH6gyhqnZttwJ4LlZsIkJjiWC8V+Nst/ULjrlBvPebUkq+z1i4TeW65jD1VTbVfwBEQ+vBW9 Zx3491HGPSKAXIWtHRRT2cj/mzT31kpHE3Gz6v+n74Og3SxqK5ytovR+HYGyW7XOzx+VB54it7R 1LvH/IisWE14KSfOCqlHjLaOrEH2GRcgwqk6CaH X-Received: by 2002:a05:600c:4ba3:b0:49f:fefc:7d01 with SMTP id 5b1f17b1804b1-4a01eb1339emr1588995e9.15.1790785189193; Wed, 30 Sep 2026 09:19:49 -0700 (PDT) From: Oleksii Kurochko To: xen-devel@lists.xenproject.org Cc: Romain Caritey , Baptiste Le Duc , Zheng Zhang , Oleksii Kurochko , Alistair Francis , Connor Davis , Andrew Cooper , Anthony PERARD , Michal Orzel , Jan Beulich , Julien Grall , =?UTF-8?q?Roger=20Pau=20Monn=C3=A9?= , Stefano Stabellini Subject: [PATCH v3 09/39] xen/riscv: build the target hart index via aplic_hart_index() Date: Wed, 30 Sep 2026 18:18:51 +0200 Message-ID: X-Mailer: git-send-email 2.55.0 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-purgate-ID: tlsNG-ef75cf/1790785189-370DDAE4-389A3620/10/73395122804 X-purgate-type: spam X-purgate-size: 5239 X-ZohoMail-DKIM: pass (identity @gmail.com) X-ZM-MESSAGEID: 1790785230144158500 Content-Type: text/plain; charset="utf-8" aplic_set_irq_affinity() open-coded the packing of the group and hart indices into the target register, and got two things wrong along the way: - imsic_config.msi[] is indexed by logical CPU id, but the index was run through cpuid_to_hartid() first. On any platform where the two spaces differ this picks another CPU's interrupt file, or reads past the array; - the same hart id was then used verbatim as the low hart index, and the group index was derived from msi[].base_addr alone. The hart index bits live in msi[].offset, the base address only covers the MMIO regset, which may hold the files of several harts. Both indices have to come out of base_addr + offset. aplic_hart_index() already extracts them that way, and is what the vAPLIC target path uses, so call it here as well and insert the result with MASK_INSR(APLIC_TARGET_HART_IDX) instead of a bare shift, which keeps the value from spilling out of the 14-bit field. This drops the last in-tree duplicate of the AIA hart index formula, and with it the last user of APLIC_TARGET_HART_IDX_SHIFT, which is removed. desc->irq is used as the EIID as is. Assert that it is a valid APLIC source, which also guarantees that it fits the EIID field. No functional change on a single-group platform whose hart ids match their CPU ids and whose IMSIC regset holds one file per hart. Fixes: d4676a1398bc ("xen/riscv: implementation of aplic and imsic operatio= ns") Signed-off-by: Oleksii Kurochko --- Changes in v3: - s/aplic_hart_field/aplic_hart_index/ (in the subject too) following the rename of the helper in "xen/riscv: implement virtual APLIC MMIO emulation". - Don't mask desc->irq with APLIC_TARGET_EIID. Instead, bound it by the APLIC source range rather than NR_IRQS, which will also have to cover device MSIs: add a BUILD_BUG_ON() that ARRAY_SIZE(target) fits the EIID field and an ASSERT() that desc->irq is a valid APLIC source (1..num_irqs), which also covers the target[desc->irq - 1] index. --- Changes in v2: - New patch. --- --- xen/arch/riscv/aplic.c | 33 ++++++++++-------------------- xen/arch/riscv/include/asm/aplic.h | 1 - 2 files changed, 11 insertions(+), 23 deletions(-) diff --git a/xen/arch/riscv/aplic.c b/xen/arch/riscv/aplic.c index febc451760bf..62bbcc9afacf 100644 --- a/xen/arch/riscv/aplic.c +++ b/xen/arch/riscv/aplic.c @@ -335,9 +335,7 @@ static unsigned int aplic_get_cpu_from_mask(const cpuma= sk_t *cpumask) static void cf_check aplic_set_irq_affinity(struct irq_desc *desc, const c= pumask_t *mask) { unsigned int cpu; - uint64_t group_index, base_ppn; - uint32_t hhxw, lhxw, hhxs, value; - const struct imsic_config *imsic =3D aplic.imsic_cfg; + uint32_t value; =20 /* * TODO: Currently, APLIC is supported only with MSI interrupts. @@ -350,27 +348,18 @@ static void cf_check aplic_set_irq_affinity(struct ir= q_desc *desc, const cpumask =20 ASSERT(spin_is_locked(&desc->lock)); =20 - cpu =3D cpuid_to_hartid(aplic_get_cpu_from_mask(mask)); - hhxw =3D imsic->group_index_bits; - lhxw =3D imsic->hart_index_bits; + cpu =3D aplic_get_cpu_from_mask(mask); + /* - * Although this variable is used only once in the calculation of - * group_index, and it might seem that hhxs could be defined as: - * hhxs =3D imsic->group_index_shift - IMSIC_MMIO_PAGE_SHIFT; - * and then the addition of IMSIC_MMIO_PAGE_SHIFT could be omitted - * when calculating the group index. - * It was done intentionally this way to follow the formula from - * the AIA specification for calculating the MSI address. + * desc->irq is used as the EIID as-is, which is only valid for APLIC + * sources: they are numbered 1..num_irqs, with at most ARRAY_SIZE(tar= get). */ - hhxs =3D imsic->group_index_shift - IMSIC_MMIO_PAGE_SHIFT * 2; - base_ppn =3D imsic->msi[cpu].base_addr >> IMSIC_MMIO_PAGE_SHIFT; - - /* Update hart and EEID in the target register */ - group_index =3D (base_ppn >> (hhxs + IMSIC_MMIO_PAGE_SHIFT)) & - (BIT(hhxw, UL) - 1); - value =3D desc->irq; - value |=3D cpu << APLIC_TARGET_HART_IDX_SHIFT; - value |=3D group_index << (lhxw + APLIC_TARGET_HART_IDX_SHIFT); + BUILD_BUG_ON(ARRAY_SIZE(aplic.regs->target) > + MASK_EXTR(~0U, APLIC_TARGET_EIID)); + ASSERT(desc->irq && desc->irq <=3D aplic_info.num_irqs); + + value =3D MASK_INSR(aplic_hart_index(cpu), APLIC_TARGET_HART_IDX) | + desc->irq; =20 spin_lock(&aplic.lock); =20 diff --git a/xen/arch/riscv/include/asm/aplic.h b/xen/arch/riscv/include/as= m/aplic.h index 664bda2cb7eb..9018936ca95a 100644 --- a/xen/arch/riscv/include/asm/aplic.h +++ b/xen/arch/riscv/include/asm/aplic.h @@ -98,7 +98,6 @@ #define APLIC_TARGET_BASE 0x3004 #define APLIC_TARGET_LAST 0x3ffc #define APLIC_TARGET_HART_IDX GENMASK(31, 18) -#define APLIC_TARGET_HART_IDX_SHIFT 18 #define APLIC_TARGET_GUEST_IDX GENMASK(17, 12) /* Bit 11 is reserved and reads as zero */ #define APLIC_TARGET_EIID GENMASK(10, 0) --=20 2.55.0 From nobody Fri Oct 23 15:32:28 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) client-ip=192.237.175.120; envelope-from=xen-devel-bounces@lists.xenproject.org; helo=lists.xenproject.org; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=pass(p=none dis=none) header.from=gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1790785472; cv=none; d=zohomail.com; s=zohoarc; b=W7MmQNKo8nqd/zwYMXhkMSyzSnbM8BiMdFRVWMVbdzLGIwZqtdor4+Zd8iWXrDR8ZBhkTsA4gRS0PmdmCbaV2dVJZ/lO0XA8nRT33oYlzxrEqDBibqc63FwAlJf+aMWeU0opbW3H/vxENn69z200kMpvB+pKS6tqstRah8AX/YQ= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1790785472; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=3BzXTGnWcfy6ALLYgep1c2vgCuLID+Lhul4DxE5IZxE=; b=HGCrZvbyD3Gegdfw7I/FMg6BSpBl1N0HnuOne39nMWuXTs6kJ1HAgw/sI9xeQ2Pia/PPbvhJ7za9UQsZ0HvQ7nOKZ2xPJ6TvjqrEpzrZO0GJn3vqbAUi2r9//saWEj/PwYmAmi63JNyLRAojhKB0ZglInBXXmIQJBeb4hDbXb/0= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) by mx.zohomail.com with SMTPS id 179078547293452.980386122452614; Wed, 30 Sep 2026 09:24:32 -0700 (PDT) Received: from list by lists.xenproject.org with outflank-mailman.1437544.1656472 (Exim 4.92) (envelope-from ) id 1xBx6L-0003AY-Gp; Wed, 30 Sep 2026 16:24:13 +0000 Received: by outflank-mailman (output) from mailman id 1437544.1656472; Wed, 30 Sep 2026 16:24:13 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1xBx6L-0003AR-E5; Wed, 30 Sep 2026 16:24:13 +0000 Received: by outflank-mailman (input) for mailman id 1437544; Wed, 30 Sep 2026 16:24:12 +0000 Received: from mx.expurgate.net ([195.190.135.10]) by lists.xenproject.org with esmtp (Exim 4.92) id 1xBx6J-0003AK-Vw for xen-devel@lists.xenproject.org; Wed, 30 Sep 2026 16:24:11 +0000 Received: from mx.expurgate.net (helo=localhost) by mx.expurgate.net with esmtp id 1xBx6J-0073tv-Cn for xen-devel@lists.xenproject.org; Wed, 30 Sep 2026 18:24:11 +0200 Received: from [10.42.69.11] (helo=localhost) by localhost with ESMTP (eXpurgate MTA 0.9.1) (envelope-from ) id 6abd37a6-e002-0a2a0a5209dd-0a2a450ba504-10 for ; Wed, 30 Sep 2026 18:24:11 +0200 Received: from [74.125.225.141] (helo=mail-wm2-f13.google.com) by tlsNG-42698a.mxtls.expurgate.net with ESMTPS (eXpurgate 4.57.1) (envelope-from ) id 6abd37ab-b7e8-0a2a450b0019-4a7de18dcc44-3 for ; Wed, 30 Sep 2026 18:24:11 +0200 Received: by mail-wm2-f13.google.com with SMTP id 5b1f17b1804b1-49e6b885ef8so33054485e9.1 for ; Wed, 30 Sep 2026 09:24:11 -0700 (PDT) Received: from fedora (user-109-243-71-234.play-internet.pl. [109.243.71.234]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-4a01cd43e66sm14620485e9.2.2026.09.30.09.24.09 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 30 Sep 2026 09:24:10 -0700 (PDT) X-Outflank-Mailman: Message body and most headers restored to incoming version X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" Authentication-Results: eu.smtp.expurgate.cloud; dkim=pass header.s=20251104 header.d=gmail.com header.i="@gmail.com" header.h="Content-Transfer-Encoding:MIME-Version:References:In-Reply-To:Message-ID:Date:Subject:Cc:To:From" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1790785451; x=1791390251; darn=lists.xenproject.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=3BzXTGnWcfy6ALLYgep1c2vgCuLID+Lhul4DxE5IZxE=; b=KMKgdIT9YQ5/nIpVIY4AkSDyymOU3BWsMMBcCuyxGvGoZo28mJ93Gt4p3Cv8TnZqPM pBz5vKbWtelT9sgP6ftmqoJ9pohNp0LW8SMZXF5wus7ouh4XvZBJ60I5NaLFpOE+rWM0 Y9kekywtncSmtqOtGxaIzCP2nHQb9mH//H/5+J26kdnjyA9QgDPj9EJCsaRwfeIIxWh0 kqeFg8CCeKYB7Lxq6WeVIXXR78xoIzFwAutlstZErAvTnmTOJe6EO8xnnh4FUekqCs0V 66SY5F2tLjvgsF7ppx/dyyDr4BxsZavVaoj2rTt9o4LOR2alFqkpgaAiZAca51YSeXrM 7cxQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1790785451; x=1791390251; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=3BzXTGnWcfy6ALLYgep1c2vgCuLID+Lhul4DxE5IZxE=; b=iyJ3ivmp9uOea9DFnQJitP/IxRu8ndxY5cAZ3kBfgU7gOAXfPGTkjl5lct21HS+WCA /yGYUI0LCXmvhq1FZ67rKBlwkHtiIrmUeXGB+GAz0uLu0GwCP48M5arVZqKjrQnG1sw/ VxmWYWMkSYpsKWPcJ7FhU1HW19H00HKPiet7aP4lgni+E3y7LUPBNnSnyPo40e/xYykK zR/oGNt8i8ksMLEWHb2dzhgIEE53OQJk4lBhCIj1EdJb2FZ4dvEhe7NOCQzCWhIiDN5V Fvn7EifcQ8ipyMWMjjVaV/f4y/nEp75ZaISpvWx1s8FaowIhmo+VsVmCEcPisQzAQ0AT C1GQ== X-Gm-Message-State: AFuF++nyUny+1POd0Uv7Y8uBzXnkJtvdb0Vp8qYBcYVBtz7hqaD00ZQs hWj3TyCfsbWARbmjSgcHBHA/ruywgtzerGRupNssNOmKjneYAxT8MBE5+wKdeg== X-Gm-Gg: AYBFou2zu2+0xDti2GGp6Z6sIOfLBkIqhN2SisyfUf4I/yNTRtymNBIzJY8zyKU3qzo qZVH/HDmjVGACmGi0fUp7P2KtCflAvXsbWpAAaSCijUYb8/DDAVa41YqJ56leQqG0qMyoya4F7h wTo1ZYRviUww3Ylfm3A2skiXEL1C2Cu18dBrgw3ZK6R+65Y++752RwCryTEUsau4okoiLSOnVVz 2h7xDPZGGXAXjYob4hvbw5M4rxo6TWnT6of9uVs9Yu/nJQNNjCCOD4p3jCzJ0wupi9/6QUpvK4K tVaTmHFgREF35EnC1rUHV3DM8svzFmpxl7UdwHzLSwdVRj79PmV/GQ66Hi8oNlQUokmo6qbM68p unnUTyYJe1t1/Dhsz2RPZtF3DFbIsFhVsKWUM/5qt79eHcifXPOqO9wERfRHfn/4XFOV1wlfGGd 5YaRbQsH2A0Lv0/YLt2KIdtSEEUs9qW9hfSpdsRIjkMhX3Y6BBIgk0aoqRJ2V1Ffrn2ii5vf0wb wiMA9rIxGOLlwVBraPxP0U1ioilZv+TI5gWdeJj X-Received: by 2002:a05:600c:3144:b0:4a0:1c0e:b2a8 with SMTP id 5b1f17b1804b1-4a01c0ecb6fmr27717895e9.28.1790785450819; Wed, 30 Sep 2026 09:24:10 -0700 (PDT) From: Oleksii Kurochko To: xen-devel@lists.xenproject.org Cc: Romain Caritey , Baptiste Le Duc , Zheng Zhang , Oleksii Kurochko , Alistair Francis , Connor Davis , Andrew Cooper , Anthony PERARD , Michal Orzel , Jan Beulich , Julien Grall , =?UTF-8?q?Roger=20Pau=20Monn=C3=A9?= , Stefano Stabellini Subject: [PATCH v3 10/39] xen/riscv: add helper to check APLIC MSI mode Date: Wed, 30 Sep 2026 18:23:29 +0200 Message-ID: <2395aff35a311735f759b76728d7c09ce5f43fcb.1790779209.git.oleksii.kurochko@gmail.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-purgate-ID: tlsNG-42698a/1790785451-1B2DC9EA-62212CE6/10/78276251493 X-purgate-type: spam X-purgate-size: 1853 X-ZohoMail-DKIM: pass (identity @gmail.com) X-ZM-MESSAGEID: 1790785473942158500 Content-Type: text/plain; charset="utf-8" Use convient helper instead of open-coding the things. Signed-off-by: Oleksii Kurochko Reviewed-by: Baptiste Le Duc Acked-by: Jan Beulich --- Changes in v3: - Add Reviewed-by: Baptiste Le Duc . - Add Acked-by: Jan Beulich . --- Changes in v2: - Rename helper. - Update the commit message. --- --- xen/arch/riscv/aplic.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/xen/arch/riscv/aplic.c b/xen/arch/riscv/aplic.c index 62bbcc9afacf..60f5f239c394 100644 --- a/xen/arch/riscv/aplic.c +++ b/xen/arch/riscv/aplic.c @@ -37,6 +37,11 @@ static struct intc_info __ro_after_init aplic_info =3D { .hw_variant =3D INTC_APLIC, }; =20 +static bool aplic_msi_mode(void) +{ + return readl(&aplic.regs->domaincfg) & APLIC_DOMAINCFG_DM; +} + /* * The arrangement of IMSIC interrupt files in MMIO space follows a topolo= gy * defined by the RISC-V AIA specification. An IMSIC group is a set of @@ -260,7 +265,7 @@ static void cf_check aplic_irq_enable(struct irq_desc *= desc) * If APLIC without MSI interrupts is required in the future, * this function will need to be updated accordingly. */ - ASSERT(readl(&aplic.regs->domaincfg) & APLIC_DOMAINCFG_DM); + ASSERT(aplic_msi_mode()); =20 ASSERT(spin_is_locked(&desc->lock)); =20 @@ -291,7 +296,7 @@ static void cf_check aplic_irq_disable(struct irq_desc = *desc) * If APLIC without MSI interrupts is required in the future, * this function will need to be updated accordingly. */ - ASSERT(readl(&aplic.regs->domaincfg) & APLIC_DOMAINCFG_DM); + ASSERT(aplic_msi_mode()); =20 ASSERT(spin_is_locked(&desc->lock)); =20 --=20 2.55.0 From nobody Fri Oct 23 15:32:28 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) client-ip=192.237.175.120; envelope-from=xen-devel-bounces@lists.xenproject.org; helo=lists.xenproject.org; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=pass(p=none dis=none) header.from=gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1790785475; cv=none; d=zohomail.com; s=zohoarc; b=Vwle6rR39A7kYiu6wDZFWXqJuj7OTqUQ/2harMck+5miJSOeHZUClK3qmZR7PGMqqRHba9sUiUdeQFJx7cfOn521XoSca21a1UkogkT4QpCSqYLlxUEG4QkZRguRGbhOQEdhsqH3pyyPS3m6uY7PlKJJvxlaits9MaG8ZI5Iv9A= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1790785475; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=NLB+e0LkNxbKffJIT5G6kYupN6psRmxaZXhCt6+lLqo=; b=lzi1Pr7Ko6ITPKTTTpZzrBSubi1n3w0uWexxg5SOd8w3mEqwQ907QTVgrieTLcad0leB0PhXbNzNk9d+ouoYUDiVSnAMSOihg7nYGPWFZcvLNLREAMz6Ho8cNHsrxuYSMpVjImDJUW1yBBblQi8uJ9zYxwf1/ATM2+ySxjfKd7A= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) by mx.zohomail.com with SMTPS id 1790785475329810.3704045055275; Wed, 30 Sep 2026 09:24:35 -0700 (PDT) Received: from list by lists.xenproject.org with outflank-mailman.1437545.1656481 (Exim 4.92) (envelope-from ) id 1xBx6N-0003Ne-Na; Wed, 30 Sep 2026 16:24:15 +0000 Received: by outflank-mailman (output) from mailman id 1437545.1656481; Wed, 30 Sep 2026 16:24:15 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1xBx6N-0003NV-KJ; Wed, 30 Sep 2026 16:24:15 +0000 Received: by outflank-mailman (input) for mailman id 1437545; Wed, 30 Sep 2026 16:24:14 +0000 Received: from mx.expurgate.net ([195.190.135.20]) by lists.xenproject.org with esmtp (Exim 4.92) id 1xBx6M-0003AQ-1E for xen-devel@lists.xenproject.org; Wed, 30 Sep 2026 16:24:14 +0000 Received: from mx.expurgate.net (helo=localhost) by mx.expurgate.net with esmtp id 1xBx6K-00AJmP-Rg for xen-devel@lists.xenproject.org; Wed, 30 Sep 2026 18:24:12 +0200 Received: from [10.42.69.5] (helo=localhost) by localhost with ESMTP (eXpurgate MTA 0.9.1) (envelope-from ) id 6abd37a1-8faa-0a2a0a5109dd-0a2a4505a464-26 for ; Wed, 30 Sep 2026 18:24:12 +0200 Received: from [74.125.225.141] (helo=mail-wm2-f13.google.com) by tlsNG-c201ff.mxtls.expurgate.net with ESMTPS (eXpurgate 4.57.1) (envelope-from ) id 6abd37ac-4cb1-0a2a45050019-4a7de18d9620-3 for ; Wed, 30 Sep 2026 18:24:12 +0200 Received: by mail-wm2-f13.google.com with SMTP id 5b1f17b1804b1-49e71cdb22bso41007795e9.2 for ; Wed, 30 Sep 2026 09:24:12 -0700 (PDT) Received: from fedora (user-109-243-71-234.play-internet.pl. [109.243.71.234]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-4a01cd43e66sm14620485e9.2.2026.09.30.09.24.10 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 30 Sep 2026 09:24:11 -0700 (PDT) X-Outflank-Mailman: Message body and most headers restored to incoming version X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" Authentication-Results: eu.smtp.expurgate.cloud; dkim=pass header.s=20251104 header.d=gmail.com header.i="@gmail.com" header.h="Content-Transfer-Encoding:MIME-Version:References:In-Reply-To:Message-ID:Date:Subject:Cc:To:From" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1790785452; x=1791390252; darn=lists.xenproject.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=NLB+e0LkNxbKffJIT5G6kYupN6psRmxaZXhCt6+lLqo=; b=GB5CmOrQoNGbV/e365A05pjBXJP1wmSEOwqiJbvMRKOcm8Hoc6LTuRaJAJs1AIkaBc MZwOUj0QIcoSKba97Ic1BDoVIEc/vSP6krKImwTjGHitcV/HMbMUS13SHaNwI/+Zz1SK dDsV0mBHv1owj9wdXujJnHtdfkksVir8Rm0o2IZX4rEqBA47wPd1kRNQIvePlDcCVOJn Khx4kHZM3r+8vjbyHWTYSwvKiakwK4uFL6Q+n1Lo70P2gVW8Jxn8+WGBgqh9VNetlqI/ kBCV0v0vPnP8cozj95qAJVRDUaaZrmT08rFie1mY84wrHYaRwc4R1jZ84TyueSsTeB9q V3DQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1790785452; x=1791390252; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=NLB+e0LkNxbKffJIT5G6kYupN6psRmxaZXhCt6+lLqo=; b=IFvphxU5JJe9f27BaG4u3dC+xZCVpDE5pMSworQQ4suee8oIeqhexFth0IJ7UUxLer 8MRexZsn1l+TBppsCs2b5aRmj6L2v0XfwQdOlxLxtgXryQQ8h4wXNUfIEllEQMHdFlMb fjcgHsbtE9i10klBT0jHLGr3SO1A+GPegE7EYnRgq0pPCgi8HZmFkDjXMzqnCaVqKiol krsHAwBt72AsiSGSRcCv525Ech3PZNoRL0TPt59DbK3x3ayDnqF5QAw9jflAIqZGvQwA ycqKo/zFuk9XUDa1ugcHuWIVzRXs4/6ZHVGosVnKMAQm/tR+PmRzCxXhaN82JFRH6TFR YD8A== X-Gm-Message-State: AFuF++nyuhsuDrBaeR8PqKe34lfiVa5Ddt6VkqAQOJ1Qy4OgLrxhKaqz KmQqjXp4u4AGxZLFIoa2Y0BJLkJln2eBeccoKOh9rphTiZX/gbicZiFfnx5ppA== X-Gm-Gg: AYBFou1XUNvF+r2YCP/jGIx595yfnAXFsV1An3FhTsM839EBP7TxBikWbypT5wDSbla tdbbztdajjC0ImoGvwFG7I9VtrEmmyZ6MdIOl3KKoFEH4aXXJYIjbYUDUcAzD4WJglpTk9ePiK3 6gZ4qfNJSaJ6vhGkp03FIb7rjiRiBiAukSDujfBr0SI7UYefW0lVeDEbLty/d9/zHtE3bkdZUF9 oNGAZdpMWcAKh2Xrxna7tG3xwr2bhggzmsOFfqIzgE+yuaChqr7EPpmLyqXqKrKq+pdvvH707jH echkbz2kT1JifnIJOLVm8aF7IJpLaxtoyIJ5Ojrqu+/oqmonBubF3gG5+1MbZWn4zKXp96xbzAY lPZiK8YXU82twP5EeaW3/cN6UkVxij6oGpZjp7anV2eDa3Ud6EZekvGkGZq/Vb8vm/rE0MwaMYg LCzBIpmkAylimxdq0k/rdEiQxqpE58lCgu7A2U6nMNHq3HbSW8W6FnoD7VRIrY8xpAD40FcT5Fz 4U3ZqQTZ5L4/4NLEkqfQ/SZMdugyg71TU5v7aIH X-Received: by 2002:a05:600c:45d3:b0:4a0:c2a:485e with SMTP id 5b1f17b1804b1-4a01b130b8bmr30415685e9.33.1790785451935; Wed, 30 Sep 2026 09:24:11 -0700 (PDT) From: Oleksii Kurochko To: xen-devel@lists.xenproject.org Cc: Romain Caritey , Baptiste Le Duc , Zheng Zhang , Oleksii Kurochko , Alistair Francis , Connor Davis , Andrew Cooper , Anthony PERARD , Michal Orzel , Jan Beulich , Julien Grall , =?UTF-8?q?Roger=20Pau=20Monn=C3=A9?= , Stefano Stabellini Subject: [PATCH v3 11/39] xen/riscv: implement vCPU context switching Date: Wed, 30 Sep 2026 18:23:30 +0200 Message-ID: <6e539cc5ded7f62c4347781785af714840893184.1790779209.git.oleksii.kurochko@gmail.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-purgate-ID: tlsNG-c201ff/1790785452-24F1F2A1-9BDD79E6/10/73395122804 X-purgate-type: spam X-purgate-size: 25016 X-ZohoMail-DKIM: pass (identity @gmail.com) X-ZM-MESSAGEID: 1790785475908158500 Content-Type: text/plain; charset="utf-8" Implement context_switch() and the helpers it needs: save/restore of H/VS CSRs, virtual timer and P2M context, and __context_switch() in assembly, which switches Xen's own callee-saved state (and thereby the stack) from prev to next. The virtual interrupt controller state isn't switched here. Add offsets of struct arch_vcpu's xen_saved_context to asm-offsets.c for use by __context_switch(). henvcfg, htimedelta and vsie are 64-bit on both RV32 and RV64, so store them as uint64_t and access them with csr_{read,write}64(). For that purpose introduce csr_read64(). The VMID has to be claimed on the context switch rather than on guest entry: once p2m_ctxt_switch_to() writes HGATP, speculation can populate G-stage entries under whatever VMID is written there. This is done by p2m_vmid_switch_to(), called right before the HGATP write: - VMIDs are a per-hart resource, so the (generation, vmid) pair of a vCPU which last ran on another hart is invalidated before a VMID is claimed for it. The local flush for a wrapped generation moves along with the claim. - Nothing is switched in for the idle vCPU, so HGATP keeps pointing at the p2m of the domain which ran on the hart last. Track that domain per hart (hgatp_owner) and keep the hart in its dirty_cpumask until a vCPU of another domain is switched in: p2m_tlb_flush() then goes on reaching the hart, and a domain which idles between two runs on the same hart keeps its VMIDs. - When the owner changes, the hart leaves the old owner's dirty_cpumask while its TLB may still hold that domain's G-stage translations, so it is moved to a new VMID generation, which makes none of them reachable again. It joins the new owner's dirty_cpumask before HGATP is written; a full barrier there, paired with one in p2m_tlb_flush(), guarantees that a concurrent P2M change either reaches the hart with an HFENCE.GVMA or is visible to it before it walks the p2m. That leaves p2m_handle_vmenter() with nothing to do, so drop it together with its call from check_for_pcpu_work(): a VMID is only ever invalidated while its vCPU isn't running, and p2m_tlb_flush() drops stale entries with a remote HFENCE.GVMA rather than by retiring VMIDs. Unlike p2m_handle_vmenter(), HGATP is written unconditionally, as it holds the G-stage root too, which on a context switch belongs to another domain. While at it, fix the inclusion order of headers in asm-offsets.c: Xen's headers go first, then arch specific ones. Signed-off-by: Oleksii Kurochko --- Changes in v3: - Update the commit message. - Introduce csr_read64(), as vsie is 64-bit on RV32 too, i.e. has to be accessed as the vsie/vsieh pair there. - Make vsie declared as uint64_t instead of register_t. - Rename the parameter of save_csr_regs() to p and of restore_csr_regs() to n, to match their callers ctxt_switch_from()/ctxt_switch_to() and the rest of the context switch helpers (p2m_ctxt_switch_{from,to}(), vtimer_ctxt_switch_{from,to}()). - s/save_csr_regs/csr_regs_ctxt_switch_from/ - s/restore_csr_regs/csr_regs_ctxt_switch_to/ - Drop the forward declaration of struct vcpu in : the return type of __context_switch() already declares the tag at file scope. - Make the next parameter of __context_switch() pointer-to-const, as next's saved context is only read. - Extend the comment above __context_switch(): as ra is switched too, it doesn't return to its caller, but to where next last called it from (next's own context_switch(), or continue_new_vcpu() for a vCPU which has never run). - Call vtimer_ctxt_switch_to() after csr_regs_ctxt_switch_to(), so that ctxt_switch_to() restores state in the reverse order of ctxt_switch_from() saving it. - Rework p2m's VMID handling in the context switch: track the domain whose p2m HGATP points at in a per-CPU hgatp_owner, so a pass through idle no longer drops the hart from that domain's dirty_cpumask nor burns a VMID generation; move the dirty_cpumask update and the invalidation of a VMID brought from another hart from schedule_tail() and ctxt_switch_to() to p2m_ctxt_switch_to(), next to the VMID claim; add the barriers ordering the dirty_cpumask update against p2m_tlb_flush(). - Initialise arch_vcpu.last_cpu to CPU_NONE instead of NR_CPUS. - Mark prev's dirty_cpu clean before ctxt_switch_to() and set current's after it. --- Changes in v2: - New patch. --- --- xen/arch/riscv/domain.c | 127 ++++++++++++++++++++++ xen/arch/riscv/entry.S | 48 ++++++++ xen/arch/riscv/include/asm/csr.h | 13 +++ xen/arch/riscv/include/asm/domain.h | 15 ++- xen/arch/riscv/include/asm/p2m.h | 1 - xen/arch/riscv/include/asm/system.h | 2 + xen/arch/riscv/p2m.c | 157 ++++++++++++++++++--------- xen/arch/riscv/riscv64/asm-offsets.c | 19 +++- xen/arch/riscv/stubs.c | 5 - xen/arch/riscv/traps.c | 2 - 10 files changed, 330 insertions(+), 59 deletions(-) diff --git a/xen/arch/riscv/domain.c b/xen/arch/riscv/domain.c index fd6229635627..f80643e2d82b 100644 --- a/xen/arch/riscv/domain.c +++ b/xen/arch/riscv/domain.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -152,6 +153,8 @@ int arch_vcpu_create(struct vcpu *v) if ( is_idle_vcpu(v) ) return 0; =20 + v->arch.last_cpu =3D CPU_NONE; + vcpu_csr_init(v); =20 if ( (rc =3D vcpu_vtimer_init(v)) ) @@ -323,6 +326,130 @@ int arch_domain_create(struct domain *d, return rc; } =20 +static void csr_regs_ctxt_switch_from(struct vcpu *p) +{ + /* + * There is no need to save these CSRs as only hypervisor writes them = in + * csr_regs_ctxt_switch_to() and guest can't access them so they shoul= dn't + * be stored here. Keep them commented here just for symmetry with the + * restore CSRs register part. + * + * p->arch.hedeleg =3D csr_read(CSR_HEDELEG); + * p->arch.hideleg =3D csr_read(CSR_HIDELEG); + * p->arch.henvcfg =3D csr_read64(CSR_HENVCFG); + * p->arch.hcounteren =3D csr_read(CSR_HCOUNTEREN); + * p->arch.htimedelta =3D csr_read64(CSR_HTIMEDELTA); + * + * if ( riscv_isa_extension_available(NULL, RISCV_ISA_EXT_smstateen) ) + * p->arch.hstateen0 =3D csr_read(CSR_HSTATEEN0); + */ + + p->arch.hvip =3D csr_read(CSR_HVIP); + + p->arch.vsstatus =3D csr_read(CSR_VSSTATUS); + p->arch.vsie =3D csr_read64(CSR_VSIE); + p->arch.vstvec =3D csr_read(CSR_VSTVEC); + p->arch.vsscratch =3D csr_read(CSR_VSSCRATCH); + p->arch.vscause =3D csr_read(CSR_VSCAUSE); + p->arch.vstval =3D csr_read(CSR_VSTVAL); + p->arch.vsepc =3D csr_read(CSR_VSEPC); +} + +static void csr_regs_ctxt_switch_to(struct vcpu *n) +{ + csr_write(CSR_HEDELEG, n->arch.hedeleg); + csr_write(CSR_HIDELEG, n->arch.hideleg); + csr_write(CSR_HVIP, n->arch.hvip); + csr_write64(CSR_HENVCFG, n->arch.henvcfg); + csr_write(CSR_HCOUNTEREN, n->arch.hcounteren); + csr_write64(CSR_HTIMEDELTA, n->arch.htimedelta); + + if ( riscv_isa_extension_available(NULL, RISCV_ISA_EXT_smstateen) ) + csr_write(CSR_HSTATEEN0, n->arch.hstateen0); + + csr_write(CSR_VSSTATUS, n->arch.vsstatus); + csr_write64(CSR_VSIE, n->arch.vsie); + csr_write(CSR_VSTVEC, n->arch.vstvec); + csr_write(CSR_VSSCRATCH, n->arch.vsscratch); + csr_write(CSR_VSCAUSE, n->arch.vscause); + csr_write(CSR_VSTVAL, n->arch.vstval); + csr_write(CSR_VSEPC, n->arch.vsepc); +} + +static void ctxt_switch_from(struct vcpu *p) +{ + /* + * When the idle VCPU is running, Xen will always stay in hypervisor + * mode. + * Therefore we don't need to save the context of an idle VCPU. + */ + if ( is_idle_vcpu(p) ) + return; + + p2m_ctxt_switch_from(p); + + vtimer_ctxt_switch_from(p); + + csr_regs_ctxt_switch_from(p); +} + +static void ctxt_switch_to(struct vcpu *n) +{ + /* + * When the idle VCPU is running, Xen will always stay in hypervisor + * mode. + * Therefore we don't need to restore the context of an idle VCPU. + */ + if ( is_idle_vcpu(n) ) + return; + + csr_regs_ctxt_switch_to(n); + + vtimer_ctxt_switch_to(n); + + p2m_ctxt_switch_to(n); +} + +static void schedule_tail(struct vcpu *prev) +{ + unsigned int cpu =3D smp_processor_id(); + + ASSERT(prev !=3D current); + + ctxt_switch_from(prev); + + write_atomic(&prev->dirty_cpu, VCPU_CPU_CLEAN); + + ctxt_switch_to(current); + + write_atomic(¤t->dirty_cpu, cpu); + + current->arch.last_cpu =3D cpu; + + /* + * sched_context_switched() internally uses a spinlock, + * which requires interrupts to be enabled. + */ + local_irq_enable(); + + sched_context_switched(prev, current); +} + +void context_switch(struct vcpu *prev, struct vcpu *next) +{ + ASSERT(local_irq_is_enabled()); + ASSERT(prev !=3D next); + ASSERT(!vcpu_cpu_dirty(next)); + + local_irq_disable(); + + set_current(next); + + prev =3D __context_switch(prev, next); + + schedule_tail(prev); +} + static void __init __maybe_unused build_assertions(void) { /* diff --git a/xen/arch/riscv/entry.S b/xen/arch/riscv/entry.S index 202a35fb03a8..017fbb06262c 100644 --- a/xen/arch/riscv/entry.S +++ b/xen/arch/riscv/entry.S @@ -99,3 +99,51 @@ restore_registers: =20 sret END(handle_trap) + +/* + * struct vcpu *__context_switch(struct vcpu *prev, const struct vcpu *nex= t) + * + * This is called on prev's stack, and returns on next's. As ra is + * switched too, it doesn't return to its caller: it returns to where + * next last called it from, i.e. into next's own context_switch(), or, + * for a vCPU which has never run, to continue_new_vcpu() with an empty + * stack. + * + * a0 - prev + * a1 - next + * + * Returns prev in a0 + */ +FUNC(__context_switch) + REG_S s0, VCPU_XEN_SAVED_CONTEXT_S0(a0) + REG_S s1, VCPU_XEN_SAVED_CONTEXT_S1(a0) + REG_S s2, VCPU_XEN_SAVED_CONTEXT_S2(a0) + REG_S s3, VCPU_XEN_SAVED_CONTEXT_S3(a0) + REG_S s4, VCPU_XEN_SAVED_CONTEXT_S4(a0) + REG_S s5, VCPU_XEN_SAVED_CONTEXT_S5(a0) + REG_S s6, VCPU_XEN_SAVED_CONTEXT_S6(a0) + REG_S s7, VCPU_XEN_SAVED_CONTEXT_S7(a0) + REG_S s8, VCPU_XEN_SAVED_CONTEXT_S8(a0) + REG_S s9, VCPU_XEN_SAVED_CONTEXT_S9(a0) + REG_S s10, VCPU_XEN_SAVED_CONTEXT_S10(a0) + REG_S s11, VCPU_XEN_SAVED_CONTEXT_S11(a0) + REG_S sp, VCPU_XEN_SAVED_CONTEXT_SP(a0) + REG_S ra, VCPU_XEN_SAVED_CONTEXT_RA(a0) + + REG_L s0, VCPU_XEN_SAVED_CONTEXT_S0(a1) + REG_L s1, VCPU_XEN_SAVED_CONTEXT_S1(a1) + REG_L s2, VCPU_XEN_SAVED_CONTEXT_S2(a1) + REG_L s3, VCPU_XEN_SAVED_CONTEXT_S3(a1) + REG_L s4, VCPU_XEN_SAVED_CONTEXT_S4(a1) + REG_L s5, VCPU_XEN_SAVED_CONTEXT_S5(a1) + REG_L s6, VCPU_XEN_SAVED_CONTEXT_S6(a1) + REG_L s7, VCPU_XEN_SAVED_CONTEXT_S7(a1) + REG_L s8, VCPU_XEN_SAVED_CONTEXT_S8(a1) + REG_L s9, VCPU_XEN_SAVED_CONTEXT_S9(a1) + REG_L s10, VCPU_XEN_SAVED_CONTEXT_S10(a1) + REG_L s11, VCPU_XEN_SAVED_CONTEXT_S11(a1) + REG_L sp, VCPU_XEN_SAVED_CONTEXT_SP(a1) + REG_L ra, VCPU_XEN_SAVED_CONTEXT_RA(a1) + + ret +END(__context_switch) diff --git a/xen/arch/riscv/include/asm/csr.h b/xen/arch/riscv/include/asm/= csr.h index a5cb24c863dd..aad82c6a6d8a 100644 --- a/xen/arch/riscv/include/asm/csr.h +++ b/xen/arch/riscv/include/asm/csr.h @@ -40,6 +40,13 @@ csr_write(csr ## H, v_ >> 32); \ }) =20 +#define csr_read64(csr) \ +({ \ + uint64_t v_ =3D csr_read(csr ## H); \ + \ + (v_ << 32) | csr_read(csr); \ +}) + /* * The two halves are read by separate instructions, so a CSR which hardwa= re * increments can carry from the low half into the high one in between, @@ -72,6 +79,12 @@ (void)csr ## H; \ csr_read(csr); \ }) + +#define csr_read64(csr) \ +({ \ + (void)csr ## H; \ + csr_read(csr); \ +}) #endif =20 #define csr_swap(csr, val) \ diff --git a/xen/arch/riscv/include/asm/domain.h b/xen/arch/riscv/include/a= sm/domain.h index 15e8fa19685e..77ad888a2d6c 100644 --- a/xen/arch/riscv/include/asm/domain.h +++ b/xen/arch/riscv/include/asm/domain.h @@ -29,6 +29,11 @@ struct arch_vcpu_io { struct arch_vcpu { struct vcpu_vmid vmid; =20 + /* + * The last CPU this vCPU ran on. Initialised to CPU_NONE. + */ + unsigned int last_cpu; + /* * Callee saved registers for Xen's state used to switch from * prev's stack to the next's stack during context switch. @@ -60,11 +65,19 @@ struct arch_vcpu { register_t hcounteren; register_t hedeleg; register_t hideleg; - register_t henvcfg; + uint64_t henvcfg; register_t hstateen0; + uint64_t htimedelta; register_t hvip; =20 register_t vsatp; + register_t vscause; + register_t vsepc; + uint64_t vsie; + register_t vsscratch; + register_t vsstatus; + register_t vstval; + register_t vstvec; =20 /* * VCPU interrupts diff --git a/xen/arch/riscv/include/asm/p2m.h b/xen/arch/riscv/include/asm/= p2m.h index 0d1dace1a0d8..9edf78377ee5 100644 --- a/xen/arch/riscv/include/asm/p2m.h +++ b/xen/arch/riscv/include/asm/p2m.h @@ -262,7 +262,6 @@ struct page_info *p2m_get_page_from_gfn(struct p2m_doma= in *p2m, gfn_t gfn, =20 void p2m_ctxt_switch_from(struct vcpu *p); void p2m_ctxt_switch_to(struct vcpu *n); -void p2m_handle_vmenter(void); =20 #endif /* ASM__RISCV__P2M_H */ =20 diff --git a/xen/arch/riscv/include/asm/system.h b/xen/arch/riscv/include/a= sm/system.h index f33af64fd2ec..d350b9c959c2 100644 --- a/xen/arch/riscv/include/asm/system.h +++ b/xen/arch/riscv/include/asm/system.h @@ -76,6 +76,8 @@ static inline bool local_irq_is_enabled(void) =20 #define arch_fetch_and_add(x, v) __sync_fetch_and_add(x, v) =20 +struct vcpu *__context_switch(struct vcpu *prev, const struct vcpu *next); + #endif /* __ASSEMBLER__ */ =20 #endif /* ASM__RISCV__SYSTEM_H */ diff --git a/xen/arch/riscv/p2m.c b/xen/arch/riscv/p2m.c index de25607247a6..02e7f6364fad 100644 --- a/xen/arch/riscv/p2m.c +++ b/xen/arch/riscv/p2m.c @@ -243,6 +243,15 @@ static void p2m_tlb_flush(struct p2m_domain *p2m) =20 p2m->need_flush =3D false; =20 + /* + * Order the p2m updates above against the read of dirty_cpumask below, + * pairing with the barrier in p2m_vmid_switch_to(). Either that hart = is + * seen here and gets an HFENCE.GVMA, or it adds itself to the mask + * afterwards, in which case it starts walking this p2m only once the + * updates are visible to it. + */ + smp_mb(); + sbi_remote_hfence_gvma(d->dirty_cpumask, 0, 0); } =20 @@ -1504,16 +1513,110 @@ void p2m_ctxt_switch_from(struct vcpu *p) * VMID, world-switch code should zero vsatp, then swap hgatp, then * finally write the new vsatp value what will be done in * p2m_ctxt_switch_to(). - * Note, that also HGATP update could happen in p2m_handle_vmenter(). */ p->arch.vsatp =3D csr_swap(CSR_VSATP, 0); =20 /* - * Nothing to do with HGATP as it will be update in p2m_ctxt_switch_to= () - * or/and in p2m_handle_vmenter(). + * Nothing to do with HGATP as it will be updated in + * p2m_ctxt_switch_to(). */ } =20 +/* + * Domain whose p2m this hart's HGATP points at. ctxt_switch_to() bails out + * early for the idle vCPU, so HGATP survives a pass through idle and keeps + * pointing at the domain which ran here last. That domain, rather than the + * one the scheduler switched away from, is what owns this hart's G-stage + * translations. The hart also keeps its place in the owner's dirty_cpumas= k: + * p2m_tlb_flush() goes on reaching it, and a domain which idles between t= wo + * runs on the same hart keeps its VMIDs. + * + * TODO: nothing resets hgatp_owner when its domain is destroyed, so a hart + * which stays idle from the domain's last run until it is freed is + * left with a dangling pointer. Once domain_relinquish_resources() + * tears down the p2m, it has to reset hgatp_owner of every hart sti= ll + * pointing at the domain (cmpxchg() against d), i.e. before the RCU + * grace period of domain_destroy() and so before the domain is free= d. + */ +static DEFINE_PER_CPU(struct domain *, hgatp_owner); + +/* + * Update this hart's place in the dirty_cpumask of the domains involved a= nd + * claim a VMID for n. Must be called before HGATP is pointed at n's p2m, = as + * it is written with the VMID claimed here. + */ +static void p2m_vmid_switch_to(struct vcpu *n) +{ + unsigned int cpu =3D smp_processor_id(); + struct domain *owner =3D this_cpu(hgatp_owner); + bool need_flush; + + ASSERT(!is_idle_vcpu(n)); + + if ( owner !=3D n->domain ) + { + /* + * Once this hart drops out of the owner's dirty_cpumask it stops + * being a target of p2m_tlb_flush(), while its TLB may still hold + * G-stage translations of that domain: none of the vCPUs of that + * domain which ran here has had its VMID invalidated. Move the ha= rt + * to a new VMID generation so that none of them can be reached + * again. + * + * This has to precede the VMID claim below, so that n gets a VMID= of + * the new generation. + */ + if ( owner ) + { + vmid_flush_hart(); + + cpumask_clear_cpu(cpu, owner->dirty_cpumask); + } + + /* + * Mark this hart in the incoming domain's dirty_cpumask before HG= ATP + * is pointed at its p2m: from that write on the hart may cache the + * p2m's translations, so p2m_tlb_flush() must already reach it. + */ + cpumask_set_cpu(cpu, n->domain->dirty_cpumask); + + /* + * Pairs with the barrier in p2m_tlb_flush(). cpumask_set_cpu() is= an + * unordered AMO on RISC-V, so without this a concurrent flusher c= ould + * read the mask without this hart in it while this hart is already + * walking the p2m it is about to be pointed at. + */ + smp_mb(); + + this_cpu(hgatp_owner) =3D n->domain; + } + + /* + * A VMID is meaningful only on the hart whose pool issued it: generat= ions + * are per-hart counters which all start at 1 and advance independentl= y, + * so the pair a vCPU brings from another hart may match this hart's + * generation by coincidence, leaving the vCPU under a VMID which is l= ive + * here for someone else. + */ + if ( n->arch.last_cpu !=3D cpu ) + vmid_flush_vcpu(n); + + /* + * Claim the VMID here rather than leaving it to the next guest entry: + * the caller makes HGATP live right after, and a stale VMID there pai= rs + * this domain's G-stage root with a tag which may already have been + * re-issued to a vCPU of another domain. + */ + need_flush =3D vmid_handle_vmenter(&n->arch.vmid); + + /* + * A VMID isn't re-used until the generation it was issued in wraps, s= o a + * G-stage flush is needed only when vmid_handle_vmenter() says so. + */ + if ( unlikely(need_flush) ) + local_hfence_gvma_all(); +} + /* * As speculation may occur at any time, an incorrect set of page tables c= ould * be used. Therefore, this function must be called only after all other g= uest @@ -1528,11 +1631,9 @@ void p2m_ctxt_switch_to(struct vcpu *n) if ( is_idle_vcpu(n) ) return; =20 + p2m_vmid_switch_to(n); + csr_write(CSR_HGATP, construct_hgatp(p2m, n->arch.vmid.vmid)); - /* - * As VMID is unique per vCPU and just re-used here thereby there is no - * need for G-stage TLB flush here. - */ =20 csr_write(CSR_VSATP, n->arch.vsatp); =20 @@ -1548,48 +1649,6 @@ void p2m_ctxt_switch_to(struct vcpu *n) flush_tlb_guest_local(); } =20 -void p2m_handle_vmenter(void) -{ - struct vcpu *curr =3D current; - struct p2m_domain *p2m =3D p2m_get_hostp2m(curr->domain); - struct vcpu_vmid *p_vmid =3D &curr->arch.vmid; - unsigned short old_vmid, new_vmid; - bool need_flush; - - BUG_ON(is_idle_vcpu(curr)); - - old_vmid =3D p_vmid->vmid; - need_flush =3D vmid_handle_vmenter(p_vmid); - new_vmid =3D p_vmid->vmid; - -#ifdef P2M_DEBUG - printk("%pv: oldvmid(%d) new_vmid(%d), need_flush(%d)\n", - curr, old_vmid, new_vmid, need_flush); -#endif - - /* - * There is no need to set VSATP to 0 to stop speculation before updat= ing - * HGATP, as VSATP is not modified here. - */ - if ( old_vmid !=3D new_vmid ) - csr_write(CSR_HGATP, construct_hgatp(p2m, p_vmid->vmid)); - - /* - * There is also no need to flush G-stage TLB unconditionally as old V= MID - * won't be reused until need_flush is set to true. - */ - if ( unlikely(need_flush) ) - local_hfence_gvma_all(); - - /* - * There is also no need to flush the VS-stage TLB: even if speculation - * occurs (VSATP + old HGATP were used), it will use the old VMID, whi= ch - * won't be reused until need_flush is set to true. When VMIDs aren't - * available there is no old VMID to rely on, but then need_flush is s= et - * on every entry, so the flush above covers that case. - */ -} - struct page_info *get_page_from_gfn(struct domain *d, unsigned long gfn, p2m_type_t *t, p2m_query_t q) { diff --git a/xen/arch/riscv/riscv64/asm-offsets.c b/xen/arch/riscv/riscv64/= asm-offsets.c index 1290b9dbbe82..c1be1614ce94 100644 --- a/xen/arch/riscv/riscv64/asm-offsets.c +++ b/xen/arch/riscv/riscv64/asm-offsets.c @@ -1,8 +1,10 @@ #define COMPILE_OFFSETS =20 +#include +#include + #include #include -#include =20 #define DEFINE(_sym, _val) = \ asm volatile ( "\n.ascii\"=3D=3D>#define " #_sym " %0 /* " #_val " */<= =3D=3D\""\ @@ -53,4 +55,19 @@ void asm_offsets(void) BLANK(); DEFINE(PCPU_INFO_SIZE, sizeof(struct pcpu_info)); BLANK(); + OFFSET(VCPU_XEN_SAVED_CONTEXT_S0, struct vcpu, arch.xen_saved_context.= s0); + OFFSET(VCPU_XEN_SAVED_CONTEXT_S1, struct vcpu, arch.xen_saved_context.= s1); + OFFSET(VCPU_XEN_SAVED_CONTEXT_S2, struct vcpu, arch.xen_saved_context.= s2); + OFFSET(VCPU_XEN_SAVED_CONTEXT_S3, struct vcpu, arch.xen_saved_context.= s3); + OFFSET(VCPU_XEN_SAVED_CONTEXT_S4, struct vcpu, arch.xen_saved_context.= s4); + OFFSET(VCPU_XEN_SAVED_CONTEXT_S5, struct vcpu, arch.xen_saved_context.= s5); + OFFSET(VCPU_XEN_SAVED_CONTEXT_S6, struct vcpu, arch.xen_saved_context.= s6); + OFFSET(VCPU_XEN_SAVED_CONTEXT_S7, struct vcpu, arch.xen_saved_context.= s7); + OFFSET(VCPU_XEN_SAVED_CONTEXT_S8, struct vcpu, arch.xen_saved_context.= s8); + OFFSET(VCPU_XEN_SAVED_CONTEXT_S9, struct vcpu, arch.xen_saved_context.= s9); + OFFSET(VCPU_XEN_SAVED_CONTEXT_S10, struct vcpu, arch.xen_saved_context= .s10); + OFFSET(VCPU_XEN_SAVED_CONTEXT_S11, struct vcpu, arch.xen_saved_context= .s11); + OFFSET(VCPU_XEN_SAVED_CONTEXT_SP, struct vcpu, arch.xen_saved_context.= sp); + OFFSET(VCPU_XEN_SAVED_CONTEXT_RA, struct vcpu, arch.xen_saved_context.= ra); + BLANK(); } diff --git a/xen/arch/riscv/stubs.c b/xen/arch/riscv/stubs.c index 3a7953593d93..e0febae432b2 100644 --- a/xen/arch/riscv/stubs.c +++ b/xen/arch/riscv/stubs.c @@ -81,11 +81,6 @@ void smp_send_state_dump(unsigned int cpu) =20 DEFINE_PER_CPU(struct vcpu *, curr_vcpu); =20 -void context_switch(struct vcpu *prev, struct vcpu *next) -{ - BUG_ON("unimplemented"); -} - void continue_running(struct vcpu *same) { BUG_ON("unimplemented"); diff --git a/xen/arch/riscv/traps.c b/xen/arch/riscv/traps.c index 10d6855d913b..9bb54d030be7 100644 --- a/xen/arch/riscv/traps.c +++ b/xen/arch/riscv/traps.c @@ -178,8 +178,6 @@ static void check_for_pcpu_work(void) vcpu_sync_interrupts(curr); =20 vcpu_flush_interrupts(curr); - - p2m_handle_vmenter(); } =20 static void timer_interrupt(void) --=20 2.55.0 From nobody Fri Oct 23 15:32:28 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) client-ip=192.237.175.120; envelope-from=xen-devel-bounces@lists.xenproject.org; helo=lists.xenproject.org; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=pass(p=none dis=none) header.from=gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1790785482; cv=none; d=zohomail.com; s=zohoarc; b=hgomVAZp1hhgFlMSxXjLRUNZl1zIzXposAOHeloC0Ob3/kGcRSYvRHHqvSaRN89KaQtWM5780ozm0yQ7/mO+cWkWIUm/9eA0UJfwJ2RvvzJxn89C9NydkZ2XzHFvM8OTExsQYpEQcc0jaqJ+lJiHB3LKCMoPDUsWRiu5zlCjzC8= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1790785482; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=poumh8/Cw0lIytsNv2ifcvrF8KG7ngFEnBawZK7cjRQ=; b=Nae2rGINU6CBXYlUSZ6vbrFKbZphVYxwAJD4kJ190pMj7IdfqQaXBjuUF3Q1wZZ1hbMWJlxBb/FsPv6UrAge0BAodIAQH9Awy4DwsoIVaztEv80lbl9e0a4xSZlYQ0ynNm4nt3ZIJtAmR2gWkaqzasWVOjYzeXlGhTNvLwAWBKo= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) by mx.zohomail.com with SMTPS id 1790785482566144.60371277646254; Wed, 30 Sep 2026 09:24:42 -0700 (PDT) Received: from list by lists.xenproject.org with outflank-mailman.1437546.1656486 (Exim 4.92) (envelope-from ) id 1xBx6N-0003Q5-Vm; Wed, 30 Sep 2026 16:24:15 +0000 Received: by outflank-mailman (output) from mailman id 1437546.1656486; Wed, 30 Sep 2026 16:24:15 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1xBx6N-0003PA-RY; Wed, 30 Sep 2026 16:24:15 +0000 Received: by outflank-mailman (input) for mailman id 1437546; Wed, 30 Sep 2026 16:24:14 +0000 Received: from mx.expurgate.net ([195.190.135.20]) by lists.xenproject.org with esmtp (Exim 4.92) id 1xBx6M-0003JR-9U for xen-devel@lists.xenproject.org; Wed, 30 Sep 2026 16:24:14 +0000 Received: from mx.expurgate.net (helo=localhost) by mx.expurgate.net with esmtp id 1xBx6L-00AJmP-Mi for xen-devel@lists.xenproject.org; Wed, 30 Sep 2026 18:24:13 +0200 Received: from [10.42.69.3] (helo=localhost) by localhost with ESMTP (eXpurgate MTA 0.9.1) (envelope-from ) id 6abd378d-8faa-0a2a0a5109dd-0a2a450394dc-34 for ; Wed, 30 Sep 2026 18:24:13 +0200 Received: from [74.125.225.140] (helo=mail-wm2-f12.google.com) by tlsNG-33051d.mxtls.expurgate.net with ESMTPS (eXpurgate 4.57.1) (envelope-from ) id 6abd37ad-fae8-0a2a45030019-4a7de18ca775-3 for ; Wed, 30 Sep 2026 18:24:13 +0200 Received: by mail-wm2-f12.google.com with SMTP id 5b1f17b1804b1-49b912d822dso41390805e9.2 for ; Wed, 30 Sep 2026 09:24:13 -0700 (PDT) Received: from fedora (user-109-243-71-234.play-internet.pl. [109.243.71.234]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-4a01cd43e66sm14620485e9.2.2026.09.30.09.24.12 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 30 Sep 2026 09:24:12 -0700 (PDT) X-Outflank-Mailman: Message body and most headers restored to incoming version X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" Authentication-Results: eu.smtp.expurgate.cloud; dkim=pass header.s=20251104 header.d=gmail.com header.i="@gmail.com" header.h="Content-Transfer-Encoding:MIME-Version:References:In-Reply-To:Message-ID:Date:Subject:Cc:To:From" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1790785453; x=1791390253; darn=lists.xenproject.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=poumh8/Cw0lIytsNv2ifcvrF8KG7ngFEnBawZK7cjRQ=; b=gbAXHYJnsMangz57PRg24VQ0ip/YX/OhIIxc00jMPLav+5xNTs8LAqUS1xDvSDYZgw mF3tRn6tePCyM3BO2bSN75hts5BSAA5kB9z/du/gzw6GvG06gMYk9CD2Zi5klhqYTu+y hb7hng9QsNoz12gBunkpZT/3LDUUutNQXbH7e9xj6gxRz0gipX+ALZuMflf9Y/JyATso qTyLUi7g4qx3BYqkXeThx+/xc8pppA9JwMsBvJDUtnNCGMuNrFkP9PAkaM6bS01ul4zt ZhP9qjCAlGVH/e9z1ngile7kl5SondxC9B+enPjc2NZC1376twwlpQxnsier/7bN4axj bSnQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1790785453; x=1791390253; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=poumh8/Cw0lIytsNv2ifcvrF8KG7ngFEnBawZK7cjRQ=; b=jhAJxfw9jTjyzm8tfSJnJlwTAqBd6gB7abPQNZVLA5GkAEQ0X9CCBZSKMQzDYKlAtG 0V6d+zhw3i3oiAfOLUhCJZ+H9X4K0DbKspWbv/RKsIRmKACQZkR+N2KiK4jL/EeDTH2S 4nW3xgRPIa+4dqBgeT2uLEbDOpRTHYuo9OMKUNN5hoor/aetMikt8fhVhJCAfGIAQYZr r3NFdSi/CX+vPe9y8v78e5wdUin4TAvcS3s8ALy8tOFLrPOPUzKjkQfYU3XZwy8gV4nN f90uR9P3HK8m3uygBY/W/OMM4iLOAprqIkOZ3tqqs7H4uPgRC6a309U5NRjey9hsMBTN IdNA== X-Gm-Message-State: AFuF++klcjquR8faTKTQbILxTD7c5yrt6TAFN8GxNPvf6ErOvIL8AWZ4 rTs4tDRSa8meVCzSypWy21te3aYt5rfSOrxVgVJb38DGw5GpgFKwbz53/XtDqw== X-Gm-Gg: AYBFou3XSFC8nl3AqerP0VOitRU8ZIDP3XvoZd4C4h8Xx9o2i1DivJ9SUW07FWtypmW er892HoAqni9KGY8MC/7/3DFPAdKC2rpMIilibaud6G34RmtikarSx4g1XV6RkNK2thOBU5mdo3 4NCgcGuoVmqqCLY9/rXzSP2Y8usnFMPwnmzpQ9OGePCkhN1scUcURgfe47xFhzaW0kz+ZFv1zpT jCijwK/5HDAr42VI5cWXTER2/7d5aznn6ezaTLqgnuvZznhAEJVCqdYdKgvwsV7kkmZ/iaPadaa WrIZtNTIjJ+BUEQwrA2vyEYZK3+Rzn4eJweyGdXCsXZeZuNYEwYzDsFol3R2NlTPZu25bN83stz z/sxkiPfYGD2KXw8v5M30IH6Cp60byyVjytKmjPb6GF/924ruE94T27G5qiU5cib0Ody5Z/UsoP 0P9hHCvK5Ir2/s8mcqIOTrc3SxdXw7Ogmh1+aSerbqRGrV5B7cVEpot4EAZU5j7E4IDsAImyqjr uOGdulLFPmDCV16g3cHYXQKpJVVOhOliYhOhf/q X-Received: by 2002:a05:600c:5391:b0:49d:2562:d670 with SMTP id 5b1f17b1804b1-4a01afdcef8mr34025055e9.14.1790785453013; Wed, 30 Sep 2026 09:24:13 -0700 (PDT) From: Oleksii Kurochko To: xen-devel@lists.xenproject.org Cc: Romain Caritey , Baptiste Le Duc , Zheng Zhang , Oleksii Kurochko , Alistair Francis , Connor Davis , Andrew Cooper , Anthony PERARD , Michal Orzel , Jan Beulich , Julien Grall , =?UTF-8?q?Roger=20Pau=20Monn=C3=A9?= , Stefano Stabellini Subject: [PATCH v3 12/39] xen/riscv: save and restore vsiselect on vCPU context switch Date: Wed, 30 Sep 2026 18:23:31 +0200 Message-ID: <3a454373368c507a7bf9693c6651a7749d2a86b7.1790779209.git.oleksii.kurochko@gmail.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-purgate-ID: tlsNG-33051d/1790785453-766FB4E9-ADC2EB43/10/73395122804 X-purgate-type: spam X-purgate-size: 4491 X-ZohoMail-DKIM: pass (identity @gmail.com) X-ZM-MESSAGEID: 1790785483884158500 Content-Type: text/plain; charset="utf-8" vsiselect is a per-hart CSR which a guest changes on its own: when V=3D1, VS-mode accesses to siselect are really accesses to vsiselect. Architecturally a vCPU has to find there the value it last wrote, but as long as the CSR isn't part of the vCPU context it finds whatever selector the vCPU which ran on the hart before it left behind. A guest which writes siselect, is descheduled and then reads sireg without rewriting siselect therefore reaches a register it never selected, and it can also observe another guest's selector value. When Smstateen is implemented, access to vsiselect and vsireg is gated by hstateen0.CSRIND (bit 60, SMSTATEEN0_SVSLCT in Xen's headers), and v->arch.hstateen0 holds the bits vcpu_csr_init() ended up with. A clear bit there covers the two cases in which the CSR has to be skipped: - Xen didn't hand the guest access to it, so the guest can't have changed the CSR and there is no state to preserve; - M-mode denied the state altogether. Smstateen makes a bit which is zero in mstateen0 read-only zero in hstateen0, and a zero bit in mstateen0 traps accesses from every privilege mode less privileged than M-mode, HS-mode included, so Xen couldn't even read the CSR to save it. Without Smstateen no bit controls access to the CSR, so it is saved and restored whenever Ssaia is available. Signed-off-by: Oleksii Kurochko Reviewed-by: Baptiste Le Duc --- Changes in v3: - Rename from "xen/riscv: save and restore AIA state on vCPU context switch", as only vsiselect is switched now. - Save and restore only vsiselect: drop hviprio1 and hviprio2. - Rename vcpu_has_aia_state() to vcpu_can_access_vsiselect() and drop its hstateen0 bit argument. - Move switching vsie to uint64_t and csr_{read,write}64() to "xen/riscv: implement vCPU context switching". - Update the commit message. --- Changes in v2: - New patch. --- --- xen/arch/riscv/domain.c | 28 ++++++++++++++++++++++++++++ xen/arch/riscv/include/asm/domain.h | 1 + 2 files changed, 29 insertions(+) diff --git a/xen/arch/riscv/domain.c b/xen/arch/riscv/domain.c index f80643e2d82b..610026fd81c0 100644 --- a/xen/arch/riscv/domain.c +++ b/xen/arch/riscv/domain.c @@ -326,6 +326,28 @@ int arch_domain_create(struct domain *d, return rc; } =20 +/* + * vsiselect is a per-hart CSR, but a guest changes it on its own: when V= =3D1, + * VS-mode accesses to siselect are really accesses to vsiselect. Hence it= is + * part of the vCPU context. + * + * When Smstateen is implemented, hstateen0.CSRIND (SMSTATEEN0_SVSLCT) gat= es + * that access, and a bit staying clear in v->arch.hstateen0 (see + * vcpu_csr_init()) means either that the guest was never given access to = the + * CSR, and so can't have changed it, or that M-mode denied the state + * altogether, in which case the CSR can't be accessed from HS-mode either. + */ +static bool vcpu_can_access_vsiselect(const struct vcpu *v) +{ + if ( !riscv_isa_extension_available(NULL, RISCV_ISA_EXT_ssaia) ) + return false; + + if ( !riscv_isa_extension_available(NULL, RISCV_ISA_EXT_smstateen) ) + return true; + + return v->arch.hstateen0 & SMSTATEEN0_SVSLCT; +} + static void csr_regs_ctxt_switch_from(struct vcpu *p) { /* @@ -353,6 +375,9 @@ static void csr_regs_ctxt_switch_from(struct vcpu *p) p->arch.vscause =3D csr_read(CSR_VSCAUSE); p->arch.vstval =3D csr_read(CSR_VSTVAL); p->arch.vsepc =3D csr_read(CSR_VSEPC); + + if ( vcpu_can_access_vsiselect(p) ) + p->arch.vsiselect =3D csr_read(CSR_VSISELECT); } =20 static void csr_regs_ctxt_switch_to(struct vcpu *n) @@ -374,6 +399,9 @@ static void csr_regs_ctxt_switch_to(struct vcpu *n) csr_write(CSR_VSCAUSE, n->arch.vscause); csr_write(CSR_VSTVAL, n->arch.vstval); csr_write(CSR_VSEPC, n->arch.vsepc); + + if ( vcpu_can_access_vsiselect(n) ) + csr_write(CSR_VSISELECT, n->arch.vsiselect); } =20 static void ctxt_switch_from(struct vcpu *p) diff --git a/xen/arch/riscv/include/asm/domain.h b/xen/arch/riscv/include/a= sm/domain.h index 77ad888a2d6c..c33d83836f2e 100644 --- a/xen/arch/riscv/include/asm/domain.h +++ b/xen/arch/riscv/include/asm/domain.h @@ -74,6 +74,7 @@ struct arch_vcpu { register_t vscause; register_t vsepc; uint64_t vsie; + register_t vsiselect; register_t vsscratch; register_t vsstatus; register_t vstval; --=20 2.55.0 From nobody Fri Oct 23 15:32:28 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) client-ip=192.237.175.120; envelope-from=xen-devel-bounces@lists.xenproject.org; helo=lists.xenproject.org; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=pass(p=none dis=none) header.from=gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1790785484; cv=none; d=zohomail.com; s=zohoarc; b=WllMX4S5M2lOqGJEtnNobmljU9bc/CeOYqaKF2pbUdvcG2Dd68CmVEfOMqLYAHn70HiiI0ksxCCAZ7nZrbP6adLpZfw1RntzVhrWMF1Fo7ExR6IFjCil68dhlBpK0t36t65Jgy9laFgnsMnxF5H7IZIxfUHnh09n6jcxsTsWO4w= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1790785484; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=gcKMiPoPBXvIwOVBRyQ2jzb4SFPZuO/OOBRln7jvQXw=; b=Sn0c7f+FtFJj0HmJEl/cUi2h8vcE+BF+l/xvGVFjYne7a/ZfiDlm1cCgKWJtnHKxWXQVXkqbQPd+cgIqoSB4v8kyAWKz08d/aLZccUMBZgJrHxsCFqaB1ve7UZHGXCrXLDE/XWpT4bXBirzc/N4Gfo/fNnmx5IGQtfRtuA/YWwQ= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) by mx.zohomail.com with SMTPS id 1790785484572245.66227877138306; Wed, 30 Sep 2026 09:24:44 -0700 (PDT) Received: from list by lists.xenproject.org with outflank-mailman.1437548.1656508 (Exim 4.92) (envelope-from ) id 1xBx6Q-00043S-HB; Wed, 30 Sep 2026 16:24:18 +0000 Received: by outflank-mailman (output) from mailman id 1437548.1656508; Wed, 30 Sep 2026 16:24:18 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1xBx6Q-00043G-Dr; Wed, 30 Sep 2026 16:24:18 +0000 Received: by outflank-mailman (input) for mailman id 1437548; Wed, 30 Sep 2026 16:24:16 +0000 Received: from mx.expurgate.net ([195.190.135.20]) by lists.xenproject.org with esmtp (Exim 4.92) id 1xBx6O-0003fD-Np for xen-devel@lists.xenproject.org; Wed, 30 Sep 2026 16:24:16 +0000 Received: from mx.expurgate.net (helo=localhost) by mx.expurgate.net with esmtp id 1xBx6O-00AJmP-4i for xen-devel@lists.xenproject.org; Wed, 30 Sep 2026 18:24:16 +0200 Received: from [10.42.69.3] (helo=localhost) by localhost with ESMTP (eXpurgate MTA 0.9.1) (envelope-from ) id 6abd378d-8faa-0a2a0a5109dd-0a2a450394dc-38 for ; Wed, 30 Sep 2026 18:24:16 +0200 Received: from [74.125.225.140] (helo=mail-wm2-f12.google.com) by tlsNG-33051d.mxtls.expurgate.net with ESMTPS (eXpurgate 4.57.1) (envelope-from ) id 6abd37af-fae8-0a2a45030019-4a7de18c8da5-3 for ; Wed, 30 Sep 2026 18:24:16 +0200 Received: by mail-wm2-f12.google.com with SMTP id 5b1f17b1804b1-49ffed768deso13012455e9.1 for ; Wed, 30 Sep 2026 09:24:16 -0700 (PDT) Received: from fedora (user-109-243-71-234.play-internet.pl. [109.243.71.234]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-4a01cd43e66sm14620485e9.2.2026.09.30.09.24.13 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 30 Sep 2026 09:24:13 -0700 (PDT) X-Outflank-Mailman: Message body and most headers restored to incoming version X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" Authentication-Results: eu.smtp.expurgate.cloud; dkim=pass header.s=20251104 header.d=gmail.com header.i="@gmail.com" header.h="Content-Transfer-Encoding:MIME-Version:References:In-Reply-To:Message-ID:Date:Subject:Cc:To:From" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1790785455; x=1791390255; darn=lists.xenproject.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=gcKMiPoPBXvIwOVBRyQ2jzb4SFPZuO/OOBRln7jvQXw=; b=mMB2UTbaJMstzVeHsOiHZuvVtmnvVSBa/SsxD7S7BpaE/7LIW/n7Y3gsIY91BlDyPl t8JXJs/hT/fW0KA4WaGeHGP2iWslsar3zGGynau3xnTMdMHuxpWOCQlKde0LdOMZpjUk xLNg/nRhnYT18u96SOpnHDE71Fj+/6Bo4otzi5XTmpTvk3KMRiLsYQ2PjytD2hTt/FBv 1cxoqbdy//rAE+HjIS51J8KIKHdupLXFQs178aRewQZL7nV1pDNotu0ZRR/GuxJMrYli XBxXKG6DMJUINPJ7/Rkyq323IzzcjZbDcSBYDT1TOkEWMJus/szQjcfnHjPj79xAAgW0 TEFQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1790785455; x=1791390255; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=gcKMiPoPBXvIwOVBRyQ2jzb4SFPZuO/OOBRln7jvQXw=; b=1kSUzopgBqqJ6zsmZ9cONFebi+mUdhhTYDmrEN1i0ehvjWuC2aTaTTAsPN19dhv57G WL3O/w0ZDQBoor1S8VWNWi9Qyjr5e8Jpfol4+S94FqIPL13k+MSI93ZZdyccQDxOduAP 6pz7X+kUXC/77LgFzeIkDXj0UZtcbWPJvU8Q8v2mxePKmdcNtNCsnwaGlD1gZo1nVJea 5hY0dNITFWd+uHD8lEZSPNfVx5BNTzpV5IYP/iEF+xLaY31ZyVzKu5FCsx1t2BqYE69m Ud0IJWitpNWdNHrBdm+oxFCoW2+HAJRgFTrSrrc0GUxywfRKwmHCcXOR5Mrmn35H3Vh8 RQkw== X-Gm-Message-State: AFuF++kOc0y8PV8kJCnAgUS4Vy90VwkoA+/5tJPsBtbidRv2wyzoJzb4 czlF78eLHxdi+4eMQyiysshLijdvLAzHO9ducV1qlViejAuSF4vpsqL+HIhScw== X-Gm-Gg: AYBFou2b9Y4y8yvdVKtG+gbRGILF/cnxO4f6FGfzYg2hZmsqF9BbzI9FpEwY7OsLZkw o4NUHE5JY0IiwxOtgaQN30HBuCXKo0mUZ40ZKajZ7f1HKAClmBfYN2jmQDMngF1rhJYlDuvWBCM /OD7Wkzdt9tSQ/edUBTkqXhJFRaAhS+3XGUeuz77LPjev1+cE1SLy0s624q+WMVtM69zaf0mc1i aCYbZEOwVFD08B1JUrdXeoXObLu2jAmPQqnbBI1MbLcoRLbqEAStjFLAVBqIUKsBUy/J1Bq8gtZ /SGyFbngYB5u42h/3k90pvfpJQux/XZwUlx0pbeQ9hUTKSIFg94ekITuAWQ9tD66YpjrXb6gXCq P8VWplrXkHgYYTeSDU2HI2R1BR91a4gFRyvnVj+L1yAKxtFDUco5zQXVudHC1IJ6Q9vG64NpbKe rnXH2MpB4KuQME7GcBMXdZKxP6I18GNEERUucnTkTkpTqI/sKDchXouIfecJCm0utTgvcnkT99Q SUxmRGvIstBDKBtV8g6NW0KhThCPfF0g3tXX5sm2g== X-Received: by 2002:a05:600c:1c16:b0:4a0:25c:8ad2 with SMTP id 5b1f17b1804b1-4a01eb04367mr3331635e9.9.1790785454033; Wed, 30 Sep 2026 09:24:14 -0700 (PDT) From: Oleksii Kurochko To: xen-devel@lists.xenproject.org Cc: Romain Caritey , Baptiste Le Duc , Zheng Zhang , Oleksii Kurochko , Alistair Francis , Connor Davis , Andrew Cooper , Anthony PERARD , Michal Orzel , Jan Beulich , Julien Grall , =?UTF-8?q?Roger=20Pau=20Monn=C3=A9?= , Stefano Stabellini Subject: [PATCH v3 13/39] xen/riscv: introduce vintc_ctxt_switch_{from,to}() Date: Wed, 30 Sep 2026 18:23:32 +0200 Message-ID: <752ca5c3e7af9e4d2037783d7d213a9bc2360c83.1790779209.git.oleksii.kurochko@gmail.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-purgate-ID: tlsNG-33051d/1790785456-6F6C64E9-E1BB166C/10/78276251493 X-purgate-type: spam X-purgate-size: 3221 X-ZohoMail-DKIM: pass (identity @gmail.com) X-ZM-MESSAGEID: 1790785485905158500 Content-Type: text/plain; charset="utf-8" Virtual interrupt controller state must be preserved across vCPU context switches. Introduce vintc_ctxt_switch_{from,to}() wrappers around new ctxt_switch_{from,to}() hooks in struct vintc_ops, and call them from the context switch path, so that this state can be saved/restored without knowing which vINTC variant a domain uses. No vINTC variant implements the hooks yet: the vAPLIC implementation is added separately. Signed-off-by: Oleksii Kurochko Acked-by: Jan Beulich Reviewed-by: Baptiste Le Duc --- Changes in v3: - s/v/{p,n} for vintc_ctxt_switch_{from,to}() arguments and also for hook prototypes. - Add Acked-by: Jan Beulich . --- Changes in v2: - Update the commit message. - s/vintc_state_{save,restore}/vintc_ctxt_switch_{to,from}. - s/{re}store_state/ctxt_switch_{to,from} for vintc_ops. - s/vcpu/v for vintc_ctxt_switch_{to,from}() arguments. --- --- xen/arch/riscv/domain.c | 4 ++++ xen/arch/riscv/include/asm/intc.h | 9 +++++++++ xen/arch/riscv/intc.c | 14 ++++++++++++++ 3 files changed, 27 insertions(+) diff --git a/xen/arch/riscv/domain.c b/xen/arch/riscv/domain.c index 610026fd81c0..fd21cb1789e6 100644 --- a/xen/arch/riscv/domain.c +++ b/xen/arch/riscv/domain.c @@ -418,6 +418,8 @@ static void ctxt_switch_from(struct vcpu *p) =20 vtimer_ctxt_switch_from(p); =20 + vintc_ctxt_switch_from(p); + csr_regs_ctxt_switch_from(p); } =20 @@ -433,6 +435,8 @@ static void ctxt_switch_to(struct vcpu *n) =20 csr_regs_ctxt_switch_to(n); =20 + vintc_ctxt_switch_to(n); + vtimer_ctxt_switch_to(n); =20 p2m_ctxt_switch_to(n); diff --git a/xen/arch/riscv/include/asm/intc.h b/xen/arch/riscv/include/asm= /intc.h index 1bfba7c6155b..59e12f3d3c6d 100644 --- a/xen/arch/riscv/include/asm/intc.h +++ b/xen/arch/riscv/include/asm/intc.h @@ -64,6 +64,12 @@ struct vintc_ops { =20 /* Deinitialize some vINTC-related stuff for a vCPU */ void (*vcpu_deinit)(struct vcpu *v); + + /* Save vINTC state of the vCPU being switched out */ + void (*ctxt_switch_from)(struct vcpu *p); + + /* Restore vINTC state of the vCPU being switched in */ + void (*ctxt_switch_to)(struct vcpu *n); }; =20 struct vintc { @@ -91,4 +97,7 @@ void domain_vintc_deinit(struct domain *d); =20 int vintc_reserve_virq(const struct domain *d, unsigned int virq); =20 +void vintc_ctxt_switch_from(struct vcpu *p); +void vintc_ctxt_switch_to(struct vcpu *n); + #endif /* ASM__RISCV__INTERRUPT_CONTOLLER_H */ diff --git a/xen/arch/riscv/intc.c b/xen/arch/riscv/intc.c index 810d126e263d..53ba2b04ab53 100644 --- a/xen/arch/riscv/intc.c +++ b/xen/arch/riscv/intc.c @@ -178,3 +178,17 @@ int __overlay_init vintc_reserve_virq(const struct dom= ain *d, =20 return test_and_set_bit(virq, d->arch.vintc->used_irqs) ? -EEXIST : 0; } + +void vintc_ctxt_switch_from(struct vcpu *p) +{ + const struct vintc_ops *ops =3D p->domain->arch.vintc->ops; + + ops->ctxt_switch_from(p); +} + +void vintc_ctxt_switch_to(struct vcpu *n) +{ + const struct vintc_ops *ops =3D n->domain->arch.vintc->ops; + + ops->ctxt_switch_to(n); +} --=20 2.55.0 From nobody Fri Oct 23 15:32:28 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) client-ip=192.237.175.120; envelope-from=xen-devel-bounces@lists.xenproject.org; helo=lists.xenproject.org; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=pass(p=none dis=none) header.from=gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1790785481; cv=none; d=zohomail.com; s=zohoarc; b=Ipfp4QofWNKuYQhWtzWsBCJY4o5bKPdpl/W4PG98xOeNnM5WRelBXnTp4XywmEsJ54n+9erp6P2WpM9bY2mMG+CMdsS+nzISLNbPZWO8pxcwTd2f1Yh1Xq/GvsJRo5v0vbRfZwDoabE/jEVUIu63XIN6j1s0eftG1tbNEHag53U= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1790785481; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=BieJeCmqOVH/qI7ZeYcHrQ/RR6oP1rpUegwUnPXQggQ=; b=jp8K3/KMYBTVkJm2qTUzScYR0pMwl+Im+UfcfZzVXJ1G/7I12CUc/MLIU4XUxRY8sJcxcy/tSW4TG8l5KcayWakqo/I6V//l77XR06MP4/cIPdrxa1MtA42nKzQ/kmok801jw2e7G3M1/57YcTfZvmv/JxRUibnDPQDYbavCn2c= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) by mx.zohomail.com with SMTPS id 1790785481026282.4391084461557; Wed, 30 Sep 2026 09:24:41 -0700 (PDT) Received: from list by lists.xenproject.org with outflank-mailman.1437547.1656499 (Exim 4.92) (envelope-from ) id 1xBx6P-0003od-AX; Wed, 30 Sep 2026 16:24:17 +0000 Received: by outflank-mailman (output) from mailman id 1437547.1656499; Wed, 30 Sep 2026 16:24:17 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1xBx6P-0003oW-6K; Wed, 30 Sep 2026 16:24:17 +0000 Received: by outflank-mailman (input) for mailman id 1437547; Wed, 30 Sep 2026 16:24:16 +0000 Received: from mx.expurgate.net ([194.145.224.10]) by lists.xenproject.org with esmtp (Exim 4.92) id 1xBx6O-0003be-If for xen-devel@lists.xenproject.org; Wed, 30 Sep 2026 16:24:16 +0000 Received: from mx.expurgate.net (helo=localhost) by mx.expurgate.net with esmtp id 1xBx6N-006Nrc-Vm for xen-devel@lists.xenproject.org; Wed, 30 Sep 2026 18:24:15 +0200 Received: from [10.42.69.10] (helo=localhost) by localhost with ESMTP (eXpurgate MTA 0.9.1) (envelope-from ) id 6abd37a6-2eae-0a2a0a5409dd-0a2a450a9f7a-20 for ; Wed, 30 Sep 2026 18:24:15 +0200 Received: from [74.125.225.140] (helo=mail-wm2-f12.google.com) by tlsNG-4011c0.mxtls.expurgate.net with ESMTPS (eXpurgate 4.57.1) (envelope-from ) id 6abd37af-f2d2-0a2a450a0019-4a7de18cd454-3 for ; Wed, 30 Sep 2026 18:24:15 +0200 Received: by mail-wm2-f12.google.com with SMTP id 5b1f17b1804b1-4a00713639cso26451975e9.1 for ; Wed, 30 Sep 2026 09:24:15 -0700 (PDT) Received: from fedora (user-109-243-71-234.play-internet.pl. [109.243.71.234]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-4a01cd43e66sm14620485e9.2.2026.09.30.09.24.14 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 30 Sep 2026 09:24:14 -0700 (PDT) X-Outflank-Mailman: Message body and most headers restored to incoming version X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" Authentication-Results: eu.smtp.expurgate.cloud; dkim=pass header.s=20251104 header.d=gmail.com header.i="@gmail.com" header.h="Content-Transfer-Encoding:MIME-Version:References:In-Reply-To:Message-ID:Date:Subject:Cc:To:From" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1790785455; x=1791390255; darn=lists.xenproject.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=BieJeCmqOVH/qI7ZeYcHrQ/RR6oP1rpUegwUnPXQggQ=; b=ZDY+i4VbRCiS5lo9TBcNSbu/yqUXz42mKyzEgnWR77M/jLRhzzSycUOdhkPq+KF9ul SNH4DMeLZlSLz/s5ITN8EQARcosNpmMTVCh5GDxzSDTY6thM9ytzDHwRUak/wQO1P6Or cBKwQUxAV9GqOnlsxAkjEKQ4p6efINH7ZyK2zkBKyQuglP2xYhMKY3Vqmiahz19l9ARv pLCS833G05gue/wDMmSl6gnJ/rrTSGNRIW62Veh3ibT5u/fjxASjmBwV/77ACBFi0OXs UUJbB6CDCKAb9tRAqaaeLpxidHPYqEzmfUUkHUtts7sc4xYJBews3VZM6S7rCP6IeyS7 /BCg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1790785455; x=1791390255; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=BieJeCmqOVH/qI7ZeYcHrQ/RR6oP1rpUegwUnPXQggQ=; b=On569ddykwSGeO9i20zX35sT4ttB/L//GOeGFVlceMVk5rjjnvSJby6rLfl2zw6zZD 7sF/vW5dp040yMuT5mOI4XWaQ4bMuuDafCDEHVYDTCF4ZDUYSdY/hBv8AfIbxs06W2D8 UloTK5KkNO6tT4bxmgSqWEvqPQfeWlF8khgnLd5m5EQusMYDk+LS6nU4r5KcDkkeE5Z1 I7ITVwLNp6IOqUXN/lR2chOaFzGAEhh0yYOgxfxhtj/y/FHbETxeb2yU7YEdMXZxljMk +ND0y35YcuPJVZhT/sMeOuZQ7SbdnkUO0EKha0tzDrzNetwnOLX4eSUymb094S/c7694 vkcA== X-Gm-Message-State: AFuF++lOPLgHB0OxA12bxh9+XksS+TdPFUU4d0f7c+irfYw/hW/Eab5p 3QcE9YMntHipFK2jgKI11lMaIyL2bXuNY0gCfHTk6Tk5RxXUGTcneFku7fceQg== X-Gm-Gg: AYBFou3EOWzRyiInsj/eAPKTg7MW/6kghq4KQL/So8paNOYxyANSeGmST85nLV1IU/a z7bgS9qBHtCQsZ6AclizXDZYLzLCQZEFFuDG7IlIm+L5W25wE1Sjfvp0P+fAILgh2KNso9nAvPq 95F0D1M56g6wBv0k0VpJBqxXSm2nU1TitwKeVeivP7YfkcZLbEIHsFTcDWrSUxLcDi0rD/Mjwzs vGnaSyjeyOzn+IXfbfZiLe/gxt+3GPqXCeNn+pS4WLeejsF/VkgdaUhx6ad6O13T40C8lD61xCP AVZfYzZfQc2jI3GEHrkCGbb4gIzxVaj2F8hO/1uUyuFRkJ5MwSeFIeRjJOR30qEtX3iix6MN+vE Hn+6HHbWWGV1yJyThWBnX76X4RgDHDzYYzOJrmYglDdz/gss9QMxCocbhbKFkovAmr825GCSk+m sgjj+zInyan8g6OeAeXpjv7mYQ7d1s0rSlRCsU8OYe25ElTEeLBQwZGVM2aIRiw/NKh/o4OBsqk IFVvPGR5gHNs4LOe5TpF4FTfNCxwS2fm0UJ3IEK X-Received: by 2002:a05:600c:3b1a:b0:49f:fe90:de63 with SMTP id 5b1f17b1804b1-4a01b12cbb8mr34768195e9.28.1790785455174; Wed, 30 Sep 2026 09:24:15 -0700 (PDT) From: Oleksii Kurochko To: xen-devel@lists.xenproject.org Cc: Romain Caritey , Baptiste Le Duc , Zheng Zhang , Oleksii Kurochko , Alistair Francis , Connor Davis , Andrew Cooper , Anthony PERARD , Michal Orzel , Jan Beulich , Julien Grall , =?UTF-8?q?Roger=20Pau=20Monn=C3=A9?= , Stefano Stabellini Subject: [PATCH v3 14/39] xen/riscv: add IMSIC vCPU context switch handlers Date: Wed, 30 Sep 2026 18:23:33 +0200 Message-ID: X-Mailer: git-send-email 2.55.0 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-purgate-ID: tlsNG-4011c0/1790785455-50ACCCFC-0AB9D3F7/10/73395122804 X-purgate-type: spam X-purgate-size: 4912 X-ZohoMail-DKIM: pass (identity @gmail.com) X-ZM-MESSAGEID: 1790785481871158500 Content-Type: text/plain; charset="utf-8" IMSIC state currently needs to track only which physical CPU owns a vCPU's IMSIC guest interrupt file, as the CPU id is part of the physical address the file is mapped at. Add imsic_ctxt_switch_from() to record that CPU when a vCPU is switched out. A vCPU running on the s/w VS-file has no h/w file bound to a CPU, so there is nothing to record for it. Nothing reads the recorded value yet. imsic_ctxt_switch_to() has nothing to do: switching a vCPU in on the CPU which owns its guest interrupt file needs no IMSIC update. Only a move to another CPU does (a new VGEIN and a remapped file), and that isn't part of the context switch. Install both as the ctxt_switch_{from,to} hooks of struct vintc_ops. MSI delivery is the only mode Xen supports (aplic_init() panics on an APLIC without an "msi-parent" property) and the only one vAPLIC emulates, so the vAPLIC state to save and restore is always the IMSIC one and no vAPLIC-level forwarder is needed. Being indirect call targets, both handlers get cf_check. Co-developed-by: Romain Caritey Signed-off-by: Oleksii Kurochko Reviewed-by: Baptiste Le Duc --- Changes in v3: - Drop the reference to aplic_init() from the comment on the .ctxt_switch_{from,to} initialization in vaplic.c. - Use p and n instead of v as the arguments of imsic_ctxt_switch_{from,to}(), as the other context switch helpers do. - Update the commit message. --- Changes in v2: - s/imsic_state_{save,restore}/imsic_ctxt_switch_{from,to}: the old names suggested saving and restoring register state, which isn't what these functions do. - Fix the comment in imsic_ctxt_switch_from(): it explained the ->vsfile_cpu sentinel while the code checks ->guest_file_id. - Adapt to ->vsfile_cpu holding v->processor instead of a hartid. - Add cf_check as both are indirect call targets now. - Fold in the vintc_ops hook-up, which was a separate patch in v1. It no longer adds vaplic_state_{save,restore}() forwarders: the BUG_ON("unimplemented") path in them was unreachable and has_msi_support() was an MMIO read done on every context switch. - Drop the claim that the not-yet-supported case is guarded by a BUG_ON(); there is no such BUG_ON(). - Update the subject accordingly. --- --- xen/arch/riscv/imsic.c | 23 +++++++++++++++++++++++ xen/arch/riscv/include/asm/imsic.h | 3 +++ xen/arch/riscv/vaplic.c | 6 ++++++ 3 files changed, 32 insertions(+) diff --git a/xen/arch/riscv/imsic.c b/xen/arch/riscv/imsic.c index 402b2f14f591..d633f59db20d 100644 --- a/xen/arch/riscv/imsic.c +++ b/xen/arch/riscv/imsic.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -342,6 +343,28 @@ static int __init imsic_parse_node(const struct dt_dev= ice_node *node, return 0; } =20 +void cf_check imsic_ctxt_switch_from(struct vcpu *p) +{ + struct vimsic_state *imsic_state =3D p->arch.vimsic_state; + unsigned long flags; + + /* + * A vCPU using the s/w IMSIC VS-file (guest_file_id =3D=3D 0) has no = h/w + * VS-file bound to a physical CPU, so there is no location to record. + */ + if ( !vcpu_guest_file_id(p) ) + return; + + write_lock_irqsave(&imsic_state->vsfile_lock, flags); + imsic_state->vsfile_cpu =3D p->processor; + write_unlock_irqrestore(&imsic_state->vsfile_lock, flags); +} + +void cf_check imsic_ctxt_switch_to(struct vcpu *n) +{ + /* Nothing to do */ +} + int cf_check vcpu_imsic_init(struct vcpu *v) { struct vimsic_state *imsic_state; diff --git a/xen/arch/riscv/include/asm/imsic.h b/xen/arch/riscv/include/as= m/imsic.h index 6baadc008d81..5463fb4c31b2 100644 --- a/xen/arch/riscv/include/asm/imsic.h +++ b/xen/arch/riscv/include/asm/imsic.h @@ -96,4 +96,7 @@ unsigned int vcpu_guest_file_id(const struct vcpu *v); =20 int vimsic_make_domu_dt_node(struct kernel_info *kinfo, unsigned int *phan= dle); =20 +void imsic_ctxt_switch_from(struct vcpu *p); +void imsic_ctxt_switch_to(struct vcpu *n); + #endif /* ASM_RISCV_IMSIC_H */ diff --git a/xen/arch/riscv/vaplic.c b/xen/arch/riscv/vaplic.c index ea4b0dc88951..4d87fdb5be42 100644 --- a/xen/arch/riscv/vaplic.c +++ b/xen/arch/riscv/vaplic.c @@ -456,6 +456,12 @@ static const struct mmio_handler_ops vaplic_mmio_ops = =3D { static const struct vintc_ops vintc_ops =3D { .vcpu_init =3D vcpu_imsic_init, .vcpu_deinit =3D vcpu_imsic_deinit, + /* + * MSI delivery is the only supported mode, so the vAPLIC state to save + * and restore is always the IMSIC one. + */ + .ctxt_switch_from =3D imsic_ctxt_switch_from, + .ctxt_switch_to =3D imsic_ctxt_switch_to, }; =20 int domain_vaplic_init(struct domain *d) --=20 2.55.0 From nobody Fri Oct 23 15:32:28 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) client-ip=192.237.175.120; envelope-from=xen-devel-bounces@lists.xenproject.org; helo=lists.xenproject.org; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=pass(p=none dis=none) header.from=gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1790785488; cv=none; d=zohomail.com; s=zohoarc; b=BqRq1MMDZIVECTS8/g0/MCzTBC6hDM6pZ2Cuiq6x55fWuDqnKAhdRYAKJ/OOdr0B+zI+lZBPplOtyvWsfLdo78H2cnFg2vZQO8Xw4UxVfu6YszesERrS7hq2hb8LWDEKqNeXjI6yuoPs76yBorfaaYYm1oDcTrJBhhuU0Cx0W/g= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1790785488; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=h6p22y/TU0N97lNSaxpm7Mkih9ikwlnvqIiwklPqahY=; b=jNXpJwl6bkxY1/qlwUQT8owDolOln6ZDoFtBkcj1D/V83EYnGxOyY+glyHkMs2PTI4eKO3L74GSqz09vKFkxntxiavflstBk7AA7sff5I5OtYogzvA5I1TZSnPGd0Cg09/EEzVp+m1PEn62cxv9n/jX9V+UpiHeZTQxc/gGkvd0= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) by mx.zohomail.com with SMTPS id 1790785488607193.02903639823865; Wed, 30 Sep 2026 09:24:48 -0700 (PDT) Received: from list by lists.xenproject.org with outflank-mailman.1437549.1656517 (Exim 4.92) (envelope-from ) id 1xBx6R-0004IT-PT; Wed, 30 Sep 2026 16:24:19 +0000 Received: by outflank-mailman (output) from mailman id 1437549.1656517; Wed, 30 Sep 2026 16:24:19 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1xBx6R-0004I6-Lt; Wed, 30 Sep 2026 16:24:19 +0000 Received: by outflank-mailman (input) for mailman id 1437549; Wed, 30 Sep 2026 16:24:18 +0000 Received: from mx.expurgate.net ([194.145.224.20]) by lists.xenproject.org with esmtp (Exim 4.92) id 1xBx6Q-0003x7-IV for xen-devel@lists.xenproject.org; Wed, 30 Sep 2026 16:24:18 +0000 Received: from mx.expurgate.net (helo=localhost) by mx.expurgate.net with esmtp id 1xBx6P-00GhSc-Fo for xen-devel@lists.xenproject.org; Wed, 30 Sep 2026 18:24:17 +0200 Received: from [10.42.69.1] (helo=localhost) by localhost with ESMTP (eXpurgate MTA 0.9.1) (envelope-from ) id 6abd37a6-bab6-0a2a0a5309dd-0a2a4501b0cc-28 for ; Wed, 30 Sep 2026 18:24:17 +0200 Received: from [74.125.225.140] (helo=mail-wm2-f12.google.com) by tlsNG-d62444.mxtls.expurgate.net with ESMTPS (eXpurgate 4.57.1) (envelope-from ) id 6abd37b1-5984-0a2a45010019-4a7de18caead-3 for ; Wed, 30 Sep 2026 18:24:17 +0200 Received: by mail-wm2-f12.google.com with SMTP id 5b1f17b1804b1-49fff6f0f87so28361075e9.3 for ; Wed, 30 Sep 2026 09:24:17 -0700 (PDT) Received: from fedora (user-109-243-71-234.play-internet.pl. [109.243.71.234]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-4a01cd43e66sm14620485e9.2.2026.09.30.09.24.15 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 30 Sep 2026 09:24:15 -0700 (PDT) X-Outflank-Mailman: Message body and most headers restored to incoming version X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" Authentication-Results: eu.smtp.expurgate.cloud; dkim=pass header.s=20251104 header.d=gmail.com header.i="@gmail.com" header.h="Content-Transfer-Encoding:MIME-Version:References:In-Reply-To:Message-ID:Date:Subject:Cc:To:From" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1790785457; x=1791390257; darn=lists.xenproject.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=h6p22y/TU0N97lNSaxpm7Mkih9ikwlnvqIiwklPqahY=; b=HgaQj/4uzrA7LCebG3/MUDaIHCwylTnYmbjrUAJl2rtujuMjHcz0BxSmpuXhEIMnZx WGOKOHy+vfm5uP7grMixG0C901JFB5hKolIU1b5s8a8Ecxf8TblbU6IFjGyyEhaaNTvG u6LCOaVCImlNcw+e07E1NvseFkwonzyk5Sbs8Wr8PDbZFeFrSyqtNkCT836ZQkZ8ZLyE zKbVs2w6kp5ZU/zZYECh7pp22jvYJlTWJBHVOim6W7qkRryJt6fjYaJ2pgsmqs2sOoIw WeFvLeJGFUqLeY0C3fsZAcOAj25CVoQSjqIaRefBXddQ2lZR7oVIg7PH0ICDpy9cTcyr uZQw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1790785457; x=1791390257; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=h6p22y/TU0N97lNSaxpm7Mkih9ikwlnvqIiwklPqahY=; b=VRRAAlN/UUgQOihmgSXcf6wO/aGp8mc4h2xXcRtJyLWQzWPA6FSvHnIXTl5gzcpCo+ LNoXdHiHrM/nG9fYySfuaJQt7ki/RDUx+iZzL1GCGAsJJPk2o+rJjtfPacjNVYJkK5RL 8gDgTAfBVvr93lHK9SR1sOtHscW3HlfIZAvmwu4HBq6flLFPIT7Tx2t/ext2ELC7hfG0 fFmy6/MV2MXxzefqcPSDZk0O/EWpS29mb5Lu/BkTO6/6mHygAvg7olhavdERlNtlg9i5 jnMbCaCgo+Jclf9UQNleKRB/U/5cRXpac8CdJiklpWTFt2z7X8CgsOD7T7SgNFv3sZEL 2hAQ== X-Gm-Message-State: AFuF++kzNDxqZILziHxUm23rptM8wAaRyJ7tvunFCNGrsc2qt54RbBhO wvMTcQtx0DbhX/ydiyjAijYvz5ud/ST4OTKFqZOk5TqJu8qL9MIXa8qkKsFi5w== X-Gm-Gg: AYBFou2jK4Md0mB+/xTpEpQz4Io7qIG+hkTX2S22UeRHAHU+AtebRbWuYBZEKIuPr5R Ht1zf9JsKSqrV/wtX7J2gnbN+K1LCpYW6UqVDImD+QFZN/eISFQD7gV7fpQ/MIu4VVYCXlElfnO nHNI4iraXj0D/fCubzfccegXqOooREChh2aXcBmzi1PKxTLGXOlxJWmpUDOJYcEZucp1yJrAaEM VigagWF8VGuLppoFSBB8Ql+2PgwGFipmlP/7jepD4f/I3EqydXMFQKPXVm7YJ9KurkN9UqqQoT5 eWvgwuMpAs/cut6ZrCsMAOqV0DP01e3NGWV81AkTO5BPN3IO/eOJVtZawrIfRQu5zvSBOq7jJXw hmiRtBxthL/4bDnWzgd4/8aWnK/MCoIY4LlIOCRsCzBWRyzLVWzl1stZZsWkaHmRc4s9pkiSu+6 oCcALtU3+vI0rbCHOAnM0gaAfn459CTTxwOurb6K40StEpI89KZ09gIEz1VIWF+V0GsJk5IbJNp g251FoxUT0fw75REKFJdaUhrtqSX4qQtlOit7sr17tPdD5gH24= X-Received: by 2002:a05:600c:1c0d:b0:49c:fa21:1c81 with SMTP id 5b1f17b1804b1-4a01aff36b2mr38760015e9.22.1790785456607; Wed, 30 Sep 2026 09:24:16 -0700 (PDT) From: Oleksii Kurochko To: xen-devel@lists.xenproject.org Cc: Romain Caritey , Baptiste Le Duc , Zheng Zhang , Oleksii Kurochko , Alistair Francis , Connor Davis , Andrew Cooper , Anthony PERARD , Michal Orzel , Jan Beulich , Julien Grall , =?UTF-8?q?Roger=20Pau=20Monn=C3=A9?= , Stefano Stabellini Subject: [PATCH v3 15/39] xen/riscv: extend exception tables with type and data fields Date: Wed, 30 Sep 2026 18:23:34 +0200 Message-ID: <8c1c0c2adf56a395b6419335161da9f11fc827c5.1790779209.git.oleksii.kurochko@gmail.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-purgate-ID: tlsNG-d62444/1790785457-BC359757-9ADD436A/10/73395122804 X-purgate-type: spam X-purgate-size: 20210 X-ZohoMail-DKIM: pass (identity @gmail.com) X-ZM-MESSAGEID: 1790785490000158500 Content-Type: text/plain; charset="utf-8" Extend the RISC-V exception table format to include a type and auxiliary data field. The existing format only supports simple fixups. Some use cases require additional context from the fault (e.g. capturing trap information), which cannot be expressed with the current EX_TYPE_FIXUP entries. Introduce a generic ASM_EXTABLE_RAW() helper to describe entries with a handler type and associated data. Reimplement ASM_EXTABLE() in terms of it using EX_TYPE_FIXUP for compatibility. Add EX_TYPE_TRAP_INFO to allow handlers to retrieve trap state (sepc/scause/stval) and pass it to the fixup path. The data field is used to encode which GPR contains a pointer to a struct trap_info. Provide ASM_EXTABLE_TRAP_INFO() as a convenience wrapper for this case, and pass the trap cause down to fixup_exception() for it. Also add gpr-num.h, providing symbolic GPR numbers for use in assembly and inline asm. It is derived from Linux 6.16, with the register list turned into a GPR_LIST() macro instead of being open-coded with .irp, so that it can be used from C as well. Resolving a GPR number to the saved value of the register relies on struct cpu_user_regs holding x0..x31 contiguously and in register-number order. Add regs_gpr_ptr() for that, and check the layout against GPR_LIST() at build time. The block doesn't have to be at the start of the structure, so anchor REG_PTR() at ->zero too rather than at the structure itself. Update the exception handling code to dispatch based on the entry type. Signed-off-by: Oleksii Kurochko --- Changes in v3: - Update the commit message. - Keep the name of the asm_extable assembler macro: renaming it to _asm_extable was unrelated to this patch. - Replace regs_get_gpr() in extable.c with regs_gpr_ptr() in asm/regs.h, returning where the register's value is saved rather than the value itself, so that a single helper serves code which reads a guest register as well as code which writes one. Anchor the array access at ®s->zero rather than casting regs itself, matching the relaxed layout requirement below, and bound the index with array_index_nospec() so that release builds, where the ASSERT() is compiled out, cannot read past the register frame. Add NR_GPRS instead of open-coding 32. - Move the layout BUILD_BUG_ON()s out of regs_get_gpr() into build_assertions() in domain.c, so that they no longer sit in one particular consumer of the mapping. - Anchor those checks at offsetof(struct cpu_user_regs, zero) rather than at offset 0: the x0..x31 block only has to be contiguous and in register-number order, it no longer has to sit at the start of the structure. Update the comment above struct cpu_user_regs accordingly, keeping the "->zero must read as 0" requirement as a separate point. - REG_PTR(): anchor at ®s->zero for the same reason. - gpr-num.h: move the part of the comment describing the generation of the .L_gpr_num_ symbols down to the construct which actually generates them; GPR_LIST() itself has other users. - gpr-num.h: emit the separator ahead of each list entry instead of after it, so that the expansion doesn't end with one and whatever follows a use of the list has to supply its own; ASM_EXTABLE_TRAP_INFO() supplies the "\n" it needs. - gpr-num.h: state in the file header what was changed compared to the Linux original. - asm/extable.h: no functional change, put EX_TRAP_INFO_REG() on a single line and reflow the comment describing the exception table entry format. - Drop BUG_ON() in ex_handler_trap_info() as trap_info pointer should be guaranteed properly filled by compilation process. --- Changes in v2: - regs_get_gpr(): take a GPR number instead of a byte offset, dropping the multiplication at the call site. A non-multiple-of-8 offset is now unrepresentable. - regs_get_gpr(): ASSERT(num < 32) instead of a range check returning 0, which isn't usable as an error indicator. No num =3D=3D 0 check: reading= x0 is harmless out of context, and a NULL trap_info is caught by the existing BUG_ON() where the dereference happens. - regs_get_gpr(): index the register frame as an array, constify regs and drop the pointless inline. - Anchor the first BUILD_BUG_ON() at offsetof(..., zero) =3D=3D 0 rather t= han at ra, pinning both ends of the x0..x31 range. - Drop MAX_REG_OFFSET; asm/processor.h is no longer touched by this patch. - ex_handler_trap_info(): use regs->sepc and the cause passed down from do_trap() instead of re-reading CSR_SEPC/CSR_SCAUSE; fixup_exception() gains a cause parameter. stval stays a CSR read as do_trap() doesn't read it. - asm/extable.h: revert the .word -> .long change, the extra parens and the stray semicolon after .popsection; use .half for the new type and data fields to match .word. - Make GPR_LIST() the single source of the ABI-name -> register-number mapping, and check struct cpu_user_regs against it at build time, so the two can no longer diverge. - Add the explanatory comment above sturc cpu_user_regs to explain an ordering of x0-x31 registers. --- --- xen/arch/riscv/domain.c | 22 ++++++++ xen/arch/riscv/extable.c | 48 +++++++++++++++- xen/arch/riscv/include/asm/extable.h | 61 ++++++++++++++------- xen/arch/riscv/include/asm/gpr-num.h | 53 ++++++++++++++++++ xen/arch/riscv/include/asm/processor.h | 14 ++++- xen/arch/riscv/include/asm/regs.h | 23 +++++++- xen/arch/riscv/include/asm/riscv_encoding.h | 7 ++- xen/arch/riscv/include/asm/traps.h | 6 ++ xen/arch/riscv/traps.c | 2 +- 9 files changed, 210 insertions(+), 26 deletions(-) create mode 100644 xen/arch/riscv/include/asm/gpr-num.h diff --git a/xen/arch/riscv/domain.c b/xen/arch/riscv/domain.c index fd21cb1789e6..f60f871aba98 100644 --- a/xen/arch/riscv/domain.c +++ b/xen/arch/riscv/domain.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -484,9 +485,30 @@ void context_switch(struct vcpu *prev, struct vcpu *ne= xt) =20 static void __init __maybe_unused build_assertions(void) { +/* + * GPR_LIST() puts nothing between its entries, so the separator has to co= me + * from here. It is emitted ahead of each entry rather than after it, so t= hat + * the expansion doesn't end with one and its use below can be terminated = like + * an ordinary statement. + */ +#define CHECK_GPR_INDEX(num, name) \ + ; BUILD_BUG_ON(offsetof(struct cpu_user_regs, name) !=3D \ + offsetof(struct cpu_user_regs, zero) + \ + (num) * sizeof(unsigned long)) + /* * Enforce the requirement documented in struct cpu_info that * guest_cpu_user_regs must be the first field. */ BUILD_BUG_ON(offsetof(struct cpu_info, guest_cpu_user_regs)); + + /* + * Enforce the requirement documented in struct cpu_user_regs that the + * x0..x31 fields are contiguous and in architectural register-number + * order, which is what lets a register number be resolved to its saved + * value by indexing them as an array anchored at ->zero. + */ + GPR_LIST(CHECK_GPR_INDEX); + +#undef CHECK_GPR_INDEX } diff --git a/xen/arch/riscv/extable.c b/xen/arch/riscv/extable.c index 5b89c4278c65..19d9e3617c81 100644 --- a/xen/arch/riscv/extable.c +++ b/xen/arch/riscv/extable.c @@ -6,8 +6,11 @@ #include #include =20 +#include #include #include +#include +#include =20 #define EX_FIELD(ptr, field) ((unsigned long)&(ptr)->field + (ptr)->field) =20 @@ -32,6 +35,12 @@ static void __init cf_check swap_ex(void *a, void *b) =20 x->fixup =3D y->fixup + delta; y->fixup =3D tmp.fixup - delta; + + x->type =3D y->type; + y->type =3D tmp.type; + + x->data =3D y->data; + y->data =3D tmp.data; } =20 static int cf_check cmp_ex(const void *a, const void *b) @@ -59,7 +68,26 @@ static void ex_handler_fixup(const struct exception_tabl= e_entry *ex, regs->sepc =3D ex_fixup(ex); } =20 -bool fixup_exception(struct cpu_user_regs *regs) +static void ex_handler_trap_info(const struct exception_table_entry *ex, + struct cpu_user_regs *regs, + unsigned long cause) +{ + struct trap_info *trap_info =3D + (struct trap_info *)*regs_gpr_ptr(regs, ex->data); + + /* + * Only stval still needs a CSR read: sepc and scause were already + * captured by the trap entry path and do_trap() respectively. Latch + * trap_info->sepc before regs->sepc is pointed at the fixup code. + */ + trap_info->sepc =3D regs->sepc; + trap_info->scause =3D cause; + trap_info->stval =3D csr_read(CSR_STVAL); + + regs->sepc =3D ex_fixup(ex); +} + +bool fixup_exception(struct cpu_user_regs *regs, unsigned long cause) { unsigned long pc =3D regs->sepc; const struct virtual_region *region =3D find_text_region(pc); @@ -77,7 +105,23 @@ bool fixup_exception(struct cpu_user_regs *regs) if ( !ex ) return false; =20 - ex_handler_fixup(ex, regs); + switch ( ex->type ) + { + case EX_TYPE_FIXUP: + ex_handler_fixup(ex, regs); + break; + + case EX_TYPE_TRAP_INFO: + ex_handler_trap_info(ex, regs, cause); + break; + + default: + printk(XENLOG_ERR + "Unsupported exception table entry type %u for pc %#lx\n", + ex->type, pc); + + return false; + } =20 return true; } diff --git a/xen/arch/riscv/include/asm/extable.h b/xen/arch/riscv/include/= asm/extable.h index c0128a91818f..1ff557b70dd6 100644 --- a/xen/arch/riscv/include/asm/extable.h +++ b/xen/arch/riscv/include/asm/extable.h @@ -3,17 +3,24 @@ #ifndef ASM__RISCV__ASM_EXTABLE_H #define ASM__RISCV__ASM_EXTABLE_H =20 +#include + +#define EX_TYPE_FIXUP 0 +#define EX_TYPE_TRAP_INFO 1 + #ifdef __ASSEMBLER__ =20 -#define ASM_EXTABLE(insn, fixup) \ - .pushsection .ex_table, "a"; \ - .balign 4; \ - .word (insn) - .; \ - .word (fixup) - .; \ +#define ASM_EXTABLE_RAW(insn, fixup, type, data) \ + .pushsection .ex_table, "a"; \ + .balign 4; \ + .word (insn) - .; \ + .word (fixup) - .; \ + .half (type); \ + .half (data); \ .popsection =20 .macro asm_extable, insn, fixup - ASM_EXTABLE(\insn, \fixup) + ASM_EXTABLE_RAW(\insn, \fixup, EX_TYPE_FIXUP, 0) .endm =20 #else /* __ASSEMBLER__ */ @@ -23,20 +30,35 @@ =20 struct cpu_user_regs; =20 -#define ASM_EXTABLE(insn, fixup) \ - ".pushsection .ex_table, \"a\"\n" \ - ".balign 4\n" \ - ".word (" #insn " - .)\n" \ - ".word (" #fixup " - .)\n" \ +#define ASM_EXTABLE_RAW(insn, fixup, type, data) \ + ".pushsection .ex_table, \"a\"\n" \ + ".balign 4\n" \ + ".word (" insn ") - .\n" \ + ".word (" fixup ") - .\n" \ + ".half (" type ")\n" \ + ".half (" data ")\n" \ ".popsection\n" =20 +#define ASM_EXTABLE(insn, fixup) \ + ASM_EXTABLE_RAW(#insn, #fixup, __stringify(EX_TYPE_FIXUP), "0") + +#define EX_TRAP_INFO_REG(gpr) "(.L_gpr_num_" #gpr ")" + +#define ASM_EXTABLE_TRAP_INFO(insn, fixup, data) \ + DEFINE_ASM_GPR_NUMS "\n" \ + ASM_EXTABLE_RAW(#insn, #fixup, __stringify(EX_TYPE_TRAP_INFO), \ + EX_TRAP_INFO_REG(data)) + /* - * The exception table consists of pairs of relative offsets: the first - * is the relative offset to an instruction that is allowed to fault, - * and the second is the relative offset at which the program should - * continue. No general-purpose registers are modified by the exception - * handling mechanism itself, so it is up to the fixup code to handle - * any necessary state cleanup. + * Each exception table entry consists of two relative offsets and a + * handler description: `insn` is the relative offset to an instruction + * that is allowed to fault, `fixup` is the relative offset at which the + * program should continue in case of a fault, `type` selects how the exce= ption + * is handled (EX_TYPE_*), and `data` holds auxiliary information for the + * handler (e.g. for EX_TYPE_TRAP_INFO, the number of the GPR that contain= s a + * pointer to a struct trap_info). No general-purpose registers are + * modified by the exception handling mechanism itself, so it is up to + * the fixup code to handle any necessary state cleanup. * * The exception table and fixup code live out of line with the main * instruction path. This means when everything is well, we don't even @@ -45,14 +67,15 @@ struct cpu_user_regs; */ struct exception_table_entry { int32_t insn, fixup; + uint16_t type, data; }; =20 extern struct exception_table_entry __start___ex_table[]; extern struct exception_table_entry __stop___ex_table[]; =20 void sort_exception_tables(void); -bool fixup_exception(struct cpu_user_regs *regs); +bool fixup_exception(struct cpu_user_regs *regs, unsigned long cause); =20 -#endif /* __ASSEMBLY__ */ +#endif /* __ASSEMBLER__ */ =20 #endif /* ASM__RISCV__ASM_EXTABLE_H */ diff --git a/xen/arch/riscv/include/asm/gpr-num.h b/xen/arch/riscv/include/= asm/gpr-num.h new file mode 100644 index 000000000000..867ee172c068 --- /dev/null +++ b/xen/arch/riscv/include/asm/gpr-num.h @@ -0,0 +1,53 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Based on Linux 6.16 arch/riscv/include/asm/gpr-num.h, with the + * register list turned into GPR_LIST() instead of being open-coded + * with .irp, so that it can also be used outside of assembly. + */ +#ifndef RISCV_GPR_NUM_H +#define RISCV_GPR_NUM_H + +/* + * GPRs by ABI name, together with their register number (x0 .. x31). + * + * This is the single source of truth for the mapping; users expand it with + * their own per-register macro. Among them, the layout of struct cpu_user= _regs + * is checked against this list at build time (see build_assertions() in + * domain.c), so neither list can be changed without the other. + */ +#define GPR_LIST(x) \ + x(0, zero) x(1, ra) x(2, sp) x(3, gp) \ + x(4, tp) x(5, t0) x(6, t1) x(7, t2) \ + x(8, s0) x(9, s1) x(10, a0) x(11, a1) \ + x(12, a2) x(13, a3) x(14, a4) x(15, a5) \ + x(16, a6) x(17, a7) x(18, s2) x(19, s3) \ + x(20, s4) x(21, s5) x(22, s6) x(23, s7) \ + x(24, s8) x(25, s9) x(26, s10) x(27, s11) \ + x(28, t3) x(29, t4) x(30, t5) x(31, t6) + +/* Number of GPRs described by GPR_LIST(). */ +#define NR_GPRS 32 + +#ifdef __ASSEMBLER__ + +/* + * Generate the .L_gpr_num_ assembler symbols, used to turn a regist= er + * name emitted by the compiler into a register number. + * + * The separator is emitted ahead of each entry rather than after it, so t= hat + * the expansion doesn't end with one: whatever follows a use of the list = has + * to supply its own separator, instead of silently relying on a trailing = one. + */ +#define GPR_NUM_EQU(num, name) ; .equ .L_gpr_num_##name, num +GPR_LIST(GPR_NUM_EQU) +#undef GPR_NUM_EQU + +#else /* __ASSEMBLER__ */ + +/* See the comment ahead of the __ASSEMBLER__ flavour above. */ +#define GPR_NUM_EQU(num, name) "\n.equ .L_gpr_num_" #name ", " #num +#define DEFINE_ASM_GPR_NUMS GPR_LIST(GPR_NUM_EQU) + +#endif /* __ASSEMBLER__ */ + +#endif /* RISCV_GPR_NUM_H */ diff --git a/xen/arch/riscv/include/asm/processor.h b/xen/arch/riscv/includ= e/asm/processor.h index b1745c107100..00c7654c3278 100644 --- a/xen/arch/riscv/include/asm/processor.h +++ b/xen/arch/riscv/include/asm/processor.h @@ -12,7 +12,19 @@ =20 #ifndef __ASSEMBLER__ =20 -/* On stack VCPU state */ +/* + * On stack VCPU state. + * + * The x0..x31 fields must remain contiguous and in architectural + * register-number order: code which resolves a register number to its sav= ed + * value indexes them as an array anchored at ->zero. Where that block sits + * within the structure is of no interest, but nothing may be inserted in + * between its fields. The layout is checked against GPR_LIST() at build + * time; see build_assertions() in domain.c. + * + * ->zero additionally has to always read as 0, since it supplies the value + * of x0 when x0 is used as a source operand. + */ struct cpu_user_regs { unsigned long zero; diff --git a/xen/arch/riscv/include/asm/regs.h b/xen/arch/riscv/include/asm= /regs.h index 531958f3d748..59573bb6013c 100644 --- a/xen/arch/riscv/include/asm/regs.h +++ b/xen/arch/riscv/include/asm/regs.h @@ -5,16 +5,35 @@ #ifndef __ASSEMBLER__ =20 #include +#include =20 -#define hyp_mode(r) (0) +#include +#include =20 -struct cpu_user_regs; +#define hyp_mode(r) (0) =20 static inline bool guest_mode(const struct cpu_user_regs *r) { BUG_ON("unimplemented"); } =20 +/* + * Resolve an architectural register number to where its value is saved in + * @regs. Relies on x0..x31 being laid out as an array anchored at ->zero;= see + * the comment above struct cpu_user_regs. + */ +static inline unsigned long *regs_gpr_ptr(struct cpu_user_regs *regs, + unsigned int num) +{ + ASSERT(num < NR_GPRS); + + /* + * Not a speculation concern, but a convenient way to keep the access = in + * bounds in release builds, where the assertion above is compiled out. + */ + return &(®s->zero)[array_index_nospec(num, NR_GPRS)]; +} + #endif /* __ASSEMBLER__ */ =20 #endif /* ASM__RISCV__REGS_H */ diff --git a/xen/arch/riscv/include/asm/riscv_encoding.h b/xen/arch/riscv/i= nclude/asm/riscv_encoding.h index 647268e6d0d4..599ae3cd601a 100644 --- a/xen/arch/riscv/include/asm/riscv_encoding.h +++ b/xen/arch/riscv/include/asm/riscv_encoding.h @@ -911,8 +911,13 @@ #define REG_OFFSET(insn, pos) \ (SHIFT_RIGHT((insn), (pos) - LOG_REGBYTES) & REG_MASK) =20 +/* + * The x0..x31 block of struct cpu_user_regs is not required to sit at the + * start of the structure, so anchor the offset at ->zero (x0) rather than + * at the structure itself. + */ #define REG_PTR(insn, pos, regs) \ - (unsigned long *)((unsigned long)(regs) + REG_OFFSET(insn, pos)) + (unsigned long *)((unsigned long)&(regs)->zero + REG_OFFSET(insn, pos)) =20 #define GET_RM(insn) (((insn) >> 12) & 7) =20 diff --git a/xen/arch/riscv/include/asm/traps.h b/xen/arch/riscv/include/as= m/traps.h index 21fa3c3259b3..8d4ab664bca9 100644 --- a/xen/arch/riscv/include/asm/traps.h +++ b/xen/arch/riscv/include/asm/traps.h @@ -7,6 +7,12 @@ =20 #ifndef __ASSEMBLER__ =20 +struct trap_info { + register_t sepc; + register_t scause; + register_t stval; +}; + void do_trap(struct cpu_user_regs *cpu_regs); void handle_trap(void); void trap_init(void); diff --git a/xen/arch/riscv/traps.c b/xen/arch/riscv/traps.c index 9bb54d030be7..144b5beaa2c8 100644 --- a/xen/arch/riscv/traps.c +++ b/xen/arch/riscv/traps.c @@ -217,7 +217,7 @@ void do_trap(struct cpu_user_regs *cpu_regs) break; } =20 - if ( fixup_exception(cpu_regs) ) + if ( fixup_exception(cpu_regs, cause) ) break; =20 fallthrough; --=20 2.55.0 From nobody Fri Oct 23 15:32:28 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) client-ip=192.237.175.120; envelope-from=xen-devel-bounces@lists.xenproject.org; helo=lists.xenproject.org; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=pass(p=none dis=none) header.from=gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1790785489; cv=none; d=zohomail.com; s=zohoarc; b=PUEVbRrTS4onwM8gn0c5euaLy0SSBUrU3bbp6OLQD52amozjk2JvyOt8k/J1uRQVFO+Er5JYZk1EPw8rCaBRccL8Wo1VreU+qQ57THu8RImkat2M1Z9HED+F2jF5whbB50RhREKDCjNJurknGC20qONTsFOi0PxKhNFbUCkZ4sI= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1790785489; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=Xiv16fYVgxMc56Axoq7ltl4tzNqcJaTaSmINYec2Vfs=; b=WYbHYD6Od3Y4CcXhBNnn9Mo80ReBYZbBilacffdNw42ot0ErQ+ZCkF5LKemGqebFpLGk4uIM1Nj1PZ8nKccVxOe7PLjqqrvil7oYR6+c5M6FqWz664l4xG4Rt3oYFKk4PkZ/Nmfo0M9yqZ7wX8gqMRp5bszBGrEX1kY6fXdb3cI= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) by mx.zohomail.com with SMTPS id 1790785489977206.4212017954319; Wed, 30 Sep 2026 09:24:49 -0700 (PDT) Received: from list by lists.xenproject.org with outflank-mailman.1437550.1656526 (Exim 4.92) (envelope-from ) id 1xBx6T-0004YJ-72; Wed, 30 Sep 2026 16:24:21 +0000 Received: by outflank-mailman (output) from mailman id 1437550.1656526; Wed, 30 Sep 2026 16:24:21 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1xBx6T-0004Y4-3a; Wed, 30 Sep 2026 16:24:21 +0000 Received: by outflank-mailman (input) for mailman id 1437550; Wed, 30 Sep 2026 16:24:19 +0000 Received: from mx.expurgate.net ([194.145.224.20]) by lists.xenproject.org with esmtp (Exim 4.92) id 1xBx6R-0004A4-3Y for xen-devel@lists.xenproject.org; Wed, 30 Sep 2026 16:24:19 +0000 Received: from mx.expurgate.net (helo=localhost) by mx.expurgate.net with esmtp id 1xBx6Q-00GhY9-GY for xen-devel@lists.xenproject.org; Wed, 30 Sep 2026 18:24:18 +0200 Received: from [10.42.69.6] (helo=localhost) by localhost with ESMTP (eXpurgate MTA 0.9.1) (envelope-from ) id 6abd37a8-8faa-0a2a0a5109dd-0a2a45069d94-10 for ; Wed, 30 Sep 2026 18:24:18 +0200 Received: from [74.125.225.140] (helo=mail-wm2-f12.google.com) by tlsNG-16d1c6.mxtls.expurgate.net with ESMTPS (eXpurgate 4.57.1) (envelope-from ) id 6abd37b2-195a-0a2a45060019-4a7de18cdcb8-3 for ; Wed, 30 Sep 2026 18:24:18 +0200 Received: by mail-wm2-f12.google.com with SMTP id 5b1f17b1804b1-49ce364488dso7623975e9.0 for ; Wed, 30 Sep 2026 09:24:18 -0700 (PDT) Received: from fedora (user-109-243-71-234.play-internet.pl. [109.243.71.234]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-4a01cd43e66sm14620485e9.2.2026.09.30.09.24.16 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 30 Sep 2026 09:24:17 -0700 (PDT) X-Outflank-Mailman: Message body and most headers restored to incoming version X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" Authentication-Results: eu.smtp.expurgate.cloud; dkim=pass header.s=20251104 header.d=gmail.com header.i="@gmail.com" header.h="Content-Transfer-Encoding:MIME-Version:References:In-Reply-To:Message-ID:Date:Subject:Cc:To:From" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1790785458; x=1791390258; darn=lists.xenproject.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=Xiv16fYVgxMc56Axoq7ltl4tzNqcJaTaSmINYec2Vfs=; b=MHgrv1l8jBJvZ04KEyhFm+FNGpnKz0/oV0bZt8F3vrcHG/KDcwqNd1ElwsVx1xhWCD fqB5CvBy60juUXwM28wOLm+f+DDWncaOYk5rckGqQuSXtixSJZsksIL0ZLtm1JoT9UZ9 WZpqZFa9oWecZNytvo235EGssyXznXyRzIsoTmZ7jqfGPDUqcwX+v8o24X66vTHR9LFi nRLOSRWY9IIrskWEI7ooeFtDIzuwf2fbngILkuSP9Ek6o/p3QXZahRnRFHdhvaJ6Dxch Gz8SDwZlo0/a65aPOqrcU+ts1G6cvByKo8gme1OKwuJBT0mBAmL+cggYOvkYaGYxTNRN 79OQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1790785458; x=1791390258; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=Xiv16fYVgxMc56Axoq7ltl4tzNqcJaTaSmINYec2Vfs=; b=MXBdFJNZeXTJWVG6BaaeSlHPGwSs2Cyb/P7Yk04lQX/x8PfekGD5+gooRCIKt84My2 jyTfcR1CKGlfvDqL7K/ajxa/+HoDV1C49sorWZ/IPL81FiblSkeBTNXF9CVwoxPul3Mb /w/m6sIZp7FsEASvmcd3/ADvpfpfYSGkQP30Qc+jnexjbNdN3Yj0YNs5cG0GCaGvv4Jm VVA1JdiVMjZlfvnS7u0lu5ai8uLfgTTX7AvKnEHw7CdquAXJGnsi263RLzYH0TiVM8Rt 3GDrQFUXynE31wfOxFepVfQ4TDHwa80JDi2gdnvktDkb3SKK+3fL6BE4+YhKS06+Tofz CMUw== X-Gm-Message-State: AFuF++l/WwJN3LiKFgSbovRqKHWErzs+fIi59C22iuOu+Pm1NWk49oSa nIHhwgqBmJFkrhD3zL+6uKsQsDZuzJihe0tCB83xWLADgIl6Fq/LFHNCUrhJXA== X-Gm-Gg: AYBFou3i2ESwAs8gSq8jWwvXPMJqz5dCRJ3klPMNJG+lAVBoRnq3mi0+0L9bXJNNj5I fEchgpnjUehB2DZyck6h+SADocf5fVzdPPx2fsibWOyE577+OxTCywP3Vbp31CVTO5LJB2NLxfD l8CIB5qNHzx0oFQDIqlQJiIa2PyocS80tkJ80oA62VMy5QqRYwEgpjXXBx5euYt4hFbFeJWbck+ gSNIuCFJS8Y7wll+Jo2xnMNT0Xl7h4/tEIPB9PLShdEHdBVbif7XSPxZPqBFgHPHqO2m3FL9shD ZuA4Ccjl0onSvyzv1YH+W1I99U4t+aj5kZXmQXtjCETi+ADl+b4vqW+uv6338TG/5sJPoORxnxC VzUsLUSSgZmgdlR0c2NHOhFtDDd29bHYiNUn78KUJkKb5Bn5idjrCpGj8DLNj7LE/MB/JwnCwUD Fg5J4ZAAVQdxDg0pTDjnz71VRHW9cTB53V4ENSzYr5/qe0OfSJVkPjGl0KnJGjqpbjjba0XGiJN 59v84iQLJ4rG9Nue5X4QZGIGpYLDWUD6RfYMNk527RkJwP1O/o= X-Received: by 2002:a05:600d:864a:20b0:4a0:ec5:46d9 with SMTP id 5b1f17b1804b1-4a01eaafdb4mr3092985e9.0.1790785457829; Wed, 30 Sep 2026 09:24:17 -0700 (PDT) From: Oleksii Kurochko To: xen-devel@lists.xenproject.org Cc: Romain Caritey , Baptiste Le Duc , Zheng Zhang , Oleksii Kurochko , Alistair Francis , Connor Davis , Andrew Cooper , Anthony PERARD , Michal Orzel , Jan Beulich , Julien Grall , =?UTF-8?q?Roger=20Pau=20Monn=C3=A9?= , Stefano Stabellini Subject: [PATCH v3 16/39] xen/riscv: decouple INSN_PSEUDO_VS_* from the hypervisor's XLEN Date: Wed, 30 Sep 2026 18:23:35 +0200 Message-ID: <198c5d8b140fb156b914eae007582ec3b0e83cba.1790779209.git.oleksii.kurochko@gmail.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-purgate-ID: tlsNG-16d1c6/1790785458-1FCCD77B-E65D8CB8/10/73395122804 X-purgate-type: spam X-purgate-size: 3246 X-ZohoMail-DKIM: pass (identity @gmail.com) X-ZM-MESSAGEID: 1790785491938158500 Content-Type: text/plain; charset="utf-8" htinst reports a pseudoinstruction when a guest page fault is taken on an implicit memory access done for VS-stage address translation. Four such values are defined, differing in the access type (read or write) and in the access width: 4 bytes (0x2000/0x2020) or 8 bytes (0x3000/0x3020). That width is the width of a VS-stage PTE, i.e. it follows the guest's paging mode (4 bytes for Sv32, 8 bytes for Sv39 and wider) and has nothing to do with the XLEN Xen itself is built for. Yet only one pair is defined, selected by Xen's XLEN and named as if it were the only one, so the 4-byte forms, which a guest running with VSXL=3D32 and Sv32 in vsatp produces, can= 't be named at all on RV64. Define all four values unconditionally instead, named after the access width they encode rather than after the build's XLEN. Dropping the ladder loses no build-time coverage: a build for an XLEN other than 32 or 64 already fails on the equivalent ladders in asm/asm.h and asm/config.h, so no replacement #error is needed here. Adding one keyed on CONFIG_RISCV_* would in any case re-introduce exactly the conflation this patch removes. This diverges from the imported version of riscv_encoding.h. No functional change: the values have no user. Signed-off-by: Oleksii Kurochko Reviewed-by: Baptiste Le Duc --- Changes in v3: - Update the commit message: the values no longer have a user in this series, as htinst_is_pseudo() recognizes a pseudoinstruction by its bits[1:0]. - Use VSXLEN=3D32/64 instead of RV32/64 in the comments of the corresponding definitions. --- Changes in v2: - New patch. --- --- xen/arch/riscv/include/asm/riscv_encoding.h | 24 +++++++-------------- 1 file changed, 8 insertions(+), 16 deletions(-) diff --git a/xen/arch/riscv/include/asm/riscv_encoding.h b/xen/arch/riscv/i= nclude/asm/riscv_encoding.h index 599ae3cd601a..2dbfd4d16067 100644 --- a/xen/arch/riscv/include/asm/riscv_encoding.h +++ b/xen/arch/riscv/include/asm/riscv_encoding.h @@ -837,25 +837,17 @@ #define INSN_MASK_FENCE_TSO 0xffffffff #define INSN_MATCH_FENCE_TSO 0x8330000f =20 -#if __riscv_xlen =3D=3D 64 - -/* 64-bit read for VS-stage address translation (RV64) */ -#define INSN_PSEUDO_VS_LOAD 0x00003000 - -/* 64-bit write for VS-stage address translation (RV64) */ -#define INSN_PSEUDO_VS_STORE 0x00003020 +/* 64-bit read for VS-stage address translation (VSXLEN=3D64) */ +#define INSN_PSEUDO_VS_LOAD64 0x00003000 =20 -#elif __riscv_xlen =3D=3D 32 +/* 64-bit write for VS-stage address translation (VSXLEN=3D64) */ +#define INSN_PSEUDO_VS_STORE64 0x00003020 =20 -/* 32-bit read for VS-stage address translation (RV32) */ -#define INSN_PSEUDO_VS_LOAD 0x00002000 +/* 32-bit read for VS-stage address translation (VSXLEN=3D32) */ +#define INSN_PSEUDO_VS_LOAD32 0x00002000 =20 -/* 32-bit write for VS-stage address translation (RV32) */ -#define INSN_PSEUDO_VS_STORE 0x00002020 - -#else -#error "Unexpected __riscv_xlen" -#endif +/* 32-bit write for VS-stage address translation (VSXLEN=3D32) */ +#define INSN_PSEUDO_VS_STORE32 0x00002020 =20 #define INSN_IS_16BIT(insn) (((insn) & 3) !=3D 3) #define INSN_IS_32BIT(insn) (!INSN_IS_16BIT(insn) && ((insn) & 0x1c) !=3D = 0x1c) --=20 2.55.0 From nobody Fri Oct 23 15:32:28 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) client-ip=192.237.175.120; envelope-from=xen-devel-bounces@lists.xenproject.org; helo=lists.xenproject.org; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=pass(p=none dis=none) header.from=gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1790785494; cv=none; d=zohomail.com; s=zohoarc; b=KGYu33+l9pXbqCaHYEwOhHgQ9D96T0Gt4z06x1+6zznZ0igycu/jkq3UhPcoxixMv1G87Py6nRa/oxf3ZAeLEQr39CyMjbwQa2BNclArHHyOisGNfjl6b+/uChWW8bpcOXWt4JB7D2s26hMkEmuf+OAk5cPZ0O2yspt3NeblgZ4= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1790785494; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=jVd+ST6LuzR+IbI8QqlLhRXhzqrzwiGYhICc8y2cDoY=; b=lbq0JwrWqR51d3RpR8HU44cC6XsYsIEVYEpjsbGeYxXHY0sqQhc+W2kDukh6jImoIShuAIez/xwiURp6VFw2PIrkjK8fa8w2ObymXi1+yGL12djPFoOgm5WlsC/XGJYJj/bnxEFxPXF3FARuLintpMR1mzdChIKbfJoDJ1di2pY= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) by mx.zohomail.com with SMTPS id 1790785494231611.4746240010153; Wed, 30 Sep 2026 09:24:54 -0700 (PDT) Received: from list by lists.xenproject.org with outflank-mailman.1437551.1656532 (Exim 4.92) (envelope-from ) id 1xBx6T-0004bC-Kh; Wed, 30 Sep 2026 16:24:21 +0000 Received: by outflank-mailman (output) from mailman id 1437551.1656532; Wed, 30 Sep 2026 16:24:21 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1xBx6T-0004aN-Bd; Wed, 30 Sep 2026 16:24:21 +0000 Received: by outflank-mailman (input) for mailman id 1437551; Wed, 30 Sep 2026 16:24:20 +0000 Received: from mx.expurgate.net ([194.145.224.20]) by lists.xenproject.org with esmtp (Exim 4.92) id 1xBx6S-0004PL-Et for xen-devel@lists.xenproject.org; Wed, 30 Sep 2026 16:24:20 +0000 Received: from mx.expurgate.net (helo=localhost) by mx.expurgate.net with esmtp id 1xBx6R-00GhY9-Ri for xen-devel@lists.xenproject.org; Wed, 30 Sep 2026 18:24:19 +0200 Received: from [10.42.69.5] (helo=localhost) by localhost with ESMTP (eXpurgate MTA 0.9.1) (envelope-from ) id 6abd37a1-8faa-0a2a0a5109dd-0a2a4505a464-40 for ; Wed, 30 Sep 2026 18:24:19 +0200 Received: from [74.125.225.141] (helo=mail-wm2-f13.google.com) by tlsNG-c201ff.mxtls.expurgate.net with ESMTPS (eXpurgate 4.57.1) (envelope-from ) id 6abd37b3-4cb1-0a2a45050019-4a7de18dc332-3 for ; Wed, 30 Sep 2026 18:24:19 +0200 Received: by mail-wm2-f13.google.com with SMTP id 5b1f17b1804b1-49b912d37b6so31256695e9.0 for ; Wed, 30 Sep 2026 09:24:19 -0700 (PDT) Received: from fedora (user-109-243-71-234.play-internet.pl. [109.243.71.234]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-4a01cd43e66sm14620485e9.2.2026.09.30.09.24.17 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 30 Sep 2026 09:24:18 -0700 (PDT) X-Outflank-Mailman: Message body and most headers restored to incoming version X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" Authentication-Results: eu.smtp.expurgate.cloud; dkim=pass header.s=20251104 header.d=gmail.com header.i="@gmail.com" header.h="Content-Transfer-Encoding:MIME-Version:References:In-Reply-To:Message-ID:Date:Subject:Cc:To:From" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1790785459; x=1791390259; darn=lists.xenproject.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=jVd+ST6LuzR+IbI8QqlLhRXhzqrzwiGYhICc8y2cDoY=; b=O9Zt95iItJyWC+O/WHesFfJ2YNgbmDZxyC2Xc8O6YxvFl1K5B1Uw6TqX55DzmIqqKM a4oBUYRSLNJAFCS/HsAfa3skF8Q8+Dz/uO8dTvJJ2Yol61THKKrFvZsHneQDJcpfVgm5 go2zyn6PAL6pduKzLO+smn1uM6xgJGfC0006G7CVLtZ3EhQiebJGSjw/8Ahwf9K8QNvK kDoUHHMvVfbHWlwpczJ5ahGSaH0E2OY1cXBuWHpsLZAtqzhs1370g6UlVuO5t+Ci9zW5 l5D29WcTFzIP2z7sm5KqRoeTDNuXmsFyvtMPwwrFspP2pAHJjF3kCFs8ksr6cIcyYGOt 2f1Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1790785459; x=1791390259; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=jVd+ST6LuzR+IbI8QqlLhRXhzqrzwiGYhICc8y2cDoY=; b=Mmikvwpfr3sbPgiGLBvR6yFY6a/4q0Yi6xJLU1RC1gXM2Opqi6asOvzNi2/T6groqS iXY+5n5d7+6dZWYjaoHEsxbQ9FHDpZbpQbhShUWABB+jPOfohd717tu0rylls5iOvBDo iSgQ8alF0hcnGS+9MTNlIGQBp6Tv+gR8iknFaXxyJtxCOz7YTTt0fh716aV4yy/50U5M yYNGcNbsVk3SxZuJ9Z/TGKlvn3dCDWqOyxh+0p3yV9wz7y1gcS/y3sXqkKQMnzsNWJFC 8UCgs/GSMf+gliSjajLQxQSYCObWkGOOjY5sWRNGxmDyBEj1K1IaXBPBkA/BeewgXyU1 Rrqw== X-Gm-Message-State: AFuF++kH7NT+jFV2xFeUqOuELnhc5ak/CCUETgNohXIYlWQa0XSjvJgR dX/KODiWYgjV0Rliqefkwy0PkRsMPeB7+easoX+DQaqcaSYZ+C2C25w9dg3suQ== X-Gm-Gg: AYBFou1e7bPjAYxDVnCSW+U88PIF8WsHwdWLpLI0LIMga3SATu+YFgAjoe67xiYwq6C Wje0UEx4Ip/V5dZrFtkfgWN+LVcxPwmzsj97yfT1tCUV1f4Sh/tArYuL+wFlAgPBGnEgg3RVKOe CGdlN6H39jDlXO8oKzbW9ehaXt3RrS5/BIMx6ZOx2dJJroCLEPeodJbpdJhqMjXzGZ/+okdkvhq OP/O6eLhMzukcjJvQVxiOiGC8xV0+9QtMfwffz/awtu6w0ZHlsIPCvg0wVsSbz0ru2ui02PvTXh myc02dkOXNYAvFpo08OgR1JZ8sTONOGLYjcPCWC+dhzW13BmpVWCApXjnyyk9VXmY+IUljdvKz4 aApXuEZolRZB5+LslQvWEba4iT+DaQXne49oKjAsStDafpP/ig8QpRG8pezolCH7de5yn0Sp+PK o5OBiWEZP1YrmRWRyb/N0KANtjFy1U1O8j1RBV7GACKCnNPIpbJDIZE6BnsLK8WX3Y/7x9q/Sb6 Tu9LW0OXCUN5AIRfeQFcVJER0yS32+dNdcdBW2R6EG0SFlLXD0= X-Received: by 2002:a05:600c:4fc3:b0:49f:f099:6f8c with SMTP id 5b1f17b1804b1-4a01aff0c5emr33171395e9.9.1790785459004; Wed, 30 Sep 2026 09:24:19 -0700 (PDT) From: Oleksii Kurochko To: xen-devel@lists.xenproject.org Cc: Romain Caritey , Baptiste Le Duc , Zheng Zhang , Oleksii Kurochko , Alistair Francis , Connor Davis , Andrew Cooper , Anthony PERARD , Michal Orzel , Jan Beulich , Julien Grall , =?UTF-8?q?Roger=20Pau=20Monn=C3=A9?= , Stefano Stabellini Subject: [PATCH v3 17/39] xen/riscv: add guest page fault handling stub Date: Wed, 30 Sep 2026 18:23:36 +0200 Message-ID: <42d1a37341eadd764022a1658bebcffcee15238a.1790779209.git.oleksii.kurochko@gmail.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-purgate-ID: tlsNG-c201ff/1790785459-251182A1-F019A0B2/10/73395122804 X-purgate-type: spam X-purgate-size: 12910 X-ZohoMail-DKIM: pass (identity @gmail.com) X-ZM-MESSAGEID: 1790785496060158500 Content-Type: text/plain; charset="utf-8" Add a handler for guest page faults and hook it into the trap path, providing the trap-side entry point which will later feed the MMIO dispatch. This will be used, for example, to trap accesses to APLIC registers so that a guest can initialize and drive an emulated interrupt controller. A G-stage (stage-2) fault has one of three causes, reported via scause: - Fetch fault: guest tried to execute from a guest-physical address that is unmapped or that G-stage marks non-executable. Never emulatable (nothing to emulate a fetch into). On real hardware this raises an instruction access fault, so Xen reflects the same fault back to the guest. Decided here. - Load fault / Store fault: left undecided by this patch, this is where MMIO emulation will hook in later. Any of these three faults can instead be reported via a pseudoinstruction in htinst, when both: (a) the fault occurred on an implicit access Xen made to walk a VS-stage page table, and (b) htval holds a nonzero value: the guest-physical address of that VS-stage PTE, not of the guest's original access. However, none of these paths consult the p2m first, and the future MMIO path won't either: RISC-V has no populate-on-demand, no paging, and no mem_access, so every guest mapping is established eagerly. A G-stage fault therefore never indicates a mapping Xen could lazily resolve to let the access complete. resolve_faulting_gpa() is a stub which always fails for now, so any guest page fault other than one taken on an implicit access for VS-stage translation currently crashes the domain. That one is reflected to the guest through trap_redirect(), which is still a BUG_ON() placeholder though, and so takes the host down. This is no worse than before this patch, where these traps fell through to do_unexpected_trap() and die(). Cache the "trap came from the guest" test in a local, as the guest page fault case needs it too. Signed-off-by: Oleksii Kurochko --- Changes in v3: - Update the commit message. - Make resolve_faulting_gpa() return an error, which the caller checks. - Add a FIXME about guest page tables residing in emulated MMIO. - Don't refer to fixup_exception() in the comment ahead of BUG_ON(!from_guest): it isn't consulted for guest page faults yet. - Mention the from_guest local in the commit message. - Say in the comment above resolve_faulting_gpa() that it stores the addre= ss in @gf->gpa. - Make emulate_store() take a pointer to const, as emulate_load() does: neither modifies *gf. --- Changes in v2: - Introduce struct guest_fault. - Change the prototypes of emulate_{load,store}() to take a non-const struct guest_fault, as emulation has to write the destination register and advance sepc. - Add handling of pseudoinstructions before the call of emulate_{load,store}. - Rename get_fault_gpa to resolve_faulting_gpa and change its prototype to take struct guest_fault. - Add handling of CAUSE_FETCH_GUEST_PAGE_FAULT now. - Document why the p2m is not consulted before a fault is injected, and add a BUILD_BUG_ON() on CONFIG_VM_EVENT to catch that assumption breaking. - Print the fault cause in the domain_crash() message rather than deriving an access type string which cannot cover every case. - Move code to introduced emulate.c instead of having it in traps.c --- --- xen/arch/riscv/Makefile | 1 + xen/arch/riscv/emulate.c | 183 +++++++++++++++++++++++++++ xen/arch/riscv/include/asm/emulate.h | 10 ++ xen/arch/riscv/include/asm/traps.h | 3 + xen/arch/riscv/traps.c | 22 +++- 5 files changed, 218 insertions(+), 1 deletion(-) create mode 100644 xen/arch/riscv/emulate.c create mode 100644 xen/arch/riscv/include/asm/emulate.h diff --git a/xen/arch/riscv/Makefile b/xen/arch/riscv/Makefile index 5454517724bd..2b84dace6bd5 100644 --- a/xen/arch/riscv/Makefile +++ b/xen/arch/riscv/Makefile @@ -6,6 +6,7 @@ obj-y +=3D domain.o obj-y +=3D domain-build.init.o obj-$(CONFIG_DOM0LESS_BOOT) +=3D dom0less-build.init.o obj-$(CONFIG_EARLY_PRINTK) +=3D early_printk.o +obj-y +=3D emulate.o obj-y +=3D entry.o obj-y +=3D extable.o obj-y +=3D guestcopy.o diff --git a/xen/arch/riscv/emulate.c b/xen/arch/riscv/emulate.c new file mode 100644 index 000000000000..cc4b1fc54054 --- /dev/null +++ b/xen/arch/riscv/emulate.c @@ -0,0 +1,183 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +/* + * RISC-V instruction emulation for trapped guest accesses + */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +/* + * The hardware-reported details of a guest page fault, gathered once by + * handle_guest_page_fault() and passed down to the emulation of the fault= ed + * access. + */ +struct guest_fault { + /* The guest register state. */ + struct cpu_user_regs *regs; + /* scause: a fetch, a load or a store/AMO guest page fault. */ + unsigned long cause; + /* + * htinst: the trapped instruction in its transformed form, or one of = the + * special values (zero, or a pseudoinstruction). + */ + unsigned long htinst; + /* htval: as written by hardware; see resolve_faulting_gpa(). */ + unsigned long htval; + /* stval: the guest virtual address of the faulting access. */ + unsigned long stval; + /* The faulting guest physical address, filled by resolve_faulting_gpa= (). */ + paddr_t gpa; +}; + +/* + * Is @htinst one of the special pseudoinstruction values, reported for a = guest + * page fault taken on an implicit memory access done for VS-stage address + * translation? + * + * It is enough to check only bits[1:0] as according to the spec: + * + * The value is one of the special pseudoinstructions defined later, all of + * which have bits 1:0 equal to 00. + */ +static bool htinst_is_pseudo(unsigned long htinst) +{ + return htinst && !(htinst & 3); +} + +/* + * Reconstruct the guest physical address the access faulted on into @gf->= gpa. + */ +static int resolve_faulting_gpa(struct guest_fault *gf) +{ + return -EOPNOTSUPP; +} + +static int emulate_load(const struct guest_fault *gf) +{ + return -EOPNOTSUPP; +} + +static int emulate_store(const struct guest_fault *gf) +{ + return -EOPNOTSUPP; +} + +static void inject_access_fault(const struct guest_fault *gf) +{ + struct trap_info utrap =3D { + .sepc =3D gf->regs->sepc, + .stval =3D gf->stval, + }; + + switch ( gf->cause ) + { + case CAUSE_FETCH_GUEST_PAGE_FAULT: + utrap.scause =3D CAUSE_FETCH_ACCESS; + break; + + case CAUSE_LOAD_GUEST_PAGE_FAULT: + utrap.scause =3D CAUSE_LOAD_ACCESS; + break; + + case CAUSE_STORE_GUEST_PAGE_FAULT: + utrap.scause =3D CAUSE_STORE_ACCESS; + break; + + default: + domain_crash(current->domain, "Impossible cause (%#lx) in %s?\n", + gf->cause, __func__); + return; + } + + trap_redirect(&utrap); +} + +void handle_guest_page_fault(struct cpu_user_regs *regs, unsigned long cau= se) +{ + struct guest_fault gf =3D { + .regs =3D regs, + .cause =3D cause, + .gpa =3D INVALID_PADDR, + }; + int rc; + + gf.htinst =3D csr_read(CSR_HTINST); + gf.htval =3D csr_read(CSR_HTVAL); + gf.stval =3D csr_read(CSR_STVAL); + + /* + * A guest-page fault may arise due to an implicit memory access during + * first-stage (VS-stage) address translation, in which case a guest + * physical address written to htval is that of the implicit memory + * access that faulted - for example, the address of a VS-level page + * table entry that could not be read. (The guest physical address + * corresponding to the original virtual address is unknown when + * VS-stage translation fails to complete) + * + * In such cases htinst reports one of the pseudoinstructions recogniz= ed + * by htinst_is_pseudo(), and the fault requires separate handling (si= nce + * G-stage translation failed on an unpopulated/unmapped guest physical + * address during a hardware page-table walk). To match bare hardware + * behavior, we must inject an access fault of the ORIGINAL access type + * (Instruction, Load, or Store/AMO) that initiated the address + * translation. + * + * FIXME: This assumes that guest page tables never reside in an emula= ted + * MMIO region, i.e. that an implicit access faulting at G-stage always + * targets an unpopulated GPA. Guests may (even transiently) place page + * tables in MMIO-backed memory, e.g. a video frame buffer. Supporting + * that would require walking the VS-stage page tables in software, + * accessing the PTEs (including A/D updates) through the MMIO handler= s, + * and then emulating the original access, instead of injecting a faul= t. + */ + if ( htinst_is_pseudo(gf.htinst) ) + { + inject_access_fault(&gf); + + return; + } + + rc =3D resolve_faulting_gpa(&gf); + if ( rc ) + goto out; + + switch ( cause ) + { + case CAUSE_LOAD_GUEST_PAGE_FAULT: + rc =3D emulate_load(&gf); + break; + + case CAUSE_STORE_GUEST_PAGE_FAULT: + rc =3D emulate_store(&gf); + break; + + case CAUSE_FETCH_GUEST_PAGE_FAULT: + /* + * Guest is trying to reach unmapped/unpopulated, or G-stage PTE d= oesn't + * allow execution (X=3D0). Generate fetch fault in this case. + */ + inject_access_fault(&gf); + return; + + default: + ASSERT_UNREACHABLE(); + rc =3D -EOPNOTSUPP; + + break; + } + + out: + if ( rc ) + domain_crash(current->domain, + "%s: unable to handle guest page fault (cause=3D%#lx)= at gpa %#"PRIpaddr"\n", + __func__, cause, gf.gpa); +} diff --git a/xen/arch/riscv/include/asm/emulate.h b/xen/arch/riscv/include/= asm/emulate.h new file mode 100644 index 000000000000..59e69ca6794c --- /dev/null +++ b/xen/arch/riscv/include/asm/emulate.h @@ -0,0 +1,10 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#ifndef RISCV_EMULATE_H +#define RISCV_EMULATE_H + +struct cpu_user_regs; + +void handle_guest_page_fault(struct cpu_user_regs *regs, unsigned long cau= se); + +#endif /* RISCV_EMULATE_H */ diff --git a/xen/arch/riscv/include/asm/traps.h b/xen/arch/riscv/include/as= m/traps.h index 8d4ab664bca9..38c6423742e0 100644 --- a/xen/arch/riscv/include/asm/traps.h +++ b/xen/arch/riscv/include/asm/traps.h @@ -17,6 +17,9 @@ void do_trap(struct cpu_user_regs *cpu_regs); void handle_trap(void); void trap_init(void); =20 +/* Reflect @trap back to the guest, i.e. enter its VS-mode trap handler. */ +void trap_redirect(const struct trap_info *trap); + #endif /* __ASSEMBLER__ */ =20 #endif /* ASM__RISCV__TRAPS_H */ diff --git a/xen/arch/riscv/traps.c b/xen/arch/riscv/traps.c index 144b5beaa2c8..4b9ec246e4c9 100644 --- a/xen/arch/riscv/traps.c +++ b/xen/arch/riscv/traps.c @@ -14,6 +14,7 @@ =20 #include #include +#include #include #include #include @@ -193,6 +194,7 @@ void do_trap(struct cpu_user_regs *cpu_regs) { register_t pc =3D cpu_regs->sepc; unsigned long cause =3D csr_read(CSR_SCAUSE); + bool from_guest =3D cpu_regs->hstatus & HSTATUS_SPV; =20 switch ( cause ) { @@ -203,6 +205,18 @@ void do_trap(struct cpu_user_regs *cpu_regs) vsbi_handle_ecall(cpu_regs); break; =20 + case CAUSE_FETCH_GUEST_PAGE_FAULT: + case CAUSE_LOAD_GUEST_PAGE_FAULT: + case CAUSE_STORE_GUEST_PAGE_FAULT: + /* + * Xen doesn't access guest memory, so it can't take a guest page + * fault itself: only a guest can get here. + */ + BUG_ON(!from_guest); + + handle_guest_page_fault(cpu_regs, cause); + break; + case CAUSE_ILLEGAL_INSTRUCTION: if ( do_bug_frame(cpu_regs, pc) >=3D 0 ) { @@ -251,7 +265,7 @@ void do_trap(struct cpu_user_regs *cpu_regs) break; } =20 - if ( cpu_regs->hstatus & HSTATUS_SPV ) + if ( from_guest ) check_for_pcpu_work(); } =20 @@ -275,3 +289,9 @@ enum mc_disposition arch_do_multicall_call(struct mc_st= ate *state) BUG_ON("unimplemented"); return mc_continue; } + +/* Redirect trap to Guest. */ +void trap_redirect(const struct trap_info *trap) +{ + BUG_ON("unimplemented"); +} --=20 2.55.0 From nobody Fri Oct 23 15:32:28 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) client-ip=192.237.175.120; envelope-from=xen-devel-bounces@lists.xenproject.org; helo=lists.xenproject.org; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=pass(p=none dis=none) header.from=gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1790785497; cv=none; d=zohomail.com; s=zohoarc; b=i8lSD0LrSjA/vhS1ss9zNqu5wGIS4Cn0I68y9TAeUDi97jMl9/GXqPmc4y4JdP5Q2GdROZNXu/fsffET/9f2diuoavn955ecfSnI3CG61Cfyq/ysD8KKKiugDBdUSjDeUS/xtl7QApIO3ygmjgmO1ik6Y9LHztVJENv9vn4aKqA= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1790785497; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=OYQQ7ScvSr55sK1nXTa6WzNLNd6SqlC9eeJ4PcwjlZo=; b=OpIXnQCSZ2OTHA2ji7lABHgolCkKuN4mg85JyoS0vDg3IIKS/O3XtIYfILx7uoRD/v1bAom3Yth7MZ/BJqhV8vIr8U1wkkMnkXj01n91DvauBDjBzzxMqijLD//krSmAxNBjzuEqTCJE5sCG6bwWxAahgzNr2hVisNwX7EZiEho= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) by mx.zohomail.com with SMTPS id 1790785497864551.198094715827; Wed, 30 Sep 2026 09:24:57 -0700 (PDT) Received: from list by lists.xenproject.org with outflank-mailman.1437553.1656542 (Exim 4.92) (envelope-from ) id 1xBx6U-0004wb-Pw; Wed, 30 Sep 2026 16:24:22 +0000 Received: by outflank-mailman (output) from mailman id 1437553.1656542; Wed, 30 Sep 2026 16:24:22 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1xBx6U-0004ud-Ke; Wed, 30 Sep 2026 16:24:22 +0000 Received: by outflank-mailman (input) for mailman id 1437553; Wed, 30 Sep 2026 16:24:21 +0000 Received: from mx.expurgate.net ([194.145.224.20]) by lists.xenproject.org with esmtp (Exim 4.92) id 1xBx6T-0004aW-Iu for xen-devel@lists.xenproject.org; Wed, 30 Sep 2026 16:24:21 +0000 Received: from mx.expurgate.net (helo=localhost) by mx.expurgate.net with esmtp id 1xBx6S-00GhYY-Vg for xen-devel@lists.xenproject.org; Wed, 30 Sep 2026 18:24:20 +0200 Received: from [10.42.69.9] (helo=localhost) by localhost with ESMTP (eXpurgate MTA 0.9.1) (envelope-from ) id 6abd37a9-bab6-0a2a0a5309dd-0a2a4509a632-12 for ; Wed, 30 Sep 2026 18:24:20 +0200 Received: from [74.125.225.140] (helo=mail-wm2-f12.google.com) by tlsNG-bad1c0.mxtls.expurgate.net with ESMTPS (eXpurgate 4.57.1) (envelope-from ) id 6abd37b4-be1a-0a2a45090019-4a7de18cc578-3 for ; Wed, 30 Sep 2026 18:24:20 +0200 Received: by mail-wm2-f12.google.com with SMTP id 5b1f17b1804b1-49ccf3ca626so34552515e9.0 for ; Wed, 30 Sep 2026 09:24:20 -0700 (PDT) Received: from fedora (user-109-243-71-234.play-internet.pl. [109.243.71.234]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-4a01cd43e66sm14620485e9.2.2026.09.30.09.24.19 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 30 Sep 2026 09:24:19 -0700 (PDT) X-Outflank-Mailman: Message body and most headers restored to incoming version X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" Authentication-Results: eu.smtp.expurgate.cloud; dkim=pass header.s=20251104 header.d=gmail.com header.i="@gmail.com" header.h="Content-Transfer-Encoding:MIME-Version:References:In-Reply-To:Message-ID:Date:Subject:Cc:To:From" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1790785460; x=1791390260; darn=lists.xenproject.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=OYQQ7ScvSr55sK1nXTa6WzNLNd6SqlC9eeJ4PcwjlZo=; b=Uy0L+mEA4lfTMMG7o1T8t6XYnMYP9gCru5DNEDNpoy7v5cBow9UrTHVTZdW+ktITtV bYubq2SMJKX8LXPR4k9My7qlZ+Wtb/AtyyF99jDwCpa4JJo8VzoV1i5A11NXiY10zgWd Ml4QaQIERG1c6ehSSJkJHpSODXf1R4jeBRbbwaQuReCyWHBaUtiP8wsrTraDIrLhgKal n1ZCGkKB0uk1BhpXhd8ak+rJh7o4mzIM1AIM1i7o8FPKRlWKuo+DYHvE/+xaMqpJlIv1 Xal2cxS+mD4JGv/8GRox/aW/LVz5mq1YyvhWuxDsM9CUVZ1N4jjmQp9fcf7QDw+0omeb yyFw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1790785460; x=1791390260; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=OYQQ7ScvSr55sK1nXTa6WzNLNd6SqlC9eeJ4PcwjlZo=; b=q3DLQ47c1FXx8vMofN45NWPdbX0xxE/G+33LqYu5V9MKxU8lFsoWU59RKAUg6G5sPp 0i1pUn51iLzW8QKWPLvW9bnFLqhB8fX/yFCSzHe1js0VgXHTKHwY6qmVlMCzvLumEvE8 o8VqBjN8p7b0tryDcCf9QOLtEpasG1afE1tSoEqhfTF+N+kycoOMwxBYCLu0VNwnvtB7 uYUah+4MfRztoaqg3PDe/LBzajC8d9QADW/yQQrIJc6ktsh3yGAISo6FqSFO8kZeSzFL F4Ke/Uqij2Ufpgj7Myh5hqkwWgMRZUVZk1e/Use5Q0rms7U9A+Ck6cI0W4CgmeEVUVgq Me9A== X-Gm-Message-State: AFuF++lHVbSWLtuvcKgHu9UQzUYR/BvT5nnCJx75uOsVD9/9b+lTQxhh 5LWcR/WeTcD0cd6jz4x+VrzDXsU7l/bgfwscX0thkh3NjKQfo4IV5tV9gFZ4AA== X-Gm-Gg: AYBFou25qv+uqX701I51VQsuJwkwJypCJSUk+HgNXr/1V40T5BoJY9Ty40hD1NMRgtB aiYNiBKnZnMkKOc7QO7SRNd65ttS6jon/4GDbLDWCup4Jzwy5UbfVUNmuaeTPwSxz+icSOxDEZY xK1m9y1PNa2Qd/QH95PK7yQ2Bm6RV6JSsjYUwWj7sFl1CeJU/8AePcRyZQKW9g56N+Jbrcs+dBU +X6tPwzF4QG+T6DQnd6ehE3+CQ0qnQxPkYxDGtfa1xegvz0a7V/mInJf0lVWMr/UFLKunBYXYSl ljvS3ScyZRrjz6hPb736ZzmGgCMpSQnLRrsszGFlz42X7vh3Av4Wc7SABxIBIzHKigw9sXpe39C Tot8bWl8bRN+asIRZnZE36fUwBirPxg47dWXi+z8MNz9JikNkXUpydkdofrdaSfjB7aCuj5SYFA g4y1v9jy9cfQZaEN6IfUspCMtsZuBju/PWAA+W0vvPBzwWwvSv6bbm1CxOntpHiIyhT2Q2bd1K+ Q3Q7dSr/stnAnHK+/UqP0Ia7YqBsN2+7YAuhxzAtQ== X-Received: by 2002:a05:600c:4514:b0:49f:ffed:2cb with SMTP id 5b1f17b1804b1-4a01aff3298mr35624915e9.6.1790785460170; Wed, 30 Sep 2026 09:24:20 -0700 (PDT) From: Oleksii Kurochko To: xen-devel@lists.xenproject.org Cc: Romain Caritey , Baptiste Le Duc , Zheng Zhang , Oleksii Kurochko , Alistair Francis , Connor Davis , Andrew Cooper , Anthony PERARD , Michal Orzel , Jan Beulich , Julien Grall , =?UTF-8?q?Roger=20Pau=20Monn=C3=A9?= , Stefano Stabellini Subject: [PATCH v3 18/39] xen/riscv: implement trap redirection to a guest Date: Wed, 30 Sep 2026 18:23:37 +0200 Message-ID: <109f3a920a2f5e58de5889ac2bcb834cc7ce967a.1790779209.git.oleksii.kurochko@gmail.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-purgate-ID: tlsNG-bad1c0/1790785460-BD0CD034-B656A627/10/73395122804 X-purgate-type: spam X-purgate-size: 5325 X-ZohoMail-DKIM: pass (identity @gmail.com) X-ZM-MESSAGEID: 1790785500054158500 Content-Type: text/plain; charset="utf-8" Two kinds of traps can't or shouldn't be handled by the hypervisor and have to be reflected to the guest's own S-mode trap handler instead: - Traps Xen takes on the guest's behalf, such as those taken by the hlv/hlvx sequences Xen uses to access guest memory. - Access faults handle_guest_page_fault() injects for a guest-page fault that can never become an emulated access. Implement trap_redirect(), until now a BUG_ON() placeholder, for that purpose. It makes the trap appear to the guest as if it had been taken directly in VS-mode: the trap information is transferred to the guest's virtual supervisor CSRs and the vCPU is resumed at its exception vector in supervisor mode, following the trap entry rules of the RISC-V privileged specification. The implementation is based on kvm_riscv_vcpu_trap_redirect() from Linux, with a few deviations: - The function reads and writes physical VS-mode CSRs, so it is only meaningful for the currently running vCPU. Instead of taking a struct vcpu argument, it always operates on current. - The MODE field of vstvec is masked off explicitly when computing the exception target PC (exceptions always vector to BASE), rather than relying on the hardwired zero bit of sepc to drop it on VM entry. - Assertions document the preconditions: the trap must have been taken from virtualized mode (hstatus.SPV set), and only synchronous exceptions may be redirected - interrupts must be injected via hvip instead, so that the hardware performs VS-mode trap entry itself, respecting vsstatus.SIE and vectored vstvec dispatch. STVEC_MODE_DIRECT and STVEC_MODE_VECTORED are unused for now and are added only for completeness alongside STVEC_MODE_MASK. Signed-off-by: Oleksii Kurochko --- Changes in v3: - Update the commit message. - Drop STVEC_BASE_MASK for now and use ~STVEC_MODE_MASK instead. --- Changes in v2: - Add new defines STVEC_*. The STVEC_MODE_DIRECT/_VECTORED values are currently unused and were included because riscv encoding header is a spec mirror full of unused encodings. - Use STVEC_BASE_MASK instead of open-coding it. - Rename riscv_vcpu_trap_redirect() to trap_redirect(): unlike its KVM counterpart the function takes no vCPU argument, it implicitly operates on current, so "vcpu" in the name describes nothing. --- xen/arch/riscv/include/asm/riscv_encoding.h | 5 +++ xen/arch/riscv/traps.c | 50 ++++++++++++++++++++- 2 files changed, 54 insertions(+), 1 deletion(-) diff --git a/xen/arch/riscv/include/asm/riscv_encoding.h b/xen/arch/riscv/i= nclude/asm/riscv_encoding.h index 2dbfd4d16067..b01da95f7ece 100644 --- a/xen/arch/riscv/include/asm/riscv_encoding.h +++ b/xen/arch/riscv/include/asm/riscv_encoding.h @@ -107,6 +107,11 @@ #define SIP_SSIP MIP_SSIP #define SIP_STIP MIP_STIP =20 +/* stvec/vstvec: MODE is bits [1:0], BASE is bits [XLEN-1:2] */ +#define STVEC_MODE_MASK _UL(0x3) +#define STVEC_MODE_DIRECT _UL(0x0) +#define STVEC_MODE_VECTORED _UL(0x1) + #define PRV_U _UL(0) #define PRV_S _UL(1) #define PRV_M _UL(3) diff --git a/xen/arch/riscv/traps.c b/xen/arch/riscv/traps.c index 4b9ec246e4c9..08aae2e5280b 100644 --- a/xen/arch/riscv/traps.c +++ b/xen/arch/riscv/traps.c @@ -293,5 +293,53 @@ enum mc_disposition arch_do_multicall_call(struct mc_s= tate *state) /* Redirect trap to Guest. */ void trap_redirect(const struct trap_info *trap) { - BUG_ON("unimplemented"); + struct cpu_user_regs *regs =3D vcpu_guest_cpu_user_regs(current); + unsigned long vsstatus =3D csr_read(CSR_VSSTATUS); + + /* + * Redirecting a trap makes sense only if the trap was taken from + * virtualized mode, i.e. sret is going to return to VS-mode. + */ + ASSERT(regs->hstatus & HSTATUS_SPV); + + /* + * Only synchronous exceptions can be redirected. Interrupts must be + * injected via hvip instead, so that the hardware itself performs + * VS-mode trap entry, respecting vsstatus.SIE and the vectored + * dispatch (BASE + 4 * cause) if vstvec is configured so. + */ + ASSERT(!(trap->scause & CAUSE_IRQ_FLAG)); + + /* Change Guest SSTATUS.SPP bit */ + vsstatus &=3D ~SSTATUS_SPP; + if ( regs->sstatus & SSTATUS_SPP ) + vsstatus |=3D SSTATUS_SPP; + + /* Change Guest SSTATUS.SPIE bit */ + vsstatus &=3D ~SSTATUS_SPIE; + if ( vsstatus & SSTATUS_SIE ) + vsstatus |=3D SSTATUS_SPIE; + + /* Clear Guest SSTATUS.SIE bit */ + vsstatus &=3D ~SSTATUS_SIE; + + /* Update Guest SSTATUS */ + csr_write(CSR_VSSTATUS, vsstatus); + + /* Update Guest SCAUSE, STVAL, and SEPC */ + csr_write(CSR_VSCAUSE, trap->scause); + csr_write(CSR_VSTVAL, trap->stval); + csr_write(CSR_VSEPC, trap->sepc); + + /* + * Set Guest PC to Guest exception vector. + * + * vstvec's MODE field is not part of the address. Exceptions always + * target BASE regardless of MODE, so mask it off explicitly instead of + * relying on the hardwired zero bit of sepc to drop it. + */ + regs->sepc =3D csr_read(CSR_VSTVEC) & ~STVEC_MODE_MASK; + + /* Set Guest privilege mode to supervisor */ + regs->sstatus |=3D SSTATUS_SPP; } --=20 2.55.0 From nobody Fri Oct 23 15:32:28 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) client-ip=192.237.175.120; envelope-from=xen-devel-bounces@lists.xenproject.org; helo=lists.xenproject.org; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=pass(p=none dis=none) header.from=gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1790785505; cv=none; d=zohomail.com; s=zohoarc; b=jS8JgRrI9x15YZSY6QK/qiZxgWTT8Bcns6GAc/i3MCI7Uc/qgvvT7tQuTL7uGNDIpG++rLcLWmDHSkKOpVf6TpgG/2gPmdb4yt4/y56C44QLh+uAK4i2XOauecCRSz3Sn+qAf9gsLWiFiP3eRzqLXTf95T+kQlOBbw0CPpMw8Pw= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1790785505; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=iYbVE5IEtZnCYn2L+fR0sdqs3ib6gAwHZo7AO3NZFAg=; b=OnA2bgBjqrAdVowglfqRMawY4o9hKlIgQrjlBPhbduPsMVph/Wqk5Eo4PtjnOouu5nh8aCwukOPMb78lZWfjlsRe0MbT5dkcLhgHbKpMWjKBm2kdXgX6lJy6bJ7FxlpV0S3lJpK24DFAbsI/TVIOuRGYPcf/OlFFrTutax12tWA= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) by mx.zohomail.com with SMTPS id 17907855052704.0296994030622955; Wed, 30 Sep 2026 09:25:05 -0700 (PDT) Received: from list by lists.xenproject.org with outflank-mailman.1437554.1656554 (Exim 4.92) (envelope-from ) id 1xBx6W-0005IT-M9; Wed, 30 Sep 2026 16:24:24 +0000 Received: by outflank-mailman (output) from mailman id 1437554.1656554; Wed, 30 Sep 2026 16:24:24 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1xBx6W-0005Hk-9y; Wed, 30 Sep 2026 16:24:24 +0000 Received: by outflank-mailman (input) for mailman id 1437554; Wed, 30 Sep 2026 16:24:22 +0000 Received: from mx.expurgate.net ([194.145.224.10]) by lists.xenproject.org with esmtp (Exim 4.92) id 1xBx6U-0004pX-Dd for xen-devel@lists.xenproject.org; Wed, 30 Sep 2026 16:24:22 +0000 Received: from mx.expurgate.net (helo=localhost) by mx.expurgate.net with esmtp id 1xBx6T-006Nvq-Qy for xen-devel@lists.xenproject.org; Wed, 30 Sep 2026 18:24:21 +0200 Received: from [10.42.69.4] (helo=localhost) by localhost with ESMTP (eXpurgate MTA 0.9.1) (envelope-from ) id 6abd37b5-e002-0a2a0a5209dd-0a2a4504eab8-0 for ; Wed, 30 Sep 2026 18:24:21 +0200 Received: from [74.125.225.140] (helo=mail-wm2-f12.google.com) by tlsNG-ebf023.mxtls.expurgate.net with ESMTPS (eXpurgate 4.57.1) (envelope-from ) id 6abd37b5-b57f-0a2a45040019-4a7de18c8a30-3 for ; Wed, 30 Sep 2026 18:24:21 +0200 Received: by mail-wm2-f12.google.com with SMTP id 5b1f17b1804b1-49ffe281cb1so28577165e9.1 for ; Wed, 30 Sep 2026 09:24:21 -0700 (PDT) Received: from fedora (user-109-243-71-234.play-internet.pl. [109.243.71.234]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-4a01cd43e66sm14620485e9.2.2026.09.30.09.24.20 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 30 Sep 2026 09:24:20 -0700 (PDT) X-Outflank-Mailman: Message body and most headers restored to incoming version X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" Authentication-Results: eu.smtp.expurgate.cloud; dkim=pass header.s=20251104 header.d=gmail.com header.i="@gmail.com" header.h="Content-Transfer-Encoding:MIME-Version:References:In-Reply-To:Message-ID:Date:Subject:Cc:To:From" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1790785461; x=1791390261; darn=lists.xenproject.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=iYbVE5IEtZnCYn2L+fR0sdqs3ib6gAwHZo7AO3NZFAg=; b=fBR/TrXBAQh9bB2vZg9oppENA6+4qsHitmrUweu81Hm0YypXk9i94w5ZkPQzDuhHS1 8g9aedvsWuwS1SI+p3rc05c7WtA+Odu1sL6GAdeP7k37hRansgdeU2E4xKeZtEI/PIpy fE72hGb+ctWOhKkCD08AtoF+zPW/cZIoCb682+zVgNQKwr0etJRz+eE559zqhIG15qEV X0zBlFMY9p7lSsXy4a5/zfSAr3Lsq6/Ohjz7bQuwImbFipHQggbSl7aK9ymoDxb9+E+a wUrAn4WL8oirGfyXeV5Y/yzmEaPLr7R4HYHSUaR1su7t5elU59O9eEYNOJLEcgUeLUnC v4QQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1790785461; x=1791390261; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=iYbVE5IEtZnCYn2L+fR0sdqs3ib6gAwHZo7AO3NZFAg=; b=OupPuOPgdQtoJlrFc7OoyZoClY2Nq4C+ikDokZBXyv1qNQSkjSzquYmeBzxSmjR/ir 2McWThWKRuGyjdrYJMdE4JHywJzJStFXClz3gLCC03JK6OMmC0ZI3EXsVaJyaip/vrfy eTQ/Iv6FJSP9+sXCeDseJJCeUciwGw4d4nly9ra0u8LjT0DEcfeOS9x3onA5W6RJISXL O1VjTd/zb34ayD5WcEFg+Z3Mcvf3iwpBf7DF1gC7+tjpQ2tITm2/TXHe944JR3hYLK95 Q4IWc/Ei81xuftReD3a8cN2qiUk7iEtCIxrThNYenh3ZIZdJJwd1Z4tvj0SpiGXIwY47 q9bQ== X-Gm-Message-State: AFuF++nyS6bmpOfMJqklOA8lE98yYQNwYOQkiVJQF+O+HhUPOLPSnzMX w8rf6Yk2EHkaDeCTGIIW+g/hJShgzolUsz+STU/eIxgAxU8/gxD5g4YODCTiLw== X-Gm-Gg: AYBFou2sj/pVhpf39J3b2jPsbNLNqGc47pNhF1VTxiVaxf49KKuGIAbQ4Q6grXXyxAU FzLBMFDVw1K/cGwXeZHp+jcXW90WoaAD6nFa3w91IWPqrZ5Tu9u89AIwbyZZutLQWMLQrO4CgDn tglUJRrNGR2MiccZvcin9PDqAOSk/qNhsmuw3wBEN+3dhVzoDtj0FyDCFgGHQPOXO9qB2WShtaW x34QbLKTnUx4SoW9qhzu+IZQ3U6d/yJTkLeQlir4er817MqFkZeJChiUQp/Y1EwVoBZ6ePoTVZW ahe3ncS3jD+4W9FIHDznKbAW+iOZnIhxxsw/9KPgum9v7V/1f+R9tZMWufE+WvQD/A0/rtgeVTy +uFj1uTsyMfux++1VX3as/V/kAkUKU+Bg+aiFOzm6QMMFi53M7FjahmViGL3CQ71l/2GoMURUcb fL1+kZF//BLilgaldnata8eQGdHvTWz0rVlOhyKduYwtPf34bfWtEyySQ8I/atWxnBrUFFq0xi7 ygRnv/KiRoUm6TaN5FF3LSR4Uo7cFhcB8gxPlJrJcwAeMqSMp0= X-Received: by 2002:a05:600c:a05:b0:4a0:6bb:237e with SMTP id 5b1f17b1804b1-4a01b01b407mr30864155e9.29.1790785461287; Wed, 30 Sep 2026 09:24:21 -0700 (PDT) From: Oleksii Kurochko To: xen-devel@lists.xenproject.org Cc: Romain Caritey , Baptiste Le Duc , Zheng Zhang , Oleksii Kurochko , Alistair Francis , Connor Davis , Andrew Cooper , Anthony PERARD , Michal Orzel , Jan Beulich , Julien Grall , =?UTF-8?q?Roger=20Pau=20Monn=C3=A9?= , Stefano Stabellini Subject: [PATCH v3 19/39] xen/riscv: detect Shtvala Date: Wed, 30 Sep 2026 18:23:38 +0200 Message-ID: X-Mailer: git-send-email 2.55.0 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-purgate-ID: tlsNG-ebf023/1790785461-C2ECEB50-B8D87D17/10/73395122804 X-purgate-type: spam X-purgate-size: 1974 X-ZohoMail-DKIM: pass (identity @gmail.com) X-ZM-MESSAGEID: 1790785506031158500 Content-Type: text/plain; charset="utf-8" The H extension allows htval, on a guest-page fault, to be written with either the faulting guest physical address or zero. The Shtvala extension removes the ambiguity of this zero-write by guaranteeing that htval is written with the faulting guest physical address in every circumstance permitted by the ISA. Not offered to guests: Shtvala describes htval, an HS-mode-only trap register a VS-mode guest never touches, and the H extension it belongs to is already hidden from guests. The guest-visible equivalent is a separate extension, Shvstvala, covering vstval instead. Signed-off-by: Oleksii Kurochko Reviewed-by: Baptiste Le Duc --- Changes in v3: - Update the commit message. --- Changes in v2: - New patch. --- --- xen/arch/riscv/cpufeature.c | 1 + xen/arch/riscv/include/asm/cpufeature.h | 1 + 2 files changed, 2 insertions(+) diff --git a/xen/arch/riscv/cpufeature.c b/xen/arch/riscv/cpufeature.c index 2d12dffae72e..c7f77d917cf5 100644 --- a/xen/arch/riscv/cpufeature.c +++ b/xen/arch/riscv/cpufeature.c @@ -195,6 +195,7 @@ static const struct riscv_isa_ext_entry __initconstrel = riscv_isa_ext[] =3D { RISCV_ISA_EXT_ENTRY(zba, ANY), RISCV_ISA_EXT_ENTRY(zbb, ANY), RISCV_ISA_EXT_ENTRY(zbs, ANY), + RISCV_ISA_EXT_ENTRY(shtvala, NONE), RISCV_ISA_EXT_ENTRY(smaia, ANY), RISCV_ISA_EXT_ENTRY(smstateen, ANY), RISCV_ISA_EXT_ENTRY(ssaia, ANY), diff --git a/xen/arch/riscv/include/asm/cpufeature.h b/xen/arch/riscv/inclu= de/asm/cpufeature.h index 2973eb13a513..ac8c68007072 100644 --- a/xen/arch/riscv/include/asm/cpufeature.h +++ b/xen/arch/riscv/include/asm/cpufeature.h @@ -36,6 +36,7 @@ enum riscv_isa_ext_id { RISCV_ISA_EXT_zba, RISCV_ISA_EXT_zbb, RISCV_ISA_EXT_zbs, + RISCV_ISA_EXT_shtvala, RISCV_ISA_EXT_smaia, RISCV_ISA_EXT_smstateen, RISCV_ISA_EXT_ssaia, --=20 2.55.0 From nobody Fri Oct 23 15:32:28 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) client-ip=192.237.175.120; envelope-from=xen-devel-bounces@lists.xenproject.org; helo=lists.xenproject.org; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=pass(p=none dis=none) header.from=gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1790785508; cv=none; d=zohomail.com; s=zohoarc; b=DTAlGBvRo7246IE8JnIL6HsJWfVqQztUKQ25+qiIZEjunPb1JAKDxNiILKIn5+mmVImskQ9S3D6kszltx3SHaHWtVUGxqv81YyFgf9/WEbLdofcgbJz5M4ewLtmIGkX1iDs6oeQ94yNWhfOoC1gLnuP+I+VmQlmcc/bR9ztj5kI= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1790785508; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=Y85EkaaCMNDVlRXtbC0r51vx5KgR2UBicrOOiZxzrlI=; b=mWA/yjt7e/LTKVT+vA/Z2A2L8PzT6ZjPOfGBM4OpF/vpnjNvkKwXII01OezJuurIobpH2byVa6OQInrb2+Dj0qpvig8PVysPuIt+WJwMjySOyP2TG9YWZ6oN5iNsurnaDwKmC0SM9ncGEZBczTZ++HG0QWr/a2k6JEk8M8SVKng= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) by mx.zohomail.com with SMTPS id 1790785508722384.9270097576308; Wed, 30 Sep 2026 09:25:08 -0700 (PDT) Received: from list by lists.xenproject.org with outflank-mailman.1437556.1656558 (Exim 4.92) (envelope-from ) id 1xBx6X-0005ON-5J; Wed, 30 Sep 2026 16:24:25 +0000 Received: by outflank-mailman (output) from mailman id 1437556.1656558; Wed, 30 Sep 2026 16:24:25 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1xBx6W-0005NQ-Rb; Wed, 30 Sep 2026 16:24:24 +0000 Received: by outflank-mailman (input) for mailman id 1437556; Wed, 30 Sep 2026 16:24:23 +0000 Received: from mx.expurgate.net ([194.145.224.20]) by lists.xenproject.org with esmtp (Exim 4.92) id 1xBx6V-00059i-KW for xen-devel@lists.xenproject.org; Wed, 30 Sep 2026 16:24:23 +0000 Received: from mx.expurgate.net (helo=localhost) by mx.expurgate.net with esmtp id 1xBx6V-00GhY9-1O for xen-devel@lists.xenproject.org; Wed, 30 Sep 2026 18:24:23 +0200 Received: from [10.42.69.3] (helo=localhost) by localhost with ESMTP (eXpurgate MTA 0.9.1) (envelope-from ) id 6abd37b7-8faa-0a2a0a5109dd-0a2a4503edf2-0 for ; Wed, 30 Sep 2026 18:24:23 +0200 Received: from [74.125.225.141] (helo=mail-wm2-f13.google.com) by tlsNG-33051d.mxtls.expurgate.net with ESMTPS (eXpurgate 4.57.1) (envelope-from ) id 6abd37b6-fae8-0a2a45030019-4a7de18dd322-3 for ; Wed, 30 Sep 2026 18:24:22 +0200 Received: by mail-wm2-f13.google.com with SMTP id 5b1f17b1804b1-49b912e4b11so33222555e9.3 for ; Wed, 30 Sep 2026 09:24:22 -0700 (PDT) Received: from fedora (user-109-243-71-234.play-internet.pl. [109.243.71.234]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-4a01cd43e66sm14620485e9.2.2026.09.30.09.24.21 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 30 Sep 2026 09:24:22 -0700 (PDT) X-Outflank-Mailman: Message body and most headers restored to incoming version X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" Authentication-Results: eu.smtp.expurgate.cloud; dkim=pass header.s=20251104 header.d=gmail.com header.i="@gmail.com" header.h="Content-Transfer-Encoding:MIME-Version:References:In-Reply-To:Message-ID:Date:Subject:Cc:To:From" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1790785462; x=1791390262; darn=lists.xenproject.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=Y85EkaaCMNDVlRXtbC0r51vx5KgR2UBicrOOiZxzrlI=; b=P2pLWGne6JHCwixS8jw79U4sTzBnenkxZUwMLhl2xgEiwMeGTZQ99sKWYsVihBHgMt trSlNyue5hpcqSvKr12AqiJeRFXkZuVYjr+9A91ttd+ZnMtAAShDq6wczyZ/Pc/ok2sx N0CecZ53+7kmAKmffYFMNDWf/a6kywIw90TJETFsNIk043fFMqB5fSz+QCsJBX7wGgS5 l32aoM1NjtPvSy+8GvbJkTdJL0MZMXeH5YlWaUNgVOr/u36T3mllSa118Pmk7xlzTQ/w ywwD1RRoTqFYfgWV3bOAb/623DTLkQrzbf4rk9sb1Sjn025e1ih3r0dKBNl8oeISgoPo UoIQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1790785462; x=1791390262; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=Y85EkaaCMNDVlRXtbC0r51vx5KgR2UBicrOOiZxzrlI=; b=RmUgjtYl8b7nkaFsCCRpPjPC8AAQhjxdajPPNhpv3BSiDRhxcSYNhCgtcQA2hOhTsr nw/9UNtfxr6bM1kg2mlNMnpZPzcFG7dmUylzQo4hQBkwa2n61k+WlaFWJ5SkshRkjUCO 5HI8irs77w8D8sFZRasv+EwxRdCaI+PiQfETlSRyvR2zw4Vv1W5GYljnpSvQkJRf0kwu ktT8BEWlvAhUENkA8MmxfaQxvjrG0BBqwShsrGXDEkCURLnyvKC0+5/fMxv+SgoZFGhJ fLvs/zTPzvqEYxR+A4qfgXSHH4lqzwcuPfXt0Wf+rmYnWgyTN0ruC/C0XGtuj5ylAFuT U/4g== X-Gm-Message-State: AFuF++lNr12pcrdzwGHhLwFoJ8oHgyZPD+1TWOuHMxdCf0FuTdrxJV9u VVeEmJjDhExx7yAqjKvf0Ds0KNL1YVrHpR3QVtAGLQvAxPI0NMOv1Gk9SinDvg== X-Gm-Gg: AYBFou3bFfKgWMhn7IrAAfja/D6GawejLsPDngB3Jmy8iITtIke6TE4JV3aHDA+PQXK YR43OVVRKVntYg4Ai3xmAvpqmX2RVZV1Fp8R0pRTvEM/gsIkRsiy284RUkCLjS7A5JfjoolL6Mh P7OTEqdGk8t3El52hoBrO9c16ElfzK1Do+OGUq70+jMvnyAwt5eR6eu+lvnlf0oKx1UPL+p5X1N fLhM8XzJ6x5iwAY348zHODmMexzRJ4A0QmIAwTXaIwLqkU102AmEKQvK3LcRXSRAGDKNZMqsz+I D9vZ4se81YE1SjGD1xQ+HjPN6OJ97BK7YQLTkiLYUY+i5WFL8BjAqDpVL9/3BAzgugQGCmWVJAF NBCNX8mIfkZZzfj57BsooUX1tm9Rd4g4XUcCJsjOrkhbGEZLuJybNpAhlj6yQlkzpYQKXFNSoAP NcEysQDp6/fvb9fHA+GAHD9ANyVtmjn76aT2EWuztj3xlu4wE/9jFO1cyuHoV3CduyEIF8uxwtO dhk/A+uVZsALoRh12JjbAue4iwu+ukwz/Hge20f X-Received: by 2002:a05:600c:6815:b0:49b:96a0:5c00 with SMTP id 5b1f17b1804b1-4a01ade9aa5mr36195235e9.13.1790785462292; Wed, 30 Sep 2026 09:24:22 -0700 (PDT) From: Oleksii Kurochko To: xen-devel@lists.xenproject.org Cc: Romain Caritey , Baptiste Le Duc , Zheng Zhang , Oleksii Kurochko , Andrew Cooper , Anthony PERARD , Michal Orzel , Jan Beulich , Julien Grall , =?UTF-8?q?Roger=20Pau=20Monn=C3=A9?= , Stefano Stabellini , Alistair Francis , Connor Davis Subject: [PATCH v3 20/39] xen/riscv: resolve the faulting guest physical address Date: Wed, 30 Sep 2026 18:23:39 +0200 Message-ID: X-Mailer: git-send-email 2.55.0 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-purgate-ID: tlsNG-33051d/1790785463-754844E9-0E833DDF/10/73395122804 X-purgate-type: spam X-purgate-size: 4973 X-ZohoMail-DKIM: pass (identity @gmail.com) X-ZM-MESSAGEID: 1790785510151158500 Content-Type: text/plain; charset="utf-8" Recover the guest physical address from htval and stval. On a guest-page fault to hypervisor, htval holds the guest physical address shifted right by 2, so that an address wider than HSXLEN fits, and stval holds the faulting guest virtual address. The shift is done on paddr_t rather than on the raw register: a guest physical address is 34 bits wide on RV32 with Sv32x4, so shifting an XLEN-wide value would drop its top two bits. However, there are two cases to distinguish when recovering the faulting GPA: - Explicit memory access: the two least significant bits of stval are the same as those of the guest physical address. - Implicit memory access for VS-stage translation: the two least significant bits of the guest physical address (GPA[1:0]) are zero. These two cases can be distinguished using the value provided in register htinst. stval needs no check against an ISA extension: a guest-page fault writes it with the faulting guest virtual address regardless. Sstvala would not be the right thing to test for either (it covers stval across every trap type which writes it, a wider guarantee than what is needed here). htval does need one. The H extension lets an implementation write it with either the faulting address or zero, so without Shtvala a zero htval cannot be told apart from a genuine fault on guest physical address 0-3, and the address has to be recovered by decoding the access and walking the VS-stage page tables in software instead. That is left as a TODO; until it is written, such a fault crashes the domain rather than acting on an address which may not be the one which faulted. Signed-off-by: Oleksii Kurochko Reviewed-by: Baptiste Le Duc --- Changes in v3: - Update the commit message. - Drop panic() inside resolve_faulting_gpa() and return -EOPNOTSUPP + printk_once(). - Leave the comment above resolve_faulting_gpa() alone: it already says what the function does since "xen/riscv: add guest page fault handling stub". - Document in docs/misc/riscv/booting.txt why Shtvala is recommended. --- Changes in v2: - New patch. --- --- docs/misc/riscv/booting.txt | 11 +++++++++++ xen/arch/riscv/emulate.c | 27 ++++++++++++++++++++++++++- 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/docs/misc/riscv/booting.txt b/docs/misc/riscv/booting.txt index c99ccafa7485..f90d8603ef57 100644 --- a/docs/misc/riscv/booting.txt +++ b/docs/misc/riscv/booting.txt @@ -38,3 +38,14 @@ Other extensions recognised by Xen are listed in riscv_i= sa_ext[] in xen/arch/riscv/cpufeature.c. Xen uses them when present, but they are not needed to boot. The second column of that table says whether the extension is also exposed to guests. + +Some of them are nevertheless recommended, as functionality depends on the= m: +- Shtvala: + Guarantees that htval is written with the faulting guest physical address + on a guest-page fault. Without it an implementation may write zero inste= ad, + which can't be told apart from a genuine fault on guest physical address= es + 0-3. Xen needs that address to emulate a guest's MMIO accesses; recoveri= ng + it in software (by walking the guest's VS-stage page tables) isn't + implemented, so on such hardware a guest-page fault reported with a zero + htval crashes the domain. See resolve_faulting_gpa() in + xen/arch/riscv/emulate.c. diff --git a/xen/arch/riscv/emulate.c b/xen/arch/riscv/emulate.c index cc4b1fc54054..a579bc4b8a15 100644 --- a/xen/arch/riscv/emulate.c +++ b/xen/arch/riscv/emulate.c @@ -9,6 +9,7 @@ #include #include =20 +#include #include #include #include @@ -58,7 +59,31 @@ static bool htinst_is_pseudo(unsigned long htinst) */ static int resolve_faulting_gpa(struct guest_fault *gf) { - return -EOPNOTSUPP; + /* + * A zero htval is either a genuine fault on guest physical address 0-= 3, or + * an implementation which does not report the address at all; only Sh= tvala + * tells the two apart. + * + * TODO: where it is absent, recover the address in software rather th= an + * giving up. + */ + if ( !gf->htval && + !riscv_isa_extension_available(NULL, RISCV_ISA_EXT_shtvala) ) + { + printk_once(XENLOG_WARNING + "Shtvala isn't supported by h/w; s/w VS-stage walk req= uired\n"); + return -EOPNOTSUPP; + } + + /* + * htval does not carry the two low bits of the address: for an explic= it + * access they are those of the faulting guest virtual address in stva= l, + * and for an implicit access made for VS-stage translation they are z= ero. + */ + gf->gpa =3D ((paddr_t)gf->htval << 2) | + (htinst_is_pseudo(gf->htinst) ? 0 : (gf->stval & 3)); + + return 0; } =20 static int emulate_load(const struct guest_fault *gf) --=20 2.55.0 From nobody Fri Oct 23 15:32:28 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) client-ip=192.237.175.120; envelope-from=xen-devel-bounces@lists.xenproject.org; helo=lists.xenproject.org; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=pass(p=none dis=none) header.from=gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1790785513; cv=none; d=zohomail.com; s=zohoarc; b=QyCGGyoaS2lL8acjbwVTAw/j2PjDbGyj/sbXHvM2RFdXeNDZ4+TpakoEhB/UZML6LnuC81F6mbgshwrak/sc/rMfCBKDI7E0PccnpsdqW4QToltQV6O+33PGpJdWiia9ygBSd0az7nA7Rl+o7s4qSTcvPRDqwx8wh6zH5YqaZkY= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1790785513; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=tqwkuuchWfrTIyA6KjmXq5aMj+FhTurJK2/FofFtnjA=; b=huIg4RYeFxebKkbJ5G4CXMiuprF/Cz+aCoxIr0EupV4YJPX1f37XoC9Bqmn5chPNR2FiO+SQ2+kucm3hi/q4043WlkAadzzTMksbzmL9M5Wki5GE+l7BDDDwT3ggBQ3Xj5SkF5o09F7G5YlaleJWmWAdqonxzOS5yV+Iqsoc4dY= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) by mx.zohomail.com with SMTPS id 1790785513877540.0856381534737; Wed, 30 Sep 2026 09:25:13 -0700 (PDT) Received: from list by lists.xenproject.org with outflank-mailman.1437557.1656571 (Exim 4.92) (envelope-from ) id 1xBx6Z-0005te-L8; Wed, 30 Sep 2026 16:24:27 +0000 Received: by outflank-mailman (output) from mailman id 1437557.1656571; Wed, 30 Sep 2026 16:24:27 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1xBx6Z-0005sq-7L; Wed, 30 Sep 2026 16:24:27 +0000 Received: by outflank-mailman (input) for mailman id 1437557; Wed, 30 Sep 2026 16:24:25 +0000 Received: from mx.expurgate.net ([194.145.224.20]) by lists.xenproject.org with esmtp (Exim 4.92) id 1xBx6W-0005Kk-Rg for xen-devel@lists.xenproject.org; Wed, 30 Sep 2026 16:24:24 +0000 Received: from mx.expurgate.net (helo=localhost) by mx.expurgate.net with esmtp id 1xBx6W-00GhY9-7w for xen-devel@lists.xenproject.org; Wed, 30 Sep 2026 18:24:24 +0200 Received: from [10.42.69.6] (helo=localhost) by localhost with ESMTP (eXpurgate MTA 0.9.1) (envelope-from ) id 6abd37a8-8faa-0a2a0a5109dd-0a2a45069d94-18 for ; Wed, 30 Sep 2026 18:24:24 +0200 Received: from [74.125.225.141] (helo=mail-wm2-f13.google.com) by tlsNG-16d1c6.mxtls.expurgate.net with ESMTPS (eXpurgate 4.57.1) (envelope-from ) id 6abd37b8-195a-0a2a45060019-4a7de18de0c4-3 for ; Wed, 30 Sep 2026 18:24:24 +0200 Received: by mail-wm2-f13.google.com with SMTP id 5b1f17b1804b1-49e79a408deso35150055e9.2 for ; Wed, 30 Sep 2026 09:24:24 -0700 (PDT) Received: from fedora (user-109-243-71-234.play-internet.pl. [109.243.71.234]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-4a01cd43e66sm14620485e9.2.2026.09.30.09.24.22 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 30 Sep 2026 09:24:23 -0700 (PDT) X-Outflank-Mailman: Message body and most headers restored to incoming version X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" Authentication-Results: eu.smtp.expurgate.cloud; dkim=pass header.s=20251104 header.d=gmail.com header.i="@gmail.com" header.h="Content-Transfer-Encoding:MIME-Version:References:In-Reply-To:Message-ID:Date:Subject:Cc:To:From" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1790785464; x=1791390264; darn=lists.xenproject.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=tqwkuuchWfrTIyA6KjmXq5aMj+FhTurJK2/FofFtnjA=; b=in22vjwjcsjBB8JqGiun1WuGUGKYe7Tgwffksy5RX7uYiMDABtzH9/4vFCFJmaK8YH 79NcL0KFPIRMXDMWpqqcEKHsX5T2+U4TTw7NiGJVscCyCskicuj0xeQpp0CGwOzN34Z7 Qz4367Y9EJ4gc5ck6jT3ufIQdV9pw7kRXgKy6mjSR4Ymwq/2MbtKDBuDSmDeYK5DzkgQ ubKysVyI0V5kOz+8tCiAnUSXVxlqR0TPAxo99618vQ1FZEjA1X25eYTyvYoqV557MSj0 a26nF5WGn7bkjAi0k+IAQiFYSMnmilpLH9FzpLpmvrGzMKh6W19rd478AXKQZ9Fve2As xMNw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1790785464; x=1791390264; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=tqwkuuchWfrTIyA6KjmXq5aMj+FhTurJK2/FofFtnjA=; b=ofjU6dffKu1t0+7C4OT2FYFMUxTYkVt0uI0egqbVkP5KbVzHqKN1GaJ5OtFrYrSCID +65eIpEbHFZiYq5WFPEIzu+/OrtRNSdPwat2Kq/spR5K6AEtM9Qrxc3gYbUqttjH+7OG fZFjzFY8BDHoJKYF1Z7L7cJ1aS+k7TfYRUAAuxrugPtftIhRPQzByHeMuiy7wBxVFH++ 4JJ+yp+GWTvtmvUOSBN0uyZRBtmJCZUftsOaYdATE37um+5HwHzjHlQqYOZoVCqa08O7 DxK86sJPVcg0minxeg2f9XZh8DP6jEq0pkQqjtcJnSyIPlTWTBXb5eAv13rk64oSZyLY g/Lg== X-Gm-Message-State: AFuF++lpImlN1dQe8aPhXbhXhSRb49bnfYBZIrspnKTlqW/KbqLs8wZI WLunz6nKYpQZhLlT30+M4cQZT05CPUFxmqxmEwsO9hhdMtXOJvjAkm6hKYx4RA== X-Gm-Gg: AYBFou1oRC5geXVNTRx9Lz3jzDrYpad5J6Wamy07U89UOL5odbcsa2zudC+ImHdch9c qvmd3mFUDmdsKqNKV8rdLHcUBB80a1+SXic1RVc3Cubz9O7iKL0/yvXBsntnUGXhhfuqDOrahHh sRdtKLYYr+2xPY7s8axVxp4xrsgCX5e9dV10SH0z190FBfv7wtpfJfNYTOpuP0NZ1LPODncsiUV bKn1SGTif88pcPlzsglozfxh7Zxl44ozlvFAmSeI1gPvuoU1HwFlgKaYwWdumYZB2CIdftVHBdF fHF5Uu578ZIAn8TDwPL+usj69Mj1cxOrgjpZTIWbyy1CllJWxPLr91LCTFQOjnVOaM9+TqJyX0K zG4whq5qrUu8NuuzuXVllQ9hjsVQPJBOG35gf9yk88Z71vlBVPWyrF8j+iti5qj07jIiQKSy6WT z/ZfXpezIo9JQ6B7y55UPsPyZQGkZrHKxeNbLwvk5+RO3MTA0ocjlLk1/XTcrPAOP75FKpiDPkH u6J1ZwdSMwAaUEGv7fWczrcNj6jX07HXdru6aF6 X-Received: by 2002:a05:600d:8642:10b0:4a0:1b15:8852 with SMTP id 5b1f17b1804b1-4a01b1588bfmr26290095e9.16.1790785463495; Wed, 30 Sep 2026 09:24:23 -0700 (PDT) From: Oleksii Kurochko To: xen-devel@lists.xenproject.org Cc: Romain Caritey , Baptiste Le Duc , Zheng Zhang , Oleksii Kurochko , Alistair Francis , Connor Davis , Andrew Cooper , Anthony PERARD , Michal Orzel , Jan Beulich , Julien Grall , =?UTF-8?q?Roger=20Pau=20Monn=C3=A9?= , Stefano Stabellini Subject: [PATCH v3 21/39] xen/riscv: add guest memory read helper Date: Wed, 30 Sep 2026 18:23:40 +0200 Message-ID: X-Mailer: git-send-email 2.55.0 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-purgate-ID: tlsNG-16d1c6/1790785464-FCC0777B-E8E2890A/10/73395122804 X-purgate-type: spam X-purgate-size: 8247 X-ZohoMail-DKIM: pass (identity @gmail.com) X-ZM-MESSAGEID: 1790785516194158500 Content-Type: text/plain; charset="utf-8" Introduce read_guest() to allow Xen to safely read guest memory using HLV/HLVX instructions while reliably capturing trap context. This is required for instruction fetch emulation and MMIO decoding, where Xen must inspect guest memory that may not be directly accessible and may fault. The implementation is based on kvm_riscv_vcpu_unpriv_read() from Linux, with one deviation: the hlv/hlvx instructions translate the guest address through the live vsatp/hgatp CSRs, i.e. through the address space of the currently running vCPU, so the function can only be called safely for current. Instead of taking a struct vcpu argument, it always operates on current directly. Signed-off-by: Oleksii Kurochko --- Changes in v3: - Rename riscv_read_guest() to read_guest(). - Document that @trap must be zero-initialised by the caller: it is written only when an access faults, so trap->scause =3D=3D 0 on return is what tells the caller that the read succeeded. - Drop the ASSERT() on hstatus.SPV: vcpu_guest_cpu_user_regs(current) is the guest frame whatever context Xen is in, so SPV is always set in it and the check couldn't catch a call made from a nested trap. State in the comment above read_guest() that it must not be called from a nested trap taken in HS-mode instead. - Declare read_guest() in asm/guest_access.h. --- Changes in v2: - Rename riscv_vcpu_unpriv_read() to riscv_read_guest() and make the guest address the first parameter. "unprivileged" described how hlv/hlvx perfo= rm the access rather than what the helper is for, and "unprivileged guest" reads as a synonym for DomU although the helper works for any domain. - Drop the hstatus save/restore and the local_irq_save() protecting it: hstatus already belongs to the vCPU which trapped, as Xen never installs a value of its own and does not reschedule before returning to the guest. ASSERT() hstatus.SPV in the saved copy instead, which also documents that the helper is only usable while handling a trap from a guest. - Poison val with ~0UL and make [val] "+&r": the fixup for the first access resumes past the loads without writing it, so a caller which checks trap->scause is no longer handed an uninitialized value. - Describe the trap_info write with a "+m" (*trap) operand instead of a "memory" clobber; the exception handler writes that structure and nothing else. - Combine the two halfwords with slli/or instead of sll/add, and use bnez for the instruction length check. - Turn the hlv.d/hlv.w selection into #if/#elif with an #error default, rather than silently using hlv.w for anything that is not RV64. - Document that at most two halfwords are fetched, i.e. that encodings wider than 32 bits are unsupported and cannot be completed by calling the helper again at guest_addr + 4, since the length check would then be applied to a continuation halfword. --- --- xen/arch/riscv/guestcopy.c | 88 +++++++++++++++++++++++ xen/arch/riscv/include/asm/guest_access.h | 4 ++ 2 files changed, 92 insertions(+) diff --git a/xen/arch/riscv/guestcopy.c b/xen/arch/riscv/guestcopy.c index 8a89212e0bea..4aa5a0d967ba 100644 --- a/xen/arch/riscv/guestcopy.c +++ b/xen/arch/riscv/guestcopy.c @@ -6,6 +6,7 @@ #include =20 #include +#include =20 #define COPY_from_guest 0U #define COPY_to_guest BIT(0, U) @@ -114,3 +115,90 @@ unsigned long copy_to_guest_phys(struct domain *d, pad= dr_t gpa, void *buf, return copy_guest(buf, gpa, len, GPA_INFO(d), COPY_to_guest | COPY_gpa); } + +/* + * Read machine word from guest memory + * + * @guest_addr: Guest address to read + * @read_insn: Flag representing whether we are reading instruction + * @trap: Output pointer to trap details if something went wrong during re= ad. + * It must be zero-initialised by the caller: it is written only wh= en + * an access faults, so trap->scause =3D=3D 0 on return is what tel= ls the + * caller that the read succeeded. + * + * The hlv/hlvx instructions translate guest_addr through the live + * vsatp/hgatp CSRs, so the read is only meaningful for the address + * space of the currently running vCPU. It must therefore only be called + * while handling a trap taken from that vCPU, never from a nested trap + * taken in HS-mode, which may have interrupted Xen at a point where + * hstatus, vsatp or hgatp don't belong to the vCPU. + * + * At most two halfwords are fetched when @read_insn is true, i.e. encodin= gs + * wider than 32 bits are not supported. Such an encoding cannot be comple= ted + * by calling this function again at @guest_addr + 4: the length check is + * applied to the first halfword read, which would then be a continuation = of + * the instruction rather than its opcode. It is up to the caller to reject + * anything that is neither a 16- nor a 32-bit encoding. + */ +unsigned long read_guest(unsigned long guest_addr, bool read_insn, + struct trap_info *trap) +{ + /* + * Poison the result: if the very first access faults, the fixup skips + * over the loads without writing it. Callers must check trap->scause. + */ + unsigned long val =3D ~0UL, tmp; + + /* + * hlv/hlvx use hstatus.SPVP for the privilege of the access, and the + * live vsatp/hgatp for the translation. Xen never installs a value of + * its own in hstatus (it is only saved on trap entry and restored + * before sret) and it doesn't reschedule before returning to the + * guest, so all three still belong to the vCPU which trapped. + */ + if ( read_insn ) + { + asm volatile ( "\n" + "1: hlvx.hu %[val], (%[addr])\n" + ASM_EXTABLE_TRAP_INFO(1b, 3f, %[ti]) + " andi %[tmp], %[val], 3\n" + " addi %[tmp], %[tmp], -3\n" + " bnez %[tmp], 3f\n" + " addi %[addr], %[addr], 2\n" + "\n" + "2: hlvx.hu %[tmp], (%[addr])\n" + ASM_EXTABLE_TRAP_INFO(2b, 3f, %[ti]) + " slli %[tmp], %[tmp], 16\n" + " or %[val], %[val], %[tmp]\n" + "3:\n" + : [val] "+&r" (val), [tmp] "=3D&r" (tmp), [addr] "+&r" (guest_addr= ), + "+m" (*trap) + : [ti] "r" (trap) ); + + /* + * Although HLVX instructions' explicit memory accesses require ex= ecute + * permissions, they still raise the same exceptions as other load + * instructions, rather than raising fetch exceptions instead. + */ + if ( trap->scause =3D=3D CAUSE_LOAD_PAGE_FAULT ) + trap->scause =3D CAUSE_FETCH_PAGE_FAULT; + } + else + { + asm volatile ( "\n" + "1: " +#if defined(CONFIG_RISCV_64) + "hlv.d %[val], (%[addr])\n" +#elif defined(CONFIG_RISCV_32) + "hlv.w %[val], (%[addr])\n" +#else +# error "unsupported RISC-V variant: no hlv for a machine word" +#endif + "2:\n" + ASM_EXTABLE_TRAP_INFO(1b, 2b, %[ti]) + : [val] "+&r" (val), "+m" (*trap) + : [addr] "r" (guest_addr), [ti] "r" (trap) ); + } + + return val; +} diff --git a/xen/arch/riscv/include/asm/guest_access.h b/xen/arch/riscv/inc= lude/asm/guest_access.h index 8d679319ded0..41c6ede4baae 100644 --- a/xen/arch/riscv/include/asm/guest_access.h +++ b/xen/arch/riscv/include/asm/guest_access.h @@ -5,6 +5,7 @@ #include =20 struct domain; +struct trap_info; =20 unsigned long raw_copy_to_guest(void *to, const void *from, unsigned len); unsigned long raw_copy_from_guest(void *to, const void *from, unsigned len= ); @@ -25,6 +26,9 @@ unsigned long raw_clear_guest(void *to, unsigned int len); unsigned long copy_to_guest_phys(struct domain *d, paddr_t gpa, void *buf, unsigned long len); =20 +unsigned long read_guest(unsigned long guest_addr, bool read_insn, + struct trap_info *trap); + #endif /* ASM__RISCV__GUEST_ACCESS_H */ /* * Local variables: --=20 2.55.0 From nobody Fri Oct 23 15:32:28 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) client-ip=192.237.175.120; envelope-from=xen-devel-bounces@lists.xenproject.org; helo=lists.xenproject.org; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=pass(p=none dis=none) header.from=gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1790785517; cv=none; d=zohomail.com; s=zohoarc; b=SWw05/ILSmHRfWW/VXMa7Ofl0ycr2WVWZEsXbNpk/nswkNJHGmv/WrnMcWK/ivC05KZuPVV8cZAXkAkB5rvtLRaPxHwkjw+p/oHT3LdUR1bEDyGVpXf/gUC95U7sOdR/xWFsmJs8ppjLgcna7rPZ2QiCsD9ZMdmmnIJmCsIx0t4= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1790785517; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=9i7xlxlm8EnXIPIV0SEz78aA/aq21fToL5xrVFch1SM=; b=mNR9lqaG0YgxwYmXLmjzUA5hq3wqaxgoYEwR2fAjlbHFDFl31r9rc4vhvGkdEjPvn6Lx5mpo95SFi0vhM0Olw07GKLjuo1J7A2noHIgdt9JphNQhNhCMgFsjTbc7ATMcy1e8dhEW9kXceTUDTvqBxT+/NTDTj2JMHJQVStYyLPU= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) by mx.zohomail.com with SMTPS id 1790785517601645.8826692316102; Wed, 30 Sep 2026 09:25:17 -0700 (PDT) Received: from list by lists.xenproject.org with outflank-mailman.1437559.1656576 (Exim 4.92) (envelope-from ) id 1xBx6a-00061b-En; Wed, 30 Sep 2026 16:24:28 +0000 Received: by outflank-mailman (output) from mailman id 1437559.1656576; Wed, 30 Sep 2026 16:24:28 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1xBx6a-0005zx-4t; Wed, 30 Sep 2026 16:24:28 +0000 Received: by outflank-mailman (input) for mailman id 1437559; Wed, 30 Sep 2026 16:24:26 +0000 Received: from mx.expurgate.net ([194.145.224.20]) by lists.xenproject.org with esmtp (Exim 4.92) id 1xBx6Y-0005f3-Co for xen-devel@lists.xenproject.org; Wed, 30 Sep 2026 16:24:26 +0000 Received: from mx.expurgate.net (helo=localhost) by mx.expurgate.net with esmtp id 1xBx6X-00GhYY-P9 for xen-devel@lists.xenproject.org; Wed, 30 Sep 2026 18:24:25 +0200 Received: from [10.42.69.5] (helo=localhost) by localhost with ESMTP (eXpurgate MTA 0.9.1) (envelope-from ) id 6abd37b9-bab6-0a2a0a5309dd-0a2a4505ca74-2 for ; Wed, 30 Sep 2026 18:24:25 +0200 Received: from [74.125.225.141] (helo=mail-wm2-f13.google.com) by tlsNG-c201ff.mxtls.expurgate.net with ESMTPS (eXpurgate 4.57.1) (envelope-from ) id 6abd37b9-4cb1-0a2a45050019-4a7de18de61a-3 for ; Wed, 30 Sep 2026 18:24:25 +0200 Received: by mail-wm2-f13.google.com with SMTP id 5b1f17b1804b1-49ffbd83a92so35231875e9.0 for ; Wed, 30 Sep 2026 09:24:25 -0700 (PDT) Received: from fedora (user-109-243-71-234.play-internet.pl. [109.243.71.234]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-4a01cd43e66sm14620485e9.2.2026.09.30.09.24.23 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 30 Sep 2026 09:24:24 -0700 (PDT) X-Outflank-Mailman: Message body and most headers restored to incoming version X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" Authentication-Results: eu.smtp.expurgate.cloud; dkim=pass header.s=20251104 header.d=gmail.com header.i="@gmail.com" header.h="Content-Transfer-Encoding:MIME-Version:References:In-Reply-To:Message-ID:Date:Subject:Cc:To:From" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1790785465; x=1791390265; darn=lists.xenproject.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=9i7xlxlm8EnXIPIV0SEz78aA/aq21fToL5xrVFch1SM=; b=mIaEpexoJHgJVHzhvgfviDyct3lc357ULmXDPOEvVyZEWu8ZrT8uS+JaYVai+AlO/O 69zNy0p2wHuDZzOgiewAv9UOxBVWVPWEE70x/bDrjjF/HdSYdrLyDYGhV9eDsnafQfVX /puSPCncPdkGg5jRSZzYzMcSFvaRVC6bBwoz0lJhvmDWmHJb23ajGALdg0gCzk7s8vxa pCtiCC1ySbUMsCT/AKReVAlNBNxvNWSd+LCfHap/AfpsipjM6WVtNODULx1H9Bu6yaxy MosNDi+snRQp62lEJeSRn9ZGqBBg2QZCMjQDHJYg2vn0ouKoqpbFqygdF7qpuVA9unkA s+1g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1790785465; x=1791390265; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=9i7xlxlm8EnXIPIV0SEz78aA/aq21fToL5xrVFch1SM=; b=bIWR0V7UIyA7SL081hnzVhyLLOZxVueyiZDoueR6oN7oY/aSHcQNuWoaFi/tRTps5Y kRu6ybEacvsxNR1zOISQP9G/AIn9CHeCvOOjlR9egm+GUJOVVncpIbigFT2vJ2Pbb+mq kGi4/SZKaLB+IMmtpIjvTFkWiMWfmpy6jpXlJ9BkABae3q6dqvC0J9nK5PRrWn0qlsUd mEwt8LX4k3iOMVtnQdc7nEegNCzLjg9o6Ebo4UiqMdt4uDXE1b0RLoMSWzd7MMgT27SO noEFrImrU7+o17k80FGb6X8ukxdqsQMpDWYqxLa7meXDycxE2eDaoaI7IgJg9QeBlvaS fwbg== X-Gm-Message-State: AFuF++k+XEeZXQbBewanzyqjMzLktch1aoPMs7STBDYl8fmLIiuP4r1n P9KhucPJ+x9tC57JN8KYfV0bvQl4sPxrp6wRffiQZBwifo/pc249AJjvjJX2pw== X-Gm-Gg: AYBFou3+NtWadUGrnE9LC+7ysmt3ABg5XMOGLY1i8B6fx2qbbMMqQYAuBQU3OnltqAy dud2kPLtiro4biMqpTNIJi4dok/FROKNcjt5Yft71aOPNqP7NAOQpK5BIL0Ua0oTDjIAHNYRnYl fJmDFzJb5mQVnnmNRxXNr5NewlmnQKBWsViYSNLke7rerlBWWCtIpCLDg5kenMuLzBgT2WOZUeQ gc1zwFeP32f4pbfFlCUFu3KegFwYNCPximNg+D6Ci/jEuAt0fdPNO8t6nWSRFiI2H0ojanDUTUK LkniqSYKYXy8PlmMzGmuH1xI3SKmp0vhUfrtdxbWh6icjBMaztG5GBaiXQZWRH3LOs2MWcLNcTD kwUPmFpawG1a2gCyr6oykls3UYlHl/0ETfqwNnDgEb9CblUL0E/CODJ7IfszAFpcVHj4t5v20MI G6RJdsrzZWX8sew5p1x+9lwmJ4ZOnqan+8J2+AWo6mIPjmhB+qEXDgX6F3M9lU4XPUdbwd9g0Is 8Yyu/xZGeKDrEurz6jaqzKWPJoMwmUllIvhC+fE X-Received: by 2002:a05:600c:a46:b0:498:943:ccc0 with SMTP id 5b1f17b1804b1-4a01afe8457mr33603975e9.6.1790785465148; Wed, 30 Sep 2026 09:24:25 -0700 (PDT) From: Oleksii Kurochko To: xen-devel@lists.xenproject.org Cc: Romain Caritey , Baptiste Le Duc , Zheng Zhang , Oleksii Kurochko , Alistair Francis , Connor Davis , Andrew Cooper , Anthony PERARD , Michal Orzel , Jan Beulich , Julien Grall , =?UTF-8?q?Roger=20Pau=20Monn=C3=A9?= , Stefano Stabellini Subject: [PATCH v3 22/39] xen/riscv: look up the exception table for any trap taken in Xen context Date: Wed, 30 Sep 2026 18:23:41 +0200 Message-ID: <4e2b4e7a99f4d2133ff92559303d19382749de7a.1790779209.git.oleksii.kurochko@gmail.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-purgate-ID: tlsNG-c201ff/1790785465-724B42A1-F82D0FB9/10/73395122804 X-purgate-type: spam X-purgate-size: 4714 X-ZohoMail-DKIM: pass (identity @gmail.com) X-ZM-MESSAGEID: 1790785518153158500 Content-Type: text/plain; charset="utf-8" do_trap() consulted the exception table only for CAUSE_ILLEGAL_INSTRUCTION, which covers csr_read_safe() but not the hlv/hlvx sequences reading guest memory: those fault with load/store (guest) page fault causes and would reach do_unexpected_trap() instead of their fixup. Move the lookup ahead of the cause switch, and gate it on the trap having been taken in Xen context and not being an interrupt: - sepc of a trap taken from the guest is a guest VA/PA, which the guest can point at an address listed in the exception table; Xen would then act on that entry and, for EX_TYPE_TRAP_INFO, write through a pointer fully under guest control. Entries are matched by exact address, so this needs no more than a numerical collision. - an interrupt taken at an address listed in the table would otherwise be "fixed up" as if the access itself had faulted, silently skipping it and handing the caller the interrupt's scause as a fault cause. Returning early skips check_for_pcpu_work(), which is correct: that only runs for traps taken from the guest. With that in place a G-stage fault reaching the switch can no longer have been caused by an hlv/hlvx covered by an entry, so anything left must have come from the guest. Say so in the comment ahead of the BUG_ON(!from_guest) in the guest page fault case. Signed-off-by: Oleksii Kurochko --- Changes in v3: - Update the comment ahead of BUG_ON(!from_guest) in the guest page fault case to refer to the fixup_exception() call added here. - Drop "assert as much" and the paragraph about caching the "trap came from the guest" test from the commit message: the BUG_ON() and the local are introduced by "xen/riscv: add guest page fault handling stub". - Refer to read_guest() instead of riscv_read_guest() in the comment in do_trap(), following the rename of the helper. --- Changes in v2: - New patch. --- --- xen/arch/riscv/traps.c | 33 +++++++++++++++++++++++++++------ 1 file changed, 27 insertions(+), 6 deletions(-) diff --git a/xen/arch/riscv/traps.c b/xen/arch/riscv/traps.c index 08aae2e5280b..dc938bae5b00 100644 --- a/xen/arch/riscv/traps.c +++ b/xen/arch/riscv/traps.c @@ -196,11 +196,34 @@ void do_trap(struct cpu_user_regs *cpu_regs) unsigned long cause =3D csr_read(CSR_SCAUSE); bool from_guest =3D cpu_regs->hstatus & HSTATUS_SPV; =20 + /* + * A synchronous trap taken in Xen context may come from an access don= e on + * a vCPU's behalf, e.g. the hlv/hlvx sequences in read_guest(), + * or from a probing access like csr_read_safe(). Both are covered by + * exception table entries which record the fault details for the call= er + * and resume execution past the faulting instruction. + * + * Traps taken from the guest must never be fixed up: sepc is then a g= uest + * address, which the guest could point at an address listed in the + * exception table, making Xen act on an entry (and, for EX_TYPE_TRAP_= INFO, + * write through a pointer) fully under guest control. + * + * Interrupts must be excluded too: one taken at an address which happ= ens + * to be listed in the exception table would otherwise be "fixed up" a= s if + * the access itself had faulted, silently skipping it. + * + * Returning early skips check_for_pcpu_work() below, which is correct: + * that only runs for traps taken from the guest. + */ + if ( !from_guest && !(cause & CAUSE_IRQ_FLAG) && + fixup_exception(cpu_regs, cause) ) + return; + switch ( cause ) { case CAUSE_VIRTUAL_SUPERVISOR_ECALL: /* CAUSE_VIRTUAL_SUPERVISOR_ECALL should come from VS-mode */ - BUG_ON(!(cpu_regs->hstatus & HSTATUS_SPV)); + BUG_ON(!from_guest); =20 vsbi_handle_ecall(cpu_regs); break; @@ -209,8 +232,9 @@ void do_trap(struct cpu_user_regs *cpu_regs) case CAUSE_LOAD_GUEST_PAGE_FAULT: case CAUSE_STORE_GUEST_PAGE_FAULT: /* - * Xen doesn't access guest memory, so it can't take a guest page - * fault itself: only a guest can get here. + * A guest page fault taken in Xen context comes from an hlv/hlvx + * access made on a vCPU's behalf and is dealt with by the + * fixup_exception() above, so only a guest can get here. */ BUG_ON(!from_guest); =20 @@ -231,9 +255,6 @@ void do_trap(struct cpu_user_regs *cpu_regs) break; } =20 - if ( fixup_exception(cpu_regs, cause) ) - break; - fallthrough; default: if ( cause & CAUSE_IRQ_FLAG ) --=20 2.55.0 From nobody Fri Oct 23 15:32:28 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) client-ip=192.237.175.120; envelope-from=xen-devel-bounces@lists.xenproject.org; helo=lists.xenproject.org; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=pass(p=none dis=none) header.from=gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1790785521; cv=none; d=zohomail.com; s=zohoarc; b=n2Y38Izeo43hQxcEKczF/pZcVoaWbH0G49YiNxWFq358iCTNTtA8mJiIiScDe4OYdpdVSbqKZJzMMiMO6MYzA+9fRooBcRCfepBK+lbulQKvdhFT0VYe1cms4+Q7XCOIyeQkNxsfswNcSTpT4W/BtRY3fA1HVACfEJQmzSC0OD8= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1790785521; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=YLpEqLfYYKeOPuRMDm9UG8/dGOxk0sub+YkoDN0whH0=; b=gpazMJV+A6IrbKPcDZFTvKOtBepZmQYlpEPmBpXGV39pR7vX57gfKufU2pgECs71/nNWBa3/zJusijHBz4RjqxIvOlQMXWyVG8Ty/HUl6zJTfy58uaPhEld/1NsmIbxp+drlYuA4vO1d2U55bQK9MYF81+gr8ruvoP4DgPW2oTk= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) by mx.zohomail.com with SMTPS id 1790785521876667.0261999032439; Wed, 30 Sep 2026 09:25:21 -0700 (PDT) Received: from list by lists.xenproject.org with outflank-mailman.1437562.1656587 (Exim 4.92) (envelope-from ) id 1xBx6c-0006Ub-S1; Wed, 30 Sep 2026 16:24:30 +0000 Received: by outflank-mailman (output) from mailman id 1437562.1656587; Wed, 30 Sep 2026 16:24:30 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1xBx6c-0006TU-HQ; Wed, 30 Sep 2026 16:24:30 +0000 Received: by outflank-mailman (input) for mailman id 1437562; Wed, 30 Sep 2026 16:24:28 +0000 Received: from mx.expurgate.net ([194.145.224.10]) by lists.xenproject.org with esmtp (Exim 4.92) id 1xBx6a-0005zo-9V for xen-devel@lists.xenproject.org; Wed, 30 Sep 2026 16:24:28 +0000 Received: from mx.expurgate.net (helo=localhost) by mx.expurgate.net with esmtp id 1xBx6Z-006Nvq-ML for xen-devel@lists.xenproject.org; Wed, 30 Sep 2026 18:24:27 +0200 Received: from [10.42.69.4] (helo=localhost) by localhost with ESMTP (eXpurgate MTA 0.9.1) (envelope-from ) id 6abd37b5-e002-0a2a0a5209dd-0a2a4504eab8-10 for ; Wed, 30 Sep 2026 18:24:27 +0200 Received: from [74.125.225.140] (helo=mail-wm2-f12.google.com) by tlsNG-ebf023.mxtls.expurgate.net with ESMTPS (eXpurgate 4.57.1) (envelope-from ) id 6abd37bb-b57f-0a2a45040019-4a7de18ca3e3-3 for ; Wed, 30 Sep 2026 18:24:27 +0200 Received: by mail-wm2-f12.google.com with SMTP id 5b1f17b1804b1-49ffb83bf7aso36077375e9.2 for ; Wed, 30 Sep 2026 09:24:27 -0700 (PDT) Received: from fedora (user-109-243-71-234.play-internet.pl. [109.243.71.234]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-4a01cd43e66sm14620485e9.2.2026.09.30.09.24.25 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 30 Sep 2026 09:24:26 -0700 (PDT) X-Outflank-Mailman: Message body and most headers restored to incoming version X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" Authentication-Results: eu.smtp.expurgate.cloud; dkim=pass header.s=20251104 header.d=gmail.com header.i="@gmail.com" header.h="Content-Transfer-Encoding:MIME-Version:References:In-Reply-To:Message-ID:Date:Subject:Cc:To:From" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1790785467; x=1791390267; darn=lists.xenproject.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=YLpEqLfYYKeOPuRMDm9UG8/dGOxk0sub+YkoDN0whH0=; b=GIjqPIlOuLJk7urAVkhTtefpFCr2NUhekLnKV7OxLlOHZ+EKDVbi0AVKEpUN8M0kTp w/waCvifTgI0Hq9p98gdg3JQFBFZHoENGyzPPvNyvVydmCtrxYBmDQCaUurwAf1TXbfo 5NfgqpxqKaY+aNHlKWDPd/LFow0itSiChEr7hAHIydDCD43r3kDrVbkMHYUgshdgGPRr 5ic8kBiDDVPx6hB4dYpgffYgAiQHfSC19hFrrZQok+Aod8t+Y0mFHweOHNz3g0uO7C/o f8AO4mlO9lMAcC1PziH96x4wUAScZa07puLdsJFwAPOBC1OQTAC+OQwD6al/jUyQUFHS kWsg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1790785467; x=1791390267; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=YLpEqLfYYKeOPuRMDm9UG8/dGOxk0sub+YkoDN0whH0=; b=elqSONM/rwzYPr36yLZVfvuqSm8Bx19Ni/EFdJUdrz2QMfoNWYrzK+nxiz2abyXdY+ ecOMAjWfWAIFWEQAUyZtzOe5bdTQPHzbmFeHhTMViTtbkG4OSgleUPf1g6k6CY1R9QDW FjYys9+6/sBNtpGGcmKMHy0fGlYnRZWCtWzCUofY5wgf7CZWTgbDaIBc/R+37zOgZLID /Eme+12c20KjwB0814pHa47dvO3IA3uQmy+55eitn2IUacbcaK/344ylVlXV0EyjO4q1 LvaljZhcGq9TKg40xkl097/m48iX+nrQk7c6Fe+kdbKN1eBv2//3oQntn6zgqLboGdtC zwRA== X-Gm-Message-State: AFuF++kUbSWnj8wXgfAA18RHT0x5rq7RZA5B0rXydkwMh2WPhuc5zz6/ 4UjOYti2cmWYphMeXPHAQndgYz5ezcE8lhltYKoc8WVsmYZ7r8QBjiHy9powzQ== X-Gm-Gg: AYBFou2L95mQNI4Jlg2OjUD6nKNt66ZBpdGfgUjzh+zEAeNXgBJv2yr9hL+ky41Y4Wu mIPq1Qg0AIrO8C+SXPDODKNTwXVQL1rmemEm9bBY2/ug9CJUNeQvGHnDIk9jem0Njqsg0g8EeGP pDOcFSMz05zcukptnKfGnqTPl4H2GCT+ZixoQK6mAjznzlWVfTh06zmfdLC98vQ5j3QZMDtwHRm oUofXniSyr4D4EbRmhjxen9F3shBw1zfagwDSXqtXCVSnfIp0tiCjHQIY8Neby1PbSzgxo0Ae9O CyznUE18P8TYalFFFxbpY4LqTqSFP9jC+zoBHUfSduFiGjLOxSD0F9U6oklOmaKmO/TZG1v2Wo1 uVm+7A0SBGUTmGNBtUvedO7ee4sMGf+XPXy2ynjhrFKXMOfy6R2sgxnG7O4kAll9TLcXF3YKoIo TBGlqEIprZI1BUL4ku9bT70ijd6OSHogLNp3VW037usqt6S4tcW824LlscDt2uZOy8wXwuT1Nnw BM9PFHxHf8dXTdkGY51DWGnxiGe3j9MrgZ3A+8v X-Received: by 2002:a05:600c:45d3:b0:49c:cee0:e7c1 with SMTP id 5b1f17b1804b1-4a01affa8ebmr31008685e9.16.1790785466850; Wed, 30 Sep 2026 09:24:26 -0700 (PDT) From: Oleksii Kurochko To: xen-devel@lists.xenproject.org Cc: Romain Caritey , Baptiste Le Duc , Zheng Zhang , Oleksii Kurochko , Alistair Francis , Connor Davis , Andrew Cooper , Anthony PERARD , Michal Orzel , Jan Beulich , Julien Grall , =?UTF-8?q?Roger=20Pau=20Monn=C3=A9?= , Stefano Stabellini Subject: [PATCH v3 23/39] xen/riscv: add helpers for decoding a trapped load or store Date: Wed, 30 Sep 2026 18:23:42 +0200 Message-ID: X-Mailer: git-send-email 2.55.0 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-purgate-ID: tlsNG-ebf023/1790785467-583C0B50-31539249/10/73395122804 X-purgate-type: spam X-purgate-size: 19805 X-ZohoMail-DKIM: pass (identity @gmail.com) X-ZM-MESSAGEID: 1790785522313158500 Content-Type: text/plain; charset="utf-8" emulate_load() and emulate_store() will both need to obtain the instruction which caused a guest MMIO trap, decode it, and locate the register operand it names. Add what the two share, ahead of either of them being implemented: struct decoded_insn, insn_fetch_faulted(), decode_ldst_insn(), guest_xlen(), guest_gpr() and advance_pc(), together with the XLEN_FIELD_*, INSN_OPCODE_* and RV_RD()/RV_RS2() definitions they need. Nothing calls any of this yet, so reference the functions from the emulate_load() stub to keep the build going; the references go away once emulate_load() gains its body later. Signed-off-by: Oleksii Kurochko --- How these helpers are used can be seen in the patches adding emulate_load() and emulate_store(). --- Changes in v3: - Update the commit message. - Restore the opcode bits of a transformed instruction with 3 rather than INSN_16BIT_MASK: the macro is dropped by "xen/riscv: drop INSN_{16,32}BIT_MASK and report unknown instruction lengths", and its name didn't fit this use anyway. - Use (void) references in emulate_load() instead of __maybe_unused. - Use read_guest(), the new name of riscv_read_guest(). - Shrink struct decoded_insn from 24 to 8 bytes (RV64): insn becomes uint32_t, as no instruction is wider than 32 bits, insn_len, len and reg become uint8_t (rather than bit-fields, for better code generation), and is_write and is_unsigned become bit-fields. - Don't take a custom htinst value with bits above bit[31] set for a transformed instruction (truncating it could yield a valid load/store encoding); fetch the instruction from guest memory instead. - Drop is_load_guest_page_fault() and open-code the check at its only user: with no store counterpart, such a helper is fragile. - Make guest_xlen() RV128-compatible by checking (xl > XLEN_FIELD_32) instead of (xl =3D=3D XLEN_FIELD_64) before consulting vsstatus.UXL. - Clarify in struct decoded_insn that insn may hold the 32-bit transformed equivalent of the trapped instruction, and that insn_len is the length of the trapped instruction in guest memory rather than of the encoding in insn. - Say that none of the extensions exposed to guests has instructions wider than 32 bits, instead of referring to what the ISA defines, which is at risk of going stale. - Document in guest_gpr() that register bits above the guest's XLEN are not guaranteed to be zero or a sign extension, so callers must not rely on them when reading and must sign-extend what they write. - Explain why utrap.sepc can't be set in the initializer: on a fault read_guest() overwrites it with the address of its own faulting access. - Mention that stval, being XLEN bits wide, may not be able to hold a wider instruction as another reason for leaving it zero. - Calculate insn_len ahead of the width check and use it there, instead of testing INSN_IS_16BIT() and INSN_IS_32BIT() separately. - Drop the resets of is_write and is_unsigned in decode_ldst_insn() and state that @di is expected to start out zeroed instead. - Report an illegal instruction for a compressed encoding read back from guest memory when C isn't exposed to the guest. - Have guest_gpr() take the decoded instruction rather than a bare register number, and assert there that the access width fits a guest register. - Decode the access width from funct3 (from bits[15:13] for the compressed forms), which the loads and stores encode uniformly, instead of matching the instruction against each of them in turn. Introduce INSN_OPCODE_{MASK,LOAD,STORE} for that. Reject by a single check what the guest's XLEN doesn't allow, i.e. an access wider than a guest register, which neither the value an emulated access moves nor the register operand guest_gpr() hands out could carry. - Say which field of the compressed forms holds the register operand: RVC_RS2S() gives rd' of a load as well as rs2' of a store. - guest_gpr(): resolve the register via regs_gpr_ptr() from asm/regs.h instead of REG_PTR(), sharing its bounds check. --- Changes in v2: - New patch. --- --- xen/arch/riscv/emulate.c | 336 ++++++++++++++++++++ xen/arch/riscv/include/asm/riscv_encoding.h | 14 + 2 files changed, 350 insertions(+) diff --git a/xen/arch/riscv/emulate.c b/xen/arch/riscv/emulate.c index a579bc4b8a15..2695a3277605 100644 --- a/xen/arch/riscv/emulate.c +++ b/xen/arch/riscv/emulate.c @@ -13,9 +13,40 @@ #include #include #include +#include +#include +#include #include #include =20 +/* + * Determine the trapped load or store instruction which caused a guest MM= IO + * trap. + */ +struct decoded_insn { + /* + * The trapped instruction: as read from guest memory, or the 32-bit + * equivalent the hardware transformed it into (see insn_fetch_faulted= ()). + * None of the extensions exposed to guests has instructions wider than + * 32 bits, and insn_fetch_faulted() rejects anything longer. + */ + uint32_t insn; + /* + * Length in bytes of the trapped instruction in guest memory: 2 or 4. + * This need not be the length of the encoding in insn, as a compressed + * instruction may have been transformed into its 32-bit equivalent. + */ + uint8_t insn_len; + /* Width of the memory access, in bytes. */ + uint8_t len; + /* Number of the register operand: rd for a load, rs2 for a store. */ + uint8_t reg; + /* The access is a store rather than a load. */ + bool is_write:1; + /* The load zero-extends its result rather than sign-extending it. */ + bool is_unsigned:1; +}; + /* * The hardware-reported details of a guest page fault, gathered once by * handle_guest_page_fault() and passed down to the emulation of the fault= ed @@ -39,6 +70,65 @@ struct guest_fault { paddr_t gpa; }; =20 +static void advance_pc(struct cpu_user_regs *regs, unsigned int step) +{ + regs->sepc +=3D step; +} + +/* + * The effective XLEN of the guest at the point of the trap: hstatus.VSXL = for a + * trap taken from VS-mode, vsstatus.UXL for one taken from VU-mode. + * + * VSXL is consulted whichever mode the trap came from, as it also gives t= he + * width of vsstatus itself: where VSXL says 32, that register has no UXL = field + * to consult and VU-mode is 32-bit as well, there being nothing to config= ure. + * + * It is needed to decode a trapped instruction: the encodings which exist= only + * for XLEN=3D64 must not be recognized for a 32-bit guest. Besides those = simply + * being reserved there, the compressed ones are ambiguous: C.LD and C.FLW + * share the encoding 0x6000 (mask 0xe003), and likewise C.SD/C.FSW, + * C.LDSP/C.FLWSP and C.SDSP/C.FSWSP. + * + * IS_ENABLED() can't be used here as HSTATUS_VSXL is defined for + * __riscv_xlen =3D=3D 64 only, the field not existing on RV32 in the firs= t place. + */ +static unsigned int guest_xlen(const struct cpu_user_regs *regs) +{ +#ifdef CONFIG_RISCV_32 + return 32; +#else + unsigned long xl =3D MASK_EXTR(regs->hstatus, HSTATUS_VSXL); + + if ( (xl > XLEN_FIELD_32) && !(regs->sstatus & SSTATUS_SPP) ) + xl =3D MASK_EXTR(csr_read(CSR_VSSTATUS), SSTATUS64_UXL); + + switch ( xl ) + { + case XLEN_FIELD_32: + return 32; + + case XLEN_FIELD_64: + return 64; + + default: + /* + * The field holds nothing else in practice: XLEN_FIELD_128 would = mean + * RV128, which no implementation provides, and the only value lef= t is + * reserved. ASSERT_UNREACHABLE() being debug-only, a width still = has + * to be answered in release builds. + * + * Answer 32, that being the safe way to be wrong: the decoder then + * fails to recognize the RV64-only encodings and emulation gives = up. + * Answering 64 for what may well be a 32-bit guest would instead = have + * it take C.FLW for C.LD and C.FSW for C.SD (see above), i.e. qui= etly + * emulate an access of the wrong width against the wrong register. + */ + ASSERT_UNREACHABLE(); + return 32; + } +#endif +} + /* * Is @htinst one of the special pseudoinstruction values, reported for a = guest * page fault taken on an implicit memory access done for VS-stage address @@ -86,8 +176,254 @@ static int resolve_faulting_gpa(struct guest_fault *gf) return 0; } =20 +/* + * Where the value of a decoded instruction's register operand is held. + * + * The register is held at its full width, whatever the guest's XLEN is (s= ee + * guest_xlen()). Where XLEN is narrower, the bits above it are not guaran= teed + * to be zero, nor even a sign extension: hardware only ignores them in so= urce + * operands, so they may have been left there by more privileged code runn= ing + * at a wider XLEN. Hence callers must not rely on those bits when reading= a + * value, and must sign-extend what they write from bit XLEN-1, as hardware + * does for the result of an operation. + */ +static unsigned long *guest_gpr(struct cpu_user_regs *regs, + const struct decoded_insn *di) +{ + /* + * decode_ldst_insn() is what fills @di in, and it rejects an access + * wider than a guest register. + */ + ASSERT(di->len <=3D (guest_xlen(regs) / BITS_PER_BYTE)); + + return regs_gpr_ptr(regs, di->reg); +} + +/* + * Obtain the instruction which caused a guest MMIO trap, filling in + * @di->insn and @di->insn_len. It either comes transformed in htinst, or = has + * to be fetched from guest memory. + * + * Returns true if the fetch faulted in turn; the resulting trap has then + * already been redirected to the guest and there is nothing further for t= he + * caller to do. Where it returns false, @di has been filled in and emulat= ion + * is to continue. + */ +static bool insn_fetch_faulted(const struct guest_fault *gf, + struct decoded_insn *di) +{ + unsigned long htinst =3D gf->htinst; + + /* + * A pseudoinstruction says nothing about the instruction the guest was + * executing, and comes with a guest physical address which isn't the = one + * that instruction accessed. handle_guest_page_fault() deals with suc= h a + * fault on its own, so no emulation can ever start for one. + */ + ASSERT(!htinst_is_pseudo(htinst)); + + /* + * Bit[0] =3D=3D 1 implies trapped instruction value is transformed in= struction + * or custom value. A transformed instruction is a 32-bit encoding, so= a + * value with any bit above bit[31] set is a custom one, which is of n= o use + * for decoding: fetch the instruction from guest memory then, as for = zero. + */ + if ( (htinst & BIT(0, UL)) && (htinst =3D=3D (uint32_t)htinst) ) + { + /* + * The transformation always yields the 32-bit format, with bits[1= :0] + * holding a marker instead of the original opcode bits: bit[0] se= t to + * flag the transformation, bit[1] clear if the trapped instruction + * was a compressed one. Restoring the opcode bits makes the value= the + * valid 32-bit encoding decode_ldst_insn() decodes. Its handling = of + * compressed encodings exists for the branch below, where a + * compressed instruction is read from guest memory as is: a trapp= ed + * one arrives here already expanded to its 32-bit equivalent, and= the + * opcode bits just restored have it decoded as such. + * + * The length then cannot come from the value anymore, only from + * bit[1]. And only a 16- or a 32-bit instruction is ever reported + * this way: the standard load and store instructions the hardware + * transforms are all of one of these two lengths, anything else c= omes + * as the zero special value handled below. + */ + di->insn =3D htinst | 3; + di->insn_len =3D (htinst & BIT(1, UL)) ? 4 : 2; + } + else + { + const struct cpu_user_regs *regs =3D gf->regs; + struct trap_info utrap =3D {}; + + /* + * Bit[0] =3D=3D 0 implies trapped instruction value is zero or sp= ecial + * value. With the pseudoinstructions ruled out above, only zero (= or a + * custom value, see above) is left: the instruction has to be rea= d from + * guest memory. + */ + + di->insn =3D read_guest(regs->sepc, true, &utrap); + if ( utrap.scause ) + { + /* + * If during getting of trapped instruction a fault happen in + * G-stage translation then CAUSE_LOAD_GUEST_PAGE_FAULT is + * generated. Such faults during this operation is considered = as + * bus error. + */ + if ( utrap.scause =3D=3D CAUSE_LOAD_GUEST_PAGE_FAULT ) + utrap.scause =3D CAUSE_FETCH_ACCESS; + + /* + * Not set in the initializer: on a fault read_guest() leaves = in + * utrap.sepc the address of its own faulting access, whereas = the + * trap is to be reported at the guest instruction. + */ + utrap.sepc =3D regs->sepc; + + trap_redirect(&utrap); + + return true; + } + + di->insn_len =3D INSN_LEN(di->insn); + + /* + * read_guest() fetches at most two halfwords, so a wider encoding= has + * been read in part only and cannot be decoded here. + * + * Report an illegal instruction: none of the extensions exposed to + * guests has instructions wider than 32 bits, so such an encoding= is + * not a valid instruction for the guest in the first place. + * + * The same goes for a compressed encoding where C isn't exposed t= o the + * guest. The instruction in guest memory may have changed since t= he + * trap, so what is read back must not be assumed to be what trapp= ed, + * nor to be valid for the guest. + */ + if ( !di->insn_len || + (di->insn_len =3D=3D 2 && + !riscv_isa_extension_available(current->domain->arch.isa, + RISCV_ISA_EXT_c)) ) + { + utrap.sepc =3D regs->sepc; + utrap.scause =3D CAUSE_ILLEGAL_INSTRUCTION; + /* + * stval is left zero, which the spec allows for an illegal + * instruction: only part of the instruction is in hand, and s= tval, + * being only XLEN bits wide, may not be able to hold all of it + * anyway. + */ + + trap_redirect(&utrap); + + return true; + } + } + + return false; +} + +/* + * Decode the load or store instruction fetched into @di, filling in the + * remaining fields of it (@di->insn and @di->insn_len are filled by + * insn_fetch_faulted()). Fields which don't apply to the instruction are = left + * alone, so @di is expected to start out zeroed. + * + * @xlen is the effective XLEN of the guest, needed as + * the encodings which exist for XLEN=3D64 only must not be recognized for= a + * 32-bit guest. + * + * Returns false if the instruction is not a load or store which can be + * emulated here. + */ +static bool decode_ldst_insn(struct decoded_insn *di, unsigned int xlen) +{ + uint32_t insn =3D di->insn; + unsigned int funct3, width_log2; + + if ( INSN_IS_16BIT(insn) ) + { + /* + * C.LW, C.LD, C.SW and C.SD (bits[1:0] =3D=3D 00), and their sp-r= elative + * C.*SP forms (bits[1:0] =3D=3D 10), have bits[15:13] of the form= x1y: + * x is set for a store, and y selects a width of 4 or 8 bytes. + */ + funct3 =3D RV_X(insn, 13, 3); + + if ( (insn & 1) || !(funct3 & 2) ) + return false; + + di->is_write =3D funct3 & 4; + width_log2 =3D 2 + (funct3 & 1); + + if ( !(insn & 2) ) + /* Quadrant 0: bits[4:2] encode rd' (load) or rs2' (store) */ + di->reg =3D RVC_RS2S(insn); + else if ( di->is_write ) + /* Quadrant 2 (CSS): bits[6:2] encode rs2 for C.SWSP / C.SDSP = */ + di->reg =3D RVC_RS2(insn); + else + { + /* Quadrant 2 (CI): bits[11:7] encode rd for C.LWSP / C.LDSP */ + di->reg =3D RV_RD(insn); + + /* C.LWSP and C.LDSP are reserved with rd being x0. */ + if ( !di->reg ) + return false; + } + } + else + { + /* + * funct3[1:0] is log2 of the width in bytes, and funct3[2] selects + * zero-extension for a load, while being reserved for a store. + */ + funct3 =3D RV_X(insn, 12, 3); + width_log2 =3D funct3 & 3; + + switch ( insn & INSN_OPCODE_MASK ) + { + case INSN_OPCODE_LOAD: + di->is_unsigned =3D funct3 & 4; + di->reg =3D RV_RD(insn); + break; + + case INSN_OPCODE_STORE: + if ( funct3 & 4 ) + return false; + di->is_write =3D true; + di->reg =3D RV_RS2(insn); + break; + + default: + return false; + } + } + + di->len =3D 1U << width_log2; + + /* + * No access is wider than XLEN, and one as wide as XLEN exists only in + * its sign-extending form: this rules out the encodings which exist f= or + * XLEN=3D64 only on a 32-bit guest, including C.FLW for C.LD (and ali= ke). + */ + if ( (di->len * BITS_PER_BYTE > xlen) || + (di->is_unsigned && di->len * BITS_PER_BYTE =3D=3D xlen) ) + return false; + + return true; +} + static int emulate_load(const struct guest_fault *gf) { + /* Transient, until the helpers gain their users. */ + (void)advance_pc; + (void)guest_xlen; + (void)guest_gpr; + (void)insn_fetch_faulted; + (void)decode_ldst_insn; + return -EOPNOTSUPP; } =20 diff --git a/xen/arch/riscv/include/asm/riscv_encoding.h b/xen/arch/riscv/i= nclude/asm/riscv_encoding.h index b01da95f7ece..1af309aa4ad5 100644 --- a/xen/arch/riscv/include/asm/riscv_encoding.h +++ b/xen/arch/riscv/include/asm/riscv_encoding.h @@ -65,6 +65,14 @@ #define SSTATUS64_UXL MSTATUS_UXL #define SSTATUS64_SD MSTATUS64_SD =20 +/* + * Width encoded by the MXL, SXL, UXL and VSXL fields, all of which share = one + * encoding. 0 is reserved. + */ +#define XLEN_FIELD_32 _UL(1) +#define XLEN_FIELD_64 _UL(2) +#define XLEN_FIELD_128 _UL(3) + #if __riscv_xlen =3D=3D 64 #define HSTATUS_VSXL _UL(0x300000000) #define HSTATUS_VSXL_SHIFT 32 @@ -854,6 +862,10 @@ /* 32-bit write for VS-stage address translation (VSXLEN=3D32) */ #define INSN_PSEUDO_VS_STORE32 0x00002020 =20 +#define INSN_OPCODE_MASK 0x7f +#define INSN_OPCODE_LOAD 0x03 +#define INSN_OPCODE_STORE 0x23 + #define INSN_IS_16BIT(insn) (((insn) & 3) !=3D 3) #define INSN_IS_32BIT(insn) (!INSN_IS_16BIT(insn) && ((insn) & 0x1c) !=3D = 0x1c) =20 @@ -895,6 +907,8 @@ (RV_X(x, 7, 2) << 6)) #define RVC_SDSP_IMM(x) ((RV_X(x, 10, 3) << 3) | \ (RV_X(x, 7, 3) << 6)) +#define RV_RD(insn) RV_X(insn, SH_RD, 5) +#define RV_RS2(insn) RV_X(insn, SH_RS2, 5) #define RVC_RS1S(insn) (8 + RV_X(insn, SH_RD, 3)) #define RVC_RS2S(insn) (8 + RV_X(insn, SH_RS2C, 3)) #define RVC_RS2(insn) RV_X(insn, SH_RS2C, 5) --=20 2.55.0 From nobody Fri Oct 23 15:32:28 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) client-ip=192.237.175.120; envelope-from=xen-devel-bounces@lists.xenproject.org; helo=lists.xenproject.org; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=pass(p=none dis=none) header.from=gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1790785526; cv=none; d=zohomail.com; s=zohoarc; b=RJGhHkkh46I+klrxN8M3YY5pcdEP8HTlY6IkcGXX2q2wIAF5/6lTNOQLneUNOtj5KteANCNaw6wQQnm/ywG2wMcK+8mQVf/n7WPpmcD9RjAcS3QszvFUn5Yj3/Iwp4ZVsrYJioAKHPRBqD+ak0rT5FSMqak0kTpY00B3nINgORo= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1790785526; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=+l1SUYb/7iJDfqo4I1DLp7p/nCakgSlHFOXqU8W+RoU=; b=mobve8KwMymYWnns4eiZOyo19kXmsGStT/MA1wzrsOAoQO1hX91sBrdBtEP/GnBgpUCw2uUSErb7LwIgknLrhUHghoEk10cE5ik6jjfwMHW1E40REVYlsyEJpta3rnGtrJfLM+Tfn3WRap1q7yYKvGS+P1fRc6jqxOjyOT4PVrw= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) by mx.zohomail.com with SMTPS id 1790785526770117.05977091418356; Wed, 30 Sep 2026 09:25:26 -0700 (PDT) Received: from list by lists.xenproject.org with outflank-mailman.1437564.1656595 (Exim 4.92) (envelope-from ) id 1xBx6d-0006dk-T0; Wed, 30 Sep 2026 16:24:31 +0000 Received: by outflank-mailman (output) from mailman id 1437564.1656595; Wed, 30 Sep 2026 16:24:31 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1xBx6d-0006c6-Es; Wed, 30 Sep 2026 16:24:31 +0000 Received: by outflank-mailman (input) for mailman id 1437564; Wed, 30 Sep 2026 16:24:29 +0000 Received: from mx.expurgate.net ([194.145.224.20]) by lists.xenproject.org with esmtp (Exim 4.92) id 1xBx6b-0006Ad-5t for xen-devel@lists.xenproject.org; Wed, 30 Sep 2026 16:24:29 +0000 Received: from mx.expurgate.net (helo=localhost) by mx.expurgate.net with esmtp id 1xBx6a-00GhYY-IT for xen-devel@lists.xenproject.org; Wed, 30 Sep 2026 18:24:28 +0200 Received: from [10.42.69.9] (helo=localhost) by localhost with ESMTP (eXpurgate MTA 0.9.1) (envelope-from ) id 6abd37a9-bab6-0a2a0a5309dd-0a2a4509a632-28 for ; Wed, 30 Sep 2026 18:24:28 +0200 Received: from [74.125.225.141] (helo=mail-wm2-f13.google.com) by tlsNG-bad1c0.mxtls.expurgate.net with ESMTPS (eXpurgate 4.57.1) (envelope-from ) id 6abd37bc-be1a-0a2a45090019-4a7de18db721-3 for ; Wed, 30 Sep 2026 18:24:28 +0200 Received: by mail-wm2-f13.google.com with SMTP id 5b1f17b1804b1-49e83a388f8so41332715e9.1 for ; Wed, 30 Sep 2026 09:24:28 -0700 (PDT) Received: from fedora (user-109-243-71-234.play-internet.pl. [109.243.71.234]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-4a01cd43e66sm14620485e9.2.2026.09.30.09.24.26 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 30 Sep 2026 09:24:27 -0700 (PDT) X-Outflank-Mailman: Message body and most headers restored to incoming version X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" Authentication-Results: eu.smtp.expurgate.cloud; dkim=pass header.s=20251104 header.d=gmail.com header.i="@gmail.com" header.h="Content-Transfer-Encoding:MIME-Version:References:In-Reply-To:Message-ID:Date:Subject:Cc:To:From" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1790785468; x=1791390268; darn=lists.xenproject.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=+l1SUYb/7iJDfqo4I1DLp7p/nCakgSlHFOXqU8W+RoU=; b=CttgJCI50UeAl/wa5oyYlhFImlUx9r1ZqWj+q5ek3esVYxUwyT0NeJowDPc6IJJDmk 1VxKO1AAWMq5YuUOOhVPhxZMDUckVQ6G2RVId2gcbH+uUdm048srsPBeJ6+xJnwLs7Gq LYy0u9YPcssaNuNX1pjkB2EyUSN6VwD1Nzfk+vIqKcEAZyszBY3cOJBa+SvE0igiyrae kVeSddt8IgbSG6nygzfofrfQpsz58SXJ59ecz8JkpRDvDKnamt3j+lAR6oJ2CxnQrVNH SN4lMj2sjfCnXQpX3mZH7mDXSkK8Fe8xruEQsh7Y/dbMZduZ/7sk3xnc1ES7SRy00PMg sHVQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1790785468; x=1791390268; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=+l1SUYb/7iJDfqo4I1DLp7p/nCakgSlHFOXqU8W+RoU=; b=WfTemBGmskDoBYGGGR91ZpWzxOekanJHhMLrffIOkMluAXR884X/nNWwWaizw0b8k2 vlvcmzbmsfyy63lMmoqeFai4xKK+u+N8pFsDvHBWb+0R3DXmiJ5ZTTB0XBpj+w63dm9t BBcpPkPOip0QpLTw2+JWkK/ohNx/Kaj0WkjQ2p0dsrXeq2InkiQZblU1zTf9RFcTYt4S iaYcVjMHWSSs4+nZeSoJbUgEusYLWvyzmNnw4oas+VmpdgRU/oX9K+urhVo+WqVRKnaG U0Za+XQAhyY6ozAhqx4W7NhBw2ekP2X59AdXQYvDQE2NfrMfYAKYsShGhy1e0hzxdNAp +crQ== X-Gm-Message-State: AFuF++lStwhL/chp1mcRiX+l4ptPcu++cjqKP+noeX28kIlYqlHll+8M +QTiL/f3qu5nfG9EXDPrhH4kh2mSluF+X9Pk6jyDzf7Oc7S2Z32sdTXF+zJZsg== X-Gm-Gg: AYBFou2zKJ4qV/ptNILgMVjJD6+2GkokMCE96VO06DKrGKbJaGTk9CybN5vgOhirpr4 5sXAZ6UtnKq7yjINiO77JX18OwStKQix+OLoFhXRduJPdJedvzT6QfewNK56Gd+PPk9DpeLO44+ /p0ShYeHrH/j4IZDCF0HcFBHyZA7LSoAy4/FuI20RGpcXXFPVOGkd2jsodeTKRD94FG1rxChhc+ sNTCirsynpiCDAihnXAWxQZoOOH+mheUntSHpBkr1nritEWk9JHF8hYBJR3pUL6UnL+jyxbdGs9 3YFKutbwyYvxx+wiE9Hgho4aLe30AKchR3/sN+sTbAR9unOo4wzP8O8X9MzSq5zevcche0VtcCZ hIzGToDk3ZAq3g/2bxaMinxf0VhzL3z6KfJFlDek04i/KQuAeH023P82CkByEaaE2fR+oki06kS CtAME8wsEw1xW+gaglla3ZMhWnpDCHCxmhBI7GYf3bM299HNjijRLCGNw5LicCDhcOWFaQebuQx KH55vR/d0OFkPJro5ZAbu1a7Ghj7kP3rqVEhz5j X-Received: by 2002:a05:600c:1f86:b0:4a0:1ea2:10c6 with SMTP id 5b1f17b1804b1-4a01ea211bamr5446765e9.17.1790785467864; Wed, 30 Sep 2026 09:24:27 -0700 (PDT) From: Oleksii Kurochko To: xen-devel@lists.xenproject.org Cc: Romain Caritey , Baptiste Le Duc , Zheng Zhang , Oleksii Kurochko , Alistair Francis , Connor Davis , Andrew Cooper , Anthony PERARD , Michal Orzel , Jan Beulich , Julien Grall , =?UTF-8?q?Roger=20Pau=20Monn=C3=A9?= , Stefano Stabellini Subject: [PATCH v3 24/39] xen/riscv: add guest load emulation for trapped MMIO accesses Date: Wed, 30 Sep 2026 18:23:43 +0200 Message-ID: X-Mailer: git-send-email 2.55.0 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-purgate-ID: tlsNG-bad1c0/1790785468-3BAD0034-1D8CB867/10/73395122804 X-purgate-type: spam X-purgate-size: 4845 X-ZohoMail-DKIM: pass (identity @gmail.com) X-ZM-MESSAGEID: 1790785528246158500 Content-Type: text/plain; charset="utf-8" Implement emulate_load() on top of the decoding interface introduced by the previous patch: fetch the trapped instruction, decode it, dispatch the access to a registered MMIO handler via do_mmio(), write the result back into the destination register and step over the instruction. Xen dispatches MMIO synchronously to an in-hypervisor handler, so unlike KVM RISC-V there is no userspace exit/return step and no equivalent of the kvm_io_bus_read() / KVM_EXIT_MMIO / kvm_riscv_vcpu_mmio_return() split; the result is consumed in place. Sign extension is done here rather than in the handlers: a signed load is normalized by a shift pair, so a handler need only report the value it read. At the moment vINTC is the only backend registered with the MMIO dispatch, so in practice this only covers vINTC traps. An access which no handler claims currently crashes the domain; injecting an access fault into the guest instead is left for later. Signed-off-by: Oleksii Kurochko --- Changes in v3: - Shorten the comment above "if ( di.reg )" by dropping redundant part. - s/sizeof(unsigned long)/sizeof(info.data) in emulate_load(). - Zero-initialize di, as decode_ldst_insn() expects it to start out zeroed. - Adjust to guest_gpr() taking the decoded instruction rather than a bare register number. --- Changes in v2: - Move the emulation code to the new arch/riscv/emulate.c, leaving traps.c with trap dispatch only. - Split the patch up: struct decoded_insn and the decoding helpers are introduced by "xen/riscv: introduce the interface for trapped instruction decoding" and filled in by "xen/riscv: implement trapped instruction decoding", so only emulate_load() itself is left here. - do_mmio() is no longer defined alongside emulate_load(); it now lives in mmio.c, next to the dispatch it drives. - Don't write the result of a load into x0. SET_RD() wrote rd unconditionally, so a load into x0 clobbered regs->zero and broke the invariant that it reads as zero when x0 is a source operand elsewhere. - Recognize the XLEN=3D64-only encodings by the guest's effective XLEN (guest_xlen()) rather than by Xen's own (CONFIG_RISCV_32). Besides those encodings simply being reserved on RV32, the compressed ones are ambiguo= us there: C.LD and C.FLW share the encoding 0x6000 (mask 0xe003), and likew= ise C.SD/C.FSW, C.LDSP/C.FLWSP and C.SDSP/C.FSWSP. - Take the faulting address from struct guest_fault, filled in by resolve_faulting_gpa(), rather than from get_faulting_gpa(). - Drop the description of a fault taken while re-reading the trapped instruction: that code is now in the patch implementing fetch_trapped_insn(), where a G-stage fault is reported to the guest as CAUSE_FETCH_ACCESS instead of hitting a BUG_ON(). - Update the commit message accordingly. --- --- xen/arch/riscv/emulate.c | 39 ++++++++++++++++++++++++++++++++------- 1 file changed, 32 insertions(+), 7 deletions(-) diff --git a/xen/arch/riscv/emulate.c b/xen/arch/riscv/emulate.c index 2695a3277605..ff8cba7d5116 100644 --- a/xen/arch/riscv/emulate.c +++ b/xen/arch/riscv/emulate.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -417,14 +418,38 @@ static bool decode_ldst_insn(struct decoded_insn *di,= unsigned int xlen) =20 static int emulate_load(const struct guest_fault *gf) { - /* Transient, until the helpers gain their users. */ - (void)advance_pc; - (void)guest_xlen; - (void)guest_gpr; - (void)insn_fetch_faulted; - (void)decode_ldst_insn; + struct cpu_user_regs *regs =3D gf->regs; + mmio_info_t info =3D { .is_write =3D false }; + struct decoded_insn di =3D {}; + unsigned int shift =3D 0; + int rc; =20 - return -EOPNOTSUPP; + /* A fault taken re-reading the instruction is redirected to the guest= . */ + if ( insn_fetch_faulted(gf, &di) ) + return 0; + + if ( !decode_ldst_insn(&di, guest_xlen(regs)) || di.is_write ) + return -EOPNOTSUPP; + + if ( !di.is_unsigned ) + shift =3D BITS_PER_BYTE * (sizeof(info.data) - di.len); + +#ifdef EMULATE_LOAD_DEBUG + gdprintk(XENLOG_DEBUG, "pc=3D%#lx, addr=3D%#"PRIpaddr", len=3D%u, shif= t=3D%u\n", + regs->sepc, gf->gpa, di.len, shift); +#endif + + rc =3D do_mmio(&info, gf->gpa, di.len); + if ( rc ) + return rc; + + /* A load into x0 discards its result. */ + if ( di.reg ) + *guest_gpr(regs, &di) =3D (long)(info.data << shift) >> shift; + + advance_pc(regs, di.insn_len); + + return 0; } =20 static int emulate_store(const struct guest_fault *gf) --=20 2.55.0 From nobody Fri Oct 23 15:32:28 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) client-ip=192.237.175.120; envelope-from=xen-devel-bounces@lists.xenproject.org; helo=lists.xenproject.org; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=pass(p=none dis=none) header.from=gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1790785533; cv=none; d=zohomail.com; s=zohoarc; b=GIGPnXg6bv6BkvQYEbPcGtZvuBZLiXyRvBTaHnHX5myidFIkZS999Ejga/mxWWFtY50bx0NJRYNyAVPgTmPkasygOC0KfxuhewKtMKxcutNF6BKnYNO/l+TklZdCWe6rVkrGLrAZQuu4NUapUpL+WNexlU3s0ko2cp8PJUQymyw= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1790785533; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=WhdgV3QVxJUr3oQpuKpqS6JUk7msudbkVBTwJRK9mRA=; b=Es4gQhsEOPN6Hdb8i4ytpUuY/GK4+l0DEokjYn61r3G4H9g4SSWRRv4i/I46K5nxntHi5QWgDs8zNDKXxH+B63/0JbLPPxxN85FjhnttS87o5vEGl5FhWzyM6B8wOCCqgvRraAsWG00mTXlvb1Qpn6wYk51L2KKGb16O2WAScLY= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) by mx.zohomail.com with SMTPS id 1790785533774770.8668226891713; Wed, 30 Sep 2026 09:25:33 -0700 (PDT) Received: from list by lists.xenproject.org with outflank-mailman.1437567.1656601 (Exim 4.92) (envelope-from ) id 1xBx6f-0006qs-D2; Wed, 30 Sep 2026 16:24:33 +0000 Received: by outflank-mailman (output) from mailman id 1437567.1656601; Wed, 30 Sep 2026 16:24:33 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1xBx6e-0006oS-MM; Wed, 30 Sep 2026 16:24:32 +0000 Received: by outflank-mailman (input) for mailman id 1437567; Wed, 30 Sep 2026 16:24:30 +0000 Received: from mx.expurgate.net ([194.145.224.10]) by lists.xenproject.org with esmtp (Exim 4.92) id 1xBx6c-0006PI-9D for xen-devel@lists.xenproject.org; Wed, 30 Sep 2026 16:24:30 +0000 Received: from mx.expurgate.net (helo=localhost) by mx.expurgate.net with esmtp id 1xBx6b-006Nvr-Lx for xen-devel@lists.xenproject.org; Wed, 30 Sep 2026 18:24:29 +0200 Received: from [10.42.69.8] (helo=localhost) by localhost with ESMTP (eXpurgate MTA 0.9.1) (envelope-from ) id 6abd37b9-2eae-0a2a0a5409dd-0a2a4508b85c-6 for ; Wed, 30 Sep 2026 18:24:29 +0200 Received: from [74.125.225.140] (helo=mail-wm2-f12.google.com) by tlsNG-c1860d.mxtls.expurgate.net with ESMTPS (eXpurgate 4.57.1) (envelope-from ) id 6abd37bd-f659-0a2a45080019-4a7de18c8a95-3 for ; Wed, 30 Sep 2026 18:24:29 +0200 Received: by mail-wm2-f12.google.com with SMTP id 5b1f17b1804b1-49ffe281cb1so28578005e9.1 for ; Wed, 30 Sep 2026 09:24:29 -0700 (PDT) Received: from fedora (user-109-243-71-234.play-internet.pl. [109.243.71.234]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-4a01cd43e66sm14620485e9.2.2026.09.30.09.24.27 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 30 Sep 2026 09:24:28 -0700 (PDT) X-Outflank-Mailman: Message body and most headers restored to incoming version X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" Authentication-Results: eu.smtp.expurgate.cloud; dkim=pass header.s=20251104 header.d=gmail.com header.i="@gmail.com" header.h="Content-Transfer-Encoding:MIME-Version:References:In-Reply-To:Message-ID:Date:Subject:Cc:To:From" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1790785469; x=1791390269; darn=lists.xenproject.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=WhdgV3QVxJUr3oQpuKpqS6JUk7msudbkVBTwJRK9mRA=; b=hIc7y2fI0aLpMkRHIOyPbNY2PVRGoZs5HdlwX+83PT26KMNyTjKs+8LSkK5G35NJIV YG23qWCEKAdxatG9DsLbyD3UM+3pRECzYRtXFPcuataU0CdQah47+gmaIAyC52T587Wb s5+wbvO9TrmtAMwDOJLR5FWe0sQtrV3ZcoMV8+0Va/geu6NXson0SAaazfHuf5C3b525 9nP4CUd7kGKh8h+BB5wS2POZVH1SZ5PJv2pMPL8yzRr1SSnfC09Zz9ZoymlD8keTV3jw 5yJa2p/CAtxAe9IILGmsB1HXr/t1sSmGmRar8oH0aSR/UyEzaKztmdbvrKIM8NisTKzo GV/A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1790785469; x=1791390269; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=WhdgV3QVxJUr3oQpuKpqS6JUk7msudbkVBTwJRK9mRA=; b=la9awBoYnKpWl7nNpp9O0KhRPG7Ed+QtScfaVXam7SRpZpaC/20soNzs6KLCK8ZuYi NXqg9UuxfmkrGr7zYiNtGqeDOh3jNvXjCUPDEN8YrKYHskGaudTRrSAIpXjzHQ2FWV2X 5s1hsD8ZjZufUxEGN03NEhs+c68ScyI5iF0v4k5F8eIbAGb2NUAo18gkE6U3hrxqFgs2 FeESOIGP/ypqH/Y6mw6DERpiq+bXTPv+7ySzdXcRI48erb74aHAb4k6hWNV7DIuGg3i3 FnayyRMg/WLFDsQ+N7ZLW8SqcSfn8r6VP4eHvkzMqZB1Sp/lPw0b8B9wk9cf1ctri0JU Bmuw== X-Gm-Message-State: AFuF++k9Kg34muPPjpN4XzR6AXd+OCmntp1yvFQ44AFuck5uilXEcI7d WGjEqJkH4u8pzs/H27BnQyRSddBuPbZHOSb/xg9mSFg7sg4j4sxBsEqFAErayA== X-Gm-Gg: AYBFou2jw5cKrOqIjI4Qc722FDYHtopSTvD1EvzqBVgTGxQrfIhSOSOBiRu/avu41Rz fkQ4S4Q0eL1XiMgw6A0VYyNTqTlUHVUJtjue7V97R/5FpjlRGI3DWvqt6G5mCis2nzMhxKpopKn /i00kYcD6QkcpOcAPZYura4TGRrzF1Enyx6ODgrwPtu2EkZxc18YYqxngiKLYfgGTBfndDrs2g6 DCOfctNY9CDhCo2/EjE56jq84DdGM6NSu4Vgla22V/oytvy4O5MIhyUz4dACa6Tmf2hiaPpXzx4 AA4zB11LRKC0oLHii9x4Ow3lK2uFBpJkp//Iba8q1BV7xVgcuagWnjS+QLXP8LbqHYAF+/sEE36 Wjx6mWzwopD8SA8Wo4dO1Lyd4BFB1G7ojOiOlygD8VLXNFufmw2xt/Pb3D3KFLFuwr8XPueYPl6 g/Y1f5p8Hx4nTEuIy+teEI9gH9d3dXNhFh7M33RyNVQesjP3khecdATrRBziGf5QE9LYxOAFXyH Kje20BIYCbYVCyCK+LiG6rWo/PtqxJRtJuqRk/7a9MTgdA8Bct9 X-Received: by 2002:a05:600d:82e7:b0:49f:c199:e1e2 with SMTP id 5b1f17b1804b1-4a01b0190cemr37567345e9.28.1790785469012; Wed, 30 Sep 2026 09:24:29 -0700 (PDT) From: Oleksii Kurochko To: xen-devel@lists.xenproject.org Cc: Romain Caritey , Baptiste Le Duc , Zheng Zhang , Oleksii Kurochko , Alistair Francis , Connor Davis , Andrew Cooper , Anthony PERARD , Michal Orzel , Jan Beulich , Julien Grall , =?UTF-8?q?Roger=20Pau=20Monn=C3=A9?= , Stefano Stabellini Subject: [PATCH v3 25/39] xen/riscv: add guest store emulation for trapped MMIO accesses Date: Wed, 30 Sep 2026 18:23:44 +0200 Message-ID: X-Mailer: git-send-email 2.55.0 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-purgate-ID: tlsNG-c1860d/1790785469-CD54C87B-27B4087A/10/73395122804 X-purgate-type: spam X-purgate-size: 3696 X-ZohoMail-DKIM: pass (identity @gmail.com) X-ZM-MESSAGEID: 1790785534239158500 Content-Type: text/plain; charset="utf-8" Extend the guest page fault handler with store emulation to support MMIO write accesses. Like emulate_load(), emulate_store() obtains the trapped instruction with insn_fetch_faulted(), which also deals with a fault taken while re-reading it, and decodes it with decode_ldst_insn(). As with the load path, the access is completed synchronously through do_mmio(). At the moment only virtual interrupt controller (vINTC) traps are expected to occur, since it is currently the only backend registered with the MMIO handler dispatch, so in practice the store is emulated via the vINTC backend. Together with load emulation, this completes the basic MMIO handling path needed for virtual interrupt controller support on RISC-V. Signed-off-by: Oleksii Kurochko Reviewed-by: Baptiste Le Duc --- Changes in v3: - Update the commit message. - Zero-initialize di, as decode_ldst_insn() expects it to start out zeroed. - Adjust to guest_gpr() taking the decoded instruction rather than a bare register number. - Don't change the prototype of emulate_store(): the stub takes a pointer to const already. --- Changes in v2: - Move the emulation code to the new arch/riscv/emulate.c, leaving traps.c with trap dispatch only. - Split the patch up: the instruction fetch and the mask/match chain now live in "xen/riscv: add helpers for decoding a trapped load or store" (struct decoded_insn, insn_fetch_faulted(), decode_ldst_insn(), guest_gpr(), advance_pc()), so only emulate_store() itself is left here. - Since the decoder is now shared with the load path, reject an encoding which is not a store (!di.is_write) explicitly; in v2 the mask/match chain was store-only and could not match a load. - Recognize the XLEN=3D64-only encodings by the guest's effective XLEN (guest_xlen()) rather than by Xen's own (CONFIG_RISCV_32). Besides those encodings simply being reserved on RV32, the compressed ones are ambiguo= us there: C.SD and C.FSW share an encoding, and likewise C.SDSP and C.FSWSP. - Read the source register through guest_gpr() instead of the GET_RS2()/GET_RS2S()/GET_RS2C() macros; which of the three register fields an encoding names is now decided by decode_ldst_insn(). - Take the faulting address from struct guest_fault, filled in by resolve_faulting_gpa(), rather than from the fault_addr parameter. - Drop the description of a fault taken while re-reading the trapped instruction: that code is now in the patch adding the decoding helpers, where a G-stage fault is reported to the guest as CAUSE_FETCH_ACCESS. - Update the commit message accordingly. --- --- xen/arch/riscv/emulate.c | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/xen/arch/riscv/emulate.c b/xen/arch/riscv/emulate.c index ff8cba7d5116..7ae3f438a726 100644 --- a/xen/arch/riscv/emulate.c +++ b/xen/arch/riscv/emulate.c @@ -454,7 +454,26 @@ static int emulate_load(const struct guest_fault *gf) =20 static int emulate_store(const struct guest_fault *gf) { - return -EOPNOTSUPP; + struct cpu_user_regs *regs =3D gf->regs; + mmio_info_t info =3D { .is_write =3D true }; + struct decoded_insn di =3D {}; + int rc; + + if ( insn_fetch_faulted(gf, &di) ) + return 0; + + if ( !decode_ldst_insn(&di, guest_xlen(regs)) || !di.is_write ) + return -EOPNOTSUPP; + + info.data =3D *guest_gpr(regs, &di); + + rc =3D do_mmio(&info, gf->gpa, di.len); + if ( rc ) + return rc; + + advance_pc(regs, di.insn_len); + + return 0; } =20 static void inject_access_fault(const struct guest_fault *gf) --=20 2.55.0 From nobody Fri Oct 23 15:32:28 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) client-ip=192.237.175.120; envelope-from=xen-devel-bounces@lists.xenproject.org; helo=lists.xenproject.org; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=pass(p=none dis=none) header.from=gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1790785540; cv=none; d=zohomail.com; s=zohoarc; b=iaQBdzILCdjGYQDSv1kjY9UxKUGLAB0vfTD8PGwcOHVkTEPF0r+5Z/1wAHe7vptanNTliDU9kMdvQLCx3sQEXenmxwlMoBUIPMBfV1c7LkRSxPjsACfW4SmEjsqD1SPI35bMhvzTZTl6tTL5E6hMnWa9ybKRDARm3aKtWuW8fNw= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1790785540; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=yPmng9jKZGj6nVECSBy4KvK2s0Y8gEQ54EyuBKvdWAM=; b=elWInSLF+vhYchP0tdh80Q/L29qqR4GCTu9kym1mtzvsd5M3z5vucWoYLslRrVb1j+hGL/WQVGzbYbnRfqlYd2oMgZix9EN8UoxVKTGM7UrrWNfalzz/xwE2vCKx0sT91ymb5OXPecVckKr8+BOzB4oVk6L4gJbVcArV8fL3ekY= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) by mx.zohomail.com with SMTPS id 1790785540589466.22165739036325; Wed, 30 Sep 2026 09:25:40 -0700 (PDT) Received: from list by lists.xenproject.org with outflank-mailman.1437569.1656607 (Exim 4.92) (envelope-from ) id 1xBx6g-00079u-FB; Wed, 30 Sep 2026 16:24:34 +0000 Received: by outflank-mailman (output) from mailman id 1437569.1656607; Wed, 30 Sep 2026 16:24:34 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1xBx6g-00078p-9k; Wed, 30 Sep 2026 16:24:34 +0000 Received: by outflank-mailman (input) for mailman id 1437569; Wed, 30 Sep 2026 16:24:31 +0000 Received: from mx.expurgate.net ([194.145.224.20]) by lists.xenproject.org with esmtp (Exim 4.92) id 1xBx6d-0006bj-I3 for xen-devel@lists.xenproject.org; Wed, 30 Sep 2026 16:24:31 +0000 Received: from mx.expurgate.net (helo=localhost) by mx.expurgate.net with esmtp id 1xBx6c-00GhY9-Um for xen-devel@lists.xenproject.org; Wed, 30 Sep 2026 18:24:30 +0200 Received: from [10.42.69.3] (helo=localhost) by localhost with ESMTP (eXpurgate MTA 0.9.1) (envelope-from ) id 6abd37b7-8faa-0a2a0a5109dd-0a2a4503edf2-20 for ; Wed, 30 Sep 2026 18:24:30 +0200 Received: from [74.125.225.140] (helo=mail-wm2-f12.google.com) by tlsNG-33051d.mxtls.expurgate.net with ESMTPS (eXpurgate 4.57.1) (envelope-from ) id 6abd37be-fae8-0a2a45030019-4a7de18ca154-3 for ; Wed, 30 Sep 2026 18:24:30 +0200 Received: by mail-wm2-f12.google.com with SMTP id 5b1f17b1804b1-49b912d3920so41824955e9.1 for ; Wed, 30 Sep 2026 09:24:30 -0700 (PDT) Received: from fedora (user-109-243-71-234.play-internet.pl. [109.243.71.234]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-4a01cd43e66sm14620485e9.2.2026.09.30.09.24.29 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 30 Sep 2026 09:24:29 -0700 (PDT) X-Outflank-Mailman: Message body and most headers restored to incoming version X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" Authentication-Results: eu.smtp.expurgate.cloud; dkim=pass header.s=20251104 header.d=gmail.com header.i="@gmail.com" header.h="Content-Transfer-Encoding:MIME-Version:References:In-Reply-To:Message-ID:Date:Subject:Cc:To:From" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1790785470; x=1791390270; darn=lists.xenproject.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=yPmng9jKZGj6nVECSBy4KvK2s0Y8gEQ54EyuBKvdWAM=; b=A+C3VPsgv4uff47yf7kkdcm/JV4eSdysbjLUXEhSXE5ituQZm/T5F6goPSi2zB18Nb hryW5wnfgEoPgp3GwD3OC8I+CE9olBrSpaVCjk+Ds+fjgfeDqKXv+DVAy2mSn2M6UH1G i+KezGsthSh2t7R3OlktepQi+Bu2Z/hw5VX+W2i8bcB9BTNfdnVvVMhC4nm7aiH2Df/K 6xhcfg6RJPfYcBgmjkvyRalJLClGW61TuecaHVASHYvsOwAmuh+dEZK3/aP+Fa9fnkOQ y3xhhOYh4/lP2aKEXSbArBiJ+gKIu1IMeR/iQX80DZXhDUx6uW6vxHNOHOROv3jGZevX 0BOg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1790785470; x=1791390270; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=yPmng9jKZGj6nVECSBy4KvK2s0Y8gEQ54EyuBKvdWAM=; b=U5MQ7S6pQf3awojF72CD7fRooL0HDp3nR+uhJbVuCnE+OlC3hOd5nH7XqN+YZsOn7n qslkm+KGFBNT/9N7oMtelwsR4oBpbPAbUZ64oPVkxvyAGYHXrMuBaBNUvNNIoZv08yTN cQWB5yOEsGhyI/wBGXpBaYR9pZuQTdBV4FxBRrqtrW1XuhDr6JtUG/HVIBvMRpLh4fuU Zw5CmFq9CgP8m0zxY2ncJNtdQJy3oYwk8Y9GytGI87WT1dVajnrGxGrbPNdNY0dqLtgP zmySmuUq4ibaUKK4dGFeYGYoLwCMEKsmPPFuLBi07hqzAb0SNmST1lEx+Uyb/mgh1GfX LuPA== X-Gm-Message-State: AFuF++mhShtn+rFfc9pO54CDYIsxinNkMRDZLnA3r5sbMuxohj/WgrUN X9kUiIjPg3WZc5EOTmLBEfoMyUlPBKMuTEG0xQAo4rW5YsaPVXHnaCwijA0OBQ== X-Gm-Gg: AYBFou32cD/E6sqJka6WFXVzwaCh/SVVPUde7Z1oa551G5mWDqEnWu/4iCOV1llIS80 eVF4GJMsuSQzuRbeEXhfMOG+CRBG8Rg590Rd0Y3JwhY+Cai4Q2JUovxBnEomlC/JEWZzJm7x/09 86KQ1ZccQFrd+HFD1qj/5rBzGiQdyJS9x3YAZQaPRH2XE4zlk0HjOrVkxOwMAoOmFQq9xpkTsKf 0eyYx4DWEYapbeLf0dD2R/LbvO6oQydBzJlgJociUnPJWHgP8ir36j7lEKatl4saBUbTsvMx0qR YeSMDQUGYhz710avO3ZOE7sa2doykLdEUtKDjZzFzQozQZ0C7YQFJfTldPGjObcJYQ0jC7jDhe7 XFGqfe+aBsb4v8wSdfhfStOeBs6P1Cs1ThkxRotJPCPYZucCWHBXEbv7UjjJ8pRRe4TQjO4sbqQ JGgm0nf4yOzCvmrOLbA4g6Ti8w7VV8dcHK1rLjseuJ7nHItJDEkRLoKYo0MgNjU/6AmZEQc3qGE EYpOaSzKfCaOBCiHRxRLxyTEdUBH03uD1WtuFbY X-Received: by 2002:a05:600c:3b1a:b0:49e:81db:4926 with SMTP id 5b1f17b1804b1-4a01aff3cdamr35109285e9.5.1790785470265; Wed, 30 Sep 2026 09:24:30 -0700 (PDT) From: Oleksii Kurochko To: xen-devel@lists.xenproject.org Cc: Romain Caritey , Baptiste Le Duc , Zheng Zhang , Oleksii Kurochko , Alistair Francis , Connor Davis , Andrew Cooper , Anthony PERARD , Michal Orzel , Jan Beulich , Julien Grall , =?UTF-8?q?Roger=20Pau=20Monn=C3=A9?= , Stefano Stabellini Subject: [PATCH v3 26/39] xen/riscv: introduce arch_move_irqs() Date: Wed, 30 Sep 2026 18:23:45 +0200 Message-ID: X-Mailer: git-send-email 2.55.0 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-purgate-ID: tlsNG-33051d/1790785470-75A814E9-DEF6315C/10/78276251493 X-purgate-type: spam X-purgate-size: 3955 X-ZohoMail-DKIM: pass (identity @gmail.com) X-ZM-MESSAGEID: 1790785542272158501 Content-Type: text/plain; charset="utf-8" When migrating a vCPU between pCPUs the hypervisor must also migrate the associated virtual interrupt state. arch_move_irqs() is the per-arch hook called by generic code to trigger that. Replace the static inline BUG_ON placeholder in asm/irq.h with a real implementation in intc.c dispatching through a new move_irqs vintc_ops callback. Wire it up in vAPLIC, which delegates to imsic_migrate_vcpu(), only a stub for now. Signed-off-by: Oleksii Kurochko Acked-by: Jan Beulich Reviewed-by: Baptiste Le Duc --- Changes in v3: - Update the commit message: drop the two last paragraphs as they are stale. - Add Acked-by: Jan Beulich . - Add Reviewed-by: Baptiste Le Duc . --- Changes in v2: - New patch. --- --- xen/arch/riscv/imsic.c | 5 +++++ xen/arch/riscv/include/asm/imsic.h | 2 ++ xen/arch/riscv/include/asm/intc.h | 3 +++ xen/arch/riscv/include/asm/irq.h | 5 +---- xen/arch/riscv/intc.c | 8 ++++++++ xen/arch/riscv/vaplic.c | 1 + 6 files changed, 20 insertions(+), 4 deletions(-) diff --git a/xen/arch/riscv/imsic.c b/xen/arch/riscv/imsic.c index d633f59db20d..c5fcdcf13b00 100644 --- a/xen/arch/riscv/imsic.c +++ b/xen/arch/riscv/imsic.c @@ -690,3 +690,8 @@ int __init vimsic_make_domu_dt_node(struct kernel_info = *kinfo, =20 return fdt_end_node(fdt); } + +void imsic_migrate_vcpu(struct vcpu *v) +{ + BUG_ON("unimplemented"); +} diff --git a/xen/arch/riscv/include/asm/imsic.h b/xen/arch/riscv/include/as= m/imsic.h index 5463fb4c31b2..22ce90e2e9b3 100644 --- a/xen/arch/riscv/include/asm/imsic.h +++ b/xen/arch/riscv/include/asm/imsic.h @@ -99,4 +99,6 @@ int vimsic_make_domu_dt_node(struct kernel_info *kinfo, u= nsigned int *phandle); void imsic_ctxt_switch_from(struct vcpu *p); void imsic_ctxt_switch_to(struct vcpu *n); =20 +void imsic_migrate_vcpu(struct vcpu *v); + #endif /* ASM_RISCV_IMSIC_H */ diff --git a/xen/arch/riscv/include/asm/intc.h b/xen/arch/riscv/include/asm= /intc.h index 59e12f3d3c6d..a22b46dae06c 100644 --- a/xen/arch/riscv/include/asm/intc.h +++ b/xen/arch/riscv/include/asm/intc.h @@ -70,6 +70,9 @@ struct vintc_ops { =20 /* Restore vINTC state of the vCPU being switched in */ void (*ctxt_switch_to)(struct vcpu *n); + + /* Move interrupts of vCPU to a different pCPU */ + void (*move_irqs)(struct vcpu *v); }; =20 struct vintc { diff --git a/xen/arch/riscv/include/asm/irq.h b/xen/arch/riscv/include/asm/= irq.h index 57e814d90cf4..311af1d16fbb 100644 --- a/xen/arch/riscv/include/asm/irq.h +++ b/xen/arch/riscv/include/asm/irq.h @@ -41,10 +41,7 @@ struct irq_desc *irq_to_desc(unsigned int irq); struct cpu_user_regs; struct dt_device_node; =20 -static inline void arch_move_irqs(struct vcpu *v) -{ - BUG_ON("unimplemented"); -} +void arch_move_irqs(struct vcpu *v); =20 int platform_get_irq(const struct dt_device_node *device, int index); =20 diff --git a/xen/arch/riscv/intc.c b/xen/arch/riscv/intc.c index 53ba2b04ab53..a51eec251563 100644 --- a/xen/arch/riscv/intc.c +++ b/xen/arch/riscv/intc.c @@ -192,3 +192,11 @@ void vintc_ctxt_switch_to(struct vcpu *n) =20 ops->ctxt_switch_to(n); } + +/* Move vCPU's IRQs from one pCPU to another */ +void arch_move_irqs(struct vcpu *v) +{ + const struct vintc_ops *ops =3D v->domain->arch.vintc->ops; + + ops->move_irqs(v); +} diff --git a/xen/arch/riscv/vaplic.c b/xen/arch/riscv/vaplic.c index 4d87fdb5be42..601b79aae430 100644 --- a/xen/arch/riscv/vaplic.c +++ b/xen/arch/riscv/vaplic.c @@ -462,6 +462,7 @@ static const struct vintc_ops vintc_ops =3D { */ .ctxt_switch_from =3D imsic_ctxt_switch_from, .ctxt_switch_to =3D imsic_ctxt_switch_to, + .move_irqs =3D imsic_migrate_vcpu, }; =20 int domain_vaplic_init(struct domain *d) --=20 2.55.0 From nobody Fri Oct 23 15:32:28 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) client-ip=192.237.175.120; envelope-from=xen-devel-bounces@lists.xenproject.org; helo=lists.xenproject.org; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=pass(p=none dis=none) header.from=gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1790785541; cv=none; d=zohomail.com; s=zohoarc; b=XQjt896cdYOlCsoi15g3aSj3jOWuWHCiF6sNq6HmZO9eSoe/oZoIsGzWPAv9jOB9LejhYozyYgJcpiiRP3VYZujMCn8uhAp9YECbp10SbFnsyxbmtdTDDgPhQNrROTDKyXFJ2wNChu5RI1a1xvQuA0bVY0jNH71gyd5Ik6cflro= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1790785541; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=d/jp8PMzGlGGiWG+GmHZRyZuEBmMNWGF6eFnVc/o6uo=; b=dd3BQEQTdccBgleWPIV1D1JxngHyZcMxbxzLrVTW3WvKsTBW6h48k/BLPj1aGcSLz84tRIaJHU6xP+Px7PG7wGFmTm6h2i+fIvT1ILJ+ofAmBqqVdfgasjxfl36LEyh3Ti6iQAZnLxt2/wR9JPg9ARgogwgmGlk8/B2Iiitpf/A= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) by mx.zohomail.com with SMTPS id 1790785541977724.3953306837548; Wed, 30 Sep 2026 09:25:41 -0700 (PDT) Received: from list by lists.xenproject.org with outflank-mailman.1437571.1656615 (Exim 4.92) (envelope-from ) id 1xBx6i-0007JE-1Q; Wed, 30 Sep 2026 16:24:36 +0000 Received: by outflank-mailman (output) from mailman id 1437571.1656615; Wed, 30 Sep 2026 16:24:35 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1xBx6h-0007Hy-2z; Wed, 30 Sep 2026 16:24:35 +0000 Received: by outflank-mailman (input) for mailman id 1437571; Wed, 30 Sep 2026 16:24:32 +0000 Received: from mx.expurgate.net ([194.145.224.10]) by lists.xenproject.org with esmtp (Exim 4.92) id 1xBx6e-0006l7-Fj for xen-devel@lists.xenproject.org; Wed, 30 Sep 2026 16:24:32 +0000 Received: from mx.expurgate.net (helo=localhost) by mx.expurgate.net with esmtp id 1xBx6d-006Nvr-Sk for xen-devel@lists.xenproject.org; Wed, 30 Sep 2026 18:24:31 +0200 Received: from [10.42.69.7] (helo=localhost) by localhost with ESMTP (eXpurgate MTA 0.9.1) (envelope-from ) id 6abd37a8-2eae-0a2a0a5409dd-0a2a4507c4d4-34 for ; Wed, 30 Sep 2026 18:24:31 +0200 Received: from [74.125.225.141] (helo=mail-wm2-f13.google.com) by tlsNG-ef75cf.mxtls.expurgate.net with ESMTPS (eXpurgate 4.57.1) (envelope-from ) id 6abd37bf-b4ea-0a2a45070019-4a7de18dd99e-3 for ; Wed, 30 Sep 2026 18:24:31 +0200 Received: by mail-wm2-f13.google.com with SMTP id 5b1f17b1804b1-49b912d391aso42605905e9.2 for ; Wed, 30 Sep 2026 09:24:31 -0700 (PDT) Received: from fedora (user-109-243-71-234.play-internet.pl. [109.243.71.234]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-4a01cd43e66sm14620485e9.2.2026.09.30.09.24.30 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 30 Sep 2026 09:24:31 -0700 (PDT) X-Outflank-Mailman: Message body and most headers restored to incoming version X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" Authentication-Results: eu.smtp.expurgate.cloud; dkim=pass header.s=20251104 header.d=gmail.com header.i="@gmail.com" header.h="Content-Transfer-Encoding:MIME-Version:References:In-Reply-To:Message-ID:Date:Subject:Cc:To:From" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1790785471; x=1791390271; darn=lists.xenproject.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=d/jp8PMzGlGGiWG+GmHZRyZuEBmMNWGF6eFnVc/o6uo=; b=TENrT3XYn7YGuR7i4dRvC2VhLVcPIxTFEGEVMOo9yWMCfTyPX4jGVWs+uImHxDhtoU 7nZ+yD2JKflzxDwH8k27GIC7kHZnmeQ1MdvHEx+1ZHbRoqdVM9g+4GM4qvIvVD8wAeBi CciJdFwn6Zmu/p9g7yCpuiqw4xGbQYLbG+pVmPGgZoLXpYDjq5SjfpMLNznYQmxwMYuy fDEwlh3t7ND6UyMTFmyMmwSIuWc9F5YQwMtHabJBBNmwz0KDBWDwffqkdLWn4y4Avo+k 0u5SWM1MZtW51AcAWaL52gxw82yxA9ttb9nbVoD+aJyjnY7rfyIKlYZjZx+1AwVWQLgx vf4w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1790785471; x=1791390271; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=d/jp8PMzGlGGiWG+GmHZRyZuEBmMNWGF6eFnVc/o6uo=; b=ktNb5ieT65eUmsA9nh4Uadd6EP8BTPqOWvSGA4bIlxLprnzsm+BAVpDPb6PSO7jHGS Tfi65Evk4Vwrhml2Ic7FJ0DH2hLl6OOkQSaRIPH5zLigee14io72Wf9a9JzCm2KIY2qo QWrp/bEsXG1tZd2MQfpmzdBJsPVj/u0JSKR0yp3HpqIht4VWplW9bm/jR1I6cV5IHeQt o0JnAkOOyA0S8PWU3q74HEARGA/G0H1qqoTbtrPtVLotRkuHO+wjyxcwQKXTNy16mQw0 ASivkNIo4vJHQQjWLogglGM3HqvRg4DIKe7ArLqLS7M74zgGt7DXCC9pA/5SxEsQ3yNz Sh0g== X-Gm-Message-State: AFuF++kuNhY08glw3RCFZ0V6z3sxa7PeL+sVg9nfhzXzx2xWu+j+JzY0 hlxY9MKFrZCXypEGXzny3hrMY0oM1hZbWBGGnTihPFwEX+GaaamiYR43OS9orQ== X-Gm-Gg: AYBFou3OaELVrnj3FlF2bNwToq2vhzKkvAwlqlKU0S3pz3mzXLsF/7CgY/YEWLZPFcS CPYNCGUJhBkAIsi7e7ulxam1vsD71ZDBWkznNRR7KRf8/of3XdoNj4rL4iCgE/2ci9YbuxOk0mt O1wKWx4fYPjN0SRoCcNS/jte4P2LNw1m6LLHrSrWVL3eIV0RKXqukFf6k+oesM4kqN5Y6/F6eFV dIokSLNDJ2ycO47cpjUlKMArLmJSXVcv4fQDTj19iAiV8gu+NxhK5hVkTETaU2LctZFh/vNGn8r P3hJYjrqiuQCb8Ms3cDRKE9QbdXauZ6SmYNgySL5tb//ayoHzh9ycr+OXwGQoCo2OBbx5yytTTg R0Cu1b+q4lH8/28vUK5NKu0usFgLJVoSGckqGWIF158cEUzfbhwvTMZ2LakSiY67w8BmiFZCedd VQb1/CTVPeDWGkX2i0UXJ6zf+tBSZvC3575hTnBUO7p+Y+k8fLPJFuxm/kKHYAW0wf2S2S1Elz1 U7Uzg/kJ/oGF22AxHeXuy/n5HJFL+HTC/+vVI8KSkUo8U/LlTowKtunPufG4Q== X-Received: by 2002:a05:600c:46cf:b0:4a0:151e:f744 with SMTP id 5b1f17b1804b1-4a01b01bb16mr34637825e9.22.1790785471263; Wed, 30 Sep 2026 09:24:31 -0700 (PDT) From: Oleksii Kurochko To: xen-devel@lists.xenproject.org Cc: Romain Caritey , Baptiste Le Duc , Zheng Zhang , Oleksii Kurochko , Alistair Francis , Connor Davis , Andrew Cooper , Anthony PERARD , Michal Orzel , Jan Beulich , Julien Grall , =?UTF-8?q?Roger=20Pau=20Monn=C3=A9?= , Stefano Stabellini Subject: [PATCH v3 27/39] xen/riscv: handle the case when no vCPU migration is needed Date: Wed, 30 Sep 2026 18:23:46 +0200 Message-ID: X-Mailer: git-send-email 2.55.0 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-purgate-ID: tlsNG-ef75cf/1790785471-362C4AE4-C5B3E5B0/10/73395122804 X-purgate-type: spam X-purgate-size: 2084 X-ZohoMail-DKIM: pass (identity @gmail.com) X-ZM-MESSAGEID: 1790785542252158500 Content-Type: text/plain; charset="utf-8" The scheduler moves a vCPU's interrupts (arch_move_irqs(), i.e. imsic_migrate_vcpu()) ahead of context_switch() whenever the unit is picked up by a pCPU other than the one it was assigned to, which can already happen for a freshly created vCPU on its very first run. No IMSIC h/w interrupt file has been mapped for such a vCPU yet, so there is nothing to migrate: return early while its last_cpu is still CPU_NONE, i.e. while it hasn't run. Keep the BUG_ON() at the end of the function until imsic_migrate_vcpu() is fully implemented, to avoid ending up with a vCPU which isn't fully migrated to the new IMSIC interrupt file. Signed-off-by: Oleksii Kurochko Reviewed-by: Baptiste Le Duc --- Changes in v3: - Reword the last paragraph of the commit message: the BUG_ON() is already present in imsic_migrate_vcpu() before this patch, so it is kept rather than added. - Check last_cpu against CPU_NONE instead of NR_CPUS, as that is the value a vCPU which never ran holds now. - Describe in the commit message how imsic_migrate_vcpu() can be called for a vCPU which never ran, rather than referring to where the IMSIC interrupt file gets attached. --- Changes in v2: - New patch. --- --- xen/arch/riscv/imsic.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/xen/arch/riscv/imsic.c b/xen/arch/riscv/imsic.c index c5fcdcf13b00..2f0bb29ae639 100644 --- a/xen/arch/riscv/imsic.c +++ b/xen/arch/riscv/imsic.c @@ -693,5 +693,15 @@ int __init vimsic_make_domu_dt_node(struct kernel_info= *kinfo, =20 void imsic_migrate_vcpu(struct vcpu *v) { + /* + * The scheduler can mark a freshly created vCPU's unit as migrated and + * invoke this before the vCPU has ever run (see the migrated branch in + * schedule()). No need to do migration for such vCPUs as they aren't = fully + * initialized (for example, context_switch() will be called after + * imsic_migrate_vcpu()). + */ + if ( v->arch.last_cpu =3D=3D CPU_NONE ) + return; + BUG_ON("unimplemented"); } --=20 2.55.0 From nobody Fri Oct 23 15:32:28 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) client-ip=192.237.175.120; envelope-from=xen-devel-bounces@lists.xenproject.org; helo=lists.xenproject.org; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=pass(p=none dis=none) header.from=gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1790785544; cv=none; d=zohomail.com; s=zohoarc; b=YW9W46FNtuTckdY7pF/68n1755+GnQ+0NeKHsZaq1WDMdZKB0LBRzsSn//zquyIWxX0TExbog9ed5tCq/Q575017HdGGriS449JQ+C+cKHG2j1VDeTrbYGIq3SrdAoQh6FSw18DpzQP3U+Y9wAnqsGUp4ipbRa3GeSBdHaPmEv4= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1790785544; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=LTNgtcZKRvFf304r+X/UGRaqmuABZGd+r6Pfp0L3A5A=; b=Es0XM4JEfBT0HhuX0hjvGpF6ylBYE3EtIJpRCDfrWv6NFfXqidHM3s6/qPpv0VkWV/gR+2kpzjVbn1iaOz8JA2vFdF0o/sTPKaG7hGA1aGB7As2g0sFuOFuCVBDahTFMYvJGsgD3dVlLMEcyVj8Ds+sJXua1yuLXqpFmyAqHw80= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) by mx.zohomail.com with SMTPS id 1790785544899175.54826291811742; Wed, 30 Sep 2026 09:25:44 -0700 (PDT) Received: from list by lists.xenproject.org with outflank-mailman.1437575.1656631 (Exim 4.92) (envelope-from ) id 1xBx6l-00080v-QP; Wed, 30 Sep 2026 16:24:39 +0000 Received: by outflank-mailman (output) from mailman id 1437575.1656631; Wed, 30 Sep 2026 16:24:39 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1xBx6k-0007xU-N6; Wed, 30 Sep 2026 16:24:38 +0000 Received: by outflank-mailman (input) for mailman id 1437575; Wed, 30 Sep 2026 16:24:35 +0000 Received: from mx.expurgate.net ([194.145.224.20]) by lists.xenproject.org with esmtp (Exim 4.92) id 1xBx6h-0007GZ-5O for xen-devel@lists.xenproject.org; Wed, 30 Sep 2026 16:24:35 +0000 Received: from mx.expurgate.net (helo=localhost) by mx.expurgate.net with esmtp id 1xBx6g-00GhYY-Hi for xen-devel@lists.xenproject.org; Wed, 30 Sep 2026 18:24:34 +0200 Received: from [10.42.69.12] (helo=localhost) by localhost with ESMTP (eXpurgate MTA 0.9.1) (envelope-from ) id 6abd37c1-bab6-0a2a0a5309dd-0a2a450c92c8-2 for ; Wed, 30 Sep 2026 18:24:34 +0200 Received: from [74.125.225.103] (helo=mail-wr2-f39.google.com) by tlsNG-d25034.mxtls.expurgate.net with ESMTPS (eXpurgate 4.57.1) (envelope-from ) id 6abd37c2-f479-0a2a450c0019-4a7de167800b-3 for ; Wed, 30 Sep 2026 18:24:34 +0200 Received: by mail-wr2-f39.google.com with SMTP id ffacd0b85a97d-48af929e59dso1300871f8f.3 for ; Wed, 30 Sep 2026 09:24:34 -0700 (PDT) Received: from fedora (user-109-243-71-234.play-internet.pl. [109.243.71.234]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-4a01cd43e66sm14620485e9.2.2026.09.30.09.24.31 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 30 Sep 2026 09:24:32 -0700 (PDT) X-Outflank-Mailman: Message body and most headers restored to incoming version X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" Authentication-Results: eu.smtp.expurgate.cloud; dkim=pass header.s=20251104 header.d=gmail.com header.i="@gmail.com" header.h="Content-Transfer-Encoding:MIME-Version:References:In-Reply-To:Message-ID:Date:Subject:Cc:To:From" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1790785474; x=1791390274; darn=lists.xenproject.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=LTNgtcZKRvFf304r+X/UGRaqmuABZGd+r6Pfp0L3A5A=; b=NGfwc8sxkMYUUv5yDP6loty/W5NHya1HmHHbVI4LV9y6DOfGYM5UgAOqAdpZGd3v/X dnjBScVRjS78eMdz6faAqL73wtX82Sa0Hlql5KkrYGxdckmEeOCAlus87W9TzrErd0iA u519f1jub00VGuPX/8yfziJK4lmVYQEWE4You+F3iTWqkrYJoYd+LbRUqDUcR5UI9Mc0 JJNV7z9EHboFsHRVMsw1I4iTwUW/SgTK4+RAmj6jStk6N2AETLGrVe8XrjWGWzEx+TxX TbbLsc9sbGAtomrORveQhEnaLanSqkV5O4fHAfUomzlT77T3iqi9dLZkeIyEO0sMOAmz dziQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1790785474; x=1791390274; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=LTNgtcZKRvFf304r+X/UGRaqmuABZGd+r6Pfp0L3A5A=; b=jfnxMvvl5asOpzeG2gsQxKUCt5ol5ymBtBET5P4t3VByJ7hLztVvae4M2kWNrDTS3I h1qrNo28/DJLQidZ474aWsctwPqHEwErvsg/A3/3gPJXIBwvEswP3Ez74lLxealRZiT5 EOjYX9RyH9OptXZ4+Gk92plCcu77KYvuUxYMvcAsbhzJm6HMj4XAig1V0Lm5XlTgET78 u+8yw+tGgpAPh6OwX+jn4Wdm4eLkEtxPaAmpW7+aVE0WMLS+qogu4nc9oi102QBPoZHE R3PJCpOpZQjZRvBbJqnylOYtk6jIi8v6v2c/omMpoofwuiDKeRv8RfFRQdesS8RuHTrW NV+A== X-Gm-Message-State: AFuF++kcUdM4oj+DCUFwakFsTVTudMw3xL+k20RPCs96tW2RjulLMQGX JwsMRskklqxhZcxT0DynEouPjNoJKsP/HH39g6roergmpOBh/blF/4XCRCFArA== X-Gm-Gg: AYBFou049m3nu8eg+qSN6X6UCAFGQm/XEMbN+rljxRs4hHluQiwYToSDB6jm0jzkqZJ U/PMvB7YETnOmviWI+Sj0+RrFmYhSeHopk7bqF/MZmeG+LmpUUVf5zWUOdczIVr1dfMIAyvajQG m7BKYU6k8ZsQSIwrbIBc7lGc9VC8v12x5sKI1aTbZAV1oD6Dk44J0SU3Hc01/mXyjiXeEpBibpY +CTXdD/x4Z5iI4Nom0mvXGCy9mTBTBiiB6HVu20K8ng1WKxGk+OUCQBz7wifd4CYpvRD3JH52EH KelZgOQJxJRaYMShwwK0OqOUK6wjRF1EobqNUA5Mi4yMVsS15ZANIUm9TwhmJYOg5JP4NosjKaX vo9RePj0W2uUpYOXURaz8ItgBXAflG5qChrB+Hlvj0ZKgDwt94ZRnArUNuOjofuUdH/1D+0bEoM rSjuIqgRAgwZMR7JS3mRTqgdnex4YiYiABOT10Rs1CnyphBiYTtlVA/u58xjQj6QlBRlpqxcFcL 5htBRA4YVYhCXgNdxLY7yKylGoeXxMvozPN/DSg X-Received: by 2002:a05:600c:350d:b0:49f:d087:6526 with SMTP id 5b1f17b1804b1-4a01b12d37amr31705665e9.34.1790785472357; Wed, 30 Sep 2026 09:24:32 -0700 (PDT) From: Oleksii Kurochko To: xen-devel@lists.xenproject.org Cc: Romain Caritey , Baptiste Le Duc , Zheng Zhang , Oleksii Kurochko , Alistair Francis , Connor Davis , Andrew Cooper , Anthony PERARD , Michal Orzel , Jan Beulich , Julien Grall , =?UTF-8?q?Roger=20Pau=20Monn=C3=A9?= , Stefano Stabellini Subject: [PATCH v3 28/39] xen/riscv: introduce vaplic_reconfigure_target() Date: Wed, 30 Sep 2026 18:23:47 +0200 Message-ID: X-Mailer: git-send-email 2.55.0 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-purgate-ID: tlsNG-d25034/1790785474-032D8A5B-BF2A2EB6/10/73395122804 X-purgate-type: spam X-purgate-size: 7028 X-ZohoMail-DKIM: pass (identity @gmail.com) X-ZM-MESSAGEID: 1790785546373158501 Content-Type: text/plain; charset="utf-8" When a vCPU is migrated to a different pCPU, its IMSIC guest interrupt file changes. Any APLIC interrupt previously configured to deliver an MSI to the old interrupt file must be retargeted to the new one. Implement vaplic_reconfigure_target() to walk the interrupts allocated to the domain and rewrite the APLIC TARGET register of every one whose guest-programmed target names the vCPU, building the new value with aplic_msi_target_gen(). Each source is rewritten under its vaplic_source lock, so that it can't race with a guest write of the same target register. Nothing calls it yet. Also assert in aplic_msi_target_gen() that the physical APLIC is in MSI delivery mode, which all of its callers rely on. Signed-off-by: Oleksii Kurochko --- Changes in v3: - Update the commit message. - Replace aplic_reconfigure_target() in aplic.c with vaplic_reconfigure_target() in vaplic.c: the sources to retarget are chosen from the guest's view of the target registers, decoded by the new vaplic_target_decode_vcpu(), instead of by matching the h/w registers against the old guest file id and pCPU, which drops the old_guest_file_id and old_cpu parameters. Each source is rewritten under its vaplic_source lock, so it can't race with a guest write of the same target register. - Hold vsfile_lock for reading while retargeting, as aplic_msi_target_gen() requires. Lock order is the vaplic_source lock, then vsfile_lock, then aplic.lock (taken by aplic_hw_write_reg()). - Replace the BUG_ON() on MSI delivery mode with an ASSERT() in aplic_msi_target_gen(), so that none of its callers can miss it; direct delivery mode isn't supported, so there's no way to get there in release builds either. - Update the comment above aplic_msi_target_gen() about why vsfile_lock has to be held. --- Changes in v2: - New patch. --- --- xen/arch/riscv/aplic.c | 12 +++++- xen/arch/riscv/include/asm/vaplic.h | 3 ++ xen/arch/riscv/vaplic.c | 58 ++++++++++++++++++++++++++++- 3 files changed, 71 insertions(+), 2 deletions(-) diff --git a/xen/arch/riscv/aplic.c b/xen/arch/riscv/aplic.c index 60f5f239c394..283e5d6046a6 100644 --- a/xen/arch/riscv/aplic.c +++ b/xen/arch/riscv/aplic.c @@ -128,7 +128,10 @@ static unsigned long aplic_hart_index(unsigned int cpu) /* * v->processor can't be used here: during a migration it names the new pC= PU * before the interrupt file is moved there. The caller has to hold - * vsfile_lock until the result is written to the h/w. + * vsfile_lock, so that the guest file id and the pCPU owning it are read = as + * a consistent pair. A value built from the old file just before a migrat= ion + * publishes the new one isn't lost: vaplic_reconfigure_target() runs after + * the publication and rewrites every source targeting the vCPU. */ uint32_t aplic_msi_target_gen(const struct vcpu *v, uint32_t base_val) { @@ -139,6 +142,13 @@ uint32_t aplic_msi_target_gen(const struct vcpu *v, ui= nt32_t base_val) ASSERT(rw_is_locked(&vimsic_state->vsfile_lock)); ASSERT(vimsic_state->vsfile_cpu < NR_CPUS); =20 + /* + * The callers rely on the physical APLIC being in MSI delivery mode. + * Checking that here rather than in each of them means none can be + * missed should direct delivery mode ever be supported. + */ + ASSERT(aplic_msi_mode()); + hart_index =3D aplic_hart_index(vimsic_state->vsfile_cpu); =20 base_val &=3D APLIC_TARGET_EIID; diff --git a/xen/arch/riscv/include/asm/vaplic.h b/xen/arch/riscv/include/a= sm/vaplic.h index 3a555742bbe0..3cc69a3c8847 100644 --- a/xen/arch/riscv/include/asm/vaplic.h +++ b/xen/arch/riscv/include/asm/vaplic.h @@ -17,6 +17,7 @@ #include =20 struct domain; +struct vcpu; =20 #define to_vaplic(d) container_of((d)->arch.vintc, struct vaplic, vintc) =20 @@ -50,4 +51,6 @@ struct vaplic { int domain_vaplic_init(struct domain *d); void domain_vaplic_deinit(struct domain *d); =20 +void vaplic_reconfigure_target(const struct vcpu *v); + #endif /* ASM__RISCV__VAPLIC_H */ diff --git a/xen/arch/riscv/vaplic.c b/xen/arch/riscv/vaplic.c index 601b79aae430..74f470ef3e52 100644 --- a/xen/arch/riscv/vaplic.c +++ b/xen/arch/riscv/vaplic.c @@ -52,6 +52,62 @@ static uint32_t vaplic_target_read(const struct domain *= d, unsigned int irqn) return read_atomic(&vaplic->regs.sources[irqn].target); } =20 +/* Decode the target vCPU from a TARGET snapshot (NULL if none). */ +static struct vcpu *vaplic_target_decode_vcpu(const struct domain *d, + uint32_t target) +{ + unsigned int hart_idx =3D MASK_EXTR(target, APLIC_TARGET_HART_IDX); + + /* + * Skip a source whose EIID is 0, e.g. one still holding its reset + * value: interrupt identity 0 isn't valid at any IMSIC interrupt file, + * so such a source delivers nothing and needs no retargeting. + * The hart index range check is only a guard: the write path refuses = to + * record values with an out-of-range hart index. + */ + if ( !(target & APLIC_TARGET_EIID) || hart_idx >=3D d->max_vcpus ) + return NULL; + + return d->vcpu[hart_idx]; +} + +void vaplic_reconfigure_target(const struct vcpu *v) +{ + struct domain *d =3D v->domain; + struct vaplic *vaplic =3D to_vaplic(d); + struct vimsic_state *vimsic_state =3D v->arch.vimsic_state; + unsigned int irqn; + + bitmap_for_each ( irqn, d->arch.vintc->used_irqs, d->arch.vintc->nr_vi= rqs ) + { + struct vaplic_source *src =3D &vaplic->regs.sources[irqn]; + unsigned long flags; + uint32_t target; + + /* APLIC interrupt sources start from 1, there is no source 0. */ + if ( !irqn ) + continue; + + spin_lock_irqsave(&src->lock, flags); + + target =3D read_atomic(&src->target); + + if ( vaplic_target_decode_vcpu(d, target) =3D=3D v ) + { + /* + * IRQs are already off under src->lock so no need for *_irqsa= ve + * here. + */ + read_lock(&vimsic_state->vsfile_lock); + aplic_hw_write_reg(offsetof(struct aplic_regs, target[irqn - 1= ]), + aplic_msi_target_gen(v, target)); + read_unlock(&vimsic_state->vsfile_lock); + } + + spin_unlock_irqrestore(&src->lock, flags); + } +} + static inline uint32_t generate_auth_mask(const struct domain *currd, unsigned int word_idx) { @@ -282,7 +338,7 @@ static bool vaplic_emulate_store(const struct vcpu *cur= r, paddr_t addr, =20 /* * src->lock keeps the stored copy and the h/w register updated - * as a pair. + * as a pair against vaplic_reconfigure_target(). */ spin_lock_irqsave(&src->lock, flags); =20 --=20 2.55.0 From nobody Fri Oct 23 15:32:28 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) client-ip=192.237.175.120; envelope-from=xen-devel-bounces@lists.xenproject.org; helo=lists.xenproject.org; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=pass(p=none dis=none) header.from=gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1790785549; cv=none; d=zohomail.com; s=zohoarc; b=kPcrsbNNXyCeBwX/MK/VWizoMpIdsoDnFddMw2oTbiMTwFjoLt8HpHrpHD2pH0M1ls9xmyRqYNrsCES8LE/b4J0r0HZ34N9kxcnPylDCDrFibQi3sUABOCq7PLr7YzDpEhySrnvMzudomTKJxjkSoNHmOoy7/d7nVVxf5zTRqEw= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1790785549; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=GGo8JiaU4BGz4uAdTLdDhy5gCB3LLQOQjuYwzTzEnoI=; b=jJTHt42raNMkwvky5WXTVdAsqHKSepiW0mY0wiTrIlvQtB4YBpsVIraevBKSd/kNj9AyDbP3SLlLIEXHOArnAfjIrsiPXpgJC7VZuP+w/qO5EGXppXzEjYOEWzCv5vw/bM14RimPqDfRYGcJvE7AtVQURxnbYUNie9tRsQqysvQ= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) by mx.zohomail.com with SMTPS id 1790785549409497.99905079203495; Wed, 30 Sep 2026 09:25:49 -0700 (PDT) Received: from list by lists.xenproject.org with outflank-mailman.1437573.1656625 (Exim 4.92) (envelope-from ) id 1xBx6k-0007nm-JP; Wed, 30 Sep 2026 16:24:38 +0000 Received: by outflank-mailman (output) from mailman id 1437573.1656625; Wed, 30 Sep 2026 16:24:38 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1xBx6j-0007lM-Qx; Wed, 30 Sep 2026 16:24:37 +0000 Received: by outflank-mailman (input) for mailman id 1437573; Wed, 30 Sep 2026 16:24:35 +0000 Received: from mx.expurgate.net ([194.145.224.20]) by lists.xenproject.org with esmtp (Exim 4.92) id 1xBx6g-0007Bo-PU for xen-devel@lists.xenproject.org; Wed, 30 Sep 2026 16:24:34 +0000 Received: from mx.expurgate.net (helo=localhost) by mx.expurgate.net with esmtp id 1xBx6g-00GhY9-5f for xen-devel@lists.xenproject.org; Wed, 30 Sep 2026 18:24:34 +0200 Received: from [10.42.69.3] (helo=localhost) by localhost with ESMTP (eXpurgate MTA 0.9.1) (envelope-from ) id 6abd37b7-8faa-0a2a0a5109dd-0a2a4503edf2-26 for ; Wed, 30 Sep 2026 18:24:34 +0200 Received: from [74.125.225.140] (helo=mail-wm2-f12.google.com) by tlsNG-33051d.mxtls.expurgate.net with ESMTPS (eXpurgate 4.57.1) (envelope-from ) id 6abd37c2-fae8-0a2a45030019-4a7de18cadb0-3 for ; Wed, 30 Sep 2026 18:24:34 +0200 Received: by mail-wm2-f12.google.com with SMTP id 5b1f17b1804b1-49fff6f0f87so28363315e9.3 for ; Wed, 30 Sep 2026 09:24:34 -0700 (PDT) Received: from fedora (user-109-243-71-234.play-internet.pl. [109.243.71.234]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-4a01cd43e66sm14620485e9.2.2026.09.30.09.24.32 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 30 Sep 2026 09:24:33 -0700 (PDT) X-Outflank-Mailman: Message body and most headers restored to incoming version X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" Authentication-Results: eu.smtp.expurgate.cloud; dkim=pass header.s=20251104 header.d=gmail.com header.i="@gmail.com" header.h="Content-Transfer-Encoding:MIME-Version:References:In-Reply-To:Message-ID:Date:Subject:Cc:To:From" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1790785473; x=1791390273; darn=lists.xenproject.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=GGo8JiaU4BGz4uAdTLdDhy5gCB3LLQOQjuYwzTzEnoI=; b=k6fqbtpux/NDhRVRKsMn28O/hV2gEz7tv9KgY47imlYF+EOFCYMCa7+CNoaqoldRTI kd2yrJ3oQuRAUk6+MwdXNjRlYYx7Ub3BpW2eATAiiq2t/o9NBodPj7qGXToUvXlGe/GV rzaI9RkjZWJ665JFmRvUjS89v58En9azA1ZoE7puwBQW1K2tFLnA37Pr3lBCNbEcm97Q cpm5CaJHtiWgiR9KqRJTyUiJDI09Wdiu+J+AHW+st18YkaqUgnnrpcPeVA3rdTUr677m M3M2z20ux1fZH3AL61cY8FIOviMDy4AaObrOl7gnR44vD0e+b9WOnkoxPO1Tz3x/cA2E pNxw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1790785473; x=1791390273; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=GGo8JiaU4BGz4uAdTLdDhy5gCB3LLQOQjuYwzTzEnoI=; b=FWjTvmS+4Px1YNerx3fmPs+Y8SSjhJx1FFQixwhw3fln1AhSipHpeI5KZ2HiSQnxaA dTgpndJ+i0teupRf4Zm8gTrs2Lc6W/CKxDorGPD6jli+3ctnxus4h+ILkuoPLvzuselL fzhzEDuA25XH8ZdHmVmyyq8urobLHEaFgTHBgs+JoalDbI+9i/focN8uf3xOq2rk+EYU ULA/vTelIwI859VHs8xCh2XDAxwlNCIDV4/nNl62Ddk6ErXd+PeQEVBuDb66Pnnq6yDd lR20yHhaP5Dcu0PY3MKRzXqfsw2Etl4RqxagcOsUFydJGP8/Prf9NHVg25PztRqPTCTn 7sWw== X-Gm-Message-State: AFuF++kvzxcDj/erxjx3fQ8AR0xsAt/qDns7S2+BwOg618+r0IvIPFhR sA7VWkzWl6E7RDqvGsUxavk8Sb8+uW4g9uRwyJ4tCzZQdiqVGwrCD2fA9FjDww== X-Gm-Gg: AYBFou2Pw3WSKipqugnckOEEcZIwywCthuAjFq3+dkQV4Ft55lVV8Mr/bnMBPq+mfqX MX+WGZ0dl7rNdVT+ZW5ElmDZTM6eHpKgsqCmaPdIhbMLfRGRakWNuVOTPEPWP2/agOYQnqCfQOT G0e+TeMhiRj61RqKi8H00qsvwo1D61x9afxMGmjrzQ/Cqf1YCH8SHZCRJazBcVK44ydAAet2jQe 7MWmiko3U3/PDaQA5ZCMDnyvyDvOX6ycuoQr2PH9D2GNdlaXx8HaLUYV5bgsoMu5XfoyU3rnLv/ zO3RgvkH2GbDkLb/xRUDKcn//fA5xDvPztV8wCr5fdVmU32T/nIDCiimc9hLpsv8jXwk2WT/Tac Tb3ImFdC/swpPmStpOf4VtZQ2vLcqqjio1DfCLW5X8Hmv9Xk6xwcGVCehaDbJKtS7TzpZsIRBiM kiIcFK4Gqz88ttZXum9wzYrd/kjH9WCf/+4BQ6rpM9T+77qucBhwCT3N/MC0ppELG48uS/Nvcqj eo8J42Gpqb23Gw4FPcdlbGNzmwpe0UsiW7Pl7Wk X-Received: by 2002:a05:600c:4e41:b0:4a0:1723:2d90 with SMTP id 5b1f17b1804b1-4a01ad7d018mr28681705e9.4.1790785473389; Wed, 30 Sep 2026 09:24:33 -0700 (PDT) From: Oleksii Kurochko To: xen-devel@lists.xenproject.org Cc: Romain Caritey , Baptiste Le Duc , Zheng Zhang , Oleksii Kurochko , Alistair Francis , Connor Davis , Andrew Cooper , Anthony PERARD , Michal Orzel , Jan Beulich , Julien Grall , =?UTF-8?q?Roger=20Pau=20Monn=C3=A9?= , Stefano Stabellini Subject: [PATCH v3 29/39] xen/riscv: prepare new IMSIC VS-file Date: Wed, 30 Sep 2026 18:23:48 +0200 Message-ID: <7f00946a6b1b67e79f94e3c665f8f0ce9d5d0e5a.1790779209.git.oleksii.kurochko@gmail.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-purgate-ID: tlsNG-33051d/1790785474-75EFF4E9-E575293E/10/73395122804 X-purgate-type: spam X-purgate-size: 12026 X-ZohoMail-DKIM: pass (identity @gmail.com) X-ZM-MESSAGEID: 1790785550392158500 Content-Type: text/plain; charset="utf-8" Implement the first steps of migrating a vCPU to a different guest interrupt file: take an interrupt file on the vCPU's new pCPU with vgein_assign() and bring it to a clean state by setting eidelivery and eithreshold to 0 and zeroing all implemented interrupt-pending and interrupt-enable bits (the eip and eie arrays). An IMSIC VS-file is reachable only through hstatus.VGEIN of the hart it belongs to, so the clearing is done by that hart, through imsic_call_on_cpu(). The helper doing it temporarily retargets hstatus.VGEIN and vsiselect, which belong to whatever vCPU is running there, and restores both before returning. vgein_assign() is only a stub for now. Software interrupt files aren't supported, so a vCPU which can't be given a hardware one hits a BUG_ON(), and the BUG_ON("unimplemented") at the end of imsic_migrate_vcpu() stays, as the migration functionality isn't complete yet. Signed-off-by: Oleksii Kurochko --- Changes in v3: - Split the switchcase comment so each part sits above the macros it describes. - Drop imsic_switchcase_ret() as it has no users in this patch. - Drop the unused mrif member from struct imsic_vsfile_data. - Leave the trailing semicolon of the switchcase macros to their users. - Use __VA_ARGS__ instead of the GNU ##__VA_ARGS__ extension and parenthesize ireg in the switchcase expansion pyramid. - Make imsic_call_on_cpu() take struct imsic_vsfile_data * instead of void *. - Explain in imsic_vsfile_local_clear() why hstatus and vsiselect are saved and restored: the file is reached by retargeting hstatus.VGEIN, imsic_vs_csr_write() alters vsiselect, and both belong to the vCPU running on the pCPU. - Introduce imsic_eix_write64() to write a whole 64-bit EIx group, documenting the EIx register layout on RV32 vs RV64 above it, which lets the #ifdef CONFIG_RISCV_32 in imsic_vsfile_local_clear() go. - Drop the unclear "Latch the pCPU" comment. - Drop the redundant parentheses around the arguments of imsic_vs_csr_write() as they are passed to csr_*() as whole expressions. - Add missing break after ASSERT_UNREACHABLE() in the default case of imsic_eix_write(). - Compute the number of EIx groups once in imsic_parse_node() and keep it in imsic_cfg.nr_eix instead of recalculating it on each migration. - Drop the introduction of BITS_PER_TYPE() in xen/include/xen/config.h as plain 64 is used instead. - Minor style and wording fixes: "} while (0)" in imsic_vs_csr_write(), no "\n" in the BUG_ON() message of vgein_assign(), and the extra args of the switchcase expansion pyramid are no longer described as optional. - Rewrite the commit message: it described saving eidelivery/eithreshold of the old interrupt file, which isn't done here, and adding the BUG_ON("unimplemented") placeholder, which is already present. - Drop the new_vsfile_{hgei,cpu} locals: vsfile_data.hgei and v->processor serve the same purpose. --- Changes in v2: - New patch. --- --- xen/arch/riscv/aia.c | 9 ++ xen/arch/riscv/imsic.c | 159 +++++++++++++++++++++++++++++ xen/arch/riscv/include/asm/aia.h | 4 + xen/arch/riscv/include/asm/imsic.h | 7 ++ 4 files changed, 179 insertions(+) diff --git a/xen/arch/riscv/aia.c b/xen/arch/riscv/aia.c index e31c9c2d24b6..229ab4b8678e 100644 --- a/xen/arch/riscv/aia.c +++ b/xen/arch/riscv/aia.c @@ -1,8 +1,10 @@ /* SPDX-License-Identifier: GPL-2.0-only */ =20 +#include #include #include #include +#include #include =20 #include @@ -21,3 +23,10 @@ void __init aia_init(void) =20 _aia_usable =3D true; } + +unsigned int vgein_assign(struct vcpu *v) +{ + BUG_ON("unimplemented"); + + return 0; +} diff --git a/xen/arch/riscv/imsic.c b/xen/arch/riscv/imsic.c index 2f0bb29ae639..f1e44dc56bb8 100644 --- a/xen/arch/riscv/imsic.c +++ b/xen/arch/riscv/imsic.c @@ -26,6 +26,7 @@ #include #include =20 +#include #include =20 #define IMSIC_HART_SIZE(guest_bits) (BIT(guest_bits, U) * IMSIC_MMIO_PAGE_= SZ) @@ -77,6 +78,72 @@ do { \ csr_clear(CSR_SIREG, v); \ } while (0) =20 +#define imsic_vs_csr_write(c, v) \ +do { \ + csr_write(CSR_VSISELECT, c); \ + csr_write(CSR_VSIREG, v); \ +} while (0) + +/* + * Leaf macros for the switchcase expansion pyramid below: + * imsic_switchcase_break(ireg, op, v) - emit "case ireg: op(ireg, v); bre= ak" + */ +#define imsic_switchcase_break(ireg, op, v) \ + case ireg: \ + op(ireg, v); \ + break + +/* + * Generic switchcase expansion pyramid. + * F is the per-operation leaf macro, ireg is the base register index. + * Extra args (e.g. an operation and/or a value) are forwarded to F via + * __VA_ARGS__. + */ +#define imsic_switchcase_2(F, ireg, ...) \ + F((ireg) + 0, __VA_ARGS__); \ + F((ireg) + 1, __VA_ARGS__) +#define imsic_switchcase_4(F, ireg, ...) \ + imsic_switchcase_2(F, (ireg) + 0, __VA_ARGS__); \ + imsic_switchcase_2(F, (ireg) + 2, __VA_ARGS__) +#define imsic_switchcase_8(F, ireg, ...) \ + imsic_switchcase_4(F, (ireg) + 0, __VA_ARGS__); \ + imsic_switchcase_4(F, (ireg) + 4, __VA_ARGS__) +#define imsic_switchcase_16(F, ireg, ...) \ + imsic_switchcase_8(F, (ireg) + 0, __VA_ARGS__); \ + imsic_switchcase_8(F, (ireg) + 8, __VA_ARGS__) +#define imsic_switchcase_32(F, ireg, ...) \ + imsic_switchcase_16(F, (ireg) + 0, __VA_ARGS__); \ + imsic_switchcase_16(F, (ireg) + 16, __VA_ARGS__) +#define imsic_switchcase_64(F, ireg, ...) \ + imsic_switchcase_32(F, (ireg) + 0, __VA_ARGS__); \ + imsic_switchcase_32(F, (ireg) + 32, __VA_ARGS__) + +static void imsic_eix_write(unsigned int ireg, unsigned long val) +{ + switch ( ireg ) + { + imsic_switchcase_64(imsic_switchcase_break, IMSIC_EIP0, + imsic_vs_csr_write, val); + imsic_switchcase_64(imsic_switchcase_break, IMSIC_EIE0, + imsic_vs_csr_write, val); + default: + ASSERT_UNREACHABLE(); + break; + } +} + +/* + * On RV64 a 64-bit EIx group is the even-numbered register alone, whereas= on + * RV32 it is split into the even-numbered (low half) and the following + * odd-numbered (high half) register. + */ +static void imsic_eix_write64(unsigned int ireg, uint64_t val) +{ + imsic_eix_write(ireg, val); + if ( IS_ENABLED(CONFIG_RISCV_32) ) + imsic_eix_write(ireg + 1, val >> 32); +} + unsigned int vcpu_guest_file_id(const struct vcpu *v) { return ACCESS_ONCE(v->arch.vimsic_state->guest_file_id); @@ -318,6 +385,8 @@ static int __init imsic_parse_node(const struct dt_devi= ce_node *node, return -ENOENT; } =20 + imsic_cfg.nr_eix =3D DIV_ROUND_UP(imsic_cfg.nr_ids + 1, 64); + /* Compute base address */ *nr_mmios =3D 0; rc =3D dt_device_get_address(node, *nr_mmios, &base_addr, NULL); @@ -389,6 +458,79 @@ int cf_check vcpu_imsic_init(struct vcpu *v) return 0; } =20 +/* + * The imsic_vsfile_local_*() helpers have to run on the pCPU owning the + * interrupt file, so they are called through imsic_call_on_cpu(), which + * passes them a single pointer. Their arguments are bundled here. + */ +struct imsic_vsfile_data { + /* Guest interrupt file to work on, i.e. the hstatus.VGEIN selecting i= t. */ + unsigned int hgei; + /* Number of 64-bit EIx groups to cover, see imsic_cfg.nr_eix. */ + unsigned int nr_eix; +}; + +/* + * Execute func() on the pCPU which owns the IMSIC interrupt file func() is + * going to work with. + * + * An IMSIC VS-file is reachable only through hstatus.VGEIN of the hart the + * file belongs to, and a guest interrupt file index is meaningless on any + * other hart, so such work always has to be done by that very hart. + * + * The local case runs with IRQs disabled to provide func() with the same + * environment it is given when it is called from the function call IPI + * handler. + */ +static void imsic_call_on_cpu(unsigned int cpu, void (*func)(void *), + struct imsic_vsfile_data *data) +{ + if ( cpu =3D=3D smp_processor_id() ) + { + unsigned long flags; + + local_irq_save(flags); + func(data); + local_irq_restore(flags); + } + else + on_selected_cpus(cpumask_of(cpu), func, data, 1); +} + +static void cf_check imsic_vsfile_local_clear(void *data) +{ + unsigned int i; + const struct imsic_vsfile_data *idata =3D data; + unsigned long new_hstatus, old_hstatus, old_vsiselect; + + /* We can only zero-out if we have a IMSIC VS-file */ + if ( !idata->hgei ) + return; + + /* + * The file is reached by retargeting hstatus.VGEIN, and + * imsic_vs_csr_write() alters vsiselect. Both belong to the vCPU runn= ing + * on this pCPU, so restore them before returning. + */ + old_vsiselect =3D csr_read(CSR_VSISELECT); + old_hstatus =3D csr_read(CSR_HSTATUS); + new_hstatus =3D old_hstatus & ~HSTATUS_VGEIN; + new_hstatus |=3D MASK_INSR(idata->hgei, HSTATUS_VGEIN); + csr_write(CSR_HSTATUS, new_hstatus); + + imsic_vs_csr_write(IMSIC_EIDELIVERY, 0); + imsic_vs_csr_write(IMSIC_EITHRESHOLD, 0); + + for ( i =3D 0; i < idata->nr_eix; i++ ) + { + imsic_eix_write64(IMSIC_EIP0 + i * 2, 0); + imsic_eix_write64(IMSIC_EIE0 + i * 2, 0); + } + + csr_write(CSR_HSTATUS, old_hstatus); + csr_write(CSR_VSISELECT, old_vsiselect); +} + void cf_check vcpu_imsic_deinit(struct vcpu *v) { XVFREE(v->arch.vimsic_state); @@ -693,6 +835,10 @@ int __init vimsic_make_domu_dt_node(struct kernel_info= *kinfo, =20 void imsic_migrate_vcpu(struct vcpu *v) { + struct imsic_vsfile_data vsfile_data =3D { + .nr_eix =3D imsic_cfg.nr_eix, + }; + /* * The scheduler can mark a freshly created vCPU's unit as migrated and * invoke this before the vCPU has ever run (see the migrated branch in @@ -703,5 +849,18 @@ void imsic_migrate_vcpu(struct vcpu *v) if ( v->arch.last_cpu =3D=3D CPU_NONE ) return; =20 + /* + * At this point, all interrupt producers are still using the old IMSIC + * VS-file. + */ + + vsfile_data.hgei =3D vgein_assign(v); + + /* We don't support SW interrupt files at the moment. */ + BUG_ON(!vsfile_data.hgei); + + /* Zero-out new IMSIC VS-file */ + imsic_call_on_cpu(v->processor, imsic_vsfile_local_clear, &vsfile_data= ); + BUG_ON("unimplemented"); } diff --git a/xen/arch/riscv/include/asm/aia.h b/xen/arch/riscv/include/asm/= aia.h index aaa4bf91fc75..53a1efb042f8 100644 --- a/xen/arch/riscv/include/asm/aia.h +++ b/xen/arch/riscv/include/asm/aia.h @@ -3,8 +3,12 @@ #ifndef RISCV_AIA_H #define RISCV_AIA_H =20 +struct vcpu; + bool aia_usable(void); =20 void aia_init(void); =20 +unsigned int vgein_assign(struct vcpu *v); + #endif /* RISCV_AIA_H */ diff --git a/xen/arch/riscv/include/asm/imsic.h b/xen/arch/riscv/include/as= m/imsic.h index 22ce90e2e9b3..8130d125f5c3 100644 --- a/xen/arch/riscv/include/asm/imsic.h +++ b/xen/arch/riscv/include/asm/imsic.h @@ -55,6 +55,13 @@ struct imsic_config { /* Number off interrupt identities */ unsigned int nr_ids; =20 + /* + * Number of 64-bit EIx groups needed to cover all the interrupt + * identities, which are 0 (never valid, but it still occupies a bit) = up + * to and including nr_ids. + */ + unsigned int nr_eix; + /* MSI */ const struct imsic_msi *msi; =20 --=20 2.55.0 From nobody Fri Oct 23 15:32:28 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) client-ip=192.237.175.120; envelope-from=xen-devel-bounces@lists.xenproject.org; helo=lists.xenproject.org; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=pass(p=none dis=none) header.from=gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1790785559; cv=none; d=zohomail.com; s=zohoarc; b=fLBUudiziuR3AFOils7T5ZgbFmvdaIILcmsTrjwZPDOtsJvw50yQcVdIrxh0R8fJAVBuySASYjVB4mPRlnWwEq0chaz3O+qFZ6nRdmCyjOkMtPXTGexLIoQpMwNGqYsR6vVWKyU6yisR/XpETIleSlxrElWQljuntlGk3t/mZ74= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1790785559; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=KA/gB3ogwiCD2vdEVkhrFhPeGIZ+VRrxnqBF242SsNk=; b=A27GGeXDFnoh5Dy4WegrwojH59zNZ1mr8RvmjPWoh/ynOPIaH141LF+i/glDjY7hE6drBnQwFq2Ra20FGmN+hutXwbzXP4VJ3Bw5A7nl2jEe8pSjkg3YvAtuTKStkLKUs+2fAvCF2payWRj7gQGUkqjdw0XftdhnFb+1TwVL1pw= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) by mx.zohomail.com with SMTPS id 1790785559335232.97518985254248; Wed, 30 Sep 2026 09:25:59 -0700 (PDT) Received: from list by lists.xenproject.org with outflank-mailman.1437577.1656639 (Exim 4.92) (envelope-from ) id 1xBx6n-0008Kh-KL; Wed, 30 Sep 2026 16:24:41 +0000 Received: by outflank-mailman (output) from mailman id 1437577.1656639; Wed, 30 Sep 2026 16:24:41 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1xBx6m-0008G1-8A; Wed, 30 Sep 2026 16:24:40 +0000 Received: by outflank-mailman (input) for mailman id 1437577; Wed, 30 Sep 2026 16:24:36 +0000 Received: from mx.expurgate.net ([194.145.224.20]) by lists.xenproject.org with esmtp (Exim 4.92) id 1xBx6i-0007Op-1W for xen-devel@lists.xenproject.org; Wed, 30 Sep 2026 16:24:36 +0000 Received: from mx.expurgate.net (helo=localhost) by mx.expurgate.net with esmtp id 1xBx6h-00GhY9-Dy for xen-devel@lists.xenproject.org; Wed, 30 Sep 2026 18:24:35 +0200 Received: from [10.42.69.3] (helo=localhost) by localhost with ESMTP (eXpurgate MTA 0.9.1) (envelope-from ) id 6abd37b7-8faa-0a2a0a5109dd-0a2a4503edf2-32 for ; Wed, 30 Sep 2026 18:24:35 +0200 Received: from [74.125.225.141] (helo=mail-wm2-f13.google.com) by tlsNG-33051d.mxtls.expurgate.net with ESMTPS (eXpurgate 4.57.1) (envelope-from ) id 6abd37c3-fae8-0a2a45030019-4a7de18dbec0-3 for ; Wed, 30 Sep 2026 18:24:35 +0200 Received: by mail-wm2-f13.google.com with SMTP id 5b1f17b1804b1-49ccf3ca626so34554065e9.0 for ; Wed, 30 Sep 2026 09:24:35 -0700 (PDT) Received: from fedora (user-109-243-71-234.play-internet.pl. [109.243.71.234]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-4a01cd43e66sm14620485e9.2.2026.09.30.09.24.33 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 30 Sep 2026 09:24:34 -0700 (PDT) X-Outflank-Mailman: Message body and most headers restored to incoming version X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" Authentication-Results: eu.smtp.expurgate.cloud; dkim=pass header.s=20251104 header.d=gmail.com header.i="@gmail.com" header.h="Content-Transfer-Encoding:MIME-Version:References:In-Reply-To:Message-ID:Date:Subject:Cc:To:From" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1790785475; x=1791390275; darn=lists.xenproject.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=KA/gB3ogwiCD2vdEVkhrFhPeGIZ+VRrxnqBF242SsNk=; b=sXVrniVBZpFMSttLvhkJGdDQ6rdmLi82XszK0P+Uvsm/DX5qEMlqWjgk+NulW26z1d PQMZJTz0mOP/NaK9f/XS0b6qPV3BGtJGcKeEe+6lg85RAJQiFRGBUofo/jtuba9xzrBy t1RtCQ+l6GC3rBEtQYcd++s5uLC6NZdml/au0YOBdV0G1PuHmpTK2F/gUHQKYsySVcom XJ/3Wbivrc7YjnQjK0wYgS8eUOOIMXX/kNnmJ6KO1zDOXnzk6/YYMtk1orA2ErTrf/OQ 7VJ2jjZS+Z5iA3BSRSa1Jg1zpW2EvLDR4gqqbrRroo9Ro+397R062l5HUtszW1fJ+LtU es3A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1790785475; x=1791390275; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=KA/gB3ogwiCD2vdEVkhrFhPeGIZ+VRrxnqBF242SsNk=; b=F7yZgP8SK9bqzsI5B/DDHocLWggYfJSN3U+vf8MgqS0ijDG5j70i+p93N0N8rlElQn 0MNRKVekgZX/cLNecFgH8ViMOZjMlZti0CvC1MjtVb2cllVZmljA/fudh2Y58pSpwjHj i2wKlZSyncr8vqlrDzuqocVJKaRSoN/C6ojkj0XEWvD604cZo1g3smsLhX4JQIla/JLd nuoDRRipMT2PUxXsDRLtLcGOEwEFBzXTFcI2UmnEReuwtXaigFSLwciY3Iqf/aLcyvRP oLwNIzjK+obCb5GmVg6IGBGsKQWkgayE16QXAkAiSR8S8Zw/W/iK2eTNaZpqmpu4GJyt 1CfA== X-Gm-Message-State: AFuF++kVt44lBxJghNOKzEp+5CS2ABLZu/sqkgvLO4NY2nO2jSoU7dMV 5R+KHFgb0LYiURvba2jkNOwG830RpMV2bgbCgpwvI8VBpAETfEFqim4EaJ4yow== X-Gm-Gg: AYBFou0jTCOczxy5YK+TZOZGpUoJuFaA8pXjRdbwMpIc48IIj4irN+vrxwl+Nff8NnW k6QaENP31BZsYVAbDdRg78n+NGmH4Jf1XFwJfn65LZuclBjTwxv5OwMEroPSFcGViOdLbdp4oKn GvwYQ1rBpfSkZ3Nn2BtITZZJduTXm/XmxddhruUCr5pOko5M+y9btL4jQrtXexRX7XrTWzH/eX9 7i1m+HeJG6OruZJPr/gDEXlqxMYE5DlD1l7GmTa9weSvvvdJ8ezo1MKfPOyjqiLS+qOQJw60MTv f5FnFKZUXsoWf1KkS2I3UhtrBawQK+z9//PK5yMmv4wuzPhAhIvTUnjs8yyAXZfsZAplaefHC6y IjHGYJXkS35pwVqhZ4WYv0BgcVdtM8Njr7bz3fbrhfDmb6nZoq8QwLDDxmgUuJKXLtiYVbnM4Vi eEDBr9o4vAF5nTNTaPR29NRs+/Zbeqai1VrB5Kvk/26Ewpj4/5h5s0fSsgyRmi92QKn2LGrw5TZ 4hpmL7OC83MgMYajSIMgBbn0XGnpej3aLcJKPhtYdmFV0m57llh X-Received: by 2002:a05:600c:3b23:b0:49c:fa20:cbfc with SMTP id 5b1f17b1804b1-4a01b119661mr35155385e9.19.1790785474621; Wed, 30 Sep 2026 09:24:34 -0700 (PDT) From: Oleksii Kurochko To: xen-devel@lists.xenproject.org Cc: Romain Caritey , Baptiste Le Duc , Zheng Zhang , Oleksii Kurochko , Alistair Francis , Connor Davis , Andrew Cooper , Anthony PERARD , Michal Orzel , Jan Beulich , Julien Grall , =?UTF-8?q?Roger=20Pau=20Monn=C3=A9?= , Stefano Stabellini Subject: [PATCH v3 30/39] xen/riscv: implement APLIC-IMSIC-hart sync barrier for vCPU migration Date: Wed, 30 Sep 2026 18:23:49 +0200 Message-ID: <2075cb10e5f6df787b29f2f087632c82b787a007.1790779209.git.oleksii.kurochko@gmail.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-purgate-ID: tlsNG-33051d/1790785475-752854E9-060C0423/10/73395122804 X-purgate-type: spam X-purgate-size: 9612 X-ZohoMail-DKIM: pass (identity @gmail.com) X-ZM-MESSAGEID: 1790785560439158500 Content-Type: text/plain; charset="utf-8" When a vCPU is moved to a different guest interrupt file, MSIs that the APLIC has already sent towards the old file may still be in flight. They must land before the old file's state is saved and the switch is done, otherwise they would be lost. To wait for them, use the APLIC's genmsi register. Writing it makes the APLIC itself send an MSI (an "extempore" MSI) with a given interrupt identity to a given hart. genmsi can only target the hart's hypervisor- level interrupt file, not a guest one, but the AIA spec guarantees that all MSIs previously sent by the same APLIC to the same hart become visible at the hart's IMSIC before the extempore MSI does. So once the extempore MSI has been delivered, no older MSI from this APLIC to the hart can still be in flight, whichever interrupt file it targets. genmsi's Busy bit clearing only tells that the APLIC has sent the extempore MSI, not that it has arrived, so the sequence described in the AIA spec under "Synchronizing interactions between a hart and the APLIC" is split in two. aplic_genmsi_barrier() does the APLIC side, while imsic_aplic_sync() does the hart side: it clears the pending bit of the reserved identity before the genmsi write and spins on it afterwards, which is what tells that the extempore MSI, and hence every older MSI from this APLIC to this hart, has really arrived. Keeping the hart side in imsic.c leaves the APLIC code free of the IMSIC local CSR accessors. The last interrupt identity (nr_ids) is reserved for this purpose. Migration doesn't use the barrier at this stage, so imsic_migrate_vcpu() only references imsic_aplic_sync() to keep the compiler from complaining about it being unused. Signed-off-by: Oleksii Kurochko --- Changes in v3: - Rename from "xen/riscv: implement APLIC-hart sync barrier for vCPU migration", as the barrier waits for the MSIs to reach the hart's IMSIC. - Re-word the commit message, describing in it how the sequence is split between aplic_genmsi_barrier() and imsic_aplic_sync(). - Move imsic_aplic_sync(), imsic_local_is_pending() and imsic_csr_read() here from "xen/riscv: remap interrupts to new IMSIC VS-file", so that both halves of the synchronization sequence are introduced together. - s/aplic_hart_field/aplic_hart_index/ following the rename of the helper in "xen/riscv: implement virtual APLIC MMIO emulation". - Drop masking of sync_id with APLIC_TARGET_EIID, which could silently chop off bits; instead add BUILD_BUG_ON() and ASSERT() to make it explicit that sync_id always fits into the EIID field. - Drop the redundant parentheses around the macro argument in imsic_csr_read(). - Use unsigned int for isel in imsic_local_is_pending() and drop the redundant !! as the function returns bool. - Rename the unused argument of imsic_aplic_sync() to unused. --- Changes in v2: - New patch. --- --- xen/arch/riscv/aplic.c | 33 +++++++++++++++++++ xen/arch/riscv/imsic.c | 52 ++++++++++++++++++++++++++++++ xen/arch/riscv/include/asm/aplic.h | 3 ++ xen/arch/riscv/include/asm/imsic.h | 8 +++++ 4 files changed, 96 insertions(+) diff --git a/xen/arch/riscv/aplic.c b/xen/arch/riscv/aplic.c index 283e5d6046a6..5f9a894b5a76 100644 --- a/xen/arch/riscv/aplic.c +++ b/xen/arch/riscv/aplic.c @@ -27,7 +27,9 @@ #include #include #include +#include #include +#include =20 static struct aplic_priv aplic =3D { .lock =3D SPIN_LOCK_UNLOCKED, @@ -183,6 +185,37 @@ void aplic_hw_write_reg(unsigned int offset, uint32_t = value) spin_unlock_irqrestore(&aplic.lock, flags); } =20 +/* + * As needed, synchronize with all IOMMUs and APLICs to ensure that no + * straggler MSIs will arrive at the old interrupt file after this step. + */ +void aplic_genmsi_barrier(void) +{ + const struct imsic_config *imsic =3D imsic_get_config(); + unsigned int cpu =3D smp_processor_id(); + unsigned long flags; + uint32_t val; + + /* + * sync_id is nr_ids, which imsic_parse_node() limits to IMSIC_MAX_ID, + * so it always fits into the EIID field. + */ + BUILD_BUG_ON(IMSIC_MAX_ID > MASK_EXTR(~0U, APLIC_TARGET_EIID)); + ASSERT(imsic->sync_id <=3D IMSIC_MAX_ID); + + val =3D MASK_INSR(aplic_hart_index(cpu), APLIC_TARGET_HART_IDX) | + imsic->sync_id; + + spin_lock_irqsave(&aplic.lock, flags); + + writel(val, &aplic.regs->genmsi); + + while ( readl(&aplic.regs->genmsi) & APLIC_GENMSI_BUSY ) + cpu_relax(); + + spin_unlock_irqrestore(&aplic.lock, flags); +} + static void __init aplic_init_hw_interrupts(void) { unsigned int i; diff --git a/xen/arch/riscv/imsic.c b/xen/arch/riscv/imsic.c index f1e44dc56bb8..8e0273eab902 100644 --- a/xen/arch/riscv/imsic.c +++ b/xen/arch/riscv/imsic.c @@ -27,6 +27,7 @@ #include =20 #include +#include #include =20 #define IMSIC_HART_SIZE(guest_bits) (BIT(guest_bits, U) * IMSIC_MMIO_PAGE_= SZ) @@ -60,6 +61,12 @@ static unsigned int __ro_after_init guest_num_msis; #define IMSIC_DISABLE_EITHRESHOLD 1 #define IMSIC_ENABLE_EITHRESHOLD 0 =20 +#define imsic_csr_read(c) \ +({ \ + csr_write(CSR_SISELECT, c); \ + csr_read(CSR_SIREG); \ +}) + #define imsic_csr_write(c, v) \ do { \ csr_write(CSR_SISELECT, c); \ @@ -203,6 +210,15 @@ void imsic_irq_enable(unsigned int irq) */ ASSERT(!local_irq_is_enabled()); =20 + if ( irq =3D=3D imsic_cfg.sync_id ) + { + printk(XENLOG_WARNING + "irq%u is reserved for APLIC sync so shouldn't be set by %s= \n", + irq, __func__); + + return; + } + spin_lock(&imsic_cfg.lock); /* * There is no irq - 1 here (look at aplic_set_irq_type()) because: @@ -241,6 +257,15 @@ void imsic_irq_disable(unsigned int irq) spin_unlock(&imsic_cfg.lock); } =20 +static bool imsic_local_is_pending(unsigned int id) +{ + unsigned int isel =3D + (id / BITS_PER_LONG) * (BITS_PER_LONG / IMSIC_EIPx_BITS) + IMSIC_E= IP0; + unsigned long bit =3D BIT(id % BITS_PER_LONG, UL); + + return imsic_csr_read(isel) & bit; +} + /* Callers aren't intended to changed imsic_cfg so return const. */ const struct imsic_config *imsic_get_config(void) { @@ -387,6 +412,9 @@ static int __init imsic_parse_node(const struct dt_devi= ce_node *node, =20 imsic_cfg.nr_eix =3D DIV_ROUND_UP(imsic_cfg.nr_ids + 1, 64); =20 + /* Reserve last identity for APLIC-to-hart synchronization */ + imsic_cfg.sync_id =3D imsic_cfg.nr_ids; + /* Compute base address */ *nr_mmios =3D 0; rc =3D dt_device_get_address(node, *nr_mmios, &base_addr, NULL); @@ -497,6 +525,27 @@ static void imsic_call_on_cpu(unsigned int cpu, void (= *func)(void *), on_selected_cpus(cpumask_of(cpu), func, data, 1); } =20 +/* + * Ensure that all the MSIs the APLIC has already generated for the hart t= his + * runs on have really reached the hart's IMSIC. + * + * The barrier is the one described by the AIA specification in + * "Synchronizing interactions between a hart and the APLIC": ask the APLI= C to + * send an MSI to the hart itself and wait until it shows up as pending in= the + * hart's own interrupt file. As it says nothing about MSIs on their way to + * any other hart, it has to be executed by the pCPU owning the interrupt = file + * the MSIs were being sent to. + */ +static void cf_check imsic_aplic_sync(void *unused) +{ + imsic_local_eix_update(imsic_cfg.sync_id, 1, true, false); + + aplic_genmsi_barrier(); + + while ( !imsic_local_is_pending(imsic_cfg.sync_id) ) + cpu_relax(); +} + static void cf_check imsic_vsfile_local_clear(void *data) { unsigned int i; @@ -862,5 +911,8 @@ void imsic_migrate_vcpu(struct vcpu *v) /* Zero-out new IMSIC VS-file */ imsic_call_on_cpu(v->processor, imsic_vsfile_local_clear, &vsfile_data= ); =20 + /* Avoid an unused-function error until the barrier has a user. */ + (void)imsic_aplic_sync; + BUG_ON("unimplemented"); } diff --git a/xen/arch/riscv/include/asm/aplic.h b/xen/arch/riscv/include/as= m/aplic.h index 9018936ca95a..bfb510b2ae5e 100644 --- a/xen/arch/riscv/include/asm/aplic.h +++ b/xen/arch/riscv/include/asm/aplic.h @@ -94,6 +94,7 @@ #define APLIC_SETIPNUM_LE 0x2000 =20 #define APLIC_GENMSI 0x3000 +#define APLIC_GENMSI_BUSY BIT(12, U) =20 #define APLIC_TARGET_BASE 0x3004 #define APLIC_TARGET_LAST 0x3ffc @@ -177,4 +178,6 @@ struct aplic_regs { uint32_t aplic_hw_read_reg(unsigned int offset); void aplic_hw_write_reg(unsigned int offset, uint32_t value); =20 +void aplic_genmsi_barrier(void); + #endif /* ASM_RISCV_APLIC_H */ diff --git a/xen/arch/riscv/include/asm/imsic.h b/xen/arch/riscv/include/as= m/imsic.h index 8130d125f5c3..f86407e21765 100644 --- a/xen/arch/riscv/include/asm/imsic.h +++ b/xen/arch/riscv/include/asm/imsic.h @@ -62,6 +62,14 @@ struct imsic_config { */ unsigned int nr_eix; =20 + /* + * Interrupt identity reserved exclusively for APLIC-to-hart + * synchronization. + * + * Must not be allocated to any interrupt source. + */ + unsigned int sync_id; + /* MSI */ const struct imsic_msi *msi; =20 --=20 2.55.0 From nobody Fri Oct 23 15:32:28 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) client-ip=192.237.175.120; envelope-from=xen-devel-bounces@lists.xenproject.org; helo=lists.xenproject.org; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=pass(p=none dis=none) header.from=gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1790785553; cv=none; d=zohomail.com; s=zohoarc; b=NOBYoQZpmMOC7dlFygM+UqUY88zRvL5Seef3Ivkmq3tB+3+Mf9qVToh4CAWlvnmqvtIccD2SgbSRcyM8U83h6nT0x0MyCenitkx28PFpBhdxrNoAc6HmgZ2IT8gKbZewSltBQlPBgY/KJ48fwmfas5kdivMi5Sqqguoz6i0pfXs= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1790785553; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=Kw3g/wSbFjxVE7ZYTroGknebkWPXGwoRkZfsFvlSlNI=; b=Ld38lBp6wuI/uTccLhkEzGN3Ye86jQqprP3O+aQBpO8wkrusuC3bR5McYYDCCfAZrilun77KOv53mkIVuOzD1XvwunMwvBQJLjttS/88xJe0qXAyV8oaCdznsEcETcnwwZrr/uRjTKUncZZxhB1qkQ0HvgA3GcvR4Cwpj86pRHg= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) by mx.zohomail.com with SMTPS id 1790785553697878.6584781654828; Wed, 30 Sep 2026 09:25:53 -0700 (PDT) Received: from list by lists.xenproject.org with outflank-mailman.1437579.1656644 (Exim 4.92) (envelope-from ) id 1xBx6o-0000AQ-EK; Wed, 30 Sep 2026 16:24:42 +0000 Received: by outflank-mailman (output) from mailman id 1437579.1656644; Wed, 30 Sep 2026 16:24:42 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1xBx6n-0008Uj-Gx; Wed, 30 Sep 2026 16:24:41 +0000 Received: by outflank-mailman (input) for mailman id 1437579; Wed, 30 Sep 2026 16:24:37 +0000 Received: from mx.expurgate.net ([194.145.224.10]) by lists.xenproject.org with esmtp (Exim 4.92) id 1xBx6j-0007a7-2N for xen-devel@lists.xenproject.org; Wed, 30 Sep 2026 16:24:37 +0000 Received: from mx.expurgate.net (helo=localhost) by mx.expurgate.net with esmtp id 1xBx6i-006O0j-EW for xen-devel@lists.xenproject.org; Wed, 30 Sep 2026 18:24:36 +0200 Received: from [10.42.69.8] (helo=localhost) by localhost with ESMTP (eXpurgate MTA 0.9.1) (envelope-from ) id 6abd37b9-2eae-0a2a0a5409dd-0a2a4508b85c-16 for ; Wed, 30 Sep 2026 18:24:36 +0200 Received: from [74.125.225.98] (helo=mail-wr2-f34.google.com) by tlsNG-c1860d.mxtls.expurgate.net with ESMTPS (eXpurgate 4.57.1) (envelope-from ) id 6abd37c4-f659-0a2a45080019-4a7de162a94e-3 for ; Wed, 30 Sep 2026 18:24:36 +0200 Received: by mail-wr2-f34.google.com with SMTP id ffacd0b85a97d-48affb828f1so1009642f8f.0 for ; Wed, 30 Sep 2026 09:24:36 -0700 (PDT) Received: from fedora (user-109-243-71-234.play-internet.pl. [109.243.71.234]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-4a01cd43e66sm14620485e9.2.2026.09.30.09.24.34 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 30 Sep 2026 09:24:35 -0700 (PDT) X-Outflank-Mailman: Message body and most headers restored to incoming version X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" Authentication-Results: eu.smtp.expurgate.cloud; dkim=pass header.s=20251104 header.d=gmail.com header.i="@gmail.com" header.h="Content-Transfer-Encoding:MIME-Version:References:In-Reply-To:Message-ID:Date:Subject:Cc:To:From" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1790785476; x=1791390276; darn=lists.xenproject.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=Kw3g/wSbFjxVE7ZYTroGknebkWPXGwoRkZfsFvlSlNI=; b=TsPojjt1V61HODQjTojCizhsvHGGRBpMFSzUEBQeMK+2oRyjyUMJHIRAHWiWClOwGT KwtlzmscgWR1DVxCgu5KzoAA2R82WKXqKR0i+mW2luQGCklnMSOReTYM+DVrYtbz/1iA Ou+U31DSOwVokToAP0XpN0uEHjkDMUI93iFt3s2ZCJ0DQTlTE51W5qnT5dSmQD2DzDZU kChWhxqVUm150t3GdSXIaoB8DNtziZ43PHlN4MH90Zcg6BMgHXok3031NNpz2F+dWRdj cNcb2qTOCYKH+FAL0B8gnTq2LpEcpwJyBwtBFAjfZgwTQAZSl6PJomhleUdtR9Txa75h Q/lA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1790785476; x=1791390276; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=Kw3g/wSbFjxVE7ZYTroGknebkWPXGwoRkZfsFvlSlNI=; b=y8Y4kxPoi1jN2gHFmMi+elLN/mZnVBvcoTBvqWkQ+XAELikg8kkWCcGXijxrlaNLCt eR5/6puBRKaFaDbIixH57hHIRadie5PVjw657n3qbYw+SbKba3QpVeJO7eDyr4I+vde4 wuWPeP/h8lDnJs/Q9g2Dw/6nW+fuYAWlVxVhc91xpmgt7glUs08UwGtj5y1+rkfAi67t qRlfHvvscbk1zajYHY+b0xspxUobU2yVAOwueKPLOpgn78N+RIpa3XKLRksHuB0dDLeN CMuEj+rXHC9o5EQO2PL8AzOoA8cyl+c0hIhp4twV2LkDTkg6dsVXV8IlT4wtmbNbaUQW X/kw== X-Gm-Message-State: AFuF++kcw/qf6Kht98KBjr9BVFncSuSPL6Crqn2R1CT8E+WeRElLmLxA 9IjoPbzfCBL2x88ZOECZ1yCP2xaTRvuXba/4bArpe9JaCaNlp/w2DhLvzPItqg== X-Gm-Gg: AYBFou0PYOoTSrWN/oOaYv6mgYMiSfO/4xePjWukzQFAALl1L2uFyMSy9CABGAfv/wa JSkxUFjuUOp9smZyK1/o+ge4Hye1upflU13Zp9VvxFhP8lx5g1JHEbPAaVSmcIynd30PDesu/ni S6yi9zbEu9HzJvtYcPHLSV9SmnWkY07HxEhuAoy+P80zEl90FgixJmzcIq0irEtBPhhbCxx11kz uBt4Eqx2i4jS4ur75vHVQ+W9/Yvwj4lOv0eZo5ZkbR/Q9fzd28KUywpvp+q/PKLRekdzgqEmeRY 1B038aAUvnlRVRfAnfFEA8P9EHSM7zFFXrzw7RBxzMfeCoRpYvVfppj1Gjo1TKssn3WSlBkewDa pzlus42dhnINK2JDB+1fHe5fr7OhMM/c19WXMDSMjGR+0xDHW8ouFCQi5fBGS+wW6+sg7WK8M6g 88gHhsoGb6O66Q199oLu2ghI0zydJooRqOndOqi6YUTKOdbV6awn90Ho5Y0S6+Yem2E2wCHu0wY JQ0mfmvoz0Tl+aMcyAJ3dXDs7zzf6DpxNSrRen8 X-Received: by 2002:a05:600c:6206:b0:4a0:857:a3a5 with SMTP id 5b1f17b1804b1-4a01b11114dmr34079965e9.16.1790785475771; Wed, 30 Sep 2026 09:24:35 -0700 (PDT) From: Oleksii Kurochko To: xen-devel@lists.xenproject.org Cc: Romain Caritey , Baptiste Le Duc , Zheng Zhang , Oleksii Kurochko , Alistair Francis , Connor Davis , Andrew Cooper , Anthony PERARD , Michal Orzel , Jan Beulich , Julien Grall , =?UTF-8?q?Roger=20Pau=20Monn=C3=A9?= , Stefano Stabellini Subject: [PATCH v3 31/39] xen/riscv: remap interrupts to new IMSIC VS-file Date: Wed, 30 Sep 2026 18:23:50 +0200 Message-ID: <45011daea86267b8f4b707bc7de6357b0712fb08.1790779209.git.oleksii.kurochko@gmail.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-purgate-ID: tlsNG-c1860d/1790785476-CE54487B-A1E4B30D/10/73395122804 X-purgate-type: spam X-purgate-size: 11923 X-ZohoMail-DKIM: pass (identity @gmail.com) X-ZM-MESSAGEID: 1790785554410158500 Content-Type: text/plain; charset="utf-8" Once the new IMSIC VS-file has been zeroed out, it has to be mapped into the guest's G-stage in place of the old one. Also, if any interrupts at an APLIC are forwarded by MSIs to the old interrupt file, reconfigure the APLIC to send them to the new interrupt file. Taking a h/w guest interrupt file (assigning it, zeroing it out, mapping it into G-stage and recording it in the vCPU's IMSIC state) is factored out into imsic_vsfile_acquire(). The relevant translation tables at all IOMMUs would also have to be updated so that MSIs for this virtual interrupt file are sent to the new physical interrupt file, but that is skipped for now as there is no IOMMU support for RISC-V. Synchronize with the APLIC to ensure that no straggler MSIs will arrive at the old interrupt file by running imsic_aplic_sync() on the pCPU which owns that file. If the new file can't be mapped into the guest, release the guest external interrupt number imsic_vsfile_acquire() took for it instead of leaking it. vgein_release() takes the pCPU explicitly instead of relying on v->processor, as on migration v->processor already refers to the new pCPU while the number to be released may belong to the old one. Keep BUG_ON("unimplemented") placeholder in imsic_migrate_vcpu() to guard against silent incorrect behaviour or unexpected panics in guest VMs until the function is fully implemented. Implement imsic_update_state(), which records the vCPU's guest interrupt file id together with the pCPU owning the file. The two are read as a pair, e.g. by imsic_migrate_vcpu() and the IMSIC context switch hooks, so they are updated under vsfile_lock as a single unit. imsic_map_guest_file() and vgein_release() are stubs for now. Signed-off-by: Oleksii Kurochko --- imsic_vsfile_acquire() isn't introduced already by "xen/riscv: prepare new IMSIC VS-file": there, taking the new file is just vgein_assign() and zeroi= ng the file out. What makes it worth a helper of its own, mapping the file into the guest, recording it in the vCPU's IMSIC state and releasing it again wi= th vgein_release() if the mapping fails, only comes with this patch. The helper is also shared with the first attach of a h/w file in "xen/riscv: introduce IMSIC h/w interrupt file attaching to vcpu". --- Changes in v3: - Update the commit message. - Move imsic_aplic_sync() and imsic_local_is_pending() to "xen/riscv: implement APLIC-IMSIC-hart sync barrier for vCPU migration" and only call the helper here. - compare old_vsfile_cpu against CPU_NONE instead of NR_CPUS. - Call vaplic_reconfigure_target() instead of aplic_reconfigure_target(). - Update the comment at the start of the migration: at that point the new IMSIC VS-file is only being prepared, the interrupt producers are moved to it later. - Factor taking a h/w guest interrupt file (assign, zero out, map into G-stage and record in the per-vCPU IMSIC state) out of imsic_migrate_vcpu() into imsic_vsfile_acquire(), introduced here instead of in "xen/riscv: introduce IMSIC h/w interrupt file attaching to vcpu". - Crash the domain instead of BUG_ON()ing when no h/w guest interrupt file is free, and report which file could not be mapped. - Introduce the vgein_release() stub here, together with its first user: release the h/w guest interrupt file taken by imsic_vsfile_acquire() if mapping it into the guest fails. Drop the stray "\n" from its BUG_ON(). - Clarify the comment ahead of imsic_vsfile_acquire() on why setting hstatus.VGEIN is left to the caller. - Implement imsic_update_state() here instead of leaving it a stub until "xen/riscv: introduce IMSIC h/w interrupt file attaching to vcpu": all it needs, vsfile_lock and CPU_NONE, is available already. The s/w IMSIC VS-file is recorded with vsfile_cpu =3D=3D CPU_NONE rather than NR_CPUS. - Make imsic_update_state() static and drop its declaration from asm/imsic.h: imsic_vsfile_acquire() is its only user. --- Changes in v2: - New patch. --- --- xen/arch/riscv/aia.c | 5 ++ xen/arch/riscv/imsic.c | 130 +++++++++++++++++++++++++++-- xen/arch/riscv/include/asm/aia.h | 1 + xen/arch/riscv/include/asm/imsic.h | 2 + 4 files changed, 130 insertions(+), 8 deletions(-) diff --git a/xen/arch/riscv/aia.c b/xen/arch/riscv/aia.c index 229ab4b8678e..bd35078b7354 100644 --- a/xen/arch/riscv/aia.c +++ b/xen/arch/riscv/aia.c @@ -30,3 +30,8 @@ unsigned int vgein_assign(struct vcpu *v) =20 return 0; } + +void vgein_release(struct vcpu *v, unsigned int vgein_id, unsigned int cpu) +{ + BUG_ON("unimplemented"); +} diff --git a/xen/arch/riscv/imsic.c b/xen/arch/riscv/imsic.c index 8e0273eab902..47854264edf3 100644 --- a/xen/arch/riscv/imsic.c +++ b/xen/arch/riscv/imsic.c @@ -29,6 +29,7 @@ #include #include #include +#include =20 #define IMSIC_HART_SIZE(guest_bits) (BIT(guest_bits, U) * IMSIC_MMIO_PAGE_= SZ) =20 @@ -156,6 +157,18 @@ unsigned int vcpu_guest_file_id(const struct vcpu *v) return ACCESS_ONCE(v->arch.vimsic_state->guest_file_id); } =20 +static void imsic_update_state(struct vcpu *v, unsigned int guest_file_id) +{ + unsigned long flags; + struct vimsic_state *vimsic_state =3D v->arch.vimsic_state; + unsigned int cpu =3D guest_file_id ? v->processor : CPU_NONE; + + write_lock_irqsave(&vimsic_state->vsfile_lock, flags); + vimsic_state->guest_file_id =3D guest_file_id; + vimsic_state->vsfile_cpu =3D cpu; + write_unlock_irqrestore(&vimsic_state->vsfile_lock, flags); +} + void __init imsic_ids_local_delivery(bool enable) { if ( enable ) @@ -462,6 +475,11 @@ void cf_check imsic_ctxt_switch_to(struct vcpu *n) /* Nothing to do */ } =20 +int imsic_map_guest_file(struct vcpu *v, unsigned int vsfile_id) +{ + return -EOPNOTSUPP; +} + int cf_check vcpu_imsic_init(struct vcpu *v) { struct vimsic_state *imsic_state; @@ -882,11 +900,71 @@ int __init vimsic_make_domu_dt_node(struct kernel_inf= o *kinfo, return fdt_end_node(fdt); } =20 +/* + * Take a h/w guest interrupt file on the pCPU @v runs on and make it the + * vCPU's one. + * + * hstatus.VGEIN is deliberately left alone: it must only point at a file + * which already holds the vCPU's interrupt state. The file taken here is + * zeroed, so for imsic_migrate_vcpu() hstatus.VGEIN can only be updated o= nce + * the state of the old file has been copied into it. Hence it is up to the + * caller to set hstatus.VGEIN at the right moment. + * + * Returns the id of the file, or 0, with the domain crashed, if none coul= d be + * taken. + */ +static unsigned int imsic_vsfile_acquire(struct vcpu *v) +{ + unsigned int cpu =3D v->processor; + struct imsic_vsfile_data vsfile_data =3D { .nr_eix =3D imsic_cfg.nr_ei= x }; + unsigned int vsfile_id; + int rc; + + vsfile_id =3D vgein_assign(v); + if ( !vsfile_id ) + { + /* + * vgein_assign() returns 0 when no free h/w guest interrupt file = is + * available. s/w guest interrupt files aren't supported yet, so s= uch + * a vCPU can't be run. + */ + domain_crash(v->domain, + "%pv: no free h/w guest interrupt file on CPU%u\n", + v, cpu); + return 0; + } + + vsfile_data.hgei =3D vsfile_id; + + /* The file could still hold the state of its previous owner */ + imsic_call_on_cpu(cpu, imsic_vsfile_local_clear, &vsfile_data); + + rc =3D imsic_map_guest_file(v, vsfile_id); + if ( rc ) + { + vgein_release(v, vsfile_id, cpu); + + /* Can't continue w/o correctly mapped IMSIC interrupt file */ + domain_crash(v->domain, + "%pv: failed to map h/w guest interrupt file %u: %d\n= ", + v, vsfile_id, rc); + return 0; + } + + imsic_update_state(v, vsfile_id); + + return vsfile_id; +} + void imsic_migrate_vcpu(struct vcpu *v) { struct imsic_vsfile_data vsfile_data =3D { .nr_eix =3D imsic_cfg.nr_eix, }; + struct vimsic_state *imsic_state =3D v->arch.vimsic_state; + unsigned long flags; + unsigned int old_vsfile_id; + unsigned int old_vsfile_cpu; =20 /* * The scheduler can mark a freshly created vCPU's unit as migrated and @@ -898,21 +976,57 @@ void imsic_migrate_vcpu(struct vcpu *v) if ( v->arch.last_cpu =3D=3D CPU_NONE ) return; =20 + read_lock_irqsave(&imsic_state->vsfile_lock, flags); + old_vsfile_id =3D imsic_state->guest_file_id; + old_vsfile_cpu =3D imsic_state->vsfile_cpu; + read_unlock_irqrestore(&imsic_state->vsfile_lock, flags); + + /* + * We don't support SW interrupt files at the moment. Bail out before + * anything is touched, as the old file has no owning pCPU in that case + * and there is nothing to retarget the producers away from. + */ + if ( old_vsfile_cpu =3D=3D CPU_NONE ) + panic("IMSIC SW-file isn't supported\n"); + /* * At this point, all interrupt producers are still using the old IMSIC - * VS-file. + * VS-file. Allocate and clear the new one before redirecting anything + * to it. */ =20 - vsfile_data.hgei =3D vgein_assign(v); + /* Zero-out, map and start to use the new IMSIC VS-file */ + vsfile_data.hgei =3D imsic_vsfile_acquire(v); + if ( !vsfile_data.hgei ) + return; =20 - /* We don't support SW interrupt files at the moment. */ - BUG_ON(!vsfile_data.hgei); + /* + * TODO: Modify the relevant translation tables at all IOMMUs so that = MSIs + * for this virtual interrupt file are now sent to the new physi= cal + * interrupt file. + */ + if ( iommu_enabled ) + printk_once("IMSIC: IOMMU MSI retargeting is not implemented\n"); =20 - /* Zero-out new IMSIC VS-file */ - imsic_call_on_cpu(v->processor, imsic_vsfile_local_clear, &vsfile_data= ); + /* + * If any interrupts at an APLIC are forwarded by MSIs to the old inte= rrupt + * file, reconfigure the APLIC to send them to the new interrupt file. + */ + vaplic_reconfigure_target(v); =20 - /* Avoid an unused-function error until the barrier has a user. */ - (void)imsic_aplic_sync; + /* + * Synchronizing interactions between a hart and the APLIC. + * + * The MSIs to be flushed are the ones still on their way to the old + * interrupt file, so the barrier has to be done by the pCPU which owns + * that file. + */ + imsic_call_on_cpu(old_vsfile_cpu, imsic_aplic_sync, NULL); + + /* + * At this point, all interrupt producers have been moved + * to the new IMSIC VS-file. + */ =20 BUG_ON("unimplemented"); } diff --git a/xen/arch/riscv/include/asm/aia.h b/xen/arch/riscv/include/asm/= aia.h index 53a1efb042f8..8e4eb2f6b14e 100644 --- a/xen/arch/riscv/include/asm/aia.h +++ b/xen/arch/riscv/include/asm/aia.h @@ -10,5 +10,6 @@ bool aia_usable(void); void aia_init(void); =20 unsigned int vgein_assign(struct vcpu *v); +void vgein_release(struct vcpu *v, unsigned int vgein_id, unsigned int cpu= ); =20 #endif /* RISCV_AIA_H */ diff --git a/xen/arch/riscv/include/asm/imsic.h b/xen/arch/riscv/include/as= m/imsic.h index f86407e21765..e08b041eebbd 100644 --- a/xen/arch/riscv/include/asm/imsic.h +++ b/xen/arch/riscv/include/asm/imsic.h @@ -114,6 +114,8 @@ int vimsic_make_domu_dt_node(struct kernel_info *kinfo,= unsigned int *phandle); void imsic_ctxt_switch_from(struct vcpu *p); void imsic_ctxt_switch_to(struct vcpu *n); =20 +int imsic_map_guest_file(struct vcpu *v, unsigned int vsfile_id); + void imsic_migrate_vcpu(struct vcpu *v); =20 #endif /* ASM_RISCV_IMSIC_H */ --=20 2.55.0 From nobody Fri Oct 23 15:32:28 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) client-ip=192.237.175.120; envelope-from=xen-devel-bounces@lists.xenproject.org; helo=lists.xenproject.org; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=pass(p=none dis=none) header.from=gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1790785561; cv=none; d=zohomail.com; s=zohoarc; b=PNSUivHXLd2FdAOaD8d8D5lw5LZ8ZG10DIRUyqfwlk0A1ntzVqxp7fv2DAlkEJflq9AIn30Ebm+coqnei58AHjLHBzgwLcs84pqvTeI5351lsUc15GujBMB4lSmewYbu0Jiq1WtQ+R78oIG63uqNPC775NF8t1ykqh429xLba7Q= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1790785561; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=+8B775fti7/8ttx95ogjutn04uKNKtBQ3/cfwHm0TQU=; b=krbumHiZhUnf6b/LRusVtNpmMOMWJPZ0JHG12gl1A8U1YXG7/MiMXMg4c6ZH1Jmt798CFBsNIs+7hWOT9LRkKwIBI5F96PsJvm0jY/m44rDmlSg9XIeduTwgSGlahg/DEkfpTlc92jAj9CtzY9f4n7m73Q+bcpjkhYGLyuMNju4= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) by mx.zohomail.com with SMTPS id 1790785561664134.52828735711773; Wed, 30 Sep 2026 09:26:01 -0700 (PDT) Received: from list by lists.xenproject.org with outflank-mailman.1437581.1656654 (Exim 4.92) (envelope-from ) id 1xBx6r-0000qp-Po; Wed, 30 Sep 2026 16:24:45 +0000 Received: by outflank-mailman (output) from mailman id 1437581.1656654; Wed, 30 Sep 2026 16:24:45 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1xBx6q-0000kn-Fl; Wed, 30 Sep 2026 16:24:44 +0000 Received: by outflank-mailman (input) for mailman id 1437581; Wed, 30 Sep 2026 16:24:39 +0000 Received: from mx.expurgate.net ([194.145.224.20]) by lists.xenproject.org with esmtp (Exim 4.92) id 1xBx6k-0007wE-NU for xen-devel@lists.xenproject.org; Wed, 30 Sep 2026 16:24:38 +0000 Received: from mx.expurgate.net (helo=localhost) by mx.expurgate.net with esmtp id 1xBx6k-00GhYY-3a for xen-devel@lists.xenproject.org; Wed, 30 Sep 2026 18:24:38 +0200 Received: from [10.42.69.9] (helo=localhost) by localhost with ESMTP (eXpurgate MTA 0.9.1) (envelope-from ) id 6abd37a9-bab6-0a2a0a5309dd-0a2a4509a632-42 for ; Wed, 30 Sep 2026 18:24:38 +0200 Received: from [74.125.225.140] (helo=mail-wm2-f12.google.com) by tlsNG-bad1c0.mxtls.expurgate.net with ESMTPS (eXpurgate 4.57.1) (envelope-from ) id 6abd37c5-be1a-0a2a45090019-4a7de18cdc36-3 for ; Wed, 30 Sep 2026 18:24:38 +0200 Received: by mail-wm2-f12.google.com with SMTP id 5b1f17b1804b1-49ce364488dso7625935e9.0 for ; Wed, 30 Sep 2026 09:24:38 -0700 (PDT) Received: from fedora (user-109-243-71-234.play-internet.pl. [109.243.71.234]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-4a01cd43e66sm14620485e9.2.2026.09.30.09.24.35 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 30 Sep 2026 09:24:36 -0700 (PDT) X-Outflank-Mailman: Message body and most headers restored to incoming version X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" Authentication-Results: eu.smtp.expurgate.cloud; dkim=pass header.s=20251104 header.d=gmail.com header.i="@gmail.com" header.h="Content-Transfer-Encoding:MIME-Version:References:In-Reply-To:Message-ID:Date:Subject:Cc:To:From" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1790785477; x=1791390277; darn=lists.xenproject.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=+8B775fti7/8ttx95ogjutn04uKNKtBQ3/cfwHm0TQU=; b=Ykk2y5T5sgwW4BrIbsp41Lp5cu3CNA1ZI1znxPziGTmFIEZDIETEv0NdfvdiVJ4NLg xQ/9yOss7vORewhmQFNlESJiWRTVBcbCVY7EcbJ4/UM8a5c7vNr/6TyboBBbrqL6fESG 8zr1yypC6ldtH5UhULUlC/XEjyqQLdWTKaPcVAflnQwAQHX5FgQA3Ksq6X2ktJhYJBkd h9GwYbwQ8cVBD0j1GCEAC65lnbUvk06xKFvFlyrp1yd2UDIYAyLp61P02wl+8EaeWrkp 6SsuQvmnvdNHKUc+gxfrdKr2pEupHIiJOckANR91h1XfOIalnqp1/nDxu4A5d9eqqqP5 WHcw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1790785477; x=1791390277; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=+8B775fti7/8ttx95ogjutn04uKNKtBQ3/cfwHm0TQU=; b=XPrqzO2VB0rfY5DY87KXkfBB6n/onBSq4TY8I2onO1GC+7hMtddEwiFWhXDY3PovTZ 7btbth7SEin/WfvKdR40gbMNTluKHB5wl6JLIwluDjCBR6xg6MfQ38ZzNv7uZhd4TUuS GHpDZSUsDydWm+5aqxVWqCppfDy7qocUPDCiFqdOsgcx9P7eNK4a5tCk1eBkggTDrbjF eoh5Snqh0FJUBuVa8IG6JzhzBpY0r6A2i/QCW2BSN6yhilN6fxLWhGUexXzSP+2TZ/4P hqW5cGRDcMHfJiBI1+vp1B/tEb17/scaSSlsqlObHPRSoVrPBwwmKNcsm/yCiTyQsXum npuQ== X-Gm-Message-State: AFuF++mq+CHo0xYFESIM3WvY42xOuMjmX3l2O8Bha4/s92344qF+KgYU OHs2o+Kr+flUZGyLrDgrim6kKetmImmONKgh2H5/9cPIZDVfP+DH5jO/TEqGXg== X-Gm-Gg: AYBFou3t3romLe+Leg/m/7kSmHWk4FUNXYfldNlgvbiXnQ+ptju6uy1VZtYp8kbJeVK uAhmTPYJRaariJC2osDJYN/EVQEe/+rZObREKTMd7ZVadtnATSPSHGqnPEQNafI23Y/rI8fq6lw owjWq/l0GsVHpwBCRLJEwkoj83tA1qUzap85b1iwfny9QIuUIGTmtWakK4c2jEJFyqsyk8ogvwD c/39Yx/04GS4L6tfQ8T5cKIsV66Xbkm8gYJ1C9wDHKNpY5C3EbJ9/L+pkkQz61rtPDtD4ERHB4+ q44G01JpxKvazDZijgWbc3UB5eD/cBitlNhVNJyRHFNWH/ypL2/D5+1sx+OkCEKDLjHVAABWeyf AEjrwDc+ivAvQ3O3YTHJKKj1Hetrlsyz2e7zit4ZFoNCtg3xL0rGFp3w7y+BYGq96JRIPOXMieY QFcwwssHjNtILtF+hjkUOTpvZuOn9DuMyqWy8ajswapNj8TcBtKPCd0cyWMZd300f3pTGKgxhNk RgWCQBkjTHaY4620703aDV9gHawBgCRPGnw3vuNVw== X-Received: by 2002:a05:600c:83ca:b0:49e:6581:7baf with SMTP id 5b1f17b1804b1-4a01eaf59c6mr3169915e9.2.1790785476847; Wed, 30 Sep 2026 09:24:36 -0700 (PDT) From: Oleksii Kurochko To: xen-devel@lists.xenproject.org Cc: Romain Caritey , Baptiste Le Duc , Zheng Zhang , Oleksii Kurochko , Alistair Francis , Connor Davis , Andrew Cooper , Anthony PERARD , Michal Orzel , Jan Beulich , Julien Grall , =?UTF-8?q?Roger=20Pau=20Monn=C3=A9?= , Stefano Stabellini Subject: [PATCH v3 32/39] xen/riscv: save and clear the old IMSIC VS-file on vCPU migration Date: Wed, 30 Sep 2026 18:23:51 +0200 Message-ID: X-Mailer: git-send-email 2.55.0 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-purgate-ID: tlsNG-bad1c0/1790785478-BF8D1034-5439D328/10/73395122804 X-purgate-type: spam X-purgate-size: 10576 X-ZohoMail-DKIM: pass (identity @gmail.com) X-ZM-MESSAGEID: 1790785562480158500 Content-Type: text/plain; charset="utf-8" When a vCPU migrates to another pCPU, its guest interrupt file has to move as well: the eidelivery, eithreshold and eip/eie state of the old IMSIC VS-file has to be carried over to the newly acquired one. Once all interrupt producers have been retargeted to the new VS-file, so that nothing can reach the old one anymore, read the state of the old one and clear it at the same time. This has to be done on the pCPU owning the old VS-file, as a guest interrupt file is only accessible through vsiselect/vsireg with hstatus.VGEIN selecting it. After that the old VS-file is no longer in use and its guest external interrupt number can be released. The state is saved into struct imsic_mrif. Its eix[] array follows the layout of a memory-resident interrupt file (MRIF) as defined by the AIA specification: pairs of 64-bit interrupt-pending and interrupt-enable doublewords, each pair covering 64 interrupt identities. eithreshold and eidelivery aren't part of an MRIF and are stored next to it as they belong to the interrupt file state too. Using the MRIF layout allows the same structure to hold the interrupt file of a vCPU which doesn't own a guest interrupt file, which is how the AIA specification describes MRIFs being used by a hypervisor. Here the structure is only a temporary copy of a guest interrupt file: it is filled and consumed by Xen alone and its address is never given to an IOMMU, so no MSI is ever recorded into it. Hence plain (non-atomic) accesses are sufficient and it can live on the stack. The saved state still has to be restored into the new VS-file, so keep the BUG_ON("unimplemented") placeholder at the end of imsic_migrate_vcpu() to avoid silently losing the guest's interrupt state. Signed-off-by: Oleksii Kurochko --- Changes in v3: - Reword the commit message: explain why the MRIF layout is used and why the copy isn't an MSI target, drop references to later patches. - Compare vsfile_cpu against CPU_NONE instead of NR_CPUS. - Introduce imsic_switchcase_ret() here, together with its first user, drop its unused variadic form and leave the trailing semicolon to its users. - Introduce the mrif member of struct imsic_vsfile_data here, together with its first user. - Initialise vsfile_data.mrif in imsic_migrate_vcpu() with a compound literal instead of adding a separate tmrif local variable, so the MRIF the old interrupt file is dumped into is visibly the one later restored from. - Drop the redundant parentheses around the arguments of imsic_vs_csr_swap() and its unnecessary local variable. - Use plain 64 instead of BITS_PER_TYPE(uint64_t) for the number of interrupt identities covered by an EIx group, and explain in the comment ahead of IMSIC_MAX_EIX where it comes from (the MRIF layout from the AIA spec). - Keep each EIx group of the MRIF as a uint64_t and introduce imsic_eix_swap64() to swap a whole group, which lets the #ifdef CONFIG_RISCV_32 in imsic_vsfile_local_read_clear() go. - Add missing break after ASSERT_UNREACHABLE() in the default case of imsic_eix_swap(). - Use MASK_INSR() to set HSTATUS.VGEIN in imsic_vsfile_local_read_clear(). - Explain in imsic_vsfile_local_read_clear() why hstatus and vsiselect are saved and restored. - Reword the comment on why no atomic accessors are needed to store the values into the MRIF. - Take the number of EIx groups from vsfile_data.nr_eix, as the nr_hw_eix local variable is gone from imsic_migrate_vcpu(). - Move the vgein_release() stub to "xen/riscv: remap interrupts to new IMSIC VS-file", where it gains its first user. --- Changes in v2: - New patch. --- --- xen/arch/riscv/imsic.c | 124 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 124 insertions(+) diff --git a/xen/arch/riscv/imsic.c b/xen/arch/riscv/imsic.c index 47854264edf3..2c4838b6b228 100644 --- a/xen/arch/riscv/imsic.c +++ b/xen/arch/riscv/imsic.c @@ -57,6 +57,28 @@ static unsigned int __ro_after_init guest_num_msis; */ #define GUEST_IMSIC_MAX_MSIS 255U =20 +/* + * The interrupt identities an IMSIC interrupt file provides are 0 (which = is + * never valid, but still occupies a bit) up to IMSIC_MAX_ID inclusive, so + * IMSIC_MAX_ID + 1 bits have to be covered. + * + * Each EIx group covers 64 identities, matching the memory-resident inter= rupt + * file (MRIF) layout from the AIA spec, where pending and enable bits are + * stored as pairs of 64-bit doublewords. + */ +#define IMSIC_MAX_EIX DIV_ROUND_UP(IMSIC_MAX_ID + 1, 64) + +struct imsic_mrif_eix { + uint64_t eip; + uint64_t eie; +}; + +struct imsic_mrif { + struct imsic_mrif_eix eix[IMSIC_MAX_EIX]; + unsigned long eithreshold; + unsigned long eidelivery; +}; + #define IMSIC_DISABLE_EIDELIVERY 0 #define IMSIC_ENABLE_EIDELIVERY 1 #define IMSIC_DISABLE_EITHRESHOLD 1 @@ -86,6 +108,12 @@ do { \ csr_clear(CSR_SIREG, v); \ } while (0) =20 +#define imsic_vs_csr_swap(c, v) \ +({ \ + csr_write(CSR_VSISELECT, c); \ + csr_swap(CSR_VSIREG, v); \ +}) + #define imsic_vs_csr_write(c, v) \ do { \ csr_write(CSR_VSISELECT, c); \ @@ -95,12 +123,17 @@ do { \ /* * Leaf macros for the switchcase expansion pyramid below: * imsic_switchcase_break(ireg, op, v) - emit "case ireg: op(ireg, v); bre= ak" + * imsic_switchcase_ret(ireg, op, v) - emit "case ireg: return op(ireg, v)" */ #define imsic_switchcase_break(ireg, op, v) \ case ireg: \ op(ireg, v); \ break =20 +#define imsic_switchcase_ret(ireg, op, v) \ + case ireg: \ + return op(ireg, v) + /* * Generic switchcase expansion pyramid. * F is the per-operation leaf macro, ireg is the base register index. @@ -126,6 +159,22 @@ do { \ imsic_switchcase_32(F, (ireg) + 0, __VA_ARGS__); \ imsic_switchcase_32(F, (ireg) + 32, __VA_ARGS__) =20 +static unsigned long imsic_eix_swap(unsigned int ireg, unsigned long val) +{ + switch ( ireg ) + { + imsic_switchcase_64(imsic_switchcase_ret, IMSIC_EIP0, + imsic_vs_csr_swap, val); + imsic_switchcase_64(imsic_switchcase_ret, IMSIC_EIE0, + imsic_vs_csr_swap, val); + default: + ASSERT_UNREACHABLE(); + break; + } + + return 0; +} + static void imsic_eix_write(unsigned int ireg, unsigned long val) { switch ( ireg ) @@ -152,6 +201,17 @@ static void imsic_eix_write64(unsigned int ireg, uint6= 4_t val) imsic_eix_write(ireg + 1, val >> 32); } =20 +/* Swap a whole 64-bit EIx group, laid out as described above. */ +static uint64_t imsic_eix_swap64(unsigned int ireg, uint64_t val) +{ + uint64_t old =3D imsic_eix_swap(ireg, val); + + if ( IS_ENABLED(CONFIG_RISCV_32) ) + old |=3D (uint64_t)imsic_eix_swap(ireg + 1, val >> 32) << 32; + + return old; +} + unsigned int vcpu_guest_file_id(const struct vcpu *v) { return ACCESS_ONCE(v->arch.vimsic_state->guest_file_id); @@ -514,6 +574,8 @@ struct imsic_vsfile_data { unsigned int hgei; /* Number of 64-bit EIx groups to cover, see imsic_cfg.nr_eix. */ unsigned int nr_eix; + /* Where the interrupt file state is saved to or restored from. */ + struct imsic_mrif *mrif; }; =20 /* @@ -598,6 +660,60 @@ static void cf_check imsic_vsfile_local_clear(void *da= ta) csr_write(CSR_VSISELECT, old_vsiselect); } =20 +static void cf_check imsic_vsfile_local_read_clear(void *data) +{ + unsigned int i; + const struct imsic_vsfile_data *idata =3D data; + struct imsic_mrif *mrif =3D idata->mrif; + unsigned long new_hstatus, old_hstatus, old_vsiselect; + + /* + * The file is reached by retargeting hstatus.VGEIN, and + * imsic_vs_csr_swap() alters vsiselect. Both belong to the vCPU runni= ng + * on this pCPU, so restore them before returning. + */ + old_vsiselect =3D csr_read(CSR_VSISELECT); + old_hstatus =3D csr_read(CSR_HSTATUS); + new_hstatus =3D old_hstatus & ~HSTATUS_VGEIN; + new_hstatus |=3D MASK_INSR(idata->hgei, HSTATUS_VGEIN); + csr_write(CSR_HSTATUS, new_hstatus); + + /* + * No atomic accessors are needed to store the values into the MRIF he= re, + * as imsic_vsfile_read_clear() is always called with a pointer to a + * temporary MRIF on the stack. + */ + + mrif->eidelivery =3D imsic_vs_csr_swap(IMSIC_EIDELIVERY, 0); + mrif->eithreshold =3D imsic_vs_csr_swap(IMSIC_EITHRESHOLD, 0); + for ( i =3D 0; i < idata->nr_eix; i++ ) + { + mrif->eix[i].eip =3D imsic_eix_swap64(IMSIC_EIP0 + i * 2, 0); + mrif->eix[i].eie =3D imsic_eix_swap64(IMSIC_EIE0 + i * 2, 0); + } + + csr_write(CSR_HSTATUS, old_hstatus); + csr_write(CSR_VSISELECT, old_vsiselect); +} + +static void imsic_vsfile_read_clear(unsigned int vsfile_id, + unsigned int vsfile_cpu, + unsigned int nr_eix, + struct imsic_mrif *mrif) +{ + struct imsic_vsfile_data idata =3D { + .hgei =3D vsfile_id, + .nr_eix =3D nr_eix, + .mrif =3D mrif, + }; + + /* We can only read clear if we have an IMSIC VS-file */ + if ( vsfile_cpu =3D=3D CPU_NONE || !vsfile_id ) + return; + + imsic_call_on_cpu(vsfile_cpu, imsic_vsfile_local_read_clear, &idata); +} + void cf_check vcpu_imsic_deinit(struct vcpu *v) { XVFREE(v->arch.vimsic_state); @@ -960,6 +1076,7 @@ void imsic_migrate_vcpu(struct vcpu *v) { struct imsic_vsfile_data vsfile_data =3D { .nr_eix =3D imsic_cfg.nr_eix, + .mrif =3D &(struct imsic_mrif){ }, }; struct vimsic_state *imsic_state =3D v->arch.vimsic_state; unsigned long flags; @@ -1028,5 +1145,12 @@ void imsic_migrate_vcpu(struct vcpu *v) * to the new IMSIC VS-file. */ =20 + /* Read and clear register state from old IMSIC VS-file */ + imsic_vsfile_read_clear(old_vsfile_id, old_vsfile_cpu, vsfile_data.nr_= eix, + vsfile_data.mrif); + + /* Free-up old IMSIC VS-file */ + vgein_release(v, old_vsfile_id, old_vsfile_cpu); + BUG_ON("unimplemented"); } --=20 2.55.0 From nobody Fri Oct 23 15:32:28 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) client-ip=192.237.175.120; envelope-from=xen-devel-bounces@lists.xenproject.org; helo=lists.xenproject.org; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=pass(p=none dis=none) header.from=gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1790785565; cv=none; d=zohomail.com; s=zohoarc; b=Bdy8WhLsRo9bgo8Q5GzmH1jppx3oLarRCnoE7ctvKIQEbmcYzvMZOVBm0V7LRzA29rAKKVihT8d+WYeb47h9f4hAE7i/QGeKNYv5HzSCLkzKl/a1arWPEpnbxMyq8rUM+/hIDdNDASdlGKUxSYqMyFOWSlInTI6ihb4JW88mGCM= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1790785565; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=h6Hg7gJxYMiiQ/gDnFpoYC7wmk8KrE2atCGH+OWlkLA=; b=h/qZQECSccVMv+XaRE+RpCAmnUi2s9W5Dptvp9b5g84ukvapeBXhGI5BsIsNhS9XcIwDdgdVB6F7CkKsvUkh72fbGCGM55MUh3//JtuWoD/kJN8EPmxasQxL1WiajBtPdcuK9C0bigSffL6cPfoCbrvdQj8D6HyYVWkojtgStqI= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) by mx.zohomail.com with SMTPS id 1790785565897328.1941463166577; Wed, 30 Sep 2026 09:26:05 -0700 (PDT) Received: from list by lists.xenproject.org with outflank-mailman.1437582.1656657 (Exim 4.92) (envelope-from ) id 1xBx6t-0001Aj-3T; Wed, 30 Sep 2026 16:24:47 +0000 Received: by outflank-mailman (output) from mailman id 1437582.1656657; Wed, 30 Sep 2026 16:24:46 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1xBx6r-00015W-WF; Wed, 30 Sep 2026 16:24:46 +0000 Received: by outflank-mailman (input) for mailman id 1437582; Wed, 30 Sep 2026 16:24:39 +0000 Received: from mx.expurgate.net ([194.145.224.10]) by lists.xenproject.org with esmtp (Exim 4.92) id 1xBx6l-00082a-9N for xen-devel@lists.xenproject.org; Wed, 30 Sep 2026 16:24:39 +0000 Received: from mx.expurgate.net (helo=localhost) by mx.expurgate.net with esmtp id 1xBx6k-006O0j-LU for xen-devel@lists.xenproject.org; Wed, 30 Sep 2026 18:24:38 +0200 Received: from [10.42.69.8] (helo=localhost) by localhost with ESMTP (eXpurgate MTA 0.9.1) (envelope-from ) id 6abd37b9-2eae-0a2a0a5409dd-0a2a4508b85c-26 for ; Wed, 30 Sep 2026 18:24:38 +0200 Received: from [74.125.225.141] (helo=mail-wm2-f13.google.com) by tlsNG-c1860d.mxtls.expurgate.net with ESMTPS (eXpurgate 4.57.1) (envelope-from ) id 6abd37c6-f659-0a2a45080019-4a7de18dd89c-3 for ; Wed, 30 Sep 2026 18:24:38 +0200 Received: by mail-wm2-f13.google.com with SMTP id 5b1f17b1804b1-49b912d822dso41393795e9.2 for ; Wed, 30 Sep 2026 09:24:38 -0700 (PDT) Received: from fedora (user-109-243-71-234.play-internet.pl. [109.243.71.234]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-4a01cd43e66sm14620485e9.2.2026.09.30.09.24.37 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 30 Sep 2026 09:24:37 -0700 (PDT) X-Outflank-Mailman: Message body and most headers restored to incoming version X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" Authentication-Results: eu.smtp.expurgate.cloud; dkim=pass header.s=20251104 header.d=gmail.com header.i="@gmail.com" header.h="Content-Transfer-Encoding:MIME-Version:References:In-Reply-To:Message-ID:Date:Subject:Cc:To:From" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1790785478; x=1791390278; darn=lists.xenproject.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=h6Hg7gJxYMiiQ/gDnFpoYC7wmk8KrE2atCGH+OWlkLA=; b=bg5A9mqRc6blLiUA5W1LTK4Ytv+c9AfcgLaeE2Zy1s1GXvZ3nOFiZORVWNQjnAqe1R vHh5Ar4VzdY35LRfuzQKAyDbbp/UOL6wwk57Tgi3T81QcyiEN9I7+AuenlQxvBnYyvhL 3Rr0Ul9lxbUBBvDWjulxGDdABdkDl67H4yc8TsMnyopcTIvwrWqi09DxKktcQzmvGod6 Z1jsNcfiaTAsJM90LYmw7eeIA3B782RQ9CI+UEtAencKyBPSr9mA+pvmBStGamJKroPO QLWa4UaH/hINYE5VC5xV9O7jQKYqyq3L2jXAubi9uAKYbptX1gwFKbi5Zd76zk6D0n/6 Excg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1790785478; x=1791390278; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=h6Hg7gJxYMiiQ/gDnFpoYC7wmk8KrE2atCGH+OWlkLA=; b=T1TOD5a19DCKaYKIHJFoguk3EnuGNcQxes7oU3jdPMnjq2vOD8R+nO4FLFH8Z1VuR7 W7uwJAK8HfpoBi5isTboMvxWLKuG02/Hk8bvujMDYpOFVyK9LetT4ZWZy1QFv4B308UT An4jOrlSv4zPgb+BasCbKsHkvL0jm4YUjHT6OFtBV3WP8JLR7zgTBlzqPBXkmGMleFid t4ntVn16JWjq3Vt4hJQrMSzMGDekDTim6W2h/EGRryv3ePiSijHxxnraRcJgeGkj0mXk 3hV6t8ransydi8ihGz9f63lsIarCctEPmFp9K4hlQnYIBumyPYLj7Ek9L317C2cLTwvE 1Fzw== X-Gm-Message-State: AFuF++m68glbr+VCJa5QpIctY3j/XYhozp4yZGJ/mhwn8uMgeMsltrYK 4mdv6kCLGET79PzbXY6hjr5mNGpANxRIdtbr1FShQH34CHi0w2PKVzFp2/enSw== X-Gm-Gg: AYBFou0wXvDx2wng6XFnbH71rmoVMFw8uKUWHuLLxlnrJhRNmqPDYEISORTr/JmwaSW hUQCNVY/YM9MrHvY5954ZFQZ0zZT/D/9IAlSii822edyA4Kw5sNveVsQfmTUFAS2wL7RUxY17ZS pHZFKq8B50JlPMrEMK7UW7AXCYbOrT4LZFxcOgUsjGkW8dMjErmsDLGsOHRuX2q5mMGQHxoNERg CDFo8IskfWNqYfQA1AfESHE3r3OBXxCRV3Z0FRqaRT6MBRf821Fu6FhxGYh5l1lrmgvYMUirgLu TE36uecxsVgo+Um6giykUFlPhoL/E0ZhxUn6YV6nqXb1pypoeLTsgY0VmRnliAuXLU2sIdlkh7X bs7fIsOXCxZTiPnQtx8EL56QJyByOYjCgn/MnTGe5SNmMhnRQ61rNi+5isBVdDp34dd4QyqOs2u k5wCaJVIOiyk5mZLI7eooQ2je9tTp1fqRM8Ifh8yf8vEjNPJfGkO1FZLl3zFmooHW2Zs4wMbDhy WPbTDVe2hAqcdQO2J3dGo4TkAH8b2hIrYOEzIOc X-Received: by 2002:a05:600c:a03:b0:49f:ffd0:4039 with SMTP id 5b1f17b1804b1-4a01b0072c1mr33525515e9.32.1790785477942; Wed, 30 Sep 2026 09:24:37 -0700 (PDT) From: Oleksii Kurochko To: xen-devel@lists.xenproject.org Cc: Romain Caritey , Baptiste Le Duc , Zheng Zhang , Oleksii Kurochko , Alistair Francis , Connor Davis , Andrew Cooper , Anthony PERARD , Michal Orzel , Jan Beulich , Julien Grall , =?UTF-8?q?Roger=20Pau=20Monn=C3=A9?= , Stefano Stabellini Subject: [PATCH v3 33/39] xen/riscv: restore register state in the new IMSIC VS-file Date: Wed, 30 Sep 2026 18:23:52 +0200 Message-ID: <9e77a699eb6c99fa8f444d5777da189fdd30679e.1790779209.git.oleksii.kurochko@gmail.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-purgate-ID: tlsNG-c1860d/1790785478-D5F4787B-33CA522F/10/73395122804 X-purgate-type: spam X-purgate-size: 6576 X-ZohoMail-DKIM: pass (identity @gmail.com) X-ZM-MESSAGEID: 1790785566484158500 Content-Type: text/plain; charset="utf-8" Complete the migration of a vCPU's guest interrupt file: move the state saved from the old IMSIC VS-file into the new one and make the vCPU use the new VS-file. The interrupt producers have already been retargeted to the new VS-file, so MSIs may land in it before the saved state is restored. Hence the saved eip/eie bits are ORed into the new VS-file rather than written to it, so that such MSIs aren't lost. eithreshold and eidelivery are restored last: the new VS-file was cleared when it was acquired, so it doesn't deliver interrupts until its pending and enable bits are complete. As with reading the old VS-file, this has to be done on the pCPU owning the new VS-file, with hstatus.VGEIN temporarily selecting it. That is v->processor, the pCPU the vCPU is migrating to. Finally, point hstatus.VGEIN in the vCPU's saved context at the new VS-file, so that it becomes the source of the vCPU's VS-level external interrupts and the file the guest accesses through its siselect/sireg. With that the migration is complete, so drop the BUG_ON("unimplemented") placeholder from imsic_migrate_vcpu(). Signed-off-by: Oleksii Kurochko --- Changes in v3: - Reword the commit message: explain why the saved state is ORed into the new VS-file and why eithreshold and eidelivery are restored last, drop the note about explanatory comments. - Leave the trailing semicolon of the switchcase macros to their users. - Drop the redundant parentheses around the arguments of imsic_vs_csr_set() as they are passed to csr_*() as whole expressions. - Add missing break after ASSERT_UNREACHABLE() in the default case of imsic_eix_set(). - Restore the state on v->processor and take the id of the new IMSIC VS-file from vsfile_data.hgei, as imsic_migrate_vcpu() no longer has separate local variables for the new VS-file. - Explain why hstatus and vsiselect are saved and restored with a short comment in imsic_vsfile_local_update(). - Introduce imsic_eix_set64() to set bits of a whole 64-bit EIx group, which lets the #ifdef CONFIG_RISCV_32 in imsic_vsfile_local_update() go. - Move the MASK_INSR() conversion and the comment rewording in imsic_vsfile_local_read_clear() to the patch introducing that function. --- Changes in v2: - New patch. --- --- xen/arch/riscv/imsic.c | 80 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 78 insertions(+), 2 deletions(-) diff --git a/xen/arch/riscv/imsic.c b/xen/arch/riscv/imsic.c index 2c4838b6b228..e35688f98bb1 100644 --- a/xen/arch/riscv/imsic.c +++ b/xen/arch/riscv/imsic.c @@ -114,6 +114,12 @@ do { \ csr_swap(CSR_VSIREG, v); \ }) =20 +#define imsic_vs_csr_set(c, v) \ +do { \ + csr_write(CSR_VSISELECT, c); \ + csr_set(CSR_VSIREG, v); \ +} while (0) + #define imsic_vs_csr_write(c, v) \ do { \ csr_write(CSR_VSISELECT, c); \ @@ -212,6 +218,28 @@ static uint64_t imsic_eix_swap64(unsigned int ireg, ui= nt64_t val) return old; } =20 +static void imsic_eix_set(unsigned int ireg, unsigned long val) +{ + switch ( ireg ) + { + imsic_switchcase_64(imsic_switchcase_break, IMSIC_EIP0, + imsic_vs_csr_set, val); + imsic_switchcase_64(imsic_switchcase_break, IMSIC_EIE0, + imsic_vs_csr_set, val); + default: + ASSERT_UNREACHABLE(); + break; + } +} + +/* Set bits of a whole 64-bit EIx group, laid out as described above. */ +static void imsic_eix_set64(unsigned int ireg, uint64_t val) +{ + imsic_eix_set(ireg, val); + if ( IS_ENABLED(CONFIG_RISCV_32) ) + imsic_eix_set(ireg + 1, val >> 32); +} + unsigned int vcpu_guest_file_id(const struct vcpu *v) { return ACCESS_ONCE(v->arch.vimsic_state->guest_file_id); @@ -1016,6 +1044,47 @@ int __init vimsic_make_domu_dt_node(struct kernel_in= fo *kinfo, return fdt_end_node(fdt); } =20 +static void cf_check imsic_vsfile_local_update(void *data) +{ + unsigned int i; + const struct imsic_vsfile_data *idata =3D data; + struct imsic_mrif *mrif =3D idata->mrif; + unsigned long new_hstatus, old_hstatus, old_vsiselect; + + /* We can only update if we have a HW IMSIC context */ + if ( !idata->hgei ) + return; + + /* + * No atomic accessors are needed to read the values out of the MRIF h= ere, + * as this is always called with a pointer to a temporary MRIF on the + * stack. + */ + + /* + * The file is reached by retargeting hstatus.VGEIN, and the + * imsic_vs_csr_*() accessors alter vsiselect. Both belong to the vCPU + * running on this pCPU, so restore them before returning. + */ + old_vsiselect =3D csr_read(CSR_VSISELECT); + old_hstatus =3D csr_read(CSR_HSTATUS); + new_hstatus =3D old_hstatus & ~HSTATUS_VGEIN; + new_hstatus |=3D MASK_INSR(idata->hgei, HSTATUS_VGEIN); + csr_write(CSR_HSTATUS, new_hstatus); + + for ( i =3D 0; i < idata->nr_eix; i++ ) + { + imsic_eix_set64(IMSIC_EIP0 + i * 2, mrif->eix[i].eip); + imsic_eix_set64(IMSIC_EIE0 + i * 2, mrif->eix[i].eie); + } + + imsic_vs_csr_write(IMSIC_EITHRESHOLD, mrif->eithreshold); + imsic_vs_csr_write(IMSIC_EIDELIVERY, mrif->eidelivery); + + csr_write(CSR_HSTATUS, old_hstatus); + csr_write(CSR_VSISELECT, old_vsiselect); +} + /* * Take a h/w guest interrupt file on the pCPU @v runs on and make it the * vCPU's one. @@ -1142,7 +1211,8 @@ void imsic_migrate_vcpu(struct vcpu *v) =20 /* * At this point, all interrupt producers have been moved - * to the new IMSIC VS-file. + * to the new IMSIC VS-file so we move register state from + * the old IMSIC VS/SW-file to the new IMSIC VS-file. */ =20 /* Read and clear register state from old IMSIC VS-file */ @@ -1152,5 +1222,11 @@ void imsic_migrate_vcpu(struct vcpu *v) /* Free-up old IMSIC VS-file */ vgein_release(v, old_vsfile_id, old_vsfile_cpu); =20 - BUG_ON("unimplemented"); + /* Restore register state in the new IMSIC VS-file */ + imsic_call_on_cpu(v->processor, imsic_vsfile_local_update, &vsfile_dat= a); + + /* Set VCPU HSTATUS.VGEIN to new IMSIC VS-file */ + vcpu_guest_cpu_user_regs(v)->hstatus &=3D ~HSTATUS_VGEIN; + vcpu_guest_cpu_user_regs(v)->hstatus |=3D + MASK_INSR(vsfile_data.hgei, HSTATUS_VGEIN); } --=20 2.55.0 From nobody Fri Oct 23 15:32:28 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) client-ip=192.237.175.120; envelope-from=xen-devel-bounces@lists.xenproject.org; helo=lists.xenproject.org; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=pass(p=none dis=none) header.from=gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1790785572; cv=none; d=zohomail.com; s=zohoarc; b=Y7enlCVnCX/tblMa/pLnJKHK43iuUUxe0AuFQc64hskAYW9QiPWaEhyO+RaRNU9vCG+q0w4tK/1P5B1bL4Qj+3Gsnia00DtRjblqnUzqw7jVSN5Xd9Zws4aq617ZV7PY65IXjFEXI0VhVnksG2App5TzHFPYshMP2xGZaEfjDm8= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1790785572; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=610DRMFDBiGcXXmSTtIhjQLzW2cXO7IOR4SB2YV3JbE=; b=QjsPRNZS0VeE9k+KZ4LA/le8LwgqaiG9/8fEznvJ+tTucB4dFTZTpX49D0CCX7gi/VBP5CUYgyMPNjNG+dIgtBCs8vA2EwPw6BkVDVfY45NaVcoor1yCqAIBIJLBpj3vF0Yc2gt7Cc9BP/WLOQqkwKVlDMScoahDuCK+eNX2+ZM= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) by mx.zohomail.com with SMTPS id 17907855728021005.3056070862175; Wed, 30 Sep 2026 09:26:12 -0700 (PDT) Received: from list by lists.xenproject.org with outflank-mailman.1437584.1656666 (Exim 4.92) (envelope-from ) id 1xBx6u-0001Nf-F3; Wed, 30 Sep 2026 16:24:48 +0000 Received: by outflank-mailman (output) from mailman id 1437584.1656666; Wed, 30 Sep 2026 16:24:48 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1xBx6t-0001Jd-BA; Wed, 30 Sep 2026 16:24:47 +0000 Received: by outflank-mailman (input) for mailman id 1437584; Wed, 30 Sep 2026 16:24:41 +0000 Received: from mx.expurgate.net ([194.145.224.20]) by lists.xenproject.org with esmtp (Exim 4.92) id 1xBx6m-0008DH-9s for xen-devel@lists.xenproject.org; Wed, 30 Sep 2026 16:24:40 +0000 Received: from mx.expurgate.net (helo=localhost) by mx.expurgate.net with esmtp id 1xBx6l-00GhdM-Jl for xen-devel@lists.xenproject.org; Wed, 30 Sep 2026 18:24:39 +0200 Received: from [10.42.69.1] (helo=localhost) by localhost with ESMTP (eXpurgate MTA 0.9.1) (envelope-from ) id 6abd37bc-8faa-0a2a0a5109dd-0a2a4501b376-16 for ; Wed, 30 Sep 2026 18:24:39 +0200 Received: from [74.125.225.140] (helo=mail-wm2-f12.google.com) by tlsNG-d62444.mxtls.expurgate.net with ESMTPS (eXpurgate 4.57.1) (envelope-from ) id 6abd37c7-5984-0a2a45010019-4a7de18cab08-3 for ; Wed, 30 Sep 2026 18:24:39 +0200 Received: by mail-wm2-f12.google.com with SMTP id 5b1f17b1804b1-49e69b9e16aso57813795e9.1 for ; Wed, 30 Sep 2026 09:24:39 -0700 (PDT) Received: from fedora (user-109-243-71-234.play-internet.pl. [109.243.71.234]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-4a01cd43e66sm14620485e9.2.2026.09.30.09.24.38 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 30 Sep 2026 09:24:38 -0700 (PDT) X-Outflank-Mailman: Message body and most headers restored to incoming version X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" Authentication-Results: eu.smtp.expurgate.cloud; dkim=pass header.s=20251104 header.d=gmail.com header.i="@gmail.com" header.h="Content-Transfer-Encoding:MIME-Version:References:In-Reply-To:Message-ID:Date:Subject:Cc:To:From" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1790785479; x=1791390279; darn=lists.xenproject.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=610DRMFDBiGcXXmSTtIhjQLzW2cXO7IOR4SB2YV3JbE=; b=dL9f2ueUN6yzy1xW4TCuGulke85dicZ0BFETOWNzj0CFT+u9g15O2nDfZL7LZWC04V 7oeCGQ7s9VHgwcsh1WiLWQ8U4IOvnf9v4/zGEGHWGpnQxSfZIQcVk+lJHywWPP0zy+hz QUnG7lqd9IqqLMsUqrupNkn49uZ7RFdA22fVvaKq7L3/oXGftYcb4XoqlQEE7j4cJoOf gXkhNyOENvtr/XuQfEKyIDwwtysBRCgpFpnrPUnUM67wgnOD5GbdytLCpScWZ1Se6nas lxclamkzEs+TwigJLRK3Js+6tx7KkiIL7QeJXZ3pFFUxMGWO57wCjkAGqFKIZeTNzsLa 8pnQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1790785479; x=1791390279; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=610DRMFDBiGcXXmSTtIhjQLzW2cXO7IOR4SB2YV3JbE=; b=1CHF8pwlpRwceA/EqUicoSWMn/hIK+LONyI2QDXqriIFpFotfaFyMFtSy3Vi7DyM4p 9Un9eP+Xw1rf9jxd7yBlul2v82DWUdeNUjhU/oAs4xeZWyHJkZ68vJmI4rcjY1JwcbMq 42e0k7ovjUDnWKNrhRVia2WTz4fpHiDt/uLTLQsEycHrH0Fu6OEuiFXeBkJE7f9O3XJY swgaJEl+tG9v1CsPkuWsF3kX0+YWeUG58NsA5o+yrTbCmDoxCdASBmSo3eLA7zfBlzeM QRArsdNWqFzVAAm2F5orbyITlKup0mC8+q6Ax7mg0SV/QlXfIQoajq5D4cnq+nfNiwUS YTWQ== X-Gm-Message-State: AFuF++lSYzmQJ6KDFgJm8d6a+AKL1ZkU3zBge19je2R/eE5E3+ZuV0Xu OXX7TKU4hg3T+arBsCysGT/068jrLmBqStvZHCqwF9YF0pxKTcDscciCe85utg== X-Gm-Gg: AYBFou3LSk9oBn4HOlPXRHSdHH+H+pPFHjPNOWmKhiIhAHijDDx047c3aujgBdVzHhB COg9yOhZhK/JXCR5tFIsRdMeEPVBTGbWI4A42BtwA0c8YdBKIawYClXrSZB3GM/n+EZzqDrh5uR PeEtkQSQVxldEYwbfy3isJiZvgc1+5VqcAllnZO8MO04GQ1yKcVVzjzJHb1OR8jo/q9/qbSEqbF rI/7tK+ppe2j+fttmD/loQXyux42o8Qs/Gw57UQDHYL26d7TwAIpS4tuFrKznCkby2wlCFJJMQp QT7DPJuNIjefvELm1U5yc3MDapaADOGgFaauo5ns9cO8tBtPaonT8iL+DIL5l49NKCLd2hsnVJD bJo113583SOWjLqA25XpZNm2joerrWNDI1tU+3F4cOK07OFv3qt/PXlHGNchwLJRnd3acL87Yq6 T9LvDKwN6APQI7fx/DHWb6vMNVzxHW7pit+InlexpXQlvOAlcDz3xMb4NkLTX166LdPdHhoJRZr ridMG7ACXXisf7MHSj4Xq12DJ7qNcEPgHAhh1Mq X-Received: by 2002:a05:600c:5391:b0:49d:2562:d670 with SMTP id 5b1f17b1804b1-4a01afdcef8mr34050445e9.14.1790785479043; Wed, 30 Sep 2026 09:24:39 -0700 (PDT) From: Oleksii Kurochko To: xen-devel@lists.xenproject.org Cc: Romain Caritey , Baptiste Le Duc , Zheng Zhang , Oleksii Kurochko , Alistair Francis , Connor Davis , Andrew Cooper , Anthony PERARD , Michal Orzel , Jan Beulich , Julien Grall , =?UTF-8?q?Roger=20Pau=20Monn=C3=A9?= , Stefano Stabellini Subject: [PATCH v3 34/39] xen/riscv: add basic VGEIN management for AIA guests Date: Wed, 30 Sep 2026 18:23:53 +0200 Message-ID: <15a569b682e0490fcb8fe9b00f971c0effdacafc.1790779209.git.oleksii.kurochko@gmail.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-purgate-ID: tlsNG-d62444/1790785479-C5540757-C4ED22F6/10/78276251493 X-purgate-type: spam X-purgate-size: 6690 X-ZohoMail-DKIM: pass (identity @gmail.com) X-ZM-MESSAGEID: 1790785574574158500 Content-Type: text/plain; charset="utf-8" It was decided to add support for IMSIC from the start instead of having AP= LIC operate in direct delivery mode, as it requires a trap-and-emulation approa= ch, which is not optimal from a performance standpoint. AIA provides a hardware-accelerated mechanism for delivering external interrupts to domains via "guest interrupt files" located in IMSIC. A single physical hart can implement multiple such files (up to GEILEN), allowing several virtual harts to receive interrupts directly from hardware. Introduce per-CPU tracking of guest interrupt file identifiers (VGEIN) for systems implementing AIA specification. Each CPU maintains a bitmap describing which guest interrupt files are currently in use. Implement helpers to initialize the bitmap based on the number of available guest interrupt files (GEILEN), assign a VGEIN to a vCPU, and release it when no longer needed. Signed-off-by: Oleksii Kurochko Acked-by: Jan Beulich Reviewed-by: Baptiste Le Duc --- Also in the next patch there is other context to understand the usage of spinlock introduced here. --- Changes in v3: - Add Acked-by: Jan Beulich . - Add Reviewed-by: Baptiste Le Duc . --- Changes in v2: - make vgein_init() pCPU agnostic as it is working with CSR which could be read only on local pCPU itself. - Move introduction of vgein_ctrl->owners[] to separate patch. - Add ASSERT() and re-init vgein->bmp with 0. - Update the commit message (drop the last sentence as ->hstatus isn't filled anymore in in vgein_*() functions). - Introduce vgein_deinit(). --- --- xen/arch/riscv/aia.c | 141 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 137 insertions(+), 4 deletions(-) diff --git a/xen/arch/riscv/aia.c b/xen/arch/riscv/aia.c index bd35078b7354..1aca07c2f70f 100644 --- a/xen/arch/riscv/aia.c +++ b/xen/arch/riscv/aia.c @@ -1,13 +1,31 @@ /* SPDX-License-Identifier: GPL-2.0-only */ =20 -#include +#include +#include #include #include #include #include +#include #include =20 +#include #include +#include +#include + +struct vgein_ctrl { + /* The least-significant bits are implemented first, apart from bit 0 = */ + unsigned long bmp; + spinlock_t lock; + unsigned int geilen; +}; + +/* + * VGEIN control structure for each physical CPU to track which VS (guest) + * interrupt file IDs are in use. + */ +static DEFINE_PER_CPU(struct vgein_ctrl, vgein); =20 static bool __ro_after_init _aia_usable; =20 @@ -16,22 +34,137 @@ bool aia_usable(void) return _aia_usable; } =20 +/* HGEIE is a per-hart CSR, so this has to run on the CPU being initialize= d. */ +static int vgein_init(void) +{ + struct vgein_ctrl *vgein =3D &this_cpu(vgein); + + spin_lock_init(&vgein->lock); + + csr_write(CSR_HGEIE, ~0UL); + vgein->geilen =3D flsl(csr_read(CSR_HGEIE) >> 1); + csr_write(CSR_HGEIE, 0); + + vgein->bmp =3D 0; + + if ( !vgein->geilen ) + return -EOPNOTSUPP; + + return 0; +} + +static void vgein_deinit(void) +{ + csr_write(CSR_HGEIE, 0); +} + +static int cf_check cpu_callback(struct notifier_block *nfb, + unsigned long action, void *hcpu) +{ + unsigned int cpu =3D (unsigned long)hcpu; + int rc =3D 0; + + switch ( action ) + { + case CPU_STARTING: + rc =3D vgein_init(); + if ( rc ) + printk(XENLOG_ERR "AIA: failed to init vgein for CPU%u: %d\n", + cpu, rc); + break; + + case CPU_DYING: + vgein_deinit(); + break; + } + + return notifier_from_errno(rc); +} + +static struct notifier_block cpu_nfb =3D { + .notifier_call =3D cpu_callback, +}; + void __init aia_init(void) { + int rc; + if ( !riscv_isa_extension_available(NULL, RISCV_ISA_EXT_ssaia) ) + { + dprintk(XENLOG_WARNING, "SSAIA isn't present in riscv,isa\n"); return; + } + + if ( (rc =3D vgein_init()) ) + { + dprintk(XENLOG_ERR, "vgein_init() failed: %d\n", rc); + return; + } =20 _aia_usable =3D true; + + register_cpu_notifier(&cpu_nfb); } =20 unsigned int vgein_assign(struct vcpu *v) { - BUG_ON("unimplemented"); + unsigned int vgein_id; + struct vgein_ctrl *vgein =3D &per_cpu(vgein, v->processor); + unsigned long *bmp =3D &vgein->bmp; + unsigned long flags; =20 - return 0; + if ( !vgein->geilen ) + return 0; + + spin_lock_irqsave(&vgein->lock, flags); + /* + * The vgein_id shouldn't be zero, as it will indicate that no guest + * external interrupt source is selected for VS-level external interru= pts + * according to RISC-V privileged spec: + * Hypervisor Status Register (hstatus) in RISC-V privileged spec: + * + * The VGEIN (Virtual Guest External Interrupt Number) field selects + * a guest external interrupt source for VS-level external interrupt= s. + * VGEIN is a WLRL field that must be able to hold values between ze= ro + * and the maximum guest external interrupt number (known as GEILEN), + * inclusive. + * When VGEIN=3D0, no guest external interrupt source is selected for + * VS-level external interrupts. + * + * So start to search from bit number 1. + */ + vgein_id =3D find_next_zero_bit(bmp, vgein->geilen + 1, 1); + + if ( vgein_id > vgein->geilen ) + vgein_id =3D 0; + else + __set_bit(vgein_id, bmp); + + spin_unlock_irqrestore(&vgein->lock, flags); + +#ifdef VGEIN_DEBUG + gprintk(XENLOG_DEBUG, "%s: %pv: vgein_id(%u), xen_cpu%u_bmp=3D%#lx\n", + __func__, v, vgein_id, v->processor, *bmp); +#endif + + return vgein_id; } =20 void vgein_release(struct vcpu *v, unsigned int vgein_id, unsigned int cpu) { - BUG_ON("unimplemented"); + unsigned long flags; + struct vgein_ctrl *vgein =3D &per_cpu(vgein, cpu); + + if ( !vgein_id ) + return; + + spin_lock_irqsave(&vgein->lock, flags); + if ( !__test_and_clear_bit(vgein_id, &vgein->bmp) ) + ASSERT_UNREACHABLE(); + spin_unlock_irqrestore(&vgein->lock, flags); + +#ifdef VGEIN_DEBUG + gprintk(XENLOG_DEBUG, "%s: %pv: vgein_id(%u), xen_cpu%u_bmp=3D%#lx\n", + __func__, v, vgein_id, cpu, vgein->bmp); +#endif } --=20 2.55.0 From nobody Fri Oct 23 15:32:28 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) client-ip=192.237.175.120; envelope-from=xen-devel-bounces@lists.xenproject.org; helo=lists.xenproject.org; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=pass(p=none dis=none) header.from=gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1790785583; cv=none; d=zohomail.com; s=zohoarc; b=HWHPilRfDvM22Y9Bh18YPxMpaYZzI9adYw/Y9DFHHYDf6YdYuJt7s6JjcBexC16S8TKc28KQ4tox997AWXVO/ahHqV8p/xAbNOu/bjOv3jHa79PSMSVji0o9u4k/N3W5dJSosWVGiY9kc+JtKyZIjeGRYu5YnegaNzqiRcFZ2Bc= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1790785583; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=GNE5X/4Zf+qRtsg8ZwPjb8BLew6qY5/EJ1Wcmse8ACc=; b=aL9wl/EQPkFb7JsSYFjYsiK2TVuG8glwYntwd94XJWKmuGDfZ8fb9M0J34xWL37DdueKgIjd6DGunOkfSLwnlLVXPIHaZLedZwho4IJYdCZrz9WL+cc8fx642e83n7dIQj5cka9HcHuFLfspI+PTMjWdAVJh1vue2UB85Ewdbjc= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) by mx.zohomail.com with SMTPS id 1790785583504947.900864806928; Wed, 30 Sep 2026 09:26:23 -0700 (PDT) Received: from list by lists.xenproject.org with outflank-mailman.1437593.1656682 (Exim 4.92) (envelope-from ) id 1xBx6y-0002AZ-5l; Wed, 30 Sep 2026 16:24:52 +0000 Received: by outflank-mailman (output) from mailman id 1437593.1656682; Wed, 30 Sep 2026 16:24:51 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1xBx6w-00025K-QO; Wed, 30 Sep 2026 16:24:50 +0000 Received: by outflank-mailman (input) for mailman id 1437593; Wed, 30 Sep 2026 16:24:44 +0000 Received: from mx.expurgate.net ([194.145.224.20]) by lists.xenproject.org with esmtp (Exim 4.92) id 1xBx6p-0000Uh-6u for xen-devel@lists.xenproject.org; Wed, 30 Sep 2026 16:24:43 +0000 Received: from mx.expurgate.net (helo=localhost) by mx.expurgate.net with esmtp id 1xBx6o-00Ghe4-IY for xen-devel@lists.xenproject.org; Wed, 30 Sep 2026 18:24:42 +0200 Received: from [10.42.69.12] (helo=localhost) by localhost with ESMTP (eXpurgate MTA 0.9.1) (envelope-from ) id 6abd37c1-bab6-0a2a0a5309dd-0a2a450c92c8-12 for ; Wed, 30 Sep 2026 18:24:42 +0200 Received: from [74.125.225.141] (helo=mail-wm2-f13.google.com) by tlsNG-d25034.mxtls.expurgate.net with ESMTPS (eXpurgate 4.57.1) (envelope-from ) id 6abd37c8-f479-0a2a450c0019-4a7de18dd6f9-3 for ; Wed, 30 Sep 2026 18:24:40 +0200 Received: by mail-wm2-f13.google.com with SMTP id 5b1f17b1804b1-49b912df756so43185765e9.3 for ; Wed, 30 Sep 2026 09:24:40 -0700 (PDT) Received: from fedora (user-109-243-71-234.play-internet.pl. [109.243.71.234]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-4a01cd43e66sm14620485e9.2.2026.09.30.09.24.39 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 30 Sep 2026 09:24:39 -0700 (PDT) X-Outflank-Mailman: Message body and most headers restored to incoming version X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" Authentication-Results: eu.smtp.expurgate.cloud; dkim=pass header.s=20251104 header.d=gmail.com header.i="@gmail.com" header.h="Content-Transfer-Encoding:MIME-Version:References:In-Reply-To:Message-ID:Date:Subject:Cc:To:From" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1790785480; x=1791390280; darn=lists.xenproject.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=GNE5X/4Zf+qRtsg8ZwPjb8BLew6qY5/EJ1Wcmse8ACc=; b=cQljBzn3dpG7QSBQfNVRwU9dS3gF4vsvm0WmZHi5miQth6qiJiWBjJaLxxY7pPvGWA d3PJdgaI+13gh3aCPShcuBuQzvTJE7eiTgm2xqtkQX7X6r9jdURrd0JFnjtwka/6ZuJQ E1KrExdpta5Y6EX1RtfjmX/ypdfmXqEHRkplP/t5SPus8wEVYCFhZRJZUXcTdsYW/eyF TElgrF9uurmJuccdMtYfuJIvZUjZORbr0lWagYwufqf5zv4RsaNEYiaIIC7cm14Jz0dw hDjsQYvwvvv4EA5Pa6H5vn1aj0fL7dGQPMWmk9YZc8KFa1pEVE0uGDNjnB3k6GU0moWR 5m4g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1790785480; x=1791390280; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=GNE5X/4Zf+qRtsg8ZwPjb8BLew6qY5/EJ1Wcmse8ACc=; b=MtzR2ZtQuhLQAWLWDt/T18ilBLbSzSiyYxbVE4Ls6bWjCfj8wKConXdSQVt6iVTTOQ wqkg6o6uPtY1+pVVN/u//38wXQ2SjLZwKnNvsVKcfy91ctjtT6CJ9oTTPgsxVVJZj9Ki ELObnShw3rFXdE5nceaNMLhisjLPfRVpnSeteQudttqWWyyHDHBoU2AapmxF8lmmnSg0 U2I1nvmPkMpqCE+m4HIXpGj3ZAEc7T+oTniOA19D6gBy3cyWe2SD0QV4D0EUPHAdsdUL YP5xP5cheEFiC+UjvBhfDrsyCedz6c/QqVAnDpGsCaCikkwE6ShKbDSBf2eTGxuA24+C 79ow== X-Gm-Message-State: AFuF++mD+eqyKoj9Ps9HI0XfIJR6WikUojjjVtK3lT04SxTFeLkhp7ni 6JjScPtfhsBqqt2Pvhg9vC9SfcWX3Pe431pXw9+l5URecm5w8c1pWDexnqh30A== X-Gm-Gg: AYBFou22Cdbz03QbNMEzumQL9HgpBAdKc7/CL8QyWESU5nbnAXsCZXSgd3n5sUKS/mL Bjk47Xyzhgu9S2WJmw4Pq6S9ylxvWk+YH5tFK9JGt8rikkQMTtx9mWFkPt1/tPoe5ikW/ndxiMF 9oXx5G5Kj6SdI/JZpUf5c0glkxupwdIo1k8w6bPo0ZD6KeBBBTMhwHmpMNdHoT2hS+LWXrWDTVz 833Y2DTWWv5wbMByvF74kw/7NnKrTc/hQeb0koSXWG03kkW42PID5hkozgyOd5Ytbswgy+IedST NBvh9dJFzDZOYtYp8ozOTfVY1vl5uOW1KSqC9/zSHY75b+rjDN5bUQmyMi3DgoDU3YkwhkObenS 0Nofz/umpjcKzHLG/k8HR2aaohvr39pdNWdy/oYyckXO5GqVuABVBwWrzBUp/B1zjZxsmguiidj zIqLCqZXMKMdCGUIQn/wpihfvNR/VZcdxxCmCfVO33Lv3jRjx/ab15Pq0Sk6Gp5RwU7Xnw0Vs6r CrSCdE5SYzW7HMXAf8Z/cfcjJgVUVIeL0eqfcF8 X-Received: by 2002:a05:600c:1912:b0:4a0:1d24:dee3 with SMTP id 5b1f17b1804b1-4a01d24e165mr15376665e9.17.1790785480052; Wed, 30 Sep 2026 09:24:40 -0700 (PDT) From: Oleksii Kurochko To: xen-devel@lists.xenproject.org Cc: Romain Caritey , Baptiste Le Duc , Zheng Zhang , Oleksii Kurochko , Alistair Francis , Connor Davis , Andrew Cooper , Anthony PERARD , Michal Orzel , Jan Beulich , Julien Grall , =?UTF-8?q?Roger=20Pau=20Monn=C3=A9?= , Stefano Stabellini Subject: [PATCH v3 35/39] xen/riscv: wake up a descheduled vCPU on a guest external interrupt Date: Wed, 30 Sep 2026 18:23:54 +0200 Message-ID: <4e78b90482e23b049774eb00b19422d8c147970a.1790779209.git.oleksii.kurochko@gmail.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-purgate-ID: tlsNG-d25034/1790785480-51F33A5B-7DBD3334/10/73395122804 X-purgate-type: spam X-purgate-size: 11985 X-ZohoMail-DKIM: pass (identity @gmail.com) X-ZM-MESSAGEID: 1790785584648158500 Content-Type: text/plain; charset="utf-8" While a vCPU is running, MSIs written to its h/w IMSIC guest interrupt file are delivered straight to VS-mode. Once the vCPU is descheduled nobody observes that file anymore, so a guest blocked on such an interrupt would stay blocked until some unrelated event happens to schedule it again. Let Xen observe the file in that window: on deschedule set the vCPU's bit in HGEIE, which turns an interrupt pending in its VS-file into an HS-level SGEI, and clear the bit again on schedule-in. HGEIP only reports an interrupt file number, so to find the vCPU to kick, keep a per-pCPU owners[] array indexed by file number and updated in vgein_assign()/vgein_release() together with the VGEIN bitmap. The SGEI handler clears the HGEIE bits it has seen before kicking their owners, so that the interrupt doesn't keep firing until the vCPU is switched in. The same applies to a vCPU which is migrated to another pCPU while it isn't running. Its old interrupt file is released during the migration, and the vCPU isn't switched in on the new pCPU until something wakes it up, so nothing would observe the new interrupt file. Hence arm HGEIE for the new interrupt file on the new pCPU in imsic_migrate_vcpu(), and clear the bit of the old one in imsic_vsfile_local_read_clear(), which already runs on the pCPU owning it. SGEIs are enabled per vCPU through v->arch.hie: vcpu_csr_init() sets IRQ_S_GEXT in it and csr_regs_ctxt_switch_to() loads it into the CSR. vgein_release() is only called on vCPU migration: a vCPU going away also has to free its VGEIN slot and drop the owners[] entry, but there is no vCPU teardown path to hook it into yet. Signed-off-by: Oleksii Kurochko --- Changes in v3: - Drop the unrelated cpu_callback() change. - Read HGEIP and HGEIE in separate statements (MISRA C Rule 13.2). - Check that guest interrupt file ID 0 isn't reported once, ahead of the loop in hgei_interrupt(), instead of on every iteration. - Drop the VGEIN_DEBUG print from hgei_interrupt(). - Explain in imsic_ctxt_switch_from() why setting the HGEIE bit last doesn't lose an interrupt. - Initialise hie with BIT(IRQ_S_GEXT, UL) and explain why SGEIs are enabled. - Arm HGEIE of the new interrupt file on v->processor, as the new_vsfile_cpu local variable is gone from imsic_migrate_vcpu(). - Describe in the commit message why HGEIE is armed for a vCPU which is migrated while it isn't running. - Correct the commit message: vgein_release() is called on vCPU migration. --- Changes in v2: - New patch. --- --- xen/arch/riscv/aia.c | 38 ++++++++++++++++++ xen/arch/riscv/domain.c | 7 ++++ xen/arch/riscv/imsic.c | 62 ++++++++++++++++++++++++++++- xen/arch/riscv/include/asm/aia.h | 2 + xen/arch/riscv/include/asm/domain.h | 1 + xen/arch/riscv/traps.c | 7 +++- 6 files changed, 115 insertions(+), 2 deletions(-) diff --git a/xen/arch/riscv/aia.c b/xen/arch/riscv/aia.c index 1aca07c2f70f..d961c5c12239 100644 --- a/xen/arch/riscv/aia.c +++ b/xen/arch/riscv/aia.c @@ -18,6 +18,13 @@ struct vgein_ctrl { /* The least-significant bits are implemented first, apart from bit 0 = */ unsigned long bmp; spinlock_t lock; + /* + * Guest interrupt file IDs run from 1 to geilen inclusive (0 means th= at + * no guest external interrupt source is selected), and geilen can nev= er + * exceed BITS_PER_LONG - 1, so indexing this array by the ID directly + * always fits. + */ + struct vcpu *owners[BITS_PER_LONG]; unsigned int geilen; }; =20 @@ -138,7 +145,10 @@ unsigned int vgein_assign(struct vcpu *v) if ( vgein_id > vgein->geilen ) vgein_id =3D 0; else + { __set_bit(vgein_id, bmp); + vgein->owners[vgein_id] =3D v; + } =20 spin_unlock_irqrestore(&vgein->lock, flags); =20 @@ -161,6 +171,7 @@ void vgein_release(struct vcpu *v, unsigned int vgein_i= d, unsigned int cpu) spin_lock_irqsave(&vgein->lock, flags); if ( !__test_and_clear_bit(vgein_id, &vgein->bmp) ) ASSERT_UNREACHABLE(); + vgein->owners[vgein_id] =3D NULL; spin_unlock_irqrestore(&vgein->lock, flags); =20 #ifdef VGEIN_DEBUG @@ -168,3 +179,30 @@ void vgein_release(struct vcpu *v, unsigned int vgein_= id, unsigned int cpu) __func__, v, vgein_id, cpu, vgein->bmp); #endif } + +void hgei_interrupt(void) +{ + unsigned long hgei_mask, flags; + struct vgein_ctrl *vgein =3D &this_cpu(vgein); + + hgei_mask =3D csr_read(CSR_HGEIP); + hgei_mask &=3D csr_read(CSR_HGEIE); + + csr_clear(CSR_HGEIE, hgei_mask); + + spin_lock_irqsave(&vgein->lock, flags); + + /* + * Bit 0 of HGEIP/HGEIE is read-only zero: guest interrupt file ID 0 + * means that no guest external interrupt source is selected. + */ + ASSERT(!(hgei_mask & 1)); + + for_each_set_bit ( guest_file_id, hgei_mask ) + { + if ( vgein->owners[guest_file_id] ) + vcpu_kick(vgein->owners[guest_file_id]); + } + + spin_unlock_irqrestore(&vgein->lock, flags); +} diff --git a/xen/arch/riscv/domain.c b/xen/arch/riscv/domain.c index f60f871aba98..6cb762bee33c 100644 --- a/xen/arch/riscv/domain.c +++ b/xen/arch/riscv/domain.c @@ -130,6 +130,12 @@ static void vcpu_csr_init(struct vcpu *v) v->arch.hstateen0 =3D (hstateen0 & csr_masks.hstateen0) | csr_masks.ro_one.hstateen0; } + + /* + * Enable SGEIs, so that a guest interrupt file marked in HGEIE while + * the vCPU is descheduled can raise an interrupt to Xen. + */ + v->arch.hie =3D BIT(IRQ_S_GEXT, UL); } =20 static void continue_new_vcpu(struct vcpu *prev) @@ -386,6 +392,7 @@ static void csr_regs_ctxt_switch_to(struct vcpu *n) csr_write(CSR_HEDELEG, n->arch.hedeleg); csr_write(CSR_HIDELEG, n->arch.hideleg); csr_write(CSR_HVIP, n->arch.hvip); + csr_write(CSR_HIE, n->arch.hie); csr_write64(CSR_HENVCFG, n->arch.henvcfg); csr_write(CSR_HCOUNTEREN, n->arch.hcounteren); csr_write64(CSR_HTIMEDELTA, n->arch.htimedelta); diff --git a/xen/arch/riscv/imsic.c b/xen/arch/riscv/imsic.c index e35688f98bb1..40d2eff14d07 100644 --- a/xen/arch/riscv/imsic.c +++ b/xen/arch/riscv/imsic.c @@ -555,12 +555,37 @@ void cf_check imsic_ctxt_switch_from(struct vcpu *p) =20 write_lock_irqsave(&imsic_state->vsfile_lock, flags); imsic_state->vsfile_cpu =3D p->processor; + /* + * Start to observe the VS-file from HS-mode: while the vCPU isn't + * running an interrupt pending in its VS-file is reported through HGE= IP + * instead of being delivered to VS-mode, which lets Xen wake the vCPU= up. + * + * An MSI is recorded in the VS-file's eip[] array until the guest cla= ims + * it, and HGEIP isn't latched but reflects whether the file currently + * has a pending-and-enabled interrupt. Hence an interrupt which arriv= ed + * before this point raises an SGEI as soon as the bit is set in HGEIE; + * nothing is lost in between. + */ + csr_set(CSR_HGEIE, BIT(imsic_state->guest_file_id, UL)); write_unlock_irqrestore(&imsic_state->vsfile_lock, flags); } =20 void cf_check imsic_ctxt_switch_to(struct vcpu *n) { - /* Nothing to do */ + struct vimsic_state *imsic_state =3D n->arch.vimsic_state; + unsigned long flags; + + /* A s/w VS-file is never observed through HGEIP. */ + if ( !vcpu_guest_file_id(n) ) + return; + + /* + * The vCPU is about to run, so hstatus.VGEIN delivers the VS-file's + * interrupts to it directly and there is nothing left for Xen to obse= rve. + */ + read_lock_irqsave(&imsic_state->vsfile_lock, flags); + csr_clear(CSR_HGEIE, BIT(imsic_state->guest_file_id, UL)); + read_unlock_irqrestore(&imsic_state->vsfile_lock, flags); } =20 int imsic_map_guest_file(struct vcpu *v, unsigned int vsfile_id) @@ -695,6 +720,12 @@ static void cf_check imsic_vsfile_local_read_clear(voi= d *data) struct imsic_mrif *mrif =3D idata->mrif; unsigned long new_hstatus, old_hstatus, old_vsiselect; =20 + /* + * The HGEIE bit imsic_ctxt_switch_from() armed belongs to the old own= er + * only. + */ + csr_clear(CSR_HGEIE, BIT(idata->hgei, UL)); + /* * The file is reached by retargeting hstatus.VGEIN, and * imsic_vs_csr_swap() alters vsiselect. Both belong to the vCPU runni= ng @@ -1044,6 +1075,21 @@ int __init vimsic_make_domu_dt_node(struct kernel_in= fo *kinfo, return fdt_end_node(fdt); } =20 +/* + * Start to observe the interrupt file from HS-mode, the same way + * imsic_ctxt_switch_from() does it for a vCPU which is switched out. + * + * The counterpart, clearing the bit of the interrupt file which is left + * behind, is done by imsic_vsfile_local_read_clear(), which already runs = on + * the pCPU owning that file. + */ +static void cf_check imsic_local_hgeie_set(void *data) +{ + const struct imsic_vsfile_data *idata =3D data; + + csr_set(CSR_HGEIE, BIT(idata->hgei, UL)); +} + static void cf_check imsic_vsfile_local_update(void *data) { unsigned int i; @@ -1225,6 +1271,20 @@ void imsic_migrate_vcpu(struct vcpu *v) /* Restore register state in the new IMSIC VS-file */ imsic_call_on_cpu(v->processor, imsic_vsfile_local_update, &vsfile_dat= a); =20 + /* + * imsic_ctxt_switch_from() armed HGEIE for the old interrupt file onl= y. + * Unless the vCPU is being switched in right now (a migration done by + * sched_context_switch(), where is_running is already set), arm it for + * the new file too: a blocked vCPU would otherwise never be woken up = by + * an interrupt pending in the new file, be it restored from the old o= ne + * or arriving later. + * + * For a vCPU which is being switched in, imsic_ctxt_switch_to() clear= s the + * bit anyway, as interrupts are then delivered to the vCPU directly. + */ + if ( !v->is_running ) + imsic_call_on_cpu(v->processor, imsic_local_hgeie_set, &vsfile_dat= a); + /* Set VCPU HSTATUS.VGEIN to new IMSIC VS-file */ vcpu_guest_cpu_user_regs(v)->hstatus &=3D ~HSTATUS_VGEIN; vcpu_guest_cpu_user_regs(v)->hstatus |=3D diff --git a/xen/arch/riscv/include/asm/aia.h b/xen/arch/riscv/include/asm/= aia.h index 8e4eb2f6b14e..6a05bdd8c236 100644 --- a/xen/arch/riscv/include/asm/aia.h +++ b/xen/arch/riscv/include/asm/aia.h @@ -12,4 +12,6 @@ void aia_init(void); unsigned int vgein_assign(struct vcpu *v); void vgein_release(struct vcpu *v, unsigned int vgein_id, unsigned int cpu= ); =20 +void hgei_interrupt(void); + #endif /* RISCV_AIA_H */ diff --git a/xen/arch/riscv/include/asm/domain.h b/xen/arch/riscv/include/a= sm/domain.h index c33d83836f2e..a3fa637b40da 100644 --- a/xen/arch/riscv/include/asm/domain.h +++ b/xen/arch/riscv/include/asm/domain.h @@ -69,6 +69,7 @@ struct arch_vcpu { register_t hstateen0; uint64_t htimedelta; register_t hvip; + register_t hie; =20 register_t vsatp; register_t vscause; diff --git a/xen/arch/riscv/traps.c b/xen/arch/riscv/traps.c index dc938bae5b00..cf18f5185ff4 100644 --- a/xen/arch/riscv/traps.c +++ b/xen/arch/riscv/traps.c @@ -12,9 +12,10 @@ #include #include =20 -#include +#include #include #include +#include #include #include #include @@ -273,6 +274,10 @@ void do_trap(struct cpu_user_regs *cpu_regs) timer_interrupt(); break; =20 + case IRQ_S_GEXT: + hgei_interrupt(); + break; + default: intr_handled =3D false; break; --=20 2.55.0 From nobody Fri Oct 23 15:32:28 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) client-ip=192.237.175.120; envelope-from=xen-devel-bounces@lists.xenproject.org; helo=lists.xenproject.org; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=pass(p=none dis=none) header.from=gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1790785575; cv=none; d=zohomail.com; s=zohoarc; b=ZDmk7qlfhulrPL0o9gvEEvtvd5R1r/AspxyQMrb3dxsqA0DO2bCYXJ068RqjBoX4i1DSFfTIgn2iEU08aVt/JOmEeY0WibafFKXyeVdmJK/sAyH+5/cj/0GO39PmxsKS8V6cF4UY84nkbG/W0PzqKGy/WgO5DPjHG6MhWyMh9Bs= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1790785575; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=ZE6aReKJdhJvPK3aQjyPOFfG4cws69nhrfoWbiddvVk=; b=HLfWa2YoC+hxgjvyOGD0kd4PN3ZC0H+tNeNp9ggh+HZfn38ZSyQsC7EU4YPo1e68TOah2ujNQ9mFhnR9cAuVYerClHIyHBXmPQYVxFotmvWXr64dx9oaEMlq9als/yshCY9G/IfvHPTT5W77anZRAFYnpZaEXsRFdczM9UEuKSs= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) by mx.zohomail.com with SMTPS id 1790785575506214.8181480730534; Wed, 30 Sep 2026 09:26:15 -0700 (PDT) Received: from list by lists.xenproject.org with outflank-mailman.1437591.1656673 (Exim 4.92) (envelope-from ) id 1xBx6v-0001lP-Vi; Wed, 30 Sep 2026 16:24:50 +0000 Received: by outflank-mailman (output) from mailman id 1437591.1656673; Wed, 30 Sep 2026 16:24:49 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1xBx6v-0001gf-8L; Wed, 30 Sep 2026 16:24:49 +0000 Received: by outflank-mailman (input) for mailman id 1437591; Wed, 30 Sep 2026 16:24:43 +0000 Received: from mx.expurgate.net ([194.145.224.10]) by lists.xenproject.org with esmtp (Exim 4.92) id 1xBx6o-0000Jt-Jc for xen-devel@lists.xenproject.org; Wed, 30 Sep 2026 16:24:42 +0000 Received: from mx.expurgate.net (helo=localhost) by mx.expurgate.net with esmtp id 1xBx6n-006O0j-Tf for xen-devel@lists.xenproject.org; Wed, 30 Sep 2026 18:24:41 +0200 Received: from [10.42.69.6] (helo=localhost) by localhost with ESMTP (eXpurgate MTA 0.9.1) (envelope-from ) id 6abd37c7-2eae-0a2a0a5409dd-0a2a450689cc-8 for ; Wed, 30 Sep 2026 18:24:41 +0200 Received: from [74.125.225.140] (helo=mail-wm2-f12.google.com) by tlsNG-16d1c6.mxtls.expurgate.net with ESMTPS (eXpurgate 4.57.1) (envelope-from ) id 6abd37c9-195a-0a2a45060019-4a7de18cd7fd-3 for ; Wed, 30 Sep 2026 18:24:41 +0200 Received: by mail-wm2-f12.google.com with SMTP id 5b1f17b1804b1-49ccf3ca626so34554735e9.0 for ; Wed, 30 Sep 2026 09:24:41 -0700 (PDT) Received: from fedora (user-109-243-71-234.play-internet.pl. [109.243.71.234]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-4a01cd43e66sm14620485e9.2.2026.09.30.09.24.40 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 30 Sep 2026 09:24:40 -0700 (PDT) X-Outflank-Mailman: Message body and most headers restored to incoming version X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" Authentication-Results: eu.smtp.expurgate.cloud; dkim=pass header.s=20251104 header.d=gmail.com header.i="@gmail.com" header.h="Content-Transfer-Encoding:MIME-Version:References:In-Reply-To:Message-ID:Date:Subject:Cc:To:From" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1790785481; x=1791390281; darn=lists.xenproject.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=ZE6aReKJdhJvPK3aQjyPOFfG4cws69nhrfoWbiddvVk=; b=BMDs48GHlZrxOwUHV2dsEk28hPuJkwpaVdebCuzewbEyukazTIUSelPZLJu1rfkT3P +anzuW4gnFYKXv6iw6wy6Oq42dc9yfQgmBM5laVHC1DNX22sXInFCzwvDfSc5LmPuf9m BS0/XHGvS9CSaMWIdyCGYMbPtus6c+2BItvV73jHzEQF/NEgt2eUxHIObHvtH51WLMRH szHP2C7yi66BPgnSa32rfpTytYraWHq1VYFNze7UmfilpdH+ejtjUoA647FD2vVHwq+r RpQgCfw17hqXb1bMMZv3hcPSw+FvGP0Tkx8gJzrQ11QeR4dZRAHkP6X98GGoZStcarqR VwWA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1790785481; x=1791390281; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=ZE6aReKJdhJvPK3aQjyPOFfG4cws69nhrfoWbiddvVk=; b=jtIxBIFduiq8ERdc8HobVoMMgXruMwci1jsmTXREMlHhos1fmGpdjooM/PaMZFD5pR 6iDVUbd5AYpqv+QNAZLxUwpZahsdMsc690os/yqx1NG3ZT1i3mzXGJEKj579TbjhQt26 OnCoFHzqbV74S8ncKcDMCJ7GboWU76OaOxTaXaI83POFS4VQcKRk0A+VCmEPk7cYWn5X sbrU2Gfidnk4q8f3y6tx35XBXHl/lbjkRcGgGuN4bW164gJDrE6AK3RQxeJQi5g5dWOJ NwgAEFW2DSuKImLV5bde21Ux8kBkK0U8w5PqpoD4MyigOd5L2p6baxOZfdryTuBKjoBL 3WlQ== X-Gm-Message-State: AFuF++lRAQkH+WwbfMIxo0y6eWHLS0xVPoD7WproSWcS7ttkU7qWz33r SXuDGvqdX7kw5mh9jsKhZc3BQzRzaP3HG8WFcuFgQLDRCRmSWntyVVrU8hPXDw== X-Gm-Gg: AYBFou3snEuOwsFO6qpXGUY47X/sv0cQx7kuYnfXbgFUzezxnraX6djXNYTbwSBSQf9 6nG3nLBPWFowOg54Xo7McbMxBjwWQdBOmVjY7asi+4gsDpPdGai9fwSnp1JfAFMXINi6Nlqr/SI SK1RwaZ7y0KyvG4RAydJiuFAeH18VhTK5+m9HpN4bgzYCAASL4Rx889yJDZLFsqCS9u7MRuO8Op edD93E5eRwaMnQNisBrlmSK+fVSDm930IVZ6Uia/PcCbpkAFaUb1EZFRhnqmRRr/WzbolID93nc PjdKGomKFxZxmJFO+5dEKcsnW58sWOIKXcWLtaj4qZ1ODqCTwAL1/cqmhvFaeMb/rZ0GD8G6V5m X/V2Jft/Vh9weO1kGaqGhipgzYukTyDVIzg6zQVcxCDAcRvbcJ7N5N+/nVEuia+N5rzFH6BANsh Z2nL8pv0WQi7/x376qJEakopBK9kQIqFsbE3icQt/S3nxEw4WaL7Dyv72c/5HFR4Fat/bBiX4SF pP3l0I0Ye9yYIVHmEdDeXc8sqPz/9TSD4GmExpw X-Received: by 2002:a05:600c:c8a:b0:49f:ce73:5e94 with SMTP id 5b1f17b1804b1-4a01b133e02mr33498825e9.34.1790785481182; Wed, 30 Sep 2026 09:24:41 -0700 (PDT) From: Oleksii Kurochko To: xen-devel@lists.xenproject.org Cc: Romain Caritey , Baptiste Le Duc , Zheng Zhang , Oleksii Kurochko , Alistair Francis , Connor Davis , Andrew Cooper , Anthony PERARD , Michal Orzel , Jan Beulich , Julien Grall , =?UTF-8?q?Roger=20Pau=20Monn=C3=A9?= , Stefano Stabellini Subject: [PATCH v3 36/39] xen/riscv: map IMSIC interrupt file for vCPUs Date: Wed, 30 Sep 2026 18:23:55 +0200 Message-ID: X-Mailer: git-send-email 2.55.0 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-purgate-ID: tlsNG-16d1c6/1790785481-F4A0477B-36E62ECB/10/78276251493 X-purgate-type: spam X-purgate-size: 5481 X-ZohoMail-DKIM: pass (identity @gmail.com) X-ZM-MESSAGEID: 1790785576576158500 Content-Type: text/plain; charset="utf-8" A guest running in VS-mode expects its own IMSIC S-file at offset 0 of its guest-physical IMSIC block. Physically, the guest-file (G-file) assigned to this vCPU lives at a hart-relative offset given by guest_file_id (assigned via the vGEIN allocator). Therefore, imsic_map_guest_file() uses stage-2 translation to redirect the guest's fixed per-vCPU GPA page (offset 0) to the specific physical guest-file page. Signed-off-by: Oleksii Kurochko Acked-by: Jan Beulich Reviewed-by: Baptiste Le Duc --- Changes in v3: - Add Acked-by: Jan Beulich - Use dprintk() instead of printk() for the IMSIC_DEBUG message in imsic_map_guest_file(). - Add Reviewed-by: Baptiste Le Duc --- Changes in v2: - Use GUEST_IMSIC_S_BASE instead of imsic_cfg.base_addr as the base of the guest address to map to, and change the type of gaddr to paddr_t as it holds a guest physical address. - Rename guest_stride to guest_offset: it is an offset of the VS-file insi= de the pCPU's IMSIC block, not a stride. - Use PRIpaddr for physical addresses and %u for unsigned values in the debug/error messages. - Switch the mapping failure message from printk() to dprintk(XENLOG_ERR, = ...). - Update the comment above imsic_map_guest_file(): vCPUs aren't pinned, th= ey run on the pCPU chosen by the scheduler, and mention that on migration a VS-file is acquired on the new pCPU and mapped at the same GFN, so the stale mapping is replaced rather than explicitly torn down. --- --- xen/arch/riscv/imsic.c | 66 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 65 insertions(+), 1 deletion(-) diff --git a/xen/arch/riscv/imsic.c b/xen/arch/riscv/imsic.c index 40d2eff14d07..a8e99997c087 100644 --- a/xen/arch/riscv/imsic.c +++ b/xen/arch/riscv/imsic.c @@ -29,6 +29,7 @@ #include #include #include +#include #include =20 #define IMSIC_HART_SIZE(guest_bits) (BIT(guest_bits, U) * IMSIC_MMIO_PAGE_= SZ) @@ -588,9 +589,72 @@ void cf_check imsic_ctxt_switch_to(struct vcpu *n) read_unlock_irqrestore(&imsic_state->vsfile_lock, flags); } =20 +/* + * Map the physical IMSIC guest interrupt file (G-file) assigned to vCPU + * into the domain's stage-2 guest-physical address space. + * + * In the machine's physical address space (SPA), each hart's IMSIC + * supervisor-level file (S-file) is located at offset 0 of its address bl= ock, + * followed contiguously by GEILEN guest files at offsets of 1, 2, ..., N = pages. + * + * Because a guest OS running in VS-mode expects its own supervisor-level + * interrupt file to be at offset 0 of its guest-physical IMSIC block, the + * hypervisor must use stage-2 address translation to map the vCPU's + * guest-physical "supervisor" page (GPA offset 0) to the specific + * physical guest file page (SPA offset guest_file_id) on the physical har= t. + * + * A vCPU runs on the pCPU the scheduler picked for it (v->processor), and + * the guest file it is given (guest_file_id, from the vGEIN allocator) + * belongs to that very pCPU's IMSIC. A guest_file_id of 0 indicates that = no + * hardware guest file is selected (matching the architectural behavior wh= ere + * vGEIN =3D 0 in the hstatus CSR selects no guest external interrupt sour= ce), + * requiring the VS-file to be emulated in software. + * + * Consequently the mapping installed here is only valid as long as the vC= PU + * stays on that pCPU. When it migrates, a VS-file is acquired on the new + * pCPU and mapped at the very same GFN, so the stale mapping needs no + * explicit tear-down: it is simply replaced. + * + * The base guest-physical address advertised to the guest in the device + * tree matches offset 0 of the vCPU's virtual IMSIC block. Stage-2 + * translation ensures that guest supervisor accesses to this page are + * transparently routed to the real hardware VS-file granted to it on + * the pCPU it currently runs on. + */ int imsic_map_guest_file(struct vcpu *v, unsigned int vsfile_id) { - return -EOPNOTSUPP; + struct domain *d =3D v->domain; + unsigned int cpu =3D v->processor; + paddr_t gaddr =3D GUEST_IMSIC_S_BASE + (IMSIC_MMIO_PAGE_SZ * v->vcpu_i= d); + paddr_t paddr, guest_offset; + int res; + + /* Nothing to map in the case of sw interrupt file. */ + if ( !vsfile_id ) + return 0; + + guest_offset =3D vsfile_id * IMSIC_MMIO_PAGE_SZ; + + paddr =3D imsic_cfg.msi[cpu].base_addr + imsic_cfg.msi[cpu].offset + + guest_offset; + +#ifdef IMSIC_DEBUG + dprintk(XENLOG_DEBUG, + "%s: %pv: ga(%#"PRIpaddr") -> pa(%#"PRIpaddr"), cpu(%u), " + "guest_file_id(%u) base_addr(%#"PRIpaddr") offset(%#lx)\n", + __func__, v, gaddr, paddr, cpu, vsfile_id, + imsic_cfg.msi[cpu].base_addr, imsic_cfg.msi[cpu].offset); +#endif + + res =3D map_regions_p2mt(d, gaddr_to_gfn(gaddr), + PFN_DOWN(IMSIC_MMIO_PAGE_SZ), maddr_to_mfn(padd= r), + arch_dt_passthrough_p2m_type()); + if ( res ) + dprintk(XENLOG_ERR, + "%s: Failed to map %#"PRIpaddr" to the guest at %#"PRIpadd= r"\n", + __func__, paddr, gaddr); + + return res; } =20 int cf_check vcpu_imsic_init(struct vcpu *v) --=20 2.55.0 From nobody Fri Oct 23 15:32:28 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) client-ip=192.237.175.120; envelope-from=xen-devel-bounces@lists.xenproject.org; helo=lists.xenproject.org; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=pass(p=none dis=none) header.from=gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1790785586; cv=none; d=zohomail.com; s=zohoarc; b=SKK8WJRVXIOuou5jFWr9ecFT2zxYGUL/iSB5KqIit3XZ/u5VYtti9HfZzZNhOR23I3KhwjtxqBBJVvAoKxN+d6NbGbFiU9xnlhf2aVV2ftVn11ds3WbrKwjEE4B05nQ4T1DCy30xinTCTMsuau3kxnsTHrH2DPLZEaoB9Su6OH8= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1790785586; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=RWiAmxyzdWnK+3Rlqd9CZyRkkOQevWr8yh/AlAvntb0=; b=HrvNgeGXR3u/lXSrwDXPnBTDxZYIq3uJlE4PxD9KJwQfgd/4vV0j2PDs+1zUZmnSwg+XqbnfbRAW0EXaaR2aJoZ7cYueYDs3dNTvyv6uEleY1UUmSRN1ian1kLofKJo/EDGiMG9Wvu2Fe5QAFH6bokb0YiTXIdNJ43hXsGa3kEE= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) by mx.zohomail.com with SMTPS id 1790785586120929.7444729923233; Wed, 30 Sep 2026 09:26:26 -0700 (PDT) Received: from list by lists.xenproject.org with outflank-mailman.1437596.1656691 (Exim 4.92) (envelope-from ) id 1xBx70-0002TL-29; Wed, 30 Sep 2026 16:24:54 +0000 Received: by outflank-mailman (output) from mailman id 1437596.1656691; Wed, 30 Sep 2026 16:24:53 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1xBx6y-0002NE-FG; Wed, 30 Sep 2026 16:24:52 +0000 Received: by outflank-mailman (input) for mailman id 1437596; Wed, 30 Sep 2026 16:24:44 +0000 Received: from mx.expurgate.net ([194.145.224.10]) by lists.xenproject.org with esmtp (Exim 4.92) id 1xBx6p-0000bq-Oa for xen-devel@lists.xenproject.org; Wed, 30 Sep 2026 16:24:43 +0000 Received: from mx.expurgate.net (helo=localhost) by mx.expurgate.net with esmtp id 1xBx6p-006O3H-2d for xen-devel@lists.xenproject.org; Wed, 30 Sep 2026 18:24:43 +0200 Received: from [10.42.69.4] (helo=localhost) by localhost with ESMTP (eXpurgate MTA 0.9.1) (envelope-from ) id 6abd37b5-e002-0a2a0a5209dd-0a2a4504eab8-32 for ; Wed, 30 Sep 2026 18:24:43 +0200 Received: from [74.125.225.140] (helo=mail-wm2-f12.google.com) by tlsNG-ebf023.mxtls.expurgate.net with ESMTPS (eXpurgate 4.57.1) (envelope-from ) id 6abd37ca-b57f-0a2a45040019-4a7de18ce73f-3 for ; Wed, 30 Sep 2026 18:24:43 +0200 Received: by mail-wm2-f12.google.com with SMTP id 5b1f17b1804b1-49cd5462b69so31527245e9.1 for ; Wed, 30 Sep 2026 09:24:43 -0700 (PDT) Received: from fedora (user-109-243-71-234.play-internet.pl. [109.243.71.234]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-4a01cd43e66sm14620485e9.2.2026.09.30.09.24.41 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 30 Sep 2026 09:24:41 -0700 (PDT) X-Outflank-Mailman: Message body and most headers restored to incoming version X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" Authentication-Results: eu.smtp.expurgate.cloud; dkim=pass header.s=20251104 header.d=gmail.com header.i="@gmail.com" header.h="Content-Transfer-Encoding:MIME-Version:References:In-Reply-To:Message-ID:Date:Subject:Cc:To:From" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1790785482; x=1791390282; darn=lists.xenproject.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=RWiAmxyzdWnK+3Rlqd9CZyRkkOQevWr8yh/AlAvntb0=; b=G6WhtVJfpjIfikOyDt4rUCMcKnFz09ravKCvo9qZZ75U+Ba87kPyDj41nE25I2MqHw voJ1awlkScf5h0Iz/uR1i9ZjebQrM8kTzyaKOq0Z4mBP9k1dJFZyfkZhW4U3lRdCa/qH CVVZMDMWU/kb95DTYV7vXiq96/dr1pAgCBdBN6xSqHp0sBvMXxj3QZKBXIDKK3cAtfyC 2wkfXwh/ezhs3oM956cXhrFGhujC9gO+BzX5MByL2OLlg7K+fNi8ytF4BjUZS+72O5SW 6bc88ma9i6ij1z6f5fcp+p91EuXELPs8FNf9zQnuyRbcaNatU7An4Co1Y9k+coujZUAP roQw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1790785482; x=1791390282; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=RWiAmxyzdWnK+3Rlqd9CZyRkkOQevWr8yh/AlAvntb0=; b=NAje1rUmlC6og2nJMux+mKy3LAr4Rvr3z3BDYZ0TmTkkZiX1B4h7Lq2EMn27VSiiWy CuD6WjCy9YQK1axgyzaGkfnm9M8qelmmeQxcRNG+XVUUokEevfajBQzY9QgYYWKCNdCA kXfSsZHSnjKfw9Iy0SWAAjq5AtgnVwAZKktdNrMvSNQUE+aHuyTCQyihzkjKKy7O8G6O nImPlr07j6jmmpWgHh8JThOXbiknQEOZ5zq7hT9FTCrMBkjwYZEnm92h+kuAINWjfAkr JuTUVuZnVts7pR3a/luFrFhp414cKNFTSGdStERCgcqikkDtwdtcrX0y5yPaSXQe+MZd WZlQ== X-Gm-Message-State: AFuF++m8N6Pc8H40UcTOqbPtkIDmBmS/s47bJuWt65W2bf0VVv/ei7b9 LCY7iB1AIjFCLA5Pfgvh8yVis/wZnALsEHeyddMdBTsUj3NfmccASmrf1fQC2g== X-Gm-Gg: AYBFou04fETDNRZL3/IcSiJQZe070NhXoGCC7NcF8MQrBSaBRv5G1pTK+btNbZY6/4w reacbzJ9P3Vaj5LcyO1ZLtIXmeElre6DDwbnIV/OjvEpRBx4sj8WKuu0NFiQICaM6ip6HEV4Uqr xhiqKyzd31vJsAN2AMl7unD4++89QgjVmAIcVvaXkmtZh23YocL/9TKXREXttbceAzZLr7ghbRj 02QlSRV27Kgq+uQp53XbjaGtsTwAguYLU8fahcfXgPPpBGsxkgjHdEMuvxv9UGtsFwnRaV5rbMm Dqqim1ff21uZseiq6+ZaGHHiK1YJOi74dkAzEnODzVaVB2DEbiUBXIvmbKr6V8YN66k+pSQp31Z ksq/Sv+NTg5YRoukAyej+cHFBNrc8ELhr8O6+lqzxdZitKPF4qwJFqi086YdQ0C0buzkEApfzuV hfkBbyPpQwV5JmPz5nJ4/oBbvMAje1h7PA0AlsWolmu7vNf/oomIjXjvuVsF0nhDrBaRRWgSty0 kD/TSp2yJwcfuPKObi4XNRcrSbljGhe2BWDBN+z X-Received: by 2002:a05:600c:4512:b0:4a0:136d:f721 with SMTP id 5b1f17b1804b1-4a01b00c143mr35331685e9.17.1790785482287; Wed, 30 Sep 2026 09:24:42 -0700 (PDT) From: Oleksii Kurochko To: xen-devel@lists.xenproject.org Cc: Romain Caritey , Baptiste Le Duc , Zheng Zhang , Oleksii Kurochko , Alistair Francis , Connor Davis , Andrew Cooper , Anthony PERARD , Michal Orzel , Jan Beulich , Julien Grall , =?UTF-8?q?Roger=20Pau=20Monn=C3=A9?= , Stefano Stabellini Subject: [PATCH v3 37/39] xen/riscv: implement continue_new_vcpu() Date: Wed, 30 Sep 2026 18:23:56 +0200 Message-ID: <0d254188c7f21c88ef1982dc9c5810f7b503e38e.1790779209.git.oleksii.kurochko@gmail.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-purgate-ID: tlsNG-ebf023/1790785483-587C6B50-2BCFDBB8/10/73395122804 X-purgate-type: spam X-purgate-size: 6951 X-ZohoMail-DKIM: pass (identity @gmail.com) X-ZM-MESSAGEID: 1790785586614158500 Content-Type: text/plain; charset="utf-8" continue_new_vcpu() is the arch hook invoked the first time a freshly created vCPU is scheduled. Implement both cases it has to cover: - for the idle vCPU, switch to its own stack and jump to idle_loop(); - for a guest vCPU, enter the guest through the new return_to_new_vcpu() path in entry.S, which restores hstatus and sepc, passes the hart id in a0 and, in a1, either the DTB address (boot vCPU, as expected by the RISC-V boot protocol) or the opaque value passed to SBI HSM hart_start() (secondary vCPUs), clears the remaining GPRs, sets sstatus.SPP and sstatus.SPIE and executes sret. The remaining GPRs have to be cleared as sret neither switches stacks nor touches the GPRs: the guest would otherwise start with Xen's values in them, sp pointing to this vCPU's Xen stack among them. Interrupts have to stay disabled across the restore. A trap taken in HS-mode overwrites hstatus.SPV, sstatus.SPP and sepc (trap entry clears hstatus.SPV in particular), so an interrupt taken between the write of hstatus and sret would make sret return to HS-mode instead of VS-mode, and restoring them afterwards is non-trivial. Instead interrupts are simply kept off and sstatus.SPIE is set, so that sret re-enables them by restoring sstatus.SIE from SPIE. Introduce get_cpu_info() and reset_stack_and_jump() in asm/current.h, needed by the above. get_cpu_info() is a macro rather than a static inline because asm/current.h is pulled in by before this_cpu() is defined and before completes struct vcpu. idle_loop() is only introduced as a stub. Signed-off-by: Oleksii Kurochko --- Changes in v3: - Drop unneeded inclusion of asm/aia.h, asm/aplic.h and asm/imsic.h. - Mark return_to_new_vcpu() declaration with asmlinkage. - Drop the "else" after reset_stack_and_jump(idle_loop), which cannot return. - Move the restore of hstatus and the setting of sstatus.SPIE from continue_new_vcpu() to return_to_new_vcpu(), so that everything sret depends on is set up in one place, and shorten the comment in continue_new_vcpu() accordingly. - Move the tp/SSCRATCH swap out to a separate patch, as nothing reads SSCRATCH yet. - Reword the comments in return_to_new_vcpu(), which suggested that the values of .a0 and .a1 are established there. - Clear the GPRs which are not meaningful to the vCPU being started before sret, so that Xen register values are not exposed to a guest. - Update the commit message: a1 carries the opaque value passed to hart_start() for secondary vCPUs, describe the clearing of the GPRs, drop the comparison with a real CPU and the reference to a later implementation of idle_loop(). --- Changes in v2: - New patch. --- --- xen/arch/riscv/domain.c | 25 +++++++++++++++++- xen/arch/riscv/entry.S | 39 ++++++++++++++++++++++++++++ xen/arch/riscv/include/asm/current.h | 4 +++ 3 files changed, 67 insertions(+), 1 deletion(-) diff --git a/xen/arch/riscv/domain.c b/xen/arch/riscv/domain.c index 6cb762bee33c..04be628dcdb4 100644 --- a/xen/arch/riscv/domain.c +++ b/xen/arch/riscv/domain.c @@ -138,9 +138,27 @@ static void vcpu_csr_init(struct vcpu *v) v->arch.hie =3D BIT(IRQ_S_GEXT, UL); } =20 +static void schedule_tail(struct vcpu *prev); +static void noreturn idle_loop(void); +void asmlinkage noreturn return_to_new_vcpu(void); + static void continue_new_vcpu(struct vcpu *prev) { - BUG_ON("unimplemented\n"); + schedule_tail(prev); + + if ( is_idle_vcpu(current) ) + reset_stack_and_jump(idle_loop); + + /* + * return_to_new_vcpu() sets up hstatus.SPV, sstatus.SPP and sepc so + * that sret enters the guest in VS-mode. A trap taken in HS-mode + * overwrites all of them (trap entry clears hstatus.SPV in particular= ), + * so interrupts have to stay disabled until sret. They are re-enabled= by + * sret itself, as return_to_new_vcpu() also sets sstatus.SPIE. + */ + local_irq_disable(); + + reset_stack_and_jump(return_to_new_vcpu); } =20 int arch_vcpu_create(struct vcpu *v) @@ -519,3 +537,8 @@ static void __init __maybe_unused build_assertions(void) =20 #undef CHECK_GPR_INDEX } + +static void noreturn idle_loop(void) +{ + BUG_ON("unimplemented"); +} diff --git a/xen/arch/riscv/entry.S b/xen/arch/riscv/entry.S index 017fbb06262c..99bc0f4974c2 100644 --- a/xen/arch/riscv/entry.S +++ b/xen/arch/riscv/entry.S @@ -147,3 +147,42 @@ FUNC(__context_switch) =20 ret END(__context_switch) + +/* + * Enter a vCPU for the first time. Must be called with interrupts disable= d, + * see continue_new_vcpu(). + */ +FUNC(return_to_new_vcpu) + REG_L t0, CPU_USER_REGS_HSTATUS(sp) + csrw CSR_HSTATUS, t0 + + REG_L t0, CPU_USER_REGS_SEPC(sp) + csrw CSR_SEPC, t0 + + /* .a0 holds the hart id */ + REG_L a0, CPU_USER_REGS_A0(sp) + + /* + * .a1 holds the DTB address for the boot vCPU, or the opaque value + * passed to SBI HSM hart_start() for secondary vCPUs + */ + REG_L a1, CPU_USER_REGS_A1(sp) + + /* Return to (V)S-mode, with interrupts re-enabled by sret */ + li t0, SSTATUS_SPP | SSTATUS_SPIE + csrs CSR_SSTATUS, t0 + + /* + * sret doesn't switch stacks and leaves the GPRs alone, so every + * register which isn't meaningful to the vCPU being started has t= o be + * cleared here: otherwise the guest would see Xen's values, sp (t= his + * vCPU's Xen stack) and ra among them. + */ + .irp reg, ra, sp, gp, tp, t0, t1, t2, s0, s1, a2, a3, a4, a5, a6, = a7, \ + s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, t3, t4, t5, t6 + mv \reg, zero + .endr + + /* Enter guest */ + sret +END(return_to_new_vcpu) diff --git a/xen/arch/riscv/include/asm/current.h b/xen/arch/riscv/include/= asm/current.h index 78ec52fd8a35..f8babcc3d926 100644 --- a/xen/arch/riscv/include/asm/current.h +++ b/xen/arch/riscv/include/asm/current.h @@ -47,6 +47,8 @@ DECLARE_PER_CPU(struct vcpu *, curr_vcpu); #define set_current(vcpu) do { current =3D (vcpu); } while (0) #define get_cpu_current(cpu) per_cpu(curr_vcpu, cpu) =20 +#define get_cpu_info() (current->arch.cpu_info) + #define guest_cpu_user_regs() ({ BUG_ON("unimplemented"); NULL; }) #define vcpu_guest_cpu_user_regs(vcpu) \ (&(vcpu)->arch.cpu_info->guest_cpu_user_regs) @@ -58,6 +60,8 @@ DECLARE_PER_CPU(struct vcpu *, curr_vcpu); unreachable(); \ } while ( false ) =20 +#define reset_stack_and_jump(fn) switch_stack_and_jump(get_cpu_info(), fn) + #define get_per_cpu_offset() __per_cpu_offset[smp_processor_id()] =20 #endif /* __ASSEMBLER__ */ --=20 2.55.0 From nobody Fri Oct 23 15:32:28 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) client-ip=192.237.175.120; envelope-from=xen-devel-bounces@lists.xenproject.org; helo=lists.xenproject.org; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=pass(p=none dis=none) header.from=gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1790785592; cv=none; d=zohomail.com; s=zohoarc; b=FcSZANbzesk700It7nkIpwthBPRR8Dr2yhpswewmTwFxSLLLpZLcRBa8KXravEo7Ijj6j0hfedwkAeGXmRc9eAXtTtKxAfi5Ny/eyf9uF6e2pKYfCuf3IhfA1WTUxIX2z9GJL1PEHVMc2GBeXBQSdEitmbE/HHowESZSAFxOsJc= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1790785592; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=s0iTnnDAHtsNz00etYwWWNUZSjjFY/v3avWFTZwG4ng=; b=kgFwGywnwO55kNFQT+/8663Q6E2vuFc78mEnxWvV8YNY3ZNIf0MkhoOVYW1Ezzh0a5Z9y0b0lotwHUXpl+2nhSi2H3QiA8h/x7YWfuE85Ld2bJuaRil2FeTLcAl5ntm8jNdTi2z2EKJiK1nEoxJeLCX82rGXEr/PJMgR8iMO9VE= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) by mx.zohomail.com with SMTPS id 179078559202494.24712071101146; Wed, 30 Sep 2026 09:26:32 -0700 (PDT) Received: from list by lists.xenproject.org with outflank-mailman.1437598.1656697 (Exim 4.92) (envelope-from ) id 1xBx70-0002kv-Vv; Wed, 30 Sep 2026 16:24:54 +0000 Received: by outflank-mailman (output) from mailman id 1437598.1656697; Wed, 30 Sep 2026 16:24:54 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1xBx6z-0002eE-RC; Wed, 30 Sep 2026 16:24:53 +0000 Received: by outflank-mailman (input) for mailman id 1437598; Wed, 30 Sep 2026 16:24:45 +0000 Received: from mx.expurgate.net ([194.145.224.20]) by lists.xenproject.org with esmtp (Exim 4.92) id 1xBx6q-0000n8-MX for xen-devel@lists.xenproject.org; Wed, 30 Sep 2026 16:24:44 +0000 Received: from mx.expurgate.net (helo=localhost) by mx.expurgate.net with esmtp id 1xBx6q-00Ghe4-1I for xen-devel@lists.xenproject.org; Wed, 30 Sep 2026 18:24:44 +0200 Received: from [10.42.69.5] (helo=localhost) by localhost with ESMTP (eXpurgate MTA 0.9.1) (envelope-from ) id 6abd37b9-bab6-0a2a0a5309dd-0a2a4505ca74-24 for ; Wed, 30 Sep 2026 18:24:44 +0200 Received: from [74.125.225.140] (helo=mail-wm2-f12.google.com) by tlsNG-c201ff.mxtls.expurgate.net with ESMTPS (eXpurgate 4.57.1) (envelope-from ) id 6abd37cb-4cb1-0a2a45050019-4a7de18c8a67-3 for ; Wed, 30 Sep 2026 18:24:43 +0200 Received: by mail-wm2-f12.google.com with SMTP id 5b1f17b1804b1-49ffe281cb1so28580015e9.1 for ; Wed, 30 Sep 2026 09:24:43 -0700 (PDT) Received: from fedora (user-109-243-71-234.play-internet.pl. [109.243.71.234]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-4a01cd43e66sm14620485e9.2.2026.09.30.09.24.42 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 30 Sep 2026 09:24:43 -0700 (PDT) X-Outflank-Mailman: Message body and most headers restored to incoming version X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" Authentication-Results: eu.smtp.expurgate.cloud; dkim=pass header.s=20251104 header.d=gmail.com header.i="@gmail.com" header.h="Content-Transfer-Encoding:MIME-Version:References:In-Reply-To:Message-ID:Date:Subject:Cc:To:From" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1790785483; x=1791390283; darn=lists.xenproject.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=s0iTnnDAHtsNz00etYwWWNUZSjjFY/v3avWFTZwG4ng=; b=b7cJo4ZqNEqJ8wNOn2ANubGzxcNJ+LS4cyybJ5ezyPSwSDwHuyp4Ih0B94X/uTYhRS dMDn8YrGlg3y6vgDWTe1mavXLqy4vj813Jh9vXsLJglHQChkI7r5mIcE4ziafnlZBO/6 dVX7Ap8E7VOxSkV5NRfdN9ivYU12tWWF6EN/MLw6eHRiM0WAP3NydBOPG8D05H0QspXO vpVxT2ljszcTrsFgf1pT5hHMXb9M9t8HdSHhly3tSogznJwFhaqojONWu7ukOgvU1gXA jbV2ttfWfPZXHjHeNSIhnRmSkMrB9J5m43qb6Yg6KvdyRBV7t3GHyFwgLTyFBIns6fiS Xgaw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1790785483; x=1791390283; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=s0iTnnDAHtsNz00etYwWWNUZSjjFY/v3avWFTZwG4ng=; b=kX0hH01YA77nk2aIJA1K/SBlbvBbyDcXuUc6lHfvKPP1JG+FCQ/HwnaizFW4gJu2ud 0cXARcLCA8D9hlXN7vvoLV7aGT70bOFdbry5y95Bd+VJuE1OERoi7QDUnrg5YFOrv4Oh YlSVArZaYTBgy2sHiqQdE+pAesaAo0njH147bc/W70que+lB7KeydfDAPHg2FLvCW/hk ljaINR/kmzIFbAT+lY7Me3oCkBb/6nBpW+w4Ya8No9bBzei+Z0KedwAL9JD/7Qa9fqJV 0tnAngf+STpdVLv5tjeHwb4wsG25X0fENAfoheJBk/KuNj2qYGqChVHr7h4RYmxB6T68 LvUA== X-Gm-Message-State: AFuF++kgSxCK4OsA95MDS6rrAnmbMx25edflP1G13Z/6VXlkcUB5FvMK ebQLLkUYeOUEeXoa7eOARj8iZHzrKNdqskCUZR8Eyx7VMrEvTUQhNksCXozCmA== X-Gm-Gg: AYBFou0kIjcVl1T9oiOeSQC1T6HgUsybb+EW0miWXH2//dcbmJ2HDN1HdXlvj8/yHC4 Oqlh2kYPG6cUSh4FSGKUiRgIM/OupvIpgUGDweUQoZUgU0A/t+ev3MJWh3ZfYeCnrxFndIiy9ZD BMT6xAcXsOxSOgiAwFRRwEMHJ8zH7UIEvRWBAVdmXQF8eEbyfyBiNpYdLxTuGwrJ6+9hohKhlsI 2roFD4kybKdIG6fZiKyjgZ77etCZ3rHOzXU8ipTE1UQ5yE24XeDyNG+Kk1bcpIv4ylomcYnWkFl HHwIigT7RS4cecu9JHtBf2O2dy2gGQ9YwMxEx4JqaVlhQoK983rU69AUgvWMOt/l1vue9Do47Yn eyVRUDfVYSefmb9KFhayIAzJAy4MHeKeh9y04MJvpQHQs9EOJvs8hTc+G9EZD6FnnuJbAsUYLwy ob7xiTLBSoKp78SpsZZ3bmhHtPtS01jzRncMx9h0CXaMaC9/F2JPeiFudm6V6qUsPXuPjvD2OmM bjLtySqWM8E45zdUaZI255Q1isyfysxdRVHVE4i X-Received: by 2002:a05:600c:6815:b0:49f:f963:7093 with SMTP id 5b1f17b1804b1-4a01b00d679mr35072615e9.23.1790785483402; Wed, 30 Sep 2026 09:24:43 -0700 (PDT) From: Oleksii Kurochko To: xen-devel@lists.xenproject.org Cc: Romain Caritey , Baptiste Le Duc , Zheng Zhang , Oleksii Kurochko , Alistair Francis , Connor Davis , Andrew Cooper , Anthony PERARD , Michal Orzel , Jan Beulich , Julien Grall , =?UTF-8?q?Roger=20Pau=20Monn=C3=A9?= , Stefano Stabellini Subject: [PATCH v3 38/39] xen/riscv: set the guest's XLEN explicitly in hstatus.VSXL Date: Wed, 30 Sep 2026 18:23:57 +0200 Message-ID: <0c65801cec7cdac1556abc610e076f33c1500d1f.1790779209.git.oleksii.kurochko@gmail.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-purgate-ID: tlsNG-c201ff/1790785483-F60AA2A1-289AC820/10/73395122804 X-purgate-type: spam X-purgate-size: 10642 X-ZohoMail-DKIM: pass (identity @gmail.com) X-ZM-MESSAGEID: 1790785592667158500 Content-Type: text/plain; charset="utf-8" The reset value of hstatus.VSXL isn't architecturally defined, so it has to be programmed explicitly from the domain's type instead of relying on whatever the hardware happens to leave there. This matters beyond the guest's own view of itself: decoding of a trapped instruction depends on the effective XLEN of the guest, as the encodings which exist for XLEN=3D64 only must not be recognized for a 32-bit one. The field is WARL: an implementation is permitted to make it read-only with a value that always keeps VSXLEN =3D=3D HSXLEN. Probe at boot which encodings can really be set, and refuse to construct a domain whose width the hardware cannot provide, rather than silently running it at the wrong XLEN. The field occupies bits 33:32 and hence doesn't exist when HSXLEN=3D32, where VSXLEN is always 32 and HSTATUS_VSXL isn't even defined. Hence the split on CONFIG_RISCV_32, even though RV32 isn't buildable yet. The domain's type is only established by set_domain_type(), that is once its kernel image has been probed, whereas vCPU0 is created before that. vcpu_csr_init() therefore leaves the field zero, and vcpu_set_vsxl() fills it in from continue_new_vcpu() instead: that runs once per vCPU with the type already settled, right before return_to_new_vcpu() loads the saved hstatus into the CSR. By then the domain is built and about to run, so it is too late to reject a width the hardware cannot provide. construct_domain() therefore checks it up front, before any of the domain's images are loaded. domain_vsxl() only maps a domain type onto the encoding, and hstatus_vsxl_settable() tells whether the hardware accepts it. The switch() in domain_vsxl() deliberately has no default case, so that adding a 128-bit domain type fails to build until the mapping is updated. While at it drop HSTATUS_VSXL_SHIFT, which has no users and isn't expected to gain any. Signed-off-by: Oleksii Kurochko --- Changes in v3: - Derive the width from the domain's type instead of hardcoding HSTATUS_VSXL_64, now that the preceding patches make d->type correct. - Probe at boot which VSXL encodings the hardware really accepts, and refuse in construct_domain() a domain whose width it cannot provide instead of silently running the guest at the wrong XLEN. - Move the write out of vcpu_csr_init(), which runs before the domain's type is known, into vcpu_set_vsxl() called from continue_new_vcpu(). As a consequence the patch is moved after the one implementing continue_new_vcpu(). - Handle RV32, where the field doesn't exist at all and VSXLEN is always 32. - Use XLEN_FIELD_{32,64} introduced earlier in the series instead of adding HSTATUS_VSXL_{32,64}: it is the same encoding, and unlike the latter it isn't hidden behind #if __riscv_xlen =3D=3D 64, which the RV32 paths need. - Drop HSTATUS_VSXL_SHIFT, which has no users. - Rework the commit message accordingly. --- Changes in v2: - New patch. --- --- xen/arch/riscv/domain-build.c | 8 ++ xen/arch/riscv/domain.c | 119 ++++++++++++++++++++ xen/arch/riscv/include/asm/domain.h | 3 + xen/arch/riscv/include/asm/riscv_encoding.h | 1 - xen/arch/riscv/include/asm/setup.h | 2 + xen/arch/riscv/setup.c | 2 + 6 files changed, 134 insertions(+), 1 deletion(-) diff --git a/xen/arch/riscv/domain-build.c b/xen/arch/riscv/domain-build.c index 1e3abe259ccd..1acaf0946130 100644 --- a/xen/arch/riscv/domain-build.c +++ b/xen/arch/riscv/domain-build.c @@ -15,9 +15,17 @@ int __init construct_domain(struct domain *d, struct ker= nel_info *kinfo) { struct vcpu *v =3D d->vcpu[0]; struct cpu_user_regs *regs =3D vcpu_guest_cpu_user_regs(v); + unsigned int vsxl =3D domain_vsxl(d); =20 BUG_ON(v->is_initialised); =20 + /* Refuse the domain before any of its images are loaded. */ + if ( !hstatus_vsxl_settable(vsxl) ) + { + printk(XENLOG_ERR "%pd: hstatus.VSXL cannot be set to %u\n", d, vs= xl); + return -EOPNOTSUPP; + } + /* * At the moment *_load() don't return value and will just panic() * inside. diff --git a/xen/arch/riscv/domain.c b/xen/arch/riscv/domain.c index 04be628dcdb4..9155ff4234e8 100644 --- a/xen/arch/riscv/domain.c +++ b/xen/arch/riscv/domain.c @@ -51,6 +51,119 @@ static struct csr_masks __ro_after_init csr_masks; #define HENVCFG_VALID_MASK 0xe0000003000000ffUL #define HSTATEEN0_VALID_MASK 0xde00000000000007UL =20 +/* + * Return the hstatus.VSXL value encoding the guest's XLEN. Whether the + * hardware can actually provide that width is a separate question, answer= ed + * by hstatus_vsxl_settable(). + * + * The switch() deliberately has no default case, so that adding a new + * domain_type (a 128-bit one, in particular) fails to build until this + * mapping is updated. + */ +unsigned int domain_vsxl(const struct domain *d) +{ + switch ( d->type ) + { + case DOMAIN_32BIT: + return XLEN_FIELD_32; + + case DOMAIN_64BIT: + return XLEN_FIELD_64; + } + + ASSERT_UNREACHABLE(); + + /* A reserved encoding, which hstatus_vsxl_settable() never accepts. */ + return 0; +} + +#ifdef CONFIG_RISCV_32 + +/* + * hstatus.VSXL occupies bits 33:32 and hence does not exist when HSXLEN= =3D32. + * VSXLEN is then always 32, so there is nothing to probe and no width oth= er + * than 32 to accept. + */ +void __init init_hstatus_vsxl_settable_mask(void) +{ +} + +bool hstatus_vsxl_settable(unsigned int vsxl) +{ + return vsxl =3D=3D XLEN_FIELD_32; +} + +static void vcpu_set_vsxl(struct vcpu *v) +{ + ASSERT(is_32bit_domain(v->domain)); +} + +#else /* CONFIG_RISCV_64 */ + +/* + * Bitmap of the hstatus.VSXL values this hardware accepts, indexed by fie= ld + * value. Not one of csr_masks: those are bit masks ANDed into a CSR write, + * this is a set of legal values of a single WARL field. + */ +static unsigned int __ro_after_init hstatus_vsxl_settable_mask; + +/* + * hstatus.VSXL is WARL and, in particular, an implementation is permitted= to + * make it read-only with a value that always keeps VSXLEN =3D=3D HSXLEN. = Probe + * once which values can really be set, so that a domain whose width the + * hardware cannot provide is refused rather than silently run at the wrong + * XLEN. + * + * Every encoding the field can hold is probed, XLEN_FIELD_128 included, so + * that a guest width added later needs no change here. + * + * Like the CSR masks below this assumes all harts behave the same way. + */ +void __init init_hstatus_vsxl_settable_mask(void) +{ + register_t hstatus =3D csr_read(CSR_HSTATUS); + + /* Encoding 0 is reserved, hence starting at the narrowest width. */ + for ( unsigned int vsxl =3D XLEN_FIELD_32; vsxl <=3D XLEN_FIELD_128; v= sxl++ ) + { + register_t test =3D (hstatus & ~HSTATUS_VSXL) | + MASK_INSR(vsxl, HSTATUS_VSXL); + + csr_write(CSR_HSTATUS, test); + + if ( MASK_EXTR(csr_read(CSR_HSTATUS), HSTATUS_VSXL) =3D=3D vsxl ) + hstatus_vsxl_settable_mask |=3D BIT(vsxl, U); + } + + csr_write(CSR_HSTATUS, hstatus); +} + +/* + * Whether the hardware really accepts the given hstatus.VSXL value, i.e. + * whether a guest of that XLEN can be run at all. + */ +bool hstatus_vsxl_settable(unsigned int vsxl) +{ + return hstatus_vsxl_settable_mask & BIT(vsxl, U); +} + +/* + * Set the guest's XLEN explicitly rather than leaving it to the WARL + * behaviour of hstatus.VSXL. + */ +static void vcpu_set_vsxl(struct vcpu *v) +{ + struct cpu_user_regs *regs =3D vcpu_guest_cpu_user_regs(v); + unsigned int vsxl =3D domain_vsxl(v->domain); + + ASSERT(hstatus_vsxl_settable(vsxl)); + + regs->hstatus =3D (regs->hstatus & ~HSTATUS_VSXL) | + MASK_INSR(vsxl, HSTATUS_VSXL); +} + +#endif /* CONFIG_RISCV_32 */ + void __init init_csr_masks(void) { /* @@ -91,6 +204,10 @@ static void vcpu_csr_init(struct vcpu *v) { v->arch.hedeleg =3D HEDELEG_DEFAULT & csr_masks.hedeleg; =20 + /* + * hstatus.VSXL is left zero here: the domain's type, and hence the + * guest's XLEN, is only known once its kernel image has been probed. + */ vcpu_guest_cpu_user_regs(v)->hstatus =3D HSTATUS_SPV | HSTATUS_SPVP; =20 v->arch.hideleg =3D HIDELEG_DEFAULT & csr_masks.hideleg; @@ -149,6 +266,8 @@ static void continue_new_vcpu(struct vcpu *prev) if ( is_idle_vcpu(current) ) reset_stack_and_jump(idle_loop); =20 + vcpu_set_vsxl(current); + /* * return_to_new_vcpu() sets up hstatus.SPV, sstatus.SPP and sepc so * that sret enters the guest in VS-mode. A trap taken in HS-mode diff --git a/xen/arch/riscv/include/asm/domain.h b/xen/arch/riscv/include/a= sm/domain.h index a3fa637b40da..f8fd5964fd74 100644 --- a/xen/arch/riscv/include/asm/domain.h +++ b/xen/arch/riscv/include/asm/domain.h @@ -146,6 +146,9 @@ int vcpu_unset_interrupt(struct vcpu *v, unsigned int i= rq); void vcpu_sync_interrupts(struct vcpu *curr); void vcpu_flush_interrupts(struct vcpu *curr); =20 +bool hstatus_vsxl_settable(unsigned int vsxl); +unsigned int domain_vsxl(const struct domain *d); + #endif /* ASM__RISCV__DOMAIN_H */ =20 /* diff --git a/xen/arch/riscv/include/asm/riscv_encoding.h b/xen/arch/riscv/i= nclude/asm/riscv_encoding.h index 1af309aa4ad5..578d772d23df 100644 --- a/xen/arch/riscv/include/asm/riscv_encoding.h +++ b/xen/arch/riscv/include/asm/riscv_encoding.h @@ -75,7 +75,6 @@ =20 #if __riscv_xlen =3D=3D 64 #define HSTATUS_VSXL _UL(0x300000000) -#define HSTATUS_VSXL_SHIFT 32 #endif #define HSTATUS_VTSR _UL(0x00400000) #define HSTATUS_VTW _UL(0x00200000) diff --git a/xen/arch/riscv/include/asm/setup.h b/xen/arch/riscv/include/as= m/setup.h index 73ce2f293348..ec36cecad50f 100644 --- a/xen/arch/riscv/include/asm/setup.h +++ b/xen/arch/riscv/include/asm/setup.h @@ -11,6 +11,8 @@ void copy_from_paddr(void *dst, paddr_t paddr, unsigned l= ong len); =20 void init_csr_masks(void); =20 +void init_hstatus_vsxl_settable_mask(void); + #endif /* ASM__RISCV__SETUP_H */ =20 /* diff --git a/xen/arch/riscv/setup.c b/xen/arch/riscv/setup.c index 05f93a74c9d3..fd699defcfc3 100644 --- a/xen/arch/riscv/setup.c +++ b/xen/arch/riscv/setup.c @@ -149,6 +149,8 @@ void __init noreturn start_xen(unsigned long bootcpu_id, =20 init_csr_masks(); =20 + init_hstatus_vsxl_settable_mask(); + preinit_xen_time(); =20 intc_preinit(); --=20 2.55.0 From nobody Fri Oct 23 15:32:28 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) client-ip=192.237.175.120; envelope-from=xen-devel-bounces@lists.xenproject.org; helo=lists.xenproject.org; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=pass(p=none dis=none) header.from=gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1790785597; cv=none; d=zohomail.com; s=zohoarc; b=Xz935UUygRjUYRBeeWnX/PX+CE3oQKwXpup1njyjyl7MrlGHr4AF/2gbQp62NSEBGp93bcsHC7/KA3JwSgkkn1P7UeRKRCgZPjMOSiIWS6shPhShVLiMLwETKQqSX2Kg4tA2BxTjo9/ZxVZWPdG4Q4pkhhmykHdxIhybVZrvNdQ= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1790785597; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=Xhuo5m+Ts0aE/+wN424cP30DitNQxPi16xR42z1U3dk=; b=CabS5pImTQkQ/7cIdVAjl4bNgI7OSXAeIYJERev2TVWwM7+idkb9t13WJozUY9aSMJE/9CLECgRBHFpjqGAv3NhWaEP63pmm4wNkMAVqV0HC8LDvyi1D70qVYyI8/hH8G/mTyuaFIQaaiFOD82Tqx5L0SC/q+PJYa8uoK4kAAKA= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) by mx.zohomail.com with SMTPS id 1790785597603296.7624556151843; Wed, 30 Sep 2026 09:26:37 -0700 (PDT) Received: from list by lists.xenproject.org with outflank-mailman.1437600.1656709 (Exim 4.92) (envelope-from ) id 1xBx74-0003T2-Fm; Wed, 30 Sep 2026 16:24:58 +0000 Received: by outflank-mailman (output) from mailman id 1437600.1656709; Wed, 30 Sep 2026 16:24:58 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1xBx73-0003OG-4f; Wed, 30 Sep 2026 16:24:57 +0000 Received: by outflank-mailman (input) for mailman id 1437600; Wed, 30 Sep 2026 16:24:46 +0000 Received: from mx.expurgate.net ([194.145.224.10]) by lists.xenproject.org with esmtp (Exim 4.92) id 1xBx6s-00013q-0r for xen-devel@lists.xenproject.org; Wed, 30 Sep 2026 16:24:46 +0000 Received: from mx.expurgate.net (helo=localhost) by mx.expurgate.net with esmtp id 1xBx6r-006O0j-Cw for xen-devel@lists.xenproject.org; Wed, 30 Sep 2026 18:24:45 +0200 Received: from [10.42.69.8] (helo=localhost) by localhost with ESMTP (eXpurgate MTA 0.9.1) (envelope-from ) id 6abd37b9-2eae-0a2a0a5409dd-0a2a4508b85c-40 for ; Wed, 30 Sep 2026 18:24:45 +0200 Received: from [74.125.225.141] (helo=mail-wm2-f13.google.com) by tlsNG-c1860d.mxtls.expurgate.net with ESMTPS (eXpurgate 4.57.1) (envelope-from ) id 6abd37cd-f659-0a2a45080019-4a7de18da123-3 for ; Wed, 30 Sep 2026 18:24:45 +0200 Received: by mail-wm2-f13.google.com with SMTP id 5b1f17b1804b1-49e8185e037so32140415e9.3 for ; Wed, 30 Sep 2026 09:24:45 -0700 (PDT) Received: from fedora (user-109-243-71-234.play-internet.pl. [109.243.71.234]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-4a01cd43e66sm14620485e9.2.2026.09.30.09.24.43 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 30 Sep 2026 09:24:44 -0700 (PDT) X-Outflank-Mailman: Message body and most headers restored to incoming version X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" Authentication-Results: eu.smtp.expurgate.cloud; dkim=pass header.s=20251104 header.d=gmail.com header.i="@gmail.com" header.h="Content-Transfer-Encoding:MIME-Version:References:In-Reply-To:Message-ID:Date:Subject:Cc:To:From" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1790785485; x=1791390285; darn=lists.xenproject.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=Xhuo5m+Ts0aE/+wN424cP30DitNQxPi16xR42z1U3dk=; b=RApMHUsYwj/jdzraIR0K+SBRHFPIpPznWa/JsMQY7CtMDk37AzptmDgiUcegzdwFmM PfNYJzVMe4IuFwNJA2kzQPO2CdDYAt9LiOLEUONGLHWWV8sip9gnO/krBsld8dPtgrbY v/Qpz5iYgLHqC96/GykqzXasKDfE7qGCuiGNDkevm4+W0ldCLKBrnKcvOXc4iaNvFKLD wpmGA0QKtH6tt86KUyP+fIqDVh7A8appdb4NZdTbCi9oic/O+MZhnFGD8NLtCoPxN97I MXPc8UuFavsHLdMHIu8gaQiZyAMpEFWWhzUK8QhKkvuElTfExOdq1Th+GFpLSlf4kQuT /ymQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1790785485; x=1791390285; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=Xhuo5m+Ts0aE/+wN424cP30DitNQxPi16xR42z1U3dk=; b=O+wHS/F5lgaqYGdaj+qIvauMiSMS3cFCya8oaDfuWpTyibmfVgBglsoLXh178ixXW9 dB9ShkCgc41Q2RFkUaoQgoolydz3hqIJY7q+eulxy+nyJockCI2hmjKYLQIVzhabsCdQ YqmPZ0+r7lkPRYkWYwiv2ipcujjPvJpfwumXVP6+DjE43Snx1windQEqxyoVebPnrOYF 8iFrLjO4wJnmtFFjvvYLCWcCNVzZA1NFCa3LXJEWvg9ojiLDsQPjio9v9IQA9/kfu8lc rKqxlhm12D73/3JLoAtIj0gNk9gIxgp0k3ObvXhY9QhDFR2evPx0yyIMBrtszNrP7hL7 zOkg== X-Gm-Message-State: AFuF++nJGF2GHcbjCeLfV6fTuIR9WQ1sEU/yofaUYfENXVW2haMS7dVN fSZPy9Q94hRDC3oCsMblkGEmt9qhP94c0OdmFwtYt6CL+ZmeF4oAC1kIYuLETA== X-Gm-Gg: AYBFou0mN3pOyGlc5A+bTntq/2Ia0BqgXGm9AxYJTFSadil7dlkonVWU4c+zn/rZNBQ Hdjin4sjDNsQihLzyiRRuHpArLCJOb34wazgZ7Oo2wxyQuXmMWc7xsRpTflG0ym7hDnjrD/jeH5 lL9UoiM0A+My30fLogEa7QjRe2wCSGDAUke62zS4CesKCf2HRLDpDcmfewFEkqdIyB0KutG+IDa 3qA/xa/XH8G8zJIetGlHbYNnPt9vDYyZ95Wo3FHLlVowf4TJtvnMRjFxsiPuiD5L9EEJiLKqj1N 2FEDF2hgSPYJXHmBNOpfNnl4R4ruHJHYVQqsTHuy3w64WZhwuDLtETv2lbUk4UG3Ca2hQz1Afi7 JbIgfjXPNHQ4K8tHZrUHtavNjLXHDEuTaH8tjO62EvXXtcR9ItDtcKZacIpJ884Q+vZWzH7drDP gvxWES4B94FyEh8B9Ys5LESlMo/cXOvUhLBs9mYggO9oVUM+AZ1YPlEIQUMP5hdfDaYCCAgCQ1E 5gmKzk7oIQ4BwQ7DBHfRfVlN7/l0jMXWCEi7WwpoFiyJ2MF7YU= X-Received: by 2002:a05:600c:45d3:b0:4a0:53e:b7d6 with SMTP id 5b1f17b1804b1-4a01aff8082mr30389455e9.16.1790785484409; Wed, 30 Sep 2026 09:24:44 -0700 (PDT) From: Oleksii Kurochko To: xen-devel@lists.xenproject.org Cc: Romain Caritey , Baptiste Le Duc , Zheng Zhang , Oleksii Kurochko , Alistair Francis , Connor Davis , Andrew Cooper , Anthony PERARD , Michal Orzel , Jan Beulich , Julien Grall , =?UTF-8?q?Roger=20Pau=20Monn=C3=A9?= , Stefano Stabellini Subject: [PATCH v3 39/39] xen/riscv: introduce IMSIC h/w interrupt file attaching to vcpu Date: Wed, 30 Sep 2026 18:23:58 +0200 Message-ID: X-Mailer: git-send-email 2.55.0 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-purgate-ID: tlsNG-c1860d/1790785485-CCF4F87B-DE3EE79E/10/73395122804 X-purgate-type: spam X-purgate-size: 10057 X-ZohoMail-DKIM: pass (identity @gmail.com) X-ZM-MESSAGEID: 1790785598697158500 Content-Type: text/plain; charset="utf-8" Introduce imsic_vsfile_attach() to give a vCPU a working guest interrupt file. A guest (VS) interrupt file has to be backed by one of the hardware guest interrupt files of the pCPU the vCPU runs on, so that pCPU has to be known first. arch_vcpu_create() is therefore not a suitable place: the pCPU assigned to a vCPU can still change before the vCPU is first scheduled, which would mean taking another file and remapping the guest's IMSIC page to it. Call imsic_vsfile_attach() from continue_new_vcpu() instead, i.e. when the vCPU is scheduled for the first time; as that isn't an __init context, neither is imsic_vsfile_attach(). Giving a vCPU its first file shares most of the steps with moving it to a new one on migration, so move the body of imsic_migrate_vcpu() to imsic_vsfile_move() and use it for both. Its first_attach argument skips the part which moves the interrupt state out of the old file: the vCPU has never run at that point, so the freshly acquired and zeroed file is all the interrupt state it has, and hstatus.VGEIN can be pointed at it right away. vAPLIC target registers are reconfigured on the first attach as well: a target the guest writes for a vCPU which has no h/w guest interrupt file yet only updates the stored copy, which reaches the h/w at this point. A vCPU which has already run is left without a h/w file only when its first attach failed, which crashed its domain. Such a vCPU can still be migrated, e.g. by an affinity change or a pCPU going offline, until the domain is destroyed, so don't panic() for it, which would take the whole host down: return early. Should a vCPU of a domain which isn't shutting down ever get there, crash that domain rather than the host. Signed-off-by: Oleksii Kurochko --- imsic_vsfile_move() isn't split out of imsic_migrate_vcpu() earlier in the series: until this patch imsic_migrate_vcpu() would be its only user, so the first_attach path would have no caller. The first attach itself can't come earlier either, as it is done from continue_new_vcpu(), introduced by "xen/riscv: implement continue_new_vcpu()". --- Changes in v3: - imsic_update_state() is now implemented by "xen/riscv: remap interrupts to new IMSIC VS-file". - Share the code of imsic_vsfile_attach() and imsic_migrate_vcpu() in imsic_vsfile_move(), whose first_attach argument skips the part moving state out of the old file. - Call vaplic_reconfigure_target() on the first attach as well, so that vAPLIC targets the guest wrote for the vCPU before it got its file reach the h/w. - Replace panic() for a vCPU left without a h/w file by domain_crash(): it can only happen to a vCPU whose first imsic_vsfile_acquire() failed and crashed its domain, and such a vCPU can still be migrated. - imsic_vsfile_acquire(), together with the vgein_release() on a mapping failure, is now introduced by "xen/riscv: remap interrupts to new IMSIC VS-file", without the cpu argument (the file is always taken on v->processor). - Include asm/imsic.h for imsic_vsfile_attach(). - Drop imsic_nr_eix() in favour of imsic_cfg.nr_eix. - Drop vcpu_set_vgein(): with the code shared in imsic_vsfile_move(), hstatus.VGEIN is updated in one place only. - Rework the commit message: drop the stale vcpu_aia_init() name and the claim that the IMSIC state has no concurrent readers yet. --- Changes in v2: - Update vcpu_aia_init() to catch sw interrupt file and update some debug messages in it. - Add vgein_release() if IMSIC h/w mapping failed. - imsic_update_state(): store v->processor rather than cpuid_to_hartid(), as ->vsfile_cpu is consumed as a Xen CPU id (aplic_hart_field(), cpumask_of()) and its NR_CPUS sentinel lives in that numbering space. - Drop parentheses around guest_file_id ? ... in imsic_update_state(). - Rename vcpu_aia_init to imsic_vsfile_attach() and move the code to imsic.c. --- --- xen/arch/riscv/domain.c | 3 ++ xen/arch/riscv/imsic.c | 79 +++++++++++++++++++++++------- xen/arch/riscv/include/asm/imsic.h | 2 + 3 files changed, 66 insertions(+), 18 deletions(-) diff --git a/xen/arch/riscv/domain.c b/xen/arch/riscv/domain.c index 9155ff4234e8..e8ae62626b76 100644 --- a/xen/arch/riscv/domain.c +++ b/xen/arch/riscv/domain.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -268,6 +269,8 @@ static void continue_new_vcpu(struct vcpu *prev) =20 vcpu_set_vsxl(current); =20 + imsic_vsfile_attach(current); + /* * return_to_new_vcpu() sets up hstatus.SPV, sstatus.SPP and sepc so * that sret enters the guest in VS-mode. A trap taken in HS-mode diff --git a/xen/arch/riscv/imsic.c b/xen/arch/riscv/imsic.c index a8e99997c087..bb8cdf437a6a 100644 --- a/xen/arch/riscv/imsic.c +++ b/xen/arch/riscv/imsic.c @@ -1251,7 +1251,14 @@ static unsigned int imsic_vsfile_acquire(struct vcpu= *v) return vsfile_id; } =20 -void imsic_migrate_vcpu(struct vcpu *v) +/* + * Give the vCPU a h/w guest interrupt file on the pCPU it runs on and move + * all its interrupt producers and state there. + * + * @first_attach tells that the vCPU is only now given its very first file, + * so there is no old file to move anything out of. + */ +static void imsic_vsfile_move(struct vcpu *v, bool first_attach) { struct imsic_vsfile_data vsfile_data =3D { .nr_eix =3D imsic_cfg.nr_eix, @@ -1262,33 +1269,38 @@ void imsic_migrate_vcpu(struct vcpu *v) unsigned int old_vsfile_id; unsigned int old_vsfile_cpu; =20 - /* - * The scheduler can mark a freshly created vCPU's unit as migrated and - * invoke this before the vCPU has ever run (see the migrated branch in - * schedule()). No need to do migration for such vCPUs as they aren't = fully - * initialized (for example, context_switch() will be called after - * imsic_migrate_vcpu()). - */ - if ( v->arch.last_cpu =3D=3D CPU_NONE ) - return; - read_lock_irqsave(&imsic_state->vsfile_lock, flags); old_vsfile_id =3D imsic_state->guest_file_id; old_vsfile_cpu =3D imsic_state->vsfile_cpu; read_unlock_irqrestore(&imsic_state->vsfile_lock, flags); =20 + ASSERT(!first_attach || old_vsfile_cpu =3D=3D CPU_NONE); + /* - * We don't support SW interrupt files at the moment. Bail out before - * anything is touched, as the old file has no owning pCPU in that case - * and there is nothing to retarget the producers away from. + * With no h/w file owned, the vCPU is either given its first file or + * uses a s/w file, and s/w files aren't supported at the moment. + * + * A vCPU which has already run has no h/w file only if its first + * imsic_vsfile_acquire() failed and crashed its domain. The vCPU can + * still be migrated until the domain is destroyed, so return early, as + * there is no old file to move anything out of. Should that ever happ= en + * for a domain which isn't shutting down, crash it rather than the ho= st; + * for one which already is, domain_crash() does nothing but log. + * + * TODO: once s/w files are supported, move the state out of the s/w f= ile + * here instead. */ - if ( old_vsfile_cpu =3D=3D CPU_NONE ) - panic("IMSIC SW-file isn't supported\n"); + if ( old_vsfile_cpu =3D=3D CPU_NONE && !first_attach ) + { + ASSERT(domain_shutting_down(v->domain)); + domain_crash(v->domain, "%pv: IMSIC s/w VS-file isn't supported\n"= , v); + return; + } =20 /* * At this point, all interrupt producers are still using the old IMSIC - * VS-file. Allocate and clear the new one before redirecting anything - * to it. + * VS-file, if any. Allocate and clear the new one before redirecting + * anything to it. */ =20 /* Zero-out, map and start to use the new IMSIC VS-file */ @@ -1310,6 +1322,13 @@ void imsic_migrate_vcpu(struct vcpu *v) */ vaplic_reconfigure_target(v); =20 + /* + * The vCPU has never run yet, so the just zeroed out file is all the + * interrupt state it has and HSTATUS.VGEIN can be pointed at it at on= ce. + */ + if ( first_attach ) + goto set_vgein; + /* * Synchronizing interactions between a hart and the APLIC. * @@ -1349,8 +1368,32 @@ void imsic_migrate_vcpu(struct vcpu *v) if ( !v->is_running ) imsic_call_on_cpu(v->processor, imsic_local_hgeie_set, &vsfile_dat= a); =20 + set_vgein: /* Set VCPU HSTATUS.VGEIN to new IMSIC VS-file */ vcpu_guest_cpu_user_regs(v)->hstatus &=3D ~HSTATUS_VGEIN; vcpu_guest_cpu_user_regs(v)->hstatus |=3D MASK_INSR(vsfile_data.hgei, HSTATUS_VGEIN); } + +void imsic_migrate_vcpu(struct vcpu *v) +{ + /* + * The scheduler can mark a freshly created vCPU's unit as migrated and + * invoke this before the vCPU has ever run (see the migrated branch in + * schedule()). No need to do migration for such vCPUs as they aren't = fully + * initialized (for example, context_switch() will be called after + * imsic_migrate_vcpu()). + */ + if ( v->arch.last_cpu =3D=3D CPU_NONE ) + return; + + imsic_vsfile_move(v, false); +} + +void imsic_vsfile_attach(struct vcpu *v) +{ + if ( !aia_usable() ) + return; + + imsic_vsfile_move(v, true); +} diff --git a/xen/arch/riscv/include/asm/imsic.h b/xen/arch/riscv/include/as= m/imsic.h index e08b041eebbd..118c3dc94a17 100644 --- a/xen/arch/riscv/include/asm/imsic.h +++ b/xen/arch/riscv/include/asm/imsic.h @@ -118,4 +118,6 @@ int imsic_map_guest_file(struct vcpu *v, unsigned int v= sfile_id); =20 void imsic_migrate_vcpu(struct vcpu *v); =20 +void imsic_vsfile_attach(struct vcpu *v); + #endif /* ASM_RISCV_IMSIC_H */ --=20 2.55.0