aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/arm64/include/asm/elf.h13
-rw-r--r--arch/arm64/include/asm/processor.h5
-rw-r--r--arch/arm64/include/uapi/asm/auxvec.h3
-rw-r--r--arch/arm64/kernel/cpufeature.c1
-rw-r--r--arch/arm64/kernel/signal.c52
5 files changed, 66 insertions, 8 deletions
diff --git a/arch/arm64/include/asm/elf.h b/arch/arm64/include/asm/elf.h
index fac1c4de7898..433b9554c6a1 100644
--- a/arch/arm64/include/asm/elf.h
+++ b/arch/arm64/include/asm/elf.h
@@ -121,6 +121,9 @@
121 121
122#ifndef __ASSEMBLY__ 122#ifndef __ASSEMBLY__
123 123
124#include <linux/bug.h>
125#include <asm/processor.h> /* for signal_minsigstksz, used by ARCH_DLINFO */
126
124typedef unsigned long elf_greg_t; 127typedef unsigned long elf_greg_t;
125 128
126#define ELF_NGREG (sizeof(struct user_pt_regs) / sizeof(elf_greg_t)) 129#define ELF_NGREG (sizeof(struct user_pt_regs) / sizeof(elf_greg_t))
@@ -148,6 +151,16 @@ typedef struct user_fpsimd_state elf_fpregset_t;
148do { \ 151do { \
149 NEW_AUX_ENT(AT_SYSINFO_EHDR, \ 152 NEW_AUX_ENT(AT_SYSINFO_EHDR, \
150 (elf_addr_t)current->mm->context.vdso); \ 153 (elf_addr_t)current->mm->context.vdso); \
154 \
155 /* \
156 * Should always be nonzero unless there's a kernel bug. \
157 * If we haven't determined a sensible value to give to \
158 * userspace, omit the entry: \
159 */ \
160 if (likely(signal_minsigstksz)) \
161 NEW_AUX_ENT(AT_MINSIGSTKSZ, signal_minsigstksz); \
162 else \
163 NEW_AUX_ENT(AT_IGNORE, 0); \
151} while (0) 164} while (0)
152 165
153#define ARCH_HAS_SETUP_ADDITIONAL_PAGES 166#define ARCH_HAS_SETUP_ADDITIONAL_PAGES
diff --git a/arch/arm64/include/asm/processor.h b/arch/arm64/include/asm/processor.h
index 767598932549..65ab83e8926e 100644
--- a/arch/arm64/include/asm/processor.h
+++ b/arch/arm64/include/asm/processor.h
@@ -35,6 +35,8 @@
35#ifdef __KERNEL__ 35#ifdef __KERNEL__
36 36
37#include <linux/build_bug.h> 37#include <linux/build_bug.h>
38#include <linux/cache.h>
39#include <linux/init.h>
38#include <linux/stddef.h> 40#include <linux/stddef.h>
39#include <linux/string.h> 41#include <linux/string.h>
40 42
@@ -244,6 +246,9 @@ void cpu_enable_pan(const struct arm64_cpu_capabilities *__unused);
244void cpu_enable_cache_maint_trap(const struct arm64_cpu_capabilities *__unused); 246void cpu_enable_cache_maint_trap(const struct arm64_cpu_capabilities *__unused);
245void cpu_clear_disr(const struct arm64_cpu_capabilities *__unused); 247void cpu_clear_disr(const struct arm64_cpu_capabilities *__unused);
246 248
249extern unsigned long __ro_after_init signal_minsigstksz; /* sigframe size */
250extern void __init minsigstksz_setup(void);
251
247/* Userspace interface for PR_SVE_{SET,GET}_VL prctl()s: */ 252/* Userspace interface for PR_SVE_{SET,GET}_VL prctl()s: */
248#define SVE_SET_VL(arg) sve_set_current_vl(arg) 253#define SVE_SET_VL(arg) sve_set_current_vl(arg)
249#define SVE_GET_VL() sve_get_current_vl() 254#define SVE_GET_VL() sve_get_current_vl()
diff --git a/arch/arm64/include/uapi/asm/auxvec.h b/arch/arm64/include/uapi/asm/auxvec.h
index ec0a86d484e1..743c0b84fd30 100644
--- a/arch/arm64/include/uapi/asm/auxvec.h
+++ b/arch/arm64/include/uapi/asm/auxvec.h
@@ -19,7 +19,8 @@
19 19
20/* vDSO location */ 20/* vDSO location */
21#define AT_SYSINFO_EHDR 33 21#define AT_SYSINFO_EHDR 33
22#define AT_MINSIGSTKSZ 51 /* stack needed for signal delivery */
22 23
23#define AT_VECTOR_SIZE_ARCH 1 /* entries in ARCH_DLINFO */ 24#define AT_VECTOR_SIZE_ARCH 2 /* entries in ARCH_DLINFO */
24 25
25#endif 26#endif
diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
index fbee8c17a4e6..d2856b129097 100644
--- a/arch/arm64/kernel/cpufeature.c
+++ b/arch/arm64/kernel/cpufeature.c
@@ -1618,6 +1618,7 @@ void __init setup_cpu_features(void)
1618 pr_info("emulated: Privileged Access Never (PAN) using TTBR0_EL1 switching\n"); 1618 pr_info("emulated: Privileged Access Never (PAN) using TTBR0_EL1 switching\n");
1619 1619
1620 sve_setup(); 1620 sve_setup();
1621 minsigstksz_setup();
1621 1622
1622 /* Advertise that we have computed the system capabilities */ 1623 /* Advertise that we have computed the system capabilities */
1623 set_sys_caps_initialised(); 1624 set_sys_caps_initialised();
diff --git a/arch/arm64/kernel/signal.c b/arch/arm64/kernel/signal.c
index 154b7d30145d..e7da5dba7ba8 100644
--- a/arch/arm64/kernel/signal.c
+++ b/arch/arm64/kernel/signal.c
@@ -17,6 +17,7 @@
17 * along with this program. If not, see <http://www.gnu.org/licenses/>. 17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */ 18 */
19 19
20#include <linux/cache.h>
20#include <linux/compat.h> 21#include <linux/compat.h>
21#include <linux/errno.h> 22#include <linux/errno.h>
22#include <linux/kernel.h> 23#include <linux/kernel.h>
@@ -570,8 +571,15 @@ badframe:
570 return 0; 571 return 0;
571} 572}
572 573
573/* Determine the layout of optional records in the signal frame */ 574/*
574static int setup_sigframe_layout(struct rt_sigframe_user_layout *user) 575 * Determine the layout of optional records in the signal frame
576 *
577 * add_all: if true, lays out the biggest possible signal frame for
578 * this task; otherwise, generates a layout for the current state
579 * of the task.
580 */
581static int setup_sigframe_layout(struct rt_sigframe_user_layout *user,
582 bool add_all)
575{ 583{
576 int err; 584 int err;
577 585
@@ -581,7 +589,7 @@ static int setup_sigframe_layout(struct rt_sigframe_user_layout *user)
581 return err; 589 return err;
582 590
583 /* fault information, if valid */ 591 /* fault information, if valid */
584 if (current->thread.fault_code) { 592 if (add_all || current->thread.fault_code) {
585 err = sigframe_alloc(user, &user->esr_offset, 593 err = sigframe_alloc(user, &user->esr_offset,
586 sizeof(struct esr_context)); 594 sizeof(struct esr_context));
587 if (err) 595 if (err)
@@ -591,8 +599,14 @@ static int setup_sigframe_layout(struct rt_sigframe_user_layout *user)
591 if (system_supports_sve()) { 599 if (system_supports_sve()) {
592 unsigned int vq = 0; 600 unsigned int vq = 0;
593 601
594 if (test_thread_flag(TIF_SVE)) 602 if (add_all || test_thread_flag(TIF_SVE)) {
595 vq = sve_vq_from_vl(current->thread.sve_vl); 603 int vl = sve_max_vl;
604
605 if (!add_all)
606 vl = current->thread.sve_vl;
607
608 vq = sve_vq_from_vl(vl);
609 }
596 610
597 err = sigframe_alloc(user, &user->sve_offset, 611 err = sigframe_alloc(user, &user->sve_offset,
598 SVE_SIG_CONTEXT_SIZE(vq)); 612 SVE_SIG_CONTEXT_SIZE(vq));
@@ -603,7 +617,6 @@ static int setup_sigframe_layout(struct rt_sigframe_user_layout *user)
603 return sigframe_alloc_end(user); 617 return sigframe_alloc_end(user);
604} 618}
605 619
606
607static int setup_sigframe(struct rt_sigframe_user_layout *user, 620static int setup_sigframe(struct rt_sigframe_user_layout *user,
608 struct pt_regs *regs, sigset_t *set) 621 struct pt_regs *regs, sigset_t *set)
609{ 622{
@@ -701,7 +714,7 @@ static int get_sigframe(struct rt_sigframe_user_layout *user,
701 int err; 714 int err;
702 715
703 init_user_layout(user); 716 init_user_layout(user);
704 err = setup_sigframe_layout(user); 717 err = setup_sigframe_layout(user, false);
705 if (err) 718 if (err)
706 return err; 719 return err;
707 720
@@ -936,3 +949,28 @@ asmlinkage void do_notify_resume(struct pt_regs *regs,
936 thread_flags = READ_ONCE(current_thread_info()->flags); 949 thread_flags = READ_ONCE(current_thread_info()->flags);
937 } while (thread_flags & _TIF_WORK_MASK); 950 } while (thread_flags & _TIF_WORK_MASK);
938} 951}
952
953unsigned long __ro_after_init signal_minsigstksz;
954
955/*
956 * Determine the stack space required for guaranteed signal devliery.
957 * This function is used to populate AT_MINSIGSTKSZ at process startup.
958 * cpufeatures setup is assumed to be complete.
959 */
960void __init minsigstksz_setup(void)
961{
962 struct rt_sigframe_user_layout user;
963
964 init_user_layout(&user);
965
966 /*
967 * If this fails, SIGFRAME_MAXSZ needs to be enlarged. It won't
968 * be big enough, but it's our best guess:
969 */
970 if (WARN_ON(setup_sigframe_layout(&user, true)))
971 return;
972
973 signal_minsigstksz = sigframe_size(&user) +
974 round_up(sizeof(struct frame_record), 16) +
975 16; /* max alignment padding */
976}