-#define INIT_THREAD_INFO(tsk) \
-{ \
- .flags = 0, \
+#define INIT_THREAD_INFO(tsk) \
+{ \
+ .flags = 0, \
+ .user_pt_regs = (struct pt_regs *)TOP_OF_INIT_STACK - 1, \
Use __top_init_kernel_stack here.
}
#else /* !__ASSEMBLER__ */
diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c
index 91f6ff618852..58c1cd4ca60a 100644
--- a/arch/x86/kernel/process.c
+++ b/arch/x86/kernel/process.c
@@ -108,6 +108,28 @@ int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src)
return 0;
}
+/*
+ * Initialize thread_info.user_pt_regs for IDT event delivery.
+ *
+ * For IDT user level event delivery, a pt_regs structure is pushed by both
+ * hardware and software and always resides at a fixed offset from top of
+ * current task kernel stack, thus thread_info.user_pt_regs is a per-task
+ * constant and NEVER changes after initialization.
+ *
+ * While for FRED user level event delivery, user_pt_regs is updated in
+ * fred_entry_from_user() immediately after user level event delivery.
+ *
+ * Note: thread_info.user_pt_regs of the init task is initialized at build
+ * time.
+ */
+void arch_init_user_pt_regs(struct task_struct *tsk)
+{
+ unsigned long top_of_stack = (unsigned long)task_stack_page(tsk) + THREAD_SIZE;
+
+ top_of_stack -= TOP_OF_KERNEL_STACK_PADDING;
+ tsk->thread_info.user_pt_regs = (struct pt_regs *)top_of_stack - 1;
+}
Can this be put into arch_dup_task_struct() instead of creating another hook?