|
@@ -17,6 +17,7 @@
|
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
*/
|
|
|
|
|
|
+#include <linux/cache.h>
|
|
|
#include <linux/compat.h>
|
|
|
#include <linux/errno.h>
|
|
|
#include <linux/kernel.h>
|
|
@@ -570,8 +571,15 @@ badframe:
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-/* Determine the layout of optional records in the signal frame */
|
|
|
-static int setup_sigframe_layout(struct rt_sigframe_user_layout *user)
|
|
|
+/*
|
|
|
+ * Determine the layout of optional records in the signal frame
|
|
|
+ *
|
|
|
+ * add_all: if true, lays out the biggest possible signal frame for
|
|
|
+ * this task; otherwise, generates a layout for the current state
|
|
|
+ * of the task.
|
|
|
+ */
|
|
|
+static int setup_sigframe_layout(struct rt_sigframe_user_layout *user,
|
|
|
+ bool add_all)
|
|
|
{
|
|
|
int err;
|
|
|
|
|
@@ -581,7 +589,7 @@ static int setup_sigframe_layout(struct rt_sigframe_user_layout *user)
|
|
|
return err;
|
|
|
|
|
|
/* fault information, if valid */
|
|
|
- if (current->thread.fault_code) {
|
|
|
+ if (add_all || current->thread.fault_code) {
|
|
|
err = sigframe_alloc(user, &user->esr_offset,
|
|
|
sizeof(struct esr_context));
|
|
|
if (err)
|
|
@@ -591,8 +599,14 @@ static int setup_sigframe_layout(struct rt_sigframe_user_layout *user)
|
|
|
if (system_supports_sve()) {
|
|
|
unsigned int vq = 0;
|
|
|
|
|
|
- if (test_thread_flag(TIF_SVE))
|
|
|
- vq = sve_vq_from_vl(current->thread.sve_vl);
|
|
|
+ if (add_all || test_thread_flag(TIF_SVE)) {
|
|
|
+ int vl = sve_max_vl;
|
|
|
+
|
|
|
+ if (!add_all)
|
|
|
+ vl = current->thread.sve_vl;
|
|
|
+
|
|
|
+ vq = sve_vq_from_vl(vl);
|
|
|
+ }
|
|
|
|
|
|
err = sigframe_alloc(user, &user->sve_offset,
|
|
|
SVE_SIG_CONTEXT_SIZE(vq));
|
|
@@ -603,7 +617,6 @@ static int setup_sigframe_layout(struct rt_sigframe_user_layout *user)
|
|
|
return sigframe_alloc_end(user);
|
|
|
}
|
|
|
|
|
|
-
|
|
|
static int setup_sigframe(struct rt_sigframe_user_layout *user,
|
|
|
struct pt_regs *regs, sigset_t *set)
|
|
|
{
|
|
@@ -701,7 +714,7 @@ static int get_sigframe(struct rt_sigframe_user_layout *user,
|
|
|
int err;
|
|
|
|
|
|
init_user_layout(user);
|
|
|
- err = setup_sigframe_layout(user);
|
|
|
+ err = setup_sigframe_layout(user, false);
|
|
|
if (err)
|
|
|
return err;
|
|
|
|
|
@@ -936,3 +949,28 @@ asmlinkage void do_notify_resume(struct pt_regs *regs,
|
|
|
thread_flags = READ_ONCE(current_thread_info()->flags);
|
|
|
} while (thread_flags & _TIF_WORK_MASK);
|
|
|
}
|
|
|
+
|
|
|
+unsigned long __ro_after_init signal_minsigstksz;
|
|
|
+
|
|
|
+/*
|
|
|
+ * Determine the stack space required for guaranteed signal devliery.
|
|
|
+ * This function is used to populate AT_MINSIGSTKSZ at process startup.
|
|
|
+ * cpufeatures setup is assumed to be complete.
|
|
|
+ */
|
|
|
+void __init minsigstksz_setup(void)
|
|
|
+{
|
|
|
+ struct rt_sigframe_user_layout user;
|
|
|
+
|
|
|
+ init_user_layout(&user);
|
|
|
+
|
|
|
+ /*
|
|
|
+ * If this fails, SIGFRAME_MAXSZ needs to be enlarged. It won't
|
|
|
+ * be big enough, but it's our best guess:
|
|
|
+ */
|
|
|
+ if (WARN_ON(setup_sigframe_layout(&user, true)))
|
|
|
+ return;
|
|
|
+
|
|
|
+ signal_minsigstksz = sigframe_size(&user) +
|
|
|
+ round_up(sizeof(struct frame_record), 16) +
|
|
|
+ 16; /* max alignment padding */
|
|
|
+}
|