From nobody Sat Jul 25 01:24:45 2026 Received: from ultrarisc.com (unknown [218.76.62.146]) by smtp.subspace.kernel.org (Postfix) with ESMTP id B044E43933A for ; Tue, 21 Jul 2026 07:58:28 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=218.76.62.146 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784620712; cv=none; b=CrEZ9zvaN4MAAC5E3SrbIbatcTgnRhixSHEZ6eiZDwt/cCLDXXMkMTbvx+vvRbTB1X5EV43Plf9pbcSyYIY3nJyyqJu4PGLoCZGW++//+ghGOJkSsijMilWcgq5e6Nft0TBQv7ztexR/0eo5AcgVH6JMUdSVRZwi6Hr214tey7o= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784620712; c=relaxed/simple; bh=f9SiS5JhfElIqgsWTvqaWagoBAEpIUxs4BttsQ6e2bk=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References; b=pb+cjvwVFXuqCmS3h+lb0FhHkCyAf8d8KP1Ona1Bu0aXst37THbzzs27olfhVkBN2ODqOdZkdnrrjbf7YSXpDuMgtpVUFinZVClKw6x0Tmth8XvIVlHpDtOopGxZEwtDoGyZ+GSiI4NnQZXDvWSefi+gpZcjEsmbChCdkoTQmG8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=ultrarisc.com; spf=pass smtp.mailfrom=ultrarisc.com; dkim=pass (1024-bit key) header.d=ultrarisc.com header.i=@ultrarisc.com header.b=lR1KqYDT; arc=none smtp.client-ip=218.76.62.146 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=ultrarisc.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=ultrarisc.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=ultrarisc.com header.i=@ultrarisc.com header.b="lR1KqYDT" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ultrarisc.com; s=dkim; h=Received:From:To:Cc:Subject:Date: Message-Id:In-Reply-To:References; bh=WLL13H6pAzg6R/XvQjZDAUGzQH 4dmGtx+tqHLvncJbY=; b=lR1KqYDT2hE+wkhLscra8FBodIhZINNId3d62fXXas dkM1xWmRRGjXbyIyqeHJKBoeRkdYDMsNA23vOauZ69ahOntCZ8GN1Ftq8dfk5mSC HCbHUmC9BbCkg4z8KdHtrZL9/3tiD4em92LtrYupP3MTmoKTjUrRVKLVo1OcCRoh U= Received: from localhost.localdomain (unknown [192.168.100.1]) by localhost.localdomain (Coremail) with SMTP id AQAAfwAnEkOyJl9q4GgUAA--.17568S3; Tue, 21 Jul 2026 15:58:50 +0800 (CST) From: Xie Bo To: linux-riscv@lists.infradead.org Cc: pjw@kernel.org, palmer@dabbelt.com, aou@eecs.berkeley.edu, alex@ghiti.fr, linux-kernel@vger.kernel.org, Xie Bo Subject: [RFC PATCH 1/3] riscv: sbi: Add FWFT get helper Date: Tue, 21 Jul 2026 15:58:10 +0800 Message-Id: <20260721075812.82708-2-xb@ultrarisc.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20260721075812.82708-1-xb@ultrarisc.com> References: <20260721075812.82708-1-xb@ultrarisc.com> X-CM-TRANSID: AQAAfwAnEkOyJl9q4GgUAA--.17568S3 X-Coremail-Antispam: 1UD129KBjvJXoW7KFyfCFyfJryxWw4rZryUAwb_yoW8ZF47pF s5CF98CFWYgF1Ik3WSy34Du3yrJw4kKa13K3y2ya4aya13tF4rAwnYv3Z0qr1kAa4jqFWr CayYgrWq9a1UXa7anT9S1TB71UUUUU7qnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnRJUUUPI14x267AKxVW8JVW5JwAFc2x0x2IEx4CE42xK8VAvwI8IcIk0 rVWrJVCq3wAFIxvE14AKwVWUJVWUGwA2048vs2IY020E87I2jVAFwI0_Jr4l82xGYIkIc2 x26xkF7I0E14v26r1I6r4UM28lY4IEw2IIxxk0rwA2F7IY1VAKz4vEj48ve4kI8wA2z4x0 Y4vE2Ix0cI8IcVAFwI0_Jr0_JF4l84ACjcxK6xIIjxv20xvEc7CjxVAFwI0_Gr0_Cr1l84 ACjcxK6I8E87Iv67AKxVW8JVWxJwA2z4x0Y4vEx4A2jsIEc7CjxVAFwI0_Gr0_Gr1UM2AI xVAIcxkEcVAq07x20xvEncxIr21l5I8CrVACY4xI64kE6c02F40Ex7xfMcIj6xIIjxv20x vE14v26r106r15McIj6I8E87Iv67AKxVW8JVWxJwAm72CE4IkC6x0Yz7v_Jr0_Gr1lF7xv r2IYc2Ij64vIr41lF7I21c0EjII2zVCS5cI20VAGYxC7MxkF7I0En4kS14v26r126r1DMx kIecxEwVCm-wCF04k20xvY0x0EwIxGrwCFx2IqxVCFs4IE7xkEbVWUJVW8JwC20s026c02 F40E14v26r1j6r18MI8I3I0E7480Y4vE14v26r106r1rMI8E67AF67kF1VAFwI0_JF0_Jw 1lIxkGc2Ij64vIr41lIxAIcVC0I7IYx2IY67AKxVWUJVWUCwCI42IY6xIIjxv20xvEc7Cj xVAFwI0_Gr0_Cr1lIxAIcVCF04k26cxKx2IYs7xG6r1j6r1xMIIF0xvEx4A2jsIE14v26r 1j6r4UMIIF0xvEx4A2jsIEc7CjxVAFwI0_Gr0_Gr1UYxBIdaVFxhVjvjDU0xZFpf9x0JUS jgsUUUUU= X-CM-SenderInfo: l0e63zxwud2x1vfou0bp/1tbiAQAOB2pdm1EAHAALsi Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" The SBI FWFT extension supports querying a feature's value on the local hart, but the RISC-V SBI wrapper currently only exposes SET operations. Add a generic GET helper which maps SBI errors to Linux errno values and only updates the caller's output on success. Signed-off-by: Xie Bo --- arch/riscv/include/asm/sbi.h | 1 + arch/riscv/kernel/sbi.c | 29 +++++++++++++++++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/arch/riscv/include/asm/sbi.h b/arch/riscv/include/asm/sbi.h index 5725e0c..b1773b1 100644 --- a/arch/riscv/include/asm/sbi.h +++ b/arch/riscv/include/asm/sbi.h @@ -607,6 +607,7 @@ int sbi_remote_hfence_vvma_asid(const struct cpumask *c= pu_mask, unsigned long asid); long sbi_probe_extension(int ext); =20 +int sbi_fwft_get(u32 feature, unsigned long *value); int sbi_fwft_set(u32 feature, unsigned long value, unsigned long flags); int sbi_fwft_set_cpumask(const cpumask_t *mask, u32 feature, unsigned long value, unsigned long flags); diff --git a/arch/riscv/kernel/sbi.c b/arch/riscv/kernel/sbi.c index c443337..51e0c58 100644 --- a/arch/riscv/kernel/sbi.c +++ b/arch/riscv/kernel/sbi.c @@ -318,6 +318,35 @@ static void cpu_sbi_fwft_set(void *arg) atomic_set(&req->error, ret); } =20 +/** + * sbi_fwft_get() - Get a feature value on the local hart + * @feature: The feature ID to get + * @value: Where to store the feature value + * + * Return: 0 on success, appropriate Linux error code otherwise. + */ +int sbi_fwft_get(u32 feature, unsigned long *value) +{ + struct sbiret ret; + int error; + + if (!sbi_fwft_supported) + return -EOPNOTSUPP; + + if (!value) + return -EINVAL; + + ret =3D sbi_ecall(SBI_EXT_FWFT, SBI_EXT_FWFT_GET, + feature, 0, 0, 0, 0, 0); + error =3D sbi_err_map_linux_errno(ret.error); + if (error) + return error; + + *value =3D ret.value; + + return 0; +} + /** * sbi_fwft_set() - Set a feature on the local hart * @feature: The feature ID to be set --=20 2.17.1 From nobody Sat Jul 25 01:24:45 2026 Received: from ultrarisc.com (unknown [218.76.62.146]) by smtp.subspace.kernel.org (Postfix) with ESMTP id A42DF43787E for ; Tue, 21 Jul 2026 07:58:28 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=218.76.62.146 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784620711; cv=none; b=o50niocOlxNjLcxjEDsEX9ZF+OVFrh9HuVD0PbdO0Kv2fxMLclRjhASRWTGrVEtx+5plOyLDxN017zRkmmhA5w39IUN2ekO7gTcBGx/G3bpb6iqTfr4LyVIMA0XcoG1bX+ijtDgpWfZ8a0f4i2K5edVaPPX7tUu+Sf1/S7zdunc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784620711; c=relaxed/simple; bh=oWOXggwd6y7a1kmp4KWCXMN3Bp596SuoP8bYnz1GZEI=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References; b=IpQr/SCdQe1lo4tBEfFjDIcWU8LXlytom4A2fPD8SBx1K9MCftxbVbKvCxoAdGl4eTgmX4p3jaPwqlmGjXJxuoJx6E2qc9gIuTc8+Adcw7AQM3d4gsC5uAr/4/TsbD3lXuTldoWRy7xNsR8PxtwZzLIFjmJuhkO/LCLUEQldCYM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=ultrarisc.com; spf=pass smtp.mailfrom=ultrarisc.com; dkim=pass (1024-bit key) header.d=ultrarisc.com header.i=@ultrarisc.com header.b=YuW5AlJ+; arc=none smtp.client-ip=218.76.62.146 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=ultrarisc.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=ultrarisc.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=ultrarisc.com header.i=@ultrarisc.com header.b="YuW5AlJ+" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ultrarisc.com; s=dkim; h=Received:From:To:Cc:Subject:Date: Message-Id:In-Reply-To:References; bh=P2eC5CO17ZmCaiY9iogmoKgMU+ GEh9yZwgxAO6EYucI=; b=YuW5AlJ+Vope2VO8opcME13yqfR3vSD8eyIZcons2E g8jxWn+zhlNxtU0slbTvcH9MugIEvXAPyAOMM1qZd89ZF27Bg7LMVG4O89RIcZLW ntFUJNwM1RRkPtkxwq3G4v1TiIpgjjz9F23RMi7jidjzh1RnmGZpDHPSw5fV4sRz 8= Received: from localhost.localdomain (unknown [192.168.100.1]) by localhost.localdomain (Coremail) with SMTP id AQAAfwAnEkOyJl9q4GgUAA--.17568S4; Tue, 21 Jul 2026 15:58:51 +0800 (CST) From: Xie Bo To: linux-riscv@lists.infradead.org Cc: pjw@kernel.org, palmer@dabbelt.com, aou@eecs.berkeley.edu, alex@ghiti.fr, linux-kernel@vger.kernel.org, Xie Bo Subject: [RFC PATCH 2/3] riscv: kexec: Select HOTPLUG_CPU for KEXEC_FILE Date: Tue, 21 Jul 2026 15:58:11 +0800 Message-Id: <20260721075812.82708-3-xb@ultrarisc.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20260721075812.82708-1-xb@ultrarisc.com> References: <20260721075812.82708-1-xb@ultrarisc.com> X-CM-TRANSID: AQAAfwAnEkOyJl9q4GgUAA--.17568S4 X-Coremail-Antispam: 1UD129KBjvdXoW7Wr4kKFy7Gw4DXrykJrWUArb_yoW3Zwb_C3 48JF15urWfCF95Zr9agr4rZr4fAayrury5Jr47trW8u34a9wn3G34qkF1UZrn7W34rZ3yf urWFvrs7Kr18WjkaLaAFLSUrUUUUjb8apTn2vfkv8UJUUUU8Yxn0WfASr-VFAUDa7-sFnT 9fnUUIcSsGvfJTRUUUbqxFF20E14v26ryj6rWUM7CY07I20VC2zVCF04k26cxKx2IYs7xG 6rWj6s0DM7CIcVAFz4kK6r1j6r18M28IrcIa0xkI8VA2jI8067AKxVWUXwA2048vs2IY02 0Ec7CjxVAFwI0_Gr0_Xr1l8cAvFVAK0II2c7xJM28CjxkF64kEwVA0rcxSw2x7M28EF7xv wVC0I7IYx2IY67AKxVWUJVWUCwA2z4x0Y4vE2Ix0cI8IcVCY1x0267AKxVW8JVWxJwA2z4 x0Y4vEx4A2jsIE14v26r4j6F4UM28EF7xvwVC2z280aVCY1x0267AKxVW8JVW8Jr1le2I2 62IYc4CY6c8Ij28IcVAaY2xG8wAqx4xG64xvF2IEw4CE5I8CrVC2j2WlYx0E2Ix0cI8IcV AFwI0_JrI_JrylYx0Ex4A2jsIE14v26r4j6F4UMcvjeVCFs4IE7xkEbVWUJVW8JwACjcxG 0xvY0x0EwIxGrwACjI8F5VA0II8E6IAqYI8I648v4I1lc7CjxVAaw2AFwI0_JF0_Jw1lc2 xSY4AK6svPMxAIw28IcxkI7VAKI48JMxC20s026xCaFVCjc4AY6r1j6r4UMI8I3I0E5I8C rVAFwI0_Jr0_Jr4lx2IqxVCjr7xvwVAFwI0_JrI_JrWlx4CE17CEb7AF67AKxVWUAVWUtw CIc40Y0x0EwIxGrwCI42IY6xIIjxv20xvE14v26r1j6r1xMIIF0xvE2Ix0cI8IcVCY1x02 67AKxVW8JVWxJwCI42IY6xAIw20EY4v20xvaj40_Jr0_JF4lIxAIcVC2z280aVAFwI0_Jr 0_Gr1lIxAIcVC2z280aVCY1x0267AKxVW8JVW8JrUvcSsGvfC2KfnxnUUI43ZEXa7VUUPk uDUUUUU== X-CM-SenderInfo: l0e63zxwud2x1vfou0bp/1tbiAQAOB2pdm1EAHAANsk Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" RISC-V machine_shutdown() uses CPU hotplug to offline secondary harts before handing control to the next kernel. ARCH_SELECTS_KEXEC selects HOTPLUG_CPU for SMP, but the KEXEC_FILE-only configuration does not. Select HOTPLUG_CPU from ARCH_SELECTS_KEXEC_FILE as well so both loading interfaces use the same shutdown guarantee. Signed-off-by: Xie Bo --- arch/riscv/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig index f7028ca..55e94e2 100644 --- a/arch/riscv/Kconfig +++ b/arch/riscv/Kconfig @@ -1097,6 +1097,7 @@ config ARCH_SUPPORTS_KEXEC_FILE config ARCH_SELECTS_KEXEC_FILE def_bool y depends on KEXEC_FILE + select HOTPLUG_CPU if SMP select HAVE_IMA_KEXEC if IMA select KEXEC_ELF =20 --=20 2.17.1 From nobody Sat Jul 25 01:24:45 2026 Received: from ultrarisc.com (unknown [218.76.62.146]) by smtp.subspace.kernel.org (Postfix) with ESMTP id A41CE43786E for ; Tue, 21 Jul 2026 07:58:29 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=218.76.62.146 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784620712; cv=none; b=POlxXhQlJx6lOjT6x6tCyebKZj0Uj3WnC11KwGUYNdWQkaFloMlJfU0KQvk8/MoY6ynwFmpHEUoXUvt8CUKVg9Nw+BnrnEXHfSgWOmfNisLK7KmuLkCnjwFYlwJ2kUCjvslOj53EYlAHDyqevbOGKdI6EwG6+kx39rrRK9RETNs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784620712; c=relaxed/simple; bh=DYof9O8WX1YKIy/5TKP+5qSpTsl7CqwiBAjywKj3hFA=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References; b=cIGZalcgpFwoXvpU2IGd+ZjIlQyA7ugV1+Lh9GrO3xlOa1bICFG5AGCJgxJrRvA9TiYvLN1kyFRar3NqCzj1TlrArCkwhNZAOBA8DTKeRUX1BiM/sDmXaUZWTBwfZeC1qV1Wce2DCGz8xcDGR+UD3vfrQSZBuP/qhdf+njjIe48= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=ultrarisc.com; spf=none smtp.mailfrom=ultrarisc.com; dkim=pass (1024-bit key) header.d=ultrarisc.com header.i=@ultrarisc.com header.b=EegCwpcd; arc=none smtp.client-ip=218.76.62.146 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=ultrarisc.com Authentication-Results: smtp.subspace.kernel.org; spf=none smtp.mailfrom=ultrarisc.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=ultrarisc.com header.i=@ultrarisc.com header.b="EegCwpcd" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ultrarisc.com; s=dkim; h=Received:From:To:Cc:Subject:Date: Message-Id:In-Reply-To:References; bh=5mI+h6L5olk5HlVJuixucCyBnh u5tdB9Nk+Ue6WSdts=; b=EegCwpcdSgL6N3ImcsauEnp2rKFUTMbgHnK0SDeQRF EECbWA746nH/Sy3yqB7mjJsgqR+rHtFFcrZ78KYA3EWX/hFlo/wkodcNnOF3hmAY ujG4ud9iA8vTsbatPX0X12WhYh2lDt+OmSYeiPVqqurTQ+q04e0rnZYraqoW9wA4 c= Received: from localhost.localdomain (unknown [192.168.100.1]) by localhost.localdomain (Coremail) with SMTP id AQAAfwAnEkOyJl9q4GgUAA--.17568S5; Tue, 21 Jul 2026 15:58:51 +0800 (CST) From: Xie Bo To: linux-riscv@lists.infradead.org Cc: pjw@kernel.org, palmer@dabbelt.com, aou@eecs.berkeley.edu, alex@ghiti.fr, linux-kernel@vger.kernel.org, Xie Bo Subject: [RFC PATCH 3/3] riscv: Add supervisor pointer masking control Date: Tue, 21 Jul 2026 15:58:12 +0800 Message-Id: <20260721075812.82708-4-xb@ultrarisc.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20260721075812.82708-1-xb@ultrarisc.com> References: <20260721075812.82708-1-xb@ultrarisc.com> X-CM-TRANSID: AQAAfwAnEkOyJl9q4GgUAA--.17568S5 X-Coremail-Antispam: 1UD129KBjvAXoW3Kw4fur1rCFyrCry3ZryxXwb_yoW8WFW3Ao WIga18WF4rtr12kF1rur17KFW2g34vgr4kZws8tan8WF17Ar10qF1vg3srta47KryfGa43 ua1SqrsrWa18XF97n29KB7ZKAUJUUUU8529EdanIXcx71UUUUU7v73VFW2AGmfu7bjvjm3 AaLaJ3UjIYCTnIWjp_UUUO07AC8VAFwI0_Wr0E3s1l1xkIjI8I6I8E6xAIw20EY4v20xva j40_Wr0E3s1l1IIY67AEw4v_Jr0_Jr4l82xGYIkIc2x26280x7IE14v26r1rM28IrcIa0x kI8VCY1x0267AKxVW5JVCq3wA2ocxC64kIII0Yj41l84x0c7CEw4AK67xGY2AK021l84AC jcxK6xIIjxv20xvE14v26r1j6r1xM28EF7xvwVC0I7IYx2IY6xkF7I0E14v26r4j6F4UM2 8EF7xvwVC2z280aVAFwI0_Gr0_Cr1l84ACjcxK6I8E87Iv6xkF7I0E14v26r4j6r4UJwAS 0I0E0xvYzxvE52x082IY62kv0487Mc02F40EFcxC0VAKzVAqx4xG6I80ewAv7VC0I7IYx2 IY67AKxVWUGVWUXwAv7VC2z280aVAFwI0_Gr0_Cr1lOx8S6xCaFVCjc4AY6r1j6r4UM4x0 Y48IcxkI7VAKI48JM4x0x7Aq67IIx4CEVc8vx2IErcIFxwCY1x0262kKe7AKxVWUAVWUtw CY02Avz4vE-syl42xK82IYc2Ij64vIr41l4I8I3I0E4IkC6x0Yz7v_Jr0_Gr1lx2IqxVAq x4xG67AKxVWUJVWUGwC20s026x8GjcxK67AKxVWUGVWUWwC2zVAF1VAY17CE14v26r126r 1DMIIYrxkI7VAKI48JMIIF0xvE2Ix0cI8IcVAFwI0_Jr0_JF4lIxAIcVC0I7IYx2IY6xkF 7I0E14v26r4j6F4UMIIF0xvE42xK8VAvwI8IcIk0rVWUJVWUCwCI42IY6I8E87Iv67AKxV WUJVW8JwCI42IY6I8E87Iv6xkF7I0E14v26r4j6r4UJbIYCTnIWIevJa73UjIFyTuYvjfU Yc_TUUUUU X-CM-SenderInfo: l0e63zxwud2x1vfou0bp/1tbiAQAOB2pdm1EAHAAPsm Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Provide internal supervisor pointer-masking lifecycle support through SBI FWFT independently of optional in-kernel consumer enablement. This lets Linux establish a known PMLEN state even when the consumer is disabled. Allow enabled consumers to select PMLEN=3D7 transactionally. Gate enable until smp_cpus_done() and serialize runtime state changes against CPU hotplug. Preserve PMLEN in the same-kernel hibernation header and configure the resume hart immediately before restoring the memory image. Fail-stop if the fresh kernel cannot establish or recover verified PMLEN0. Reset retained state on successor boot and secondary hart entry. Before kexec, reset every hart at its final offline or handoff point so an older kernel cannot inherit PMLEN7. Refuse a crash handoff while a possibly tagged hart remains stale. Keep consumer enablement fail-closed on firmware errors. Roll back an unsuccessful initial transaction, distinguish rollback failure as a permanent broken state, and reject harts whose required local state cannot be established. Signed-off-by: Xie Bo --- arch/riscv/Kconfig | 22 ++++ arch/riscv/include/asm/sspm.h | 78 ++++++++++++ arch/riscv/kernel/Makefile | 1 + arch/riscv/kernel/cpu-hotplug.c | 3 +- arch/riscv/kernel/hibernate.c | 12 ++ arch/riscv/kernel/machine_kexec.c | 10 +- arch/riscv/kernel/setup.c | 2 + arch/riscv/kernel/smp.c | 2 + arch/riscv/kernel/smpboot.c | 11 +- arch/riscv/kernel/sspm.c | 202 ++++++++++++++++++++++++++++++ 10 files changed, 337 insertions(+), 6 deletions(-) create mode 100644 arch/riscv/include/asm/sspm.h create mode 100644 arch/riscv/kernel/sspm.c diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig index 55e94e2..18b90b4 100644 --- a/arch/riscv/Kconfig +++ b/arch/riscv/Kconfig @@ -572,6 +572,28 @@ config RISCV_ISA_SUPM If this option is disabled, userspace will be unable to use the prctl(PR_{SET,GET}_TAGGED_ADDR_CTRL) API. =20 +config RISCV_SSPM + bool + depends on 64BIT && RISCV_SBI + default y + help + Provide internal supervisor pointer-masking lifecycle support for + hibernation and for resetting firmware state retained across kexec. + +config RISCV_ISA_SSPM + bool "Sspm extension for supervisor pointer masking" + depends on RISCV_SSPM + default y + help + Allow an in-kernel consumer to enable + supervisor-mode pointer masking with PMLEN=3D7 through SBI FWFT. + + Pointer masking remains disabled until a kernel consumer explicitly + requests it. Internal reset and hibernation support remains available + when this consumer option is disabled. + + If unsure, say Y. + config RISCV_ISA_SVNAPOT bool "Svnapot extension support for supervisor mode NAPOT pages" depends on 64BIT && MMU diff --git a/arch/riscv/include/asm/sspm.h b/arch/riscv/include/asm/sspm.h new file mode 100644 index 0000000..c95626a --- /dev/null +++ b/arch/riscv/include/asm/sspm.h @@ -0,0 +1,78 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +#ifndef _ASM_RISCV_SSPM_H +#define _ASM_RISCV_SSPM_H + +#include +#include +#include +#include + +#ifdef CONFIG_RISCV_SSPM +void __init riscv_sspm_boot_reset(void); +unsigned long riscv_sspm_hibernate_pmlen(void); +bool riscv_sspm_hibernate_pmlen_valid(unsigned long pmlen); +int riscv_sspm_hibernate_restore(unsigned long pmlen); +int riscv_sspm_prepare_cpu(void); +void __init riscv_sspm_smp_cpus_done(void); +bool riscv_sspm_may_be_active(void); +void riscv_sspm_reset_local_or_panic(const char *context); +#else +static inline void __init riscv_sspm_boot_reset(void) +{ +} + +static inline unsigned long riscv_sspm_hibernate_pmlen(void) +{ + return 0; +} + +static inline bool riscv_sspm_hibernate_pmlen_valid(unsigned long pmlen) +{ + return pmlen =3D=3D 0 || pmlen =3D=3D 7; +} + +static inline int riscv_sspm_hibernate_restore(unsigned long pmlen) +{ + if (!riscv_sspm_hibernate_pmlen_valid(pmlen)) + return -EINVAL; + + return pmlen ? -EOPNOTSUPP : 0; +} + +static inline int riscv_sspm_prepare_cpu(void) +{ + return 0; +} + +static inline void __init riscv_sspm_smp_cpus_done(void) +{ +} + +static inline bool riscv_sspm_may_be_active(void) +{ + return false; +} + +static inline void riscv_sspm_reset_local_or_panic(const char *context) +{ +} +#endif + +#ifdef CONFIG_RISCV_ISA_SSPM +int riscv_sspm_enable(void); + +/* True means the consumer contract is safe; false does not guarantee PMLE= N=3D0. */ +bool riscv_sspm_enabled(void); +#else +static inline int riscv_sspm_enable(void) +{ + return -EOPNOTSUPP; +} + +static inline bool riscv_sspm_enabled(void) +{ + return false; +} +#endif + +#endif /* _ASM_RISCV_SSPM_H */ diff --git a/arch/riscv/kernel/Makefile b/arch/riscv/kernel/Makefile index cabb99c..0a6464a 100644 --- a/arch/riscv/kernel/Makefile +++ b/arch/riscv/kernel/Makefile @@ -101,6 +101,7 @@ obj-$(CONFIG_DYNAMIC_FTRACE) +=3D mcount-dyn.o obj-$(CONFIG_PERF_EVENTS) +=3D perf_callchain.o obj-$(CONFIG_HAVE_PERF_REGS) +=3D perf_regs.o obj-$(CONFIG_RISCV_SBI) +=3D sbi.o sbi_ecall.o +obj-$(CONFIG_RISCV_SSPM) +=3D sspm.o ifeq ($(CONFIG_RISCV_SBI), y) obj-$(CONFIG_SMP) +=3D sbi-ipi.o obj-$(CONFIG_SMP) +=3D cpu_ops_sbi.o diff --git a/arch/riscv/kernel/cpu-hotplug.c b/arch/riscv/kernel/cpu-hotplu= g.c index 0bc56d8..8e0b497 100644 --- a/arch/riscv/kernel/cpu-hotplug.c +++ b/arch/riscv/kernel/cpu-hotplug.c @@ -15,6 +15,7 @@ #include #include #include +#include =20 bool cpu_has_hotplug(unsigned int cpu) { @@ -67,8 +68,8 @@ void arch_cpuhp_cleanup_dead_cpu(unsigned int cpu) void __noreturn arch_cpu_idle_dead(void) { idle_task_exit(); - cpuhp_ap_report_dead(); + riscv_sspm_reset_local_or_panic("offline hart"); =20 cpu_ops->cpu_stop(); /* It should never reach here */ diff --git a/arch/riscv/kernel/hibernate.c b/arch/riscv/kernel/hibernate.c index 9828438..a82de7d 100644 --- a/arch/riscv/kernel/hibernate.c +++ b/arch/riscv/kernel/hibernate.c @@ -16,6 +16,7 @@ #include #include #include +#include #include =20 #include @@ -53,12 +54,14 @@ struct arch_hibernate_hdr_invariants { * @hartid: to make sure same boot_cpu executes the hibernate/restore code. * @saved_satp: original page table used by the hibernated image. * @restore_cpu_addr: the kernel's image address to restore the CPU contex= t. + * @pmlen: supervisor pointer-mask length used by the hibernated image. */ static struct arch_hibernate_hdr { struct arch_hibernate_hdr_invariants invariants; unsigned long hartid; unsigned long saved_satp; unsigned long restore_cpu_addr; + unsigned long pmlen; } resume_hdr; =20 static void arch_hdr_invariants(struct arch_hibernate_hdr_invariants *i) @@ -101,6 +104,7 @@ int arch_hibernation_header_save(void *addr, unsigned i= nt max_size) hdr->hartid =3D cpuid_to_hartid_map(sleep_cpu); hdr->saved_satp =3D csr_read(CSR_SATP); hdr->restore_cpu_addr =3D (unsigned long)__hibernate_cpu_resume; + hdr->pmlen =3D riscv_sspm_hibernate_pmlen(); =20 return 0; } @@ -121,6 +125,10 @@ int arch_hibernation_header_restore(void *addr) pr_crit("Hibernate image not generated by this kernel!\n"); return -EINVAL; } + if (!riscv_sspm_hibernate_pmlen_valid(hdr->pmlen)) { + pr_crit("Invalid PMLEN in hibernate image: %lu\n", hdr->pmlen); + return -EINVAL; + } =20 sleep_cpu =3D riscv_hartid_to_cpuid(hdr->hartid); if (sleep_cpu < 0) { @@ -395,6 +403,10 @@ int swsusp_arch_resume(void) if (ret) return ret; =20 + ret =3D riscv_sspm_hibernate_restore(resume_hdr.pmlen); + if (ret) + return ret; + hibernate_restore_image(resume_hdr.saved_satp, (PFN_DOWN(__pa(resume_pg_d= ir)) | satp_mode), resume_hdr.restore_cpu_addr); =20 diff --git a/arch/riscv/kernel/machine_kexec.c b/arch/riscv/kernel/machine_= kexec.c index 738df17..f9cb98d 100644 --- a/arch/riscv/kernel/machine_kexec.c +++ b/arch/riscv/kernel/machine_kexec.c @@ -12,6 +12,7 @@ #include /* For PAGE_MASK */ #include /* For fdt_check_header() */ #include /* For set_memory_x() */ +#include #include /* For unreachable() */ #include /* For cpu_down() */ #include @@ -161,8 +162,12 @@ machine_kexec(struct kimage *image) riscv_kexec_method kexec_method =3D NULL; =20 #ifdef CONFIG_SMP - WARN(smp_crash_stop_failed(), - "Some CPUs may be stale, kdump will be unreliable.\n"); + bool stop_failed =3D smp_crash_stop_failed(); + + WARN(stop_failed, + "Some CPUs may be stale, kdump will be unreliable.\n"); + if (stop_failed && riscv_sspm_may_be_active()) + panic("Sspm: cannot hand off with stale PMLEN state"); #endif =20 if (image->type !=3D KEXEC_TYPE_CRASH) @@ -179,6 +184,7 @@ machine_kexec(struct kimage *image) =20 /* Jump to the relocation code */ pr_notice("Bye...\n"); + riscv_sspm_reset_local_or_panic("kexec boot hart"); kexec_method(first_ind_entry, jump_addr, fdt_addr, this_hart_id, kernel_map.va_pa_offset); unreachable(); diff --git a/arch/riscv/kernel/setup.c b/arch/riscv/kernel/setup.c index 52d1d2b..3b565cb 100644 --- a/arch/riscv/kernel/setup.c +++ b/arch/riscv/kernel/setup.c @@ -34,6 +34,7 @@ #include #include #include +#include #include #include #include @@ -315,6 +316,7 @@ void __init setup_arch(char **cmdline_p) =20 early_ioremap_setup(); sbi_init(); + riscv_sspm_boot_reset(); jump_label_init(); parse_early_param(); =20 diff --git a/arch/riscv/kernel/smp.c b/arch/riscv/kernel/smp.c index fa66f9c..d87a731 100644 --- a/arch/riscv/kernel/smp.c +++ b/arch/riscv/kernel/smp.c @@ -27,6 +27,7 @@ #include #include #include +#include =20 enum ipi_message_type { IPI_RESCHEDULE, @@ -92,6 +93,7 @@ static atomic_t waiting_for_crash_ipi =3D ATOMIC_INIT(0); static inline void ipi_cpu_crash_stop(unsigned int cpu, struct pt_regs *re= gs) { crash_save_cpu(regs, cpu); + riscv_sspm_reset_local_or_panic("crash secondary hart"); =20 atomic_dec(&waiting_for_crash_ipi); =20 diff --git a/arch/riscv/kernel/smpboot.c b/arch/riscv/kernel/smpboot.c index f6ef579..e18cb37 100644 --- a/arch/riscv/kernel/smpboot.c +++ b/arch/riscv/kernel/smpboot.c @@ -34,6 +34,7 @@ #include #include #include +#include #include #include =20 @@ -210,6 +211,7 @@ int __cpu_up(unsigned int cpu, struct task_struct *tidl= e) =20 void __init smp_cpus_done(unsigned int max_cpus) { + riscv_sspm_smp_cpus_done(); } =20 /* @@ -229,14 +231,17 @@ asmlinkage __visible void smp_callin(void) return; } =20 - /* All kernel threads share the same mm context. */ - mmgrab(mm); - current->active_mm =3D mm; + if (riscv_sspm_prepare_cpu()) + return; =20 #ifdef CONFIG_HOTPLUG_PARALLEL cpuhp_ap_sync_alive(); #endif =20 + /* All kernel threads share the same mm context. */ + mmgrab(mm); + current->active_mm =3D mm; + store_cpu_topology(curr_cpuid); notify_cpu_starting(curr_cpuid); =20 diff --git a/arch/riscv/kernel/sspm.c b/arch/riscv/kernel/sspm.c new file mode 100644 index 0000000..6198660 --- /dev/null +++ b/arch/riscv/kernel/sspm.c @@ -0,0 +1,202 @@ +// SPDX-License-Identifier: GPL-2.0-only +#include +#include +#include +#include +#include + +#include +#include + +#define RISCV_SSPM_PMLEN 7 + +enum riscv_sspm_state { + RISCV_SSPM_DISABLED, + RISCV_SSPM_ENABLING, + RISCV_SSPM_ENABLED, + RISCV_SSPM_FAILED, + RISCV_SSPM_BROKEN, +}; + +static enum riscv_sspm_state riscv_sspm_state __read_mostly; +static bool riscv_sspm_smp_ready __read_mostly =3D !IS_ENABLED(CONFIG_SMP); +#ifdef CONFIG_RISCV_ISA_SSPM +static DEFINE_MUTEX(riscv_sspm_lock); +static int riscv_sspm_error __read_mostly; +#endif + +static int riscv_sspm_set_local(unsigned long pmlen) +{ + unsigned long value; + int ret; + + ret =3D sbi_fwft_set(SBI_FWFT_POINTER_MASKING_PMLEN, pmlen, 0); + if (ret) + return ret; + + ret =3D sbi_fwft_get(SBI_FWFT_POINTER_MASKING_PMLEN, &value); + if (ret) + return ret; + + return value =3D=3D pmlen ? 0 : -EIO; +} + +static int riscv_sspm_reset_local(void) +{ + int ret; + + ret =3D riscv_sspm_set_local(0); + return ret =3D=3D -EOPNOTSUPP ? 0 : ret; +} + +void riscv_sspm_reset_local_or_panic(const char *context) +{ + int ret; + + ret =3D riscv_sspm_reset_local(); + if (ret) + panic("Sspm: failed to reset %s PMLEN: %d", context, ret); +} + +void __init riscv_sspm_boot_reset(void) +{ + /* + * Firmware may retain FWFT state across kexec or a crash handoff. Reset + * it before the Linux successor starts relying on canonical addresses. + */ + riscv_sspm_reset_local_or_panic("boot hart"); +} + +unsigned long riscv_sspm_hibernate_pmlen(void) +{ + return riscv_sspm_enabled() ? RISCV_SSPM_PMLEN : 0; +} + +bool riscv_sspm_hibernate_pmlen_valid(unsigned long pmlen) +{ + return pmlen =3D=3D 0 || pmlen =3D=3D RISCV_SSPM_PMLEN; +} + +int riscv_sspm_hibernate_restore(unsigned long pmlen) +{ + int ret; + + if (!riscv_sspm_hibernate_pmlen_valid(pmlen)) + return -EINVAL; + + if (!pmlen) { + riscv_sspm_reset_local_or_panic("hibernate"); + return 0; + } + + ret =3D riscv_sspm_set_local(pmlen); + if (ret) + riscv_sspm_reset_local_or_panic("hibernate cleanup"); + + return ret; +} + +void __init riscv_sspm_smp_cpus_done(void) +{ + WRITE_ONCE(riscv_sspm_smp_ready, true); +} + +bool riscv_sspm_may_be_active(void) +{ + enum riscv_sspm_state state =3D READ_ONCE(riscv_sspm_state); + + return state =3D=3D RISCV_SSPM_ENABLING || state =3D=3D RISCV_SSPM_ENABLE= D || + state =3D=3D RISCV_SSPM_BROKEN; +} + +int riscv_sspm_prepare_cpu(void) +{ + enum riscv_sspm_state state =3D READ_ONCE(riscv_sspm_state); + unsigned int cpu =3D smp_processor_id(); + int ret, cleanup_ret; + + if (state =3D=3D RISCV_SSPM_DISABLED || state =3D=3D RISCV_SSPM_FAILED || + state =3D=3D RISCV_SSPM_BROKEN) { + ret =3D riscv_sspm_reset_local(); + if (ret) + pr_crit("Sspm: CPU%u failed to reset PMLEN: %d\n", + cpu, ret); + + return ret; + } + + if (state !=3D RISCV_SSPM_ENABLED) + return 0; + + ret =3D riscv_sspm_set_local(RISCV_SSPM_PMLEN); + if (ret) { + pr_err("Sspm: CPU%u failed to enable PMLEN=3D7: %d\n", cpu, ret); + cleanup_ret =3D sbi_fwft_set(SBI_FWFT_POINTER_MASKING_PMLEN, 0, 0); + if (cleanup_ret) + pr_crit("Sspm: CPU%u failed to clean up PMLEN: %d\n", + cpu, cleanup_ret); + } + + return ret; +} + +#ifdef CONFIG_RISCV_ISA_SSPM +int riscv_sspm_enable(void) +{ + int ret, rollback_ret; + + mutex_lock(&riscv_sspm_lock); + + if (!READ_ONCE(riscv_sspm_smp_ready)) { + ret =3D -EAGAIN; + goto out_unlock; + } + + if (riscv_sspm_state =3D=3D RISCV_SSPM_ENABLED) { + ret =3D 0; + goto out_unlock; + } + + if (riscv_sspm_state =3D=3D RISCV_SSPM_FAILED || + riscv_sspm_state =3D=3D RISCV_SSPM_BROKEN) { + ret =3D riscv_sspm_error; + goto out_unlock; + } + + cpus_read_lock(); + WRITE_ONCE(riscv_sspm_state, RISCV_SSPM_ENABLING); + + ret =3D sbi_fwft_set_online_cpus(SBI_FWFT_POINTER_MASKING_PMLEN, + RISCV_SSPM_PMLEN, 0); + if (!ret) { + WRITE_ONCE(riscv_sspm_state, RISCV_SSPM_ENABLED); + cpus_read_unlock(); + goto out_unlock; + } + + rollback_ret =3D sbi_fwft_set_online_cpus(SBI_FWFT_POINTER_MASKING_PMLEN, + 0, 0); + pr_warn("Sspm: failed to enable PMLEN=3D7: %d\n", ret); + if (rollback_ret) { + pr_crit("Sspm: failed to roll back PMLEN: %d\n", rollback_ret); + riscv_sspm_error =3D rollback_ret; + WRITE_ONCE(riscv_sspm_state, RISCV_SSPM_BROKEN); + ret =3D rollback_ret; + } else { + riscv_sspm_error =3D ret; + WRITE_ONCE(riscv_sspm_state, RISCV_SSPM_FAILED); + } + + cpus_read_unlock(); + +out_unlock: + mutex_unlock(&riscv_sspm_lock); + + return ret; +} + +bool riscv_sspm_enabled(void) +{ + return READ_ONCE(riscv_sspm_state) =3D=3D RISCV_SSPM_ENABLED; +} +#endif --=20 2.17.1