From patchwork Wed Oct 16 20:27:45 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Samuel Holland X-Patchwork-Id: 1998288 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=pass (2048-bit key; secure) header.d=lists.infradead.org header.i=@lists.infradead.org header.a=rsa-sha256 header.s=bombadil.20210309 header.b=W9QGt5z9; dkim=fail reason="signature verification failed" (2048-bit key; secure) header.d=infradead.org header.i=@infradead.org header.a=rsa-sha256 header.s=desiato.20200630 header.b=NI9ZKHDV; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=sifive.com header.i=@sifive.com header.a=rsa-sha256 header.s=google header.b=fsU5XUMu; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=none (no SPF record) smtp.mailfrom=lists.infradead.org (client-ip=2607:7c80:54:3::133; helo=bombadil.infradead.org; envelope-from=kvm-riscv-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org; receiver=patchwork.ozlabs.org) Received: from bombadil.infradead.org (bombadil.infradead.org [IPv6:2607:7c80:54:3::133]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (secp384r1) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4XTPKH2fQ2z1xwC for ; Thu, 17 Oct 2024 08:30:59 +1100 (AEDT) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-ID:Date:Subject:Cc:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=AOVOINvIrKF2veyNFvjJwEEMIzuVVBjxejL3jeQccW4=; b=W9QGt5z98Izcxq o1dIf+4uG+g3C3S4KjAGbbwK7lAoTzzrduuDOxeIggimyGNFpulwL67zVMCr5/5xSag542LkyjLvy XkPN+/1+i6BOV8mA7iVuxOk+788gCvruNLEzJk1vC9I/GnrUbRK3fCh8VEca8QPvn7Qt7QAGgOttw WDpq1smToqafe7u5f5j0V2LmB6nZZHWPZ9RDb2UesLvS5p24mq4KMw1zFjcWtjsNtAbEO3ChCTNSr +2UJ9ryOkVMGgyb8S3fw+mDcLXkHe+bOnFV2wSqSASKG3d6JNNyvpd0lChAfZc4/6MmiV1CFSbM6z gsB52TbO3fL8/7uuBhvQ==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.98 #2 (Red Hat Linux)) id 1t1Bbd-0000000D2xK-3qxU; Wed, 16 Oct 2024 21:30:57 +0000 Received: from desiato.infradead.org ([2001:8b0:10b:1:d65d:64ff:fe57:4e05]) by bombadil.infradead.org with esmtps (Exim 4.98 #2 (Red Hat Linux)) id 1t1AdE-0000000CwWn-3VMm for kvm-riscv@bombadil.infradead.org; Wed, 16 Oct 2024 20:28:32 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=desiato.20200630; h=Content-Transfer-Encoding:MIME-Version :References:In-Reply-To:Message-ID:Date:Subject:Cc:To:From:Sender:Reply-To: Content-Type:Content-ID:Content-Description; bh=eo/JV88hOL+S2Nr/0pjLrqapJLfVH6+MO5UxiP8a69U=; b=NI9ZKHDVfa4eeYxszGqFNl0qUx Wzd6AcMXR41i1g1PL/G8ZY/Ft+zab8MQ2NCYabVlCR8hqK9plxiTz0T47+OI8JsybDVagJXNm4Vkh db1kWahlW3PeSdbjJpRdxUqZuLmfIcPSb76gKXPrNDf5IzNwx4aOJn7xphFua9EbcOkRp3pYBWEni GNx0zEMWEyNTuZqHV6iU3cLGdZW65jJAsDgDGxv/Q1bo8K630p8WjEExpOrw2350uY6pjjzR/qkDT EYODLjmgB+Ddi0/tB6wiftBAxAD/6TbOC32p8CQehnadw1U3ggUzWWja7Go7XmoCxbw0AByuHen2S iM2+WfgA==; Received: from mail-pg1-x52f.google.com ([2607:f8b0:4864:20::52f]) by desiato.infradead.org with esmtps (Exim 4.98 #2 (Red Hat Linux)) id 1t1AdA-00000006u5q-0Yzn for kvm-riscv@lists.infradead.org; Wed, 16 Oct 2024 20:28:30 +0000 Received: by mail-pg1-x52f.google.com with SMTP id 41be03b00d2f7-7ea8d7341e6so164250a12.3 for ; Wed, 16 Oct 2024 13:28:26 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sifive.com; s=google; t=1729110504; x=1729715304; darn=lists.infradead.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; bh=eo/JV88hOL+S2Nr/0pjLrqapJLfVH6+MO5UxiP8a69U=; b=fsU5XUMu/C6nSe3sh1+k0Av7bfK4uUM67IpP7WWm47QB58gBYYRhoCyIK5Z/tOhDNg dNU3qqa6tdGZvZkcWKPlNNNdFLFmxNJETTharPBMDuBJjlTIJPlbOBsJwssnZiel2PIR hlYRb2PMpkO3tnJSecstZi5qcItOG6IrM2qJa66w/UlpI9w2muCO5lyHpyLxgWHEoSiZ jYtz88RMU9uaybLiYe78Dk61EwgdHKGpKzxsnDcex5s6doOqBVPcef5idfH0CKqsQPq0 dlyRXvfKelFYJsdXMrpFPGXMwlqQa2vct/3esHgtSOeOY7C2OTAtorIEh+V4fREqZYPZ ZPAg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1729110504; x=1729715304; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=eo/JV88hOL+S2Nr/0pjLrqapJLfVH6+MO5UxiP8a69U=; b=LwaB0NyhEQJUzTqfr0iMyA/24Lfq+3wgdvHI3SbCM3pk8Crj1zoc9F7vPFbp7izvFj b8+3n3hmPY8FoupTDw3ur1RhDZ2+jLj2rQKhjMGZaQiHGHx8VBEJXtRPduwH+JbNAdAu znjL3457r13sWkBZwxXWW8o6bKsbCtxLZUEwf2X7woMAPMVPJj7Lkq5XFNJKbtQ2d+nt bqgtG2080XleInwQ3FGV1uJrpwEb9cc3pn3i63ZrEcFTLfgKIet/f25X9NXE6Qsrc9vF 2m+qxEBlCJ1aUc6Y7hTKVvirhMFRSTPvcVIlVQVOTiAZ1+9XkuqkcuADPOM20gZSiSbh MXOg== X-Forwarded-Encrypted: i=1; AJvYcCUm7czptgku8OApulOrZRsU99Ca6fSaLkYi63SWZTkMjbbOIs9JVW63csfqYAgmxre6js8ZxAXEgKM=@lists.infradead.org X-Gm-Message-State: AOJu0Yzgr6yjkgHcMchs1cDzyVSHFk4Pclrgu/sUiGuAQnvG0bFpovkq ewD0T/4ZsRVunYAuKTRW5hxZTAltH0X3J3aQaayw2mJsL6CJLc4uU9IDJUat+gQ= X-Google-Smtp-Source: AGHT+IEJIDriZqg0yBJTxMeg1P8T+SpmofcxsatsSbAlwqzSvOscPzTniDFKaKdVE7curJ4vos+ZWw== X-Received: by 2002:a17:90b:881:b0:2e2:a097:bb02 with SMTP id 98e67ed59e1d1-2e3ab7f85a6mr6439669a91.11.1729110504350; Wed, 16 Oct 2024 13:28:24 -0700 (PDT) Received: from sw06.internal.sifive.com ([4.53.31.132]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-2e3e08f8f89sm228613a91.38.2024.10.16.13.28.22 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 16 Oct 2024 13:28:23 -0700 (PDT) From: Samuel Holland To: Palmer Dabbelt , linux-riscv@lists.infradead.org Cc: Catalin Marinas , Atish Patra , linux-kselftest@vger.kernel.org, Rob Herring , "Kirill A . Shutemov" , Shuah Khan , devicetree@vger.kernel.org, Anup Patel , linux-kernel@vger.kernel.org, Jonathan Corbet , kvm-riscv@lists.infradead.org, Conor Dooley , kasan-dev@googlegroups.com, linux-doc@vger.kernel.org, Evgenii Stepanov , Charlie Jenkins , Krzysztof Kozlowski , Samuel Holland Subject: [PATCH v5 04/10] riscv: Add support for userspace pointer masking Date: Wed, 16 Oct 2024 13:27:45 -0700 Message-ID: <20241016202814.4061541-5-samuel.holland@sifive.com> X-Mailer: git-send-email 2.45.1 In-Reply-To: <20241016202814.4061541-1-samuel.holland@sifive.com> References: <20241016202814.4061541-1-samuel.holland@sifive.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20241016_212828_440648_59FE8EA5 X-CRM114-Status: GOOD ( 28.21 ) X-Spam-Score: -0.2 (/) X-Spam-Report: Spam detection software, running on the system "desiato.infradead.org", has NOT identified this incoming email as spam. The original message has been attached to this so you can view it or label similar future email. If you have any questions, see the administrator of that system for details. Content preview: RISC-V supports pointer masking with a variable number of tag bits (which is called "PMLEN" in the specification) and which is configured at the next higher privilege level. Wire up the PR_SET_TAGGED_ADDR_CTRL and PR_GET_TAGGED_ADDR_CTRL prctls so userspace can request a lower bound on the number of tag bits and determine the actual number of tag bits. As with arm64's PR_ [...] Content analysis details: (-0.2 points, 5.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at https://www.dnswl.org/, no trust [2607:f8b0:4864:20:0:0:0:52f listed in] [list.dnswl.org] -0.0 SPF_PASS SPF: sender matches SPF record 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.1 DKIM_VALID_EF Message has a valid DKIM or DK signature from envelope-from domain X-BeenThere: kvm-riscv@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "kvm-riscv" Errors-To: kvm-riscv-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org RISC-V supports pointer masking with a variable number of tag bits (which is called "PMLEN" in the specification) and which is configured at the next higher privilege level. Wire up the PR_SET_TAGGED_ADDR_CTRL and PR_GET_TAGGED_ADDR_CTRL prctls so userspace can request a lower bound on the number of tag bits and determine the actual number of tag bits. As with arm64's PR_TAGGED_ADDR_ENABLE, the pointer masking configuration is thread-scoped, inherited on clone() and fork() and cleared on execve(). Reviewed-by: Charlie Jenkins Tested-by: Charlie Jenkins Signed-off-by: Samuel Holland --- Changes in v5: - Document how PR_[SG]ET_TAGGED_ADDR_CTRL are used on RISC-V Changes in v4: - Switch IS_ENABLED back to #ifdef to fix riscv32 build Changes in v3: - Rename CONFIG_RISCV_ISA_POINTER_MASKING to CONFIG_RISCV_ISA_SUPM, since it only controls the userspace part of pointer masking - Use IS_ENABLED instead of #ifdef when possible - Use an enum for the supported PMLEN values - Simplify the logic in set_tagged_addr_ctrl() Changes in v2: - Rebase on riscv/linux.git for-next - Add and use the envcfg_update_bits() helper function - Inline flush_tagged_addr_state() Documentation/arch/riscv/uabi.rst | 12 ++++ arch/riscv/Kconfig | 11 ++++ arch/riscv/include/asm/processor.h | 8 +++ arch/riscv/include/asm/switch_to.h | 11 ++++ arch/riscv/kernel/process.c | 91 ++++++++++++++++++++++++++++++ include/uapi/linux/prctl.h | 5 +- 6 files changed, 137 insertions(+), 1 deletion(-) diff --git a/Documentation/arch/riscv/uabi.rst b/Documentation/arch/riscv/uabi.rst index 2b420bab0527..ddb8359a46ed 100644 --- a/Documentation/arch/riscv/uabi.rst +++ b/Documentation/arch/riscv/uabi.rst @@ -68,3 +68,15 @@ Misaligned accesses Misaligned scalar accesses are supported in userspace, but they may perform poorly. Misaligned vector accesses are only supported if the Zicclsm extension is supported. + +Pointer masking +--------------- + +Support for pointer masking in userspace (the Supm extension) is provided via +the ``PR_SET_TAGGED_ADDR_CTRL`` and ``PR_GET_TAGGED_ADDR_CTRL`` ``prctl()`` +operations. Pointer masking is disabled by default. To enable it, userspace +must call ``PR_SET_TAGGED_ADDR_CTRL`` with the ``PR_PMLEN`` field set to the +number of mask/tag bits needed by the application. ``PR_PMLEN`` is interpreted +as a lower bound; if the kernel is unable to satisfy the request, the +``PR_SET_TAGGED_ADDR_CTRL`` operation will fail. The actual number of tag bits +is returned in ``PR_PMLEN`` by the ``PR_GET_TAGGED_ADDR_CTRL`` operation. diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig index 22dc5ea4196c..0ef449465378 100644 --- a/arch/riscv/Kconfig +++ b/arch/riscv/Kconfig @@ -531,6 +531,17 @@ config RISCV_ISA_C If you don't know what to do here, say Y. +config RISCV_ISA_SUPM + bool "Supm extension for userspace pointer masking" + depends on 64BIT + default y + help + Add support for pointer masking in userspace (Supm) when the + underlying hardware extension (Smnpm or Ssnpm) is detected at boot. + + If this option is disabled, userspace will be unable to use + the prctl(PR_{SET,GET}_TAGGED_ADDR_CTRL) API. + config RISCV_ISA_SVNAPOT bool "Svnapot extension support for supervisor mode NAPOT pages" depends on 64BIT && MMU diff --git a/arch/riscv/include/asm/processor.h b/arch/riscv/include/asm/processor.h index c1a492508835..5f56eb9d114a 100644 --- a/arch/riscv/include/asm/processor.h +++ b/arch/riscv/include/asm/processor.h @@ -178,6 +178,14 @@ extern int set_unalign_ctl(struct task_struct *tsk, unsigned int val); #define RISCV_SET_ICACHE_FLUSH_CTX(arg1, arg2) riscv_set_icache_flush_ctx(arg1, arg2) extern int riscv_set_icache_flush_ctx(unsigned long ctx, unsigned long per_thread); +#ifdef CONFIG_RISCV_ISA_SUPM +/* PR_{SET,GET}_TAGGED_ADDR_CTRL prctl */ +long set_tagged_addr_ctrl(struct task_struct *task, unsigned long arg); +long get_tagged_addr_ctrl(struct task_struct *task); +#define SET_TAGGED_ADDR_CTRL(arg) set_tagged_addr_ctrl(current, arg) +#define GET_TAGGED_ADDR_CTRL() get_tagged_addr_ctrl(current) +#endif + #endif /* __ASSEMBLY__ */ #endif /* _ASM_RISCV_PROCESSOR_H */ diff --git a/arch/riscv/include/asm/switch_to.h b/arch/riscv/include/asm/switch_to.h index 9685cd85e57c..94e33216b2d9 100644 --- a/arch/riscv/include/asm/switch_to.h +++ b/arch/riscv/include/asm/switch_to.h @@ -70,6 +70,17 @@ static __always_inline bool has_fpu(void) { return false; } #define __switch_to_fpu(__prev, __next) do { } while (0) #endif +static inline void envcfg_update_bits(struct task_struct *task, + unsigned long mask, unsigned long val) +{ + unsigned long envcfg; + + envcfg = (task->thread.envcfg & ~mask) | val; + task->thread.envcfg = envcfg; + if (task == current) + csr_write(CSR_ENVCFG, envcfg); +} + static inline void __switch_to_envcfg(struct task_struct *next) { asm volatile (ALTERNATIVE("nop", "csrw " __stringify(CSR_ENVCFG) ", %0", diff --git a/arch/riscv/kernel/process.c b/arch/riscv/kernel/process.c index e3142d8a6e28..200d2ed64dfe 100644 --- a/arch/riscv/kernel/process.c +++ b/arch/riscv/kernel/process.c @@ -7,6 +7,7 @@ * Copyright (C) 2017 SiFive */ +#include #include #include #include @@ -180,6 +181,10 @@ void flush_thread(void) memset(¤t->thread.vstate, 0, sizeof(struct __riscv_v_ext_state)); clear_tsk_thread_flag(current, TIF_RISCV_V_DEFER_RESTORE); #endif +#ifdef CONFIG_RISCV_ISA_SUPM + if (riscv_has_extension_unlikely(RISCV_ISA_EXT_SUPM)) + envcfg_update_bits(current, ENVCFG_PMM, ENVCFG_PMM_PMLEN_0); +#endif } void arch_release_task_struct(struct task_struct *tsk) @@ -242,3 +247,89 @@ void __init arch_task_cache_init(void) { riscv_v_setup_ctx_cache(); } + +#ifdef CONFIG_RISCV_ISA_SUPM +enum { + PMLEN_0 = 0, + PMLEN_7 = 7, + PMLEN_16 = 16, +}; + +static bool have_user_pmlen_7; +static bool have_user_pmlen_16; + +long set_tagged_addr_ctrl(struct task_struct *task, unsigned long arg) +{ + unsigned long valid_mask = PR_PMLEN_MASK; + struct thread_info *ti = task_thread_info(task); + unsigned long pmm; + u8 pmlen; + + if (is_compat_thread(ti)) + return -EINVAL; + + if (arg & ~valid_mask) + return -EINVAL; + + /* + * Prefer the smallest PMLEN that satisfies the user's request, + * in case choosing a larger PMLEN has a performance impact. + */ + pmlen = FIELD_GET(PR_PMLEN_MASK, arg); + if (pmlen == PMLEN_0) + pmm = ENVCFG_PMM_PMLEN_0; + else if (pmlen <= PMLEN_7 && have_user_pmlen_7) + pmm = ENVCFG_PMM_PMLEN_7; + else if (pmlen <= PMLEN_16 && have_user_pmlen_16) + pmm = ENVCFG_PMM_PMLEN_16; + else + return -EINVAL; + + envcfg_update_bits(task, ENVCFG_PMM, pmm); + + return 0; +} + +long get_tagged_addr_ctrl(struct task_struct *task) +{ + struct thread_info *ti = task_thread_info(task); + long ret = 0; + + if (is_compat_thread(ti)) + return -EINVAL; + + switch (task->thread.envcfg & ENVCFG_PMM) { + case ENVCFG_PMM_PMLEN_7: + ret = FIELD_PREP(PR_PMLEN_MASK, PMLEN_7); + break; + case ENVCFG_PMM_PMLEN_16: + ret = FIELD_PREP(PR_PMLEN_MASK, PMLEN_16); + break; + } + + return ret; +} + +static bool try_to_set_pmm(unsigned long value) +{ + csr_set(CSR_ENVCFG, value); + return (csr_read_clear(CSR_ENVCFG, ENVCFG_PMM) & ENVCFG_PMM) == value; +} + +static int __init tagged_addr_init(void) +{ + if (!riscv_has_extension_unlikely(RISCV_ISA_EXT_SUPM)) + return 0; + + /* + * envcfg.PMM is a WARL field. Detect which values are supported. + * Assume the supported PMLEN values are the same on all harts. + */ + csr_clear(CSR_ENVCFG, ENVCFG_PMM); + have_user_pmlen_7 = try_to_set_pmm(ENVCFG_PMM_PMLEN_7); + have_user_pmlen_16 = try_to_set_pmm(ENVCFG_PMM_PMLEN_16); + + return 0; +} +core_initcall(tagged_addr_init); +#endif /* CONFIG_RISCV_ISA_SUPM */ diff --git a/include/uapi/linux/prctl.h b/include/uapi/linux/prctl.h index 35791791a879..cefd656ebf43 100644 --- a/include/uapi/linux/prctl.h +++ b/include/uapi/linux/prctl.h @@ -230,7 +230,7 @@ struct prctl_mm_map { # define PR_PAC_APDBKEY (1UL << 3) # define PR_PAC_APGAKEY (1UL << 4) -/* Tagged user address controls for arm64 */ +/* Tagged user address controls for arm64 and RISC-V */ #define PR_SET_TAGGED_ADDR_CTRL 55 #define PR_GET_TAGGED_ADDR_CTRL 56 # define PR_TAGGED_ADDR_ENABLE (1UL << 0) @@ -244,6 +244,9 @@ struct prctl_mm_map { # define PR_MTE_TAG_MASK (0xffffUL << PR_MTE_TAG_SHIFT) /* Unused; kept only for source compatibility */ # define PR_MTE_TCF_SHIFT 1 +/* RISC-V pointer masking tag length */ +# define PR_PMLEN_SHIFT 24 +# define PR_PMLEN_MASK (0x7fUL << PR_PMLEN_SHIFT) /* Control reclaim behavior when allocating memory */ #define PR_SET_IO_FLUSHER 57