From: Samuel Holland <samuel.holland@sifive.com> To: Palmer Dabbelt <palmer@dabbelt.com>, linux-riscv@lists.infradead.org Cc: devicetree@vger.kernel.org, Catalin Marinas <catalin.marinas@arm.com>, linux-kernel@vger.kernel.org, tech-j-ext@lists.risc-v.org, Conor Dooley <conor@kernel.org>, kasan-dev@googlegroups.com, Evgenii Stepanov <eugenis@google.com>, Krzysztof Kozlowski <krzysztof.kozlowski+dt@linaro.org>, Rob Herring <robh+dt@kernel.org>, Samuel Holland <samuel.holland@sifive.com>, Guo Ren <guoren@kernel.org>, Paul Walmsley <paul.walmsley@sifive.com>, Stefan Roesch <shr@devkernel.io> Subject: [RFC PATCH 6/9] riscv: Add support for userspace pointer masking Date: Tue, 19 Mar 2024 14:58:32 -0700 [thread overview] Message-ID: <20240319215915.832127-7-samuel.holland@sifive.com> (raw) In-Reply-To: <20240319215915.832127-1-samuel.holland@sifive.com> RISC-V supports pointer masking with a variable number of tag bits ("PMLEN") 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 minimum number of tag bits and determine the actual number of tag bits. As with PR_TAGGED_ADDR_ENABLE, the pointer masking configuration is thread-scoped, inherited on clone() and fork() and cleared on exec(). Signed-off-by: Samuel Holland <samuel.holland@sifive.com> --- arch/riscv/Kconfig | 8 +++ arch/riscv/include/asm/processor.h | 8 +++ arch/riscv/kernel/process.c | 107 +++++++++++++++++++++++++++++ include/uapi/linux/prctl.h | 3 + 4 files changed, 126 insertions(+) diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig index e3142ce531a0..a1a1585120f0 100644 --- a/arch/riscv/Kconfig +++ b/arch/riscv/Kconfig @@ -479,6 +479,14 @@ config RISCV_ISA_C If you don't know what to do here, say Y. +config RISCV_ISA_POINTER_MASKING + bool "Smmpm, Smnpm, and Ssnpm extensions for pointer masking" + depends on 64BIT + default y + help + Add support to dynamically detect the presence of the Smmpm, Smnpm, + and Ssnpm extensions (pointer masking) and enable their usage. + 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 06b87402a4d8..64b34e839802 100644 --- a/arch/riscv/include/asm/processor.h +++ b/arch/riscv/include/asm/processor.h @@ -185,6 +185,14 @@ extern int set_unalign_ctl(struct task_struct *tsk, unsigned int val); #define GET_UNALIGN_CTL(tsk, addr) get_unalign_ctl((tsk), (addr)) #define SET_UNALIGN_CTL(tsk, val) set_unalign_ctl((tsk), (val)) +#ifdef CONFIG_RISCV_ISA_POINTER_MASKING +/* 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/kernel/process.c b/arch/riscv/kernel/process.c index 92922dbd5b5c..3578e75f4aa4 100644 --- a/arch/riscv/kernel/process.c +++ b/arch/riscv/kernel/process.c @@ -7,6 +7,7 @@ * Copyright (C) 2017 SiFive */ +#include <linux/bitfield.h> #include <linux/cpu.h> #include <linux/kernel.h> #include <linux/sched.h> @@ -154,6 +155,18 @@ void start_thread(struct pt_regs *regs, unsigned long pc, #endif } +static void flush_tagged_addr_state(void) +{ +#ifdef CONFIG_RISCV_ISA_POINTER_MASKING + if (!riscv_has_extension_unlikely(RISCV_ISA_EXT_SxNPM)) + return; + + current->thread.envcfg &= ~ENVCFG_PMM; + + sync_envcfg(current); +#endif +} + void flush_thread(void) { #ifdef CONFIG_FPU @@ -173,6 +186,7 @@ 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 + flush_tagged_addr_state(); } void arch_release_task_struct(struct task_struct *tsk) @@ -236,3 +250,96 @@ void __init arch_task_cache_init(void) { riscv_v_setup_ctx_cache(); } + +#ifdef CONFIG_RISCV_ISA_POINTER_MASKING +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); + u8 pmlen; + + if (is_compat_thread(ti)) + return -EINVAL; + + if (arg & ~valid_mask) + return -EINVAL; + + pmlen = FIELD_GET(PR_PMLEN_MASK, arg); + if (pmlen > 16) { + return -EINVAL; + } else if (pmlen > 7) { + if (have_user_pmlen_16) + pmlen = 16; + else + return -EINVAL; + } else if (pmlen > 0) { + /* + * Prefer the smallest PMLEN that satisfies the user's request, + * in case choosing a larger PMLEN has a performance impact. + */ + if (have_user_pmlen_7) + pmlen = 7; + else if (have_user_pmlen_16) + pmlen = 16; + else + return -EINVAL; + } + + task->thread.envcfg &= ~ENVCFG_PMM; + if (pmlen == 7) + task->thread.envcfg |= ENVCFG_PMM_PMLEN_7; + else if (pmlen == 16) + task->thread.envcfg |= ENVCFG_PMM_PMLEN_16; + + if (task == current) + sync_envcfg(current); + + 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, 7); + break; + case ENVCFG_PMM_PMLEN_16: + ret |= FIELD_PREP(PR_PMLEN_MASK, 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_SxNPM)) + 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_POINTER_MASKING */ diff --git a/include/uapi/linux/prctl.h b/include/uapi/linux/prctl.h index 370ed14b1ae0..488b0d8e8495 100644 --- a/include/uapi/linux/prctl.h +++ b/include/uapi/linux/prctl.h @@ -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 -- 2.43.1
WARNING: multiple messages have this Message-ID (diff)
From: Samuel Holland <samuel.holland@sifive.com> To: Palmer Dabbelt <palmer@dabbelt.com>, linux-riscv@lists.infradead.org Cc: devicetree@vger.kernel.org, Catalin Marinas <catalin.marinas@arm.com>, linux-kernel@vger.kernel.org, tech-j-ext@lists.risc-v.org, Conor Dooley <conor@kernel.org>, kasan-dev@googlegroups.com, Evgenii Stepanov <eugenis@google.com>, Krzysztof Kozlowski <krzysztof.kozlowski+dt@linaro.org>, Rob Herring <robh+dt@kernel.org>, Samuel Holland <samuel.holland@sifive.com>, Guo Ren <guoren@kernel.org>, Paul Walmsley <paul.walmsley@sifive.com>, Stefan Roesch <shr@devkernel.io> Subject: [RFC PATCH 6/9] riscv: Add support for userspace pointer masking Date: Tue, 19 Mar 2024 14:58:32 -0700 [thread overview] Message-ID: <20240319215915.832127-7-samuel.holland@sifive.com> (raw) In-Reply-To: <20240319215915.832127-1-samuel.holland@sifive.com> RISC-V supports pointer masking with a variable number of tag bits ("PMLEN") 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 minimum number of tag bits and determine the actual number of tag bits. As with PR_TAGGED_ADDR_ENABLE, the pointer masking configuration is thread-scoped, inherited on clone() and fork() and cleared on exec(). Signed-off-by: Samuel Holland <samuel.holland@sifive.com> --- arch/riscv/Kconfig | 8 +++ arch/riscv/include/asm/processor.h | 8 +++ arch/riscv/kernel/process.c | 107 +++++++++++++++++++++++++++++ include/uapi/linux/prctl.h | 3 + 4 files changed, 126 insertions(+) diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig index e3142ce531a0..a1a1585120f0 100644 --- a/arch/riscv/Kconfig +++ b/arch/riscv/Kconfig @@ -479,6 +479,14 @@ config RISCV_ISA_C If you don't know what to do here, say Y. +config RISCV_ISA_POINTER_MASKING + bool "Smmpm, Smnpm, and Ssnpm extensions for pointer masking" + depends on 64BIT + default y + help + Add support to dynamically detect the presence of the Smmpm, Smnpm, + and Ssnpm extensions (pointer masking) and enable their usage. + 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 06b87402a4d8..64b34e839802 100644 --- a/arch/riscv/include/asm/processor.h +++ b/arch/riscv/include/asm/processor.h @@ -185,6 +185,14 @@ extern int set_unalign_ctl(struct task_struct *tsk, unsigned int val); #define GET_UNALIGN_CTL(tsk, addr) get_unalign_ctl((tsk), (addr)) #define SET_UNALIGN_CTL(tsk, val) set_unalign_ctl((tsk), (val)) +#ifdef CONFIG_RISCV_ISA_POINTER_MASKING +/* 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/kernel/process.c b/arch/riscv/kernel/process.c index 92922dbd5b5c..3578e75f4aa4 100644 --- a/arch/riscv/kernel/process.c +++ b/arch/riscv/kernel/process.c @@ -7,6 +7,7 @@ * Copyright (C) 2017 SiFive */ +#include <linux/bitfield.h> #include <linux/cpu.h> #include <linux/kernel.h> #include <linux/sched.h> @@ -154,6 +155,18 @@ void start_thread(struct pt_regs *regs, unsigned long pc, #endif } +static void flush_tagged_addr_state(void) +{ +#ifdef CONFIG_RISCV_ISA_POINTER_MASKING + if (!riscv_has_extension_unlikely(RISCV_ISA_EXT_SxNPM)) + return; + + current->thread.envcfg &= ~ENVCFG_PMM; + + sync_envcfg(current); +#endif +} + void flush_thread(void) { #ifdef CONFIG_FPU @@ -173,6 +186,7 @@ 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 + flush_tagged_addr_state(); } void arch_release_task_struct(struct task_struct *tsk) @@ -236,3 +250,96 @@ void __init arch_task_cache_init(void) { riscv_v_setup_ctx_cache(); } + +#ifdef CONFIG_RISCV_ISA_POINTER_MASKING +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); + u8 pmlen; + + if (is_compat_thread(ti)) + return -EINVAL; + + if (arg & ~valid_mask) + return -EINVAL; + + pmlen = FIELD_GET(PR_PMLEN_MASK, arg); + if (pmlen > 16) { + return -EINVAL; + } else if (pmlen > 7) { + if (have_user_pmlen_16) + pmlen = 16; + else + return -EINVAL; + } else if (pmlen > 0) { + /* + * Prefer the smallest PMLEN that satisfies the user's request, + * in case choosing a larger PMLEN has a performance impact. + */ + if (have_user_pmlen_7) + pmlen = 7; + else if (have_user_pmlen_16) + pmlen = 16; + else + return -EINVAL; + } + + task->thread.envcfg &= ~ENVCFG_PMM; + if (pmlen == 7) + task->thread.envcfg |= ENVCFG_PMM_PMLEN_7; + else if (pmlen == 16) + task->thread.envcfg |= ENVCFG_PMM_PMLEN_16; + + if (task == current) + sync_envcfg(current); + + 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, 7); + break; + case ENVCFG_PMM_PMLEN_16: + ret |= FIELD_PREP(PR_PMLEN_MASK, 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_SxNPM)) + 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_POINTER_MASKING */ diff --git a/include/uapi/linux/prctl.h b/include/uapi/linux/prctl.h index 370ed14b1ae0..488b0d8e8495 100644 --- a/include/uapi/linux/prctl.h +++ b/include/uapi/linux/prctl.h @@ -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 -- 2.43.1 _______________________________________________ linux-riscv mailing list linux-riscv@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-riscv
next prev parent reply other threads:[~2024-03-19 21:59 UTC|newest] Thread overview: 54+ messages / expand[flat|nested] mbox.gz Atom feed top 2024-03-19 21:58 [RFC PATCH 0/9] riscv: Userspace pointer masking and tagged address ABI Samuel Holland 2024-03-19 21:58 ` Samuel Holland 2024-03-19 21:58 ` [RFC PATCH 1/9] dt-bindings: riscv: Add pointer masking ISA extensions Samuel Holland 2024-03-19 21:58 ` Samuel Holland 2024-03-19 21:58 ` [RFC PATCH 2/9] riscv: Add ISA extension parsing for pointer masking Samuel Holland 2024-03-19 21:58 ` Samuel Holland 2024-03-19 21:58 ` [RFC PATCH 3/9] riscv: Add CSR definitions " Samuel Holland 2024-03-19 21:58 ` Samuel Holland 2024-03-19 21:58 ` [RFC PATCH 4/9] riscv: Define is_compat_thread() Samuel Holland 2024-03-19 21:58 ` Samuel Holland 2024-03-19 21:58 ` [RFC PATCH 5/9] riscv: Split per-CPU and per-thread envcfg bits Samuel Holland 2024-03-19 21:58 ` Samuel Holland 2024-03-19 23:55 ` [RISC-V] [tech-j-ext] " Deepak Gupta 2024-03-19 23:55 ` Deepak Gupta 2024-03-20 2:20 ` Samuel Holland 2024-03-20 2:20 ` Samuel Holland 2024-03-20 4:39 ` Deepak Gupta 2024-03-20 4:39 ` Deepak Gupta 2024-03-22 0:13 ` Samuel Holland 2024-03-22 0:13 ` Samuel Holland 2024-03-22 17:13 ` Deepak Gupta 2024-03-22 17:13 ` Deepak Gupta 2024-03-23 9:35 ` Andrew Jones 2024-03-23 9:35 ` Andrew Jones 2024-03-23 20:37 ` Deepak Gupta 2024-03-23 20:37 ` Deepak Gupta 2024-03-22 8:09 ` Andrew Jones 2024-03-22 8:09 ` Andrew Jones 2024-03-22 16:52 ` Deepak Gupta 2024-03-22 16:52 ` Deepak Gupta 2024-03-20 8:06 ` Conor Dooley 2024-03-20 8:06 ` Conor Dooley [not found] ` <17BE5F38AFE245E5.29196@lists.riscv.org> 2024-03-20 23:27 ` Deepak Gupta 2024-03-20 23:27 ` Deepak Gupta 2024-03-22 3:43 ` Samuel Holland 2024-03-22 3:43 ` Samuel Holland 2024-03-22 7:58 ` Andrew Jones 2024-03-22 7:58 ` Andrew Jones 2024-03-28 1:58 ` Deepak Gupta 2024-03-28 1:58 ` Deepak Gupta [not found] ` <17C0CB122DBB0EAE.6770@lists.riscv.org> 2024-03-28 19:34 ` Deepak Gupta 2024-03-28 19:34 ` Deepak Gupta 2024-03-19 21:58 ` Samuel Holland [this message] 2024-03-19 21:58 ` [RFC PATCH 6/9] riscv: Add support for userspace pointer masking Samuel Holland 2024-03-19 21:58 ` [RFC PATCH 7/9] riscv: Add support for the tagged address ABI Samuel Holland 2024-03-19 21:58 ` Samuel Holland 2024-03-19 21:58 ` [RFC PATCH 8/9] riscv: Allow ptrace control of " Samuel Holland 2024-03-19 21:58 ` Samuel Holland 2024-03-19 21:58 ` [RFC PATCH 9/9] selftests: riscv: Add a pointer masking test Samuel Holland 2024-03-19 21:58 ` Samuel Holland 2024-03-20 17:21 ` Conor Dooley 2024-03-20 17:21 ` Conor Dooley 2024-03-20 18:04 ` Samuel Holland 2024-03-20 18:04 ` Samuel Holland
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=20240319215915.832127-7-samuel.holland@sifive.com \ --to=samuel.holland@sifive.com \ --cc=catalin.marinas@arm.com \ --cc=conor@kernel.org \ --cc=devicetree@vger.kernel.org \ --cc=eugenis@google.com \ --cc=guoren@kernel.org \ --cc=kasan-dev@googlegroups.com \ --cc=krzysztof.kozlowski+dt@linaro.org \ --cc=linux-kernel@vger.kernel.org \ --cc=linux-riscv@lists.infradead.org \ --cc=palmer@dabbelt.com \ --cc=paul.walmsley@sifive.com \ --cc=robh+dt@kernel.org \ --cc=shr@devkernel.io \ --cc=tech-j-ext@lists.risc-v.org \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: linkBe sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.