Message ID | 20230317113538.10878-15-andy.chiu@sifive.com (mailing list archive) |
---|---|
State | Superseded |
Headers | show |
Series | riscv: Add vector ISA support | expand |
Context | Check | Description |
---|---|---|
conchuod/cover_letter | success | Series has a cover letter |
conchuod/tree_selection | success | Guessed tree name to be for-next |
conchuod/fixes_present | success | Fixes tag not required for -next series |
conchuod/maintainers_pattern | success | MAINTAINERS pattern errors before the patch: 1 and now 1 |
conchuod/verify_signedoff | success | Signed-off-by tag matches author and committer |
conchuod/kdoc | success | Errors and warnings before: 0 this patch: 0 |
conchuod/build_rv64_clang_allmodconfig | success | Errors and warnings before: 2309 this patch: 2309 |
conchuod/module_param | success | Was 0 now: 0 |
conchuod/build_rv64_gcc_allmodconfig | success | Errors and warnings before: 17800 this patch: 17800 |
conchuod/build_rv32_defconfig | success | Build OK |
conchuod/dtb_warn_rv64 | success | Errors and warnings before: 3 this patch: 3 |
conchuod/header_inline | success | No static functions without inline keyword in header files |
conchuod/checkpatch | warning | WARNING: Avoid unnecessary line continuations |
conchuod/source_inline | success | Was 0 now: 0 |
conchuod/build_rv64_nommu_k210_defconfig | success | Build OK |
conchuod/verify_fixes | success | No Fixes tag |
conchuod/build_rv64_nommu_virt_defconfig | success | Build OK |
Andy Chiu <andy.chiu@sifive.com> writes: > From: Vincent Chen <vincent.chen@sifive.com> > > The vector register belongs to the signal context. They need to be stored > and restored as entering and leaving the signal handler. According to the > V-extension specification, the maximum length of the vector registers can > be 2^(XLEN-1). Hence, if userspace refers to the MINSIGSTKSZ to create a > sigframe, it may not be enough. To resolve this problem, this patch refers > to the commit 94b07c1f8c39c > ("arm64: signal: Report signal frame size to userspace via auxv") to enable > userspace to know the minimum required sigframe size through the auxiliary > vector and use it to allocate enough memory for signal context. > > Note that auxv always reports size of the sigframe as if V exists for > all starting processes, whenever the kernel has CONFIG_RISCV_ISA_V. The > reason is that users usually reference this value to allocate an > alternative signal stack, and the user may use V anytime. So the user > must reserve a space for V-context in sigframe in case that the signal > handler invokes after the kernel allocating V. > > Signed-off-by: Greentime Hu <greentime.hu@sifive.com> > Signed-off-by: Vincent Chen <vincent.chen@sifive.com> > Signed-off-by: Andy Chiu <andy.chiu@sifive.com> > Acked-by: Conor Dooley <conor.dooley@microchip.com> Reviewed-by: Björn Töpel <bjorn@rivosinc.com>
On Fri, Mar 17, 2023 at 7:37 PM Andy Chiu <andy.chiu@sifive.com> wrote: > > From: Vincent Chen <vincent.chen@sifive.com> > > The vector register belongs to the signal context. They need to be stored > and restored as entering and leaving the signal handler. According to the > V-extension specification, the maximum length of the vector registers can > be 2^(XLEN-1). Hence, if userspace refers to the MINSIGSTKSZ to create a > sigframe, it may not be enough. To resolve this problem, this patch refers > to the commit 94b07c1f8c39c > ("arm64: signal: Report signal frame size to userspace via auxv") to enable > userspace to know the minimum required sigframe size through the auxiliary > vector and use it to allocate enough memory for signal context. > > Note that auxv always reports size of the sigframe as if V exists for > all starting processes, whenever the kernel has CONFIG_RISCV_ISA_V. The > reason is that users usually reference this value to allocate an > alternative signal stack, and the user may use V anytime. So the user > must reserve a space for V-context in sigframe in case that the signal > handler invokes after the kernel allocating V. > > Signed-off-by: Greentime Hu <greentime.hu@sifive.com> > Signed-off-by: Vincent Chen <vincent.chen@sifive.com> > Signed-off-by: Andy Chiu <andy.chiu@sifive.com> > Acked-by: Conor Dooley <conor.dooley@microchip.com> > --- > arch/riscv/include/asm/elf.h | 9 +++++++++ > arch/riscv/include/asm/processor.h | 2 ++ > arch/riscv/include/uapi/asm/auxvec.h | 1 + > arch/riscv/kernel/signal.c | 20 +++++++++++++++----- > 4 files changed, 27 insertions(+), 5 deletions(-) > > diff --git a/arch/riscv/include/asm/elf.h b/arch/riscv/include/asm/elf.h > index 30e7d2455960..ca23c4f6c440 100644 > --- a/arch/riscv/include/asm/elf.h > +++ b/arch/riscv/include/asm/elf.h > @@ -105,6 +105,15 @@ do { \ > get_cache_size(3, CACHE_TYPE_UNIFIED)); \ > NEW_AUX_ENT(AT_L3_CACHEGEOMETRY, \ > get_cache_geometry(3, CACHE_TYPE_UNIFIED)); \ > + /* \ > + * Should always be nonzero unless there's a kernel bug. \ > + * If we haven't determined a sensible value to give to \ > + * userspace, omit the entry: \ > + */ \ > + if (likely(signal_minsigstksz)) \ > + NEW_AUX_ENT(AT_MINSIGSTKSZ, signal_minsigstksz); \ > + else \ > + NEW_AUX_ENT(AT_IGNORE, 0); \ > } while (0) > #define ARCH_HAS_SETUP_ADDITIONAL_PAGES > struct linux_binprm; > diff --git a/arch/riscv/include/asm/processor.h b/arch/riscv/include/asm/processor.h > index f0ddf691ac5e..38ded8c5f207 100644 > --- a/arch/riscv/include/asm/processor.h > +++ b/arch/riscv/include/asm/processor.h > @@ -7,6 +7,7 @@ > #define _ASM_RISCV_PROCESSOR_H > > #include <linux/const.h> > +#include <linux/cache.h> > > #include <vdso/processor.h> > > @@ -81,6 +82,7 @@ int riscv_of_parent_hartid(struct device_node *node, unsigned long *hartid); > extern void riscv_fill_hwcap(void); > extern int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src); > > +extern unsigned long signal_minsigstksz __ro_after_init; > #endif /* __ASSEMBLY__ */ > > #endif /* _ASM_RISCV_PROCESSOR_H */ > diff --git a/arch/riscv/include/uapi/asm/auxvec.h b/arch/riscv/include/uapi/asm/auxvec.h > index fb187a33ce58..10aaa83db89e 100644 > --- a/arch/riscv/include/uapi/asm/auxvec.h > +++ b/arch/riscv/include/uapi/asm/auxvec.h > @@ -35,5 +35,6 @@ > > /* entries in ARCH_DLINFO */ > #define AT_VECTOR_SIZE_ARCH 9 > +#define AT_MINSIGSTKSZ 51 > > #endif /* _UAPI_ASM_RISCV_AUXVEC_H */ > diff --git a/arch/riscv/kernel/signal.c b/arch/riscv/kernel/signal.c > index 55d2215d18ea..d2d9232498ca 100644 > --- a/arch/riscv/kernel/signal.c > +++ b/arch/riscv/kernel/signal.c > @@ -21,6 +21,8 @@ > #include <asm/vector.h> > #include <asm/csr.h> > > +unsigned long signal_minsigstksz __ro_after_init; > + > extern u32 __user_rt_sigreturn[2]; > static size_t riscv_v_sc_size __ro_after_init; > > @@ -195,7 +197,7 @@ static long restore_sigcontext(struct pt_regs *regs, > return err; > } > > -static size_t get_rt_frame_size(void) > +static size_t get_rt_frame_size(bool cal_all) > { > struct rt_sigframe __user *frame; > size_t frame_size; > @@ -203,8 +205,10 @@ static size_t get_rt_frame_size(void) > > frame_size = sizeof(*frame); > > - if (has_vector() && riscv_v_vstate_query(task_pt_regs(current))) > - total_context_size += riscv_v_sc_size; > + if (has_vector()) { > + if (cal_all || riscv_v_vstate_query(task_pt_regs(current))) > + total_context_size += riscv_v_sc_size; > + } > /* > * Preserved a __riscv_ctx_hdr for END signal context header if an > * extension uses __riscv_extra_ext_header > @@ -224,7 +228,7 @@ SYSCALL_DEFINE0(rt_sigreturn) > struct rt_sigframe __user *frame; > struct task_struct *task; > sigset_t set; > - size_t frame_size = get_rt_frame_size(); > + size_t frame_size = get_rt_frame_size(false); > > /* Always make any pending restarted system calls return -EINTR */ > current->restart_block.fn = do_no_restart_syscall; > @@ -320,7 +324,7 @@ static int setup_rt_frame(struct ksignal *ksig, sigset_t *set, > { > struct rt_sigframe __user *frame; > long err = 0; > - size_t frame_size = get_rt_frame_size(); > + size_t frame_size = get_rt_frame_size(false); > > frame = get_sigframe(ksig, regs, frame_size); > if (!access_ok(frame, frame_size)) > @@ -483,4 +487,10 @@ void __init init_rt_signal_env(void) > { > riscv_v_sc_size = sizeof(struct __riscv_ctx_hdr) + > sizeof(struct __sc_riscv_v_state) + riscv_v_vsize; > + /* > + * Determine the stack space required for guaranteed signal delivery. > + * The signal_minsigstksz will be populated into the AT_MINSIGSTKSZ entry > + * in the auxiliary array at process startup. > + */ > + signal_minsigstksz = get_rt_frame_size(true); > } > -- > 2.17.1 > Reviewed-by: Guo Ren <guoren@kernel.org>
diff --git a/arch/riscv/include/asm/elf.h b/arch/riscv/include/asm/elf.h index 30e7d2455960..ca23c4f6c440 100644 --- a/arch/riscv/include/asm/elf.h +++ b/arch/riscv/include/asm/elf.h @@ -105,6 +105,15 @@ do { \ get_cache_size(3, CACHE_TYPE_UNIFIED)); \ NEW_AUX_ENT(AT_L3_CACHEGEOMETRY, \ get_cache_geometry(3, CACHE_TYPE_UNIFIED)); \ + /* \ + * Should always be nonzero unless there's a kernel bug. \ + * If we haven't determined a sensible value to give to \ + * userspace, omit the entry: \ + */ \ + if (likely(signal_minsigstksz)) \ + NEW_AUX_ENT(AT_MINSIGSTKSZ, signal_minsigstksz); \ + else \ + NEW_AUX_ENT(AT_IGNORE, 0); \ } while (0) #define ARCH_HAS_SETUP_ADDITIONAL_PAGES struct linux_binprm; diff --git a/arch/riscv/include/asm/processor.h b/arch/riscv/include/asm/processor.h index f0ddf691ac5e..38ded8c5f207 100644 --- a/arch/riscv/include/asm/processor.h +++ b/arch/riscv/include/asm/processor.h @@ -7,6 +7,7 @@ #define _ASM_RISCV_PROCESSOR_H #include <linux/const.h> +#include <linux/cache.h> #include <vdso/processor.h> @@ -81,6 +82,7 @@ int riscv_of_parent_hartid(struct device_node *node, unsigned long *hartid); extern void riscv_fill_hwcap(void); extern int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src); +extern unsigned long signal_minsigstksz __ro_after_init; #endif /* __ASSEMBLY__ */ #endif /* _ASM_RISCV_PROCESSOR_H */ diff --git a/arch/riscv/include/uapi/asm/auxvec.h b/arch/riscv/include/uapi/asm/auxvec.h index fb187a33ce58..10aaa83db89e 100644 --- a/arch/riscv/include/uapi/asm/auxvec.h +++ b/arch/riscv/include/uapi/asm/auxvec.h @@ -35,5 +35,6 @@ /* entries in ARCH_DLINFO */ #define AT_VECTOR_SIZE_ARCH 9 +#define AT_MINSIGSTKSZ 51 #endif /* _UAPI_ASM_RISCV_AUXVEC_H */ diff --git a/arch/riscv/kernel/signal.c b/arch/riscv/kernel/signal.c index 55d2215d18ea..d2d9232498ca 100644 --- a/arch/riscv/kernel/signal.c +++ b/arch/riscv/kernel/signal.c @@ -21,6 +21,8 @@ #include <asm/vector.h> #include <asm/csr.h> +unsigned long signal_minsigstksz __ro_after_init; + extern u32 __user_rt_sigreturn[2]; static size_t riscv_v_sc_size __ro_after_init; @@ -195,7 +197,7 @@ static long restore_sigcontext(struct pt_regs *regs, return err; } -static size_t get_rt_frame_size(void) +static size_t get_rt_frame_size(bool cal_all) { struct rt_sigframe __user *frame; size_t frame_size; @@ -203,8 +205,10 @@ static size_t get_rt_frame_size(void) frame_size = sizeof(*frame); - if (has_vector() && riscv_v_vstate_query(task_pt_regs(current))) - total_context_size += riscv_v_sc_size; + if (has_vector()) { + if (cal_all || riscv_v_vstate_query(task_pt_regs(current))) + total_context_size += riscv_v_sc_size; + } /* * Preserved a __riscv_ctx_hdr for END signal context header if an * extension uses __riscv_extra_ext_header @@ -224,7 +228,7 @@ SYSCALL_DEFINE0(rt_sigreturn) struct rt_sigframe __user *frame; struct task_struct *task; sigset_t set; - size_t frame_size = get_rt_frame_size(); + size_t frame_size = get_rt_frame_size(false); /* Always make any pending restarted system calls return -EINTR */ current->restart_block.fn = do_no_restart_syscall; @@ -320,7 +324,7 @@ static int setup_rt_frame(struct ksignal *ksig, sigset_t *set, { struct rt_sigframe __user *frame; long err = 0; - size_t frame_size = get_rt_frame_size(); + size_t frame_size = get_rt_frame_size(false); frame = get_sigframe(ksig, regs, frame_size); if (!access_ok(frame, frame_size)) @@ -483,4 +487,10 @@ void __init init_rt_signal_env(void) { riscv_v_sc_size = sizeof(struct __riscv_ctx_hdr) + sizeof(struct __sc_riscv_v_state) + riscv_v_vsize; + /* + * Determine the stack space required for guaranteed signal delivery. + * The signal_minsigstksz will be populated into the AT_MINSIGSTKSZ entry + * in the auxiliary array at process startup. + */ + signal_minsigstksz = get_rt_frame_size(true); }