Commit 95c7b075 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'powerpc-5.12-6' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux

Pull powerpc fixes from Michael Ellerman:
 "Some some more powerpc fixes for 5.12:

   - Fix an oops triggered by ptrace when CONFIG_PPC_FPU_REGS=n

   - Fix an oops on sigreturn when the VDSO is unmapped on 32-bit

   - Fix vdso_wrapper.o not being rebuilt everytime vdso.so is rebuilt

  Thanks to Christophe Leroy"

* tag 'powerpc-5.12-6' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux:
  powerpc/vdso: Make sure vdso_wrapper.o is rebuilt everytime vdso.so is rebuilt
  powerpc/signal32: Fix Oops on sigreturn with unmapped VDSO
  powerpc/ptrace: Don't return error when getting/setting FP regs without CONFIG_PPC_FPU_REGS
parents d5fa1dad 791f9e36
...@@ -191,3 +191,7 @@ $(obj)/prom_init_check: $(src)/prom_init_check.sh $(obj)/prom_init.o FORCE ...@@ -191,3 +191,7 @@ $(obj)/prom_init_check: $(src)/prom_init_check.sh $(obj)/prom_init.o FORCE
targets += prom_init_check targets += prom_init_check
clean-files := vmlinux.lds clean-files := vmlinux.lds
# Force dependency (incbin is bad)
$(obj)/vdso32_wrapper.o : $(obj)/vdso32/vdso32.so.dbg
$(obj)/vdso64_wrapper.o : $(obj)/vdso64/vdso64.so.dbg
...@@ -6,11 +6,11 @@ ...@@ -6,11 +6,11 @@
CFLAGS_ptrace-view.o += -DUTS_MACHINE='"$(UTS_MACHINE)"' CFLAGS_ptrace-view.o += -DUTS_MACHINE='"$(UTS_MACHINE)"'
obj-y += ptrace.o ptrace-view.o obj-y += ptrace.o ptrace-view.o
obj-$(CONFIG_PPC_FPU_REGS) += ptrace-fpu.o obj-y += ptrace-fpu.o
obj-$(CONFIG_COMPAT) += ptrace32.o obj-$(CONFIG_COMPAT) += ptrace32.o
obj-$(CONFIG_VSX) += ptrace-vsx.o obj-$(CONFIG_VSX) += ptrace-vsx.o
ifneq ($(CONFIG_VSX),y) ifneq ($(CONFIG_VSX),y)
obj-$(CONFIG_PPC_FPU_REGS) += ptrace-novsx.o obj-y += ptrace-novsx.o
endif endif
obj-$(CONFIG_ALTIVEC) += ptrace-altivec.o obj-$(CONFIG_ALTIVEC) += ptrace-altivec.o
obj-$(CONFIG_SPE) += ptrace-spe.o obj-$(CONFIG_SPE) += ptrace-spe.o
......
...@@ -165,22 +165,8 @@ int ptrace_put_reg(struct task_struct *task, int regno, unsigned long data); ...@@ -165,22 +165,8 @@ int ptrace_put_reg(struct task_struct *task, int regno, unsigned long data);
extern const struct user_regset_view user_ppc_native_view; extern const struct user_regset_view user_ppc_native_view;
/* ptrace-fpu */ /* ptrace-fpu */
#ifdef CONFIG_PPC_FPU_REGS
int ptrace_get_fpr(struct task_struct *child, int index, unsigned long *data); int ptrace_get_fpr(struct task_struct *child, int index, unsigned long *data);
int ptrace_put_fpr(struct task_struct *child, int index, unsigned long data); int ptrace_put_fpr(struct task_struct *child, int index, unsigned long data);
#else
static inline int
ptrace_get_fpr(struct task_struct *child, int index, unsigned long *data)
{
return -EIO;
}
static inline int
ptrace_put_fpr(struct task_struct *child, int index, unsigned long data)
{
return -EIO;
}
#endif
/* ptrace-(no)adv */ /* ptrace-(no)adv */
void ppc_gethwdinfo(struct ppc_debug_info *dbginfo); void ppc_gethwdinfo(struct ppc_debug_info *dbginfo);
......
...@@ -8,32 +8,42 @@ ...@@ -8,32 +8,42 @@
int ptrace_get_fpr(struct task_struct *child, int index, unsigned long *data) int ptrace_get_fpr(struct task_struct *child, int index, unsigned long *data)
{ {
#ifdef CONFIG_PPC_FPU_REGS
unsigned int fpidx = index - PT_FPR0; unsigned int fpidx = index - PT_FPR0;
#endif
if (index > PT_FPSCR) if (index > PT_FPSCR)
return -EIO; return -EIO;
#ifdef CONFIG_PPC_FPU_REGS
flush_fp_to_thread(child); flush_fp_to_thread(child);
if (fpidx < (PT_FPSCR - PT_FPR0)) if (fpidx < (PT_FPSCR - PT_FPR0))
memcpy(data, &child->thread.TS_FPR(fpidx), sizeof(long)); memcpy(data, &child->thread.TS_FPR(fpidx), sizeof(long));
else else
*data = child->thread.fp_state.fpscr; *data = child->thread.fp_state.fpscr;
#else
*data = 0;
#endif
return 0; return 0;
} }
int ptrace_put_fpr(struct task_struct *child, int index, unsigned long data) int ptrace_put_fpr(struct task_struct *child, int index, unsigned long data)
{ {
#ifdef CONFIG_PPC_FPU_REGS
unsigned int fpidx = index - PT_FPR0; unsigned int fpidx = index - PT_FPR0;
#endif
if (index > PT_FPSCR) if (index > PT_FPSCR)
return -EIO; return -EIO;
#ifdef CONFIG_PPC_FPU_REGS
flush_fp_to_thread(child); flush_fp_to_thread(child);
if (fpidx < (PT_FPSCR - PT_FPR0)) if (fpidx < (PT_FPSCR - PT_FPR0))
memcpy(&child->thread.TS_FPR(fpidx), &data, sizeof(long)); memcpy(&child->thread.TS_FPR(fpidx), &data, sizeof(long));
else else
child->thread.fp_state.fpscr = data; child->thread.fp_state.fpscr = data;
#endif
return 0; return 0;
} }
......
...@@ -21,12 +21,16 @@ ...@@ -21,12 +21,16 @@
int fpr_get(struct task_struct *target, const struct user_regset *regset, int fpr_get(struct task_struct *target, const struct user_regset *regset,
struct membuf to) struct membuf to)
{ {
#ifdef CONFIG_PPC_FPU_REGS
BUILD_BUG_ON(offsetof(struct thread_fp_state, fpscr) != BUILD_BUG_ON(offsetof(struct thread_fp_state, fpscr) !=
offsetof(struct thread_fp_state, fpr[32])); offsetof(struct thread_fp_state, fpr[32]));
flush_fp_to_thread(target); flush_fp_to_thread(target);
return membuf_write(&to, &target->thread.fp_state, 33 * sizeof(u64)); return membuf_write(&to, &target->thread.fp_state, 33 * sizeof(u64));
#else
return membuf_write(&to, &empty_zero_page, 33 * sizeof(u64));
#endif
} }
/* /*
...@@ -46,6 +50,7 @@ int fpr_set(struct task_struct *target, const struct user_regset *regset, ...@@ -46,6 +50,7 @@ int fpr_set(struct task_struct *target, const struct user_regset *regset,
unsigned int pos, unsigned int count, unsigned int pos, unsigned int count,
const void *kbuf, const void __user *ubuf) const void *kbuf, const void __user *ubuf)
{ {
#ifdef CONFIG_PPC_FPU_REGS
BUILD_BUG_ON(offsetof(struct thread_fp_state, fpscr) != BUILD_BUG_ON(offsetof(struct thread_fp_state, fpscr) !=
offsetof(struct thread_fp_state, fpr[32])); offsetof(struct thread_fp_state, fpr[32]));
...@@ -53,4 +58,7 @@ int fpr_set(struct task_struct *target, const struct user_regset *regset, ...@@ -53,4 +58,7 @@ int fpr_set(struct task_struct *target, const struct user_regset *regset,
return user_regset_copyin(&pos, &count, &kbuf, &ubuf, return user_regset_copyin(&pos, &count, &kbuf, &ubuf,
&target->thread.fp_state, 0, -1); &target->thread.fp_state, 0, -1);
#else
return 0;
#endif
} }
...@@ -522,13 +522,11 @@ static const struct user_regset native_regsets[] = { ...@@ -522,13 +522,11 @@ static const struct user_regset native_regsets[] = {
.size = sizeof(long), .align = sizeof(long), .size = sizeof(long), .align = sizeof(long),
.regset_get = gpr_get, .set = gpr_set .regset_get = gpr_get, .set = gpr_set
}, },
#ifdef CONFIG_PPC_FPU_REGS
[REGSET_FPR] = { [REGSET_FPR] = {
.core_note_type = NT_PRFPREG, .n = ELF_NFPREG, .core_note_type = NT_PRFPREG, .n = ELF_NFPREG,
.size = sizeof(double), .align = sizeof(double), .size = sizeof(double), .align = sizeof(double),
.regset_get = fpr_get, .set = fpr_set .regset_get = fpr_get, .set = fpr_set
}, },
#endif
#ifdef CONFIG_ALTIVEC #ifdef CONFIG_ALTIVEC
[REGSET_VMX] = { [REGSET_VMX] = {
.core_note_type = NT_PPC_VMX, .n = 34, .core_note_type = NT_PPC_VMX, .n = 34,
......
...@@ -775,7 +775,7 @@ int handle_rt_signal32(struct ksignal *ksig, sigset_t *oldset, ...@@ -775,7 +775,7 @@ int handle_rt_signal32(struct ksignal *ksig, sigset_t *oldset,
else else
prepare_save_user_regs(1); prepare_save_user_regs(1);
if (!user_write_access_begin(frame, sizeof(*frame))) if (!user_access_begin(frame, sizeof(*frame)))
goto badframe; goto badframe;
/* Put the siginfo & fill in most of the ucontext */ /* Put the siginfo & fill in most of the ucontext */
...@@ -809,17 +809,15 @@ int handle_rt_signal32(struct ksignal *ksig, sigset_t *oldset, ...@@ -809,17 +809,15 @@ int handle_rt_signal32(struct ksignal *ksig, sigset_t *oldset,
unsafe_put_user(PPC_INST_ADDI + __NR_rt_sigreturn, &mctx->mc_pad[0], unsafe_put_user(PPC_INST_ADDI + __NR_rt_sigreturn, &mctx->mc_pad[0],
failed); failed);
unsafe_put_user(PPC_INST_SC, &mctx->mc_pad[1], failed); unsafe_put_user(PPC_INST_SC, &mctx->mc_pad[1], failed);
asm("dcbst %y0; sync; icbi %y0; sync" :: "Z" (mctx->mc_pad[0]));
} }
unsafe_put_sigset_t(&frame->uc.uc_sigmask, oldset, failed); unsafe_put_sigset_t(&frame->uc.uc_sigmask, oldset, failed);
user_write_access_end(); user_access_end();
if (copy_siginfo_to_user(&frame->info, &ksig->info)) if (copy_siginfo_to_user(&frame->info, &ksig->info))
goto badframe; goto badframe;
if (tramp == (unsigned long)mctx->mc_pad)
flush_icache_range(tramp, tramp + 2 * sizeof(unsigned long));
regs->link = tramp; regs->link = tramp;
#ifdef CONFIG_PPC_FPU_REGS #ifdef CONFIG_PPC_FPU_REGS
...@@ -844,7 +842,7 @@ int handle_rt_signal32(struct ksignal *ksig, sigset_t *oldset, ...@@ -844,7 +842,7 @@ int handle_rt_signal32(struct ksignal *ksig, sigset_t *oldset,
return 0; return 0;
failed: failed:
user_write_access_end(); user_access_end();
badframe: badframe:
signal_fault(tsk, regs, "handle_rt_signal32", frame); signal_fault(tsk, regs, "handle_rt_signal32", frame);
...@@ -879,7 +877,7 @@ int handle_signal32(struct ksignal *ksig, sigset_t *oldset, ...@@ -879,7 +877,7 @@ int handle_signal32(struct ksignal *ksig, sigset_t *oldset,
else else
prepare_save_user_regs(1); prepare_save_user_regs(1);
if (!user_write_access_begin(frame, sizeof(*frame))) if (!user_access_begin(frame, sizeof(*frame)))
goto badframe; goto badframe;
sc = (struct sigcontext __user *) &frame->sctx; sc = (struct sigcontext __user *) &frame->sctx;
...@@ -908,11 +906,9 @@ int handle_signal32(struct ksignal *ksig, sigset_t *oldset, ...@@ -908,11 +906,9 @@ int handle_signal32(struct ksignal *ksig, sigset_t *oldset,
/* Set up the sigreturn trampoline: li r0,sigret; sc */ /* Set up the sigreturn trampoline: li r0,sigret; sc */
unsafe_put_user(PPC_INST_ADDI + __NR_sigreturn, &mctx->mc_pad[0], failed); unsafe_put_user(PPC_INST_ADDI + __NR_sigreturn, &mctx->mc_pad[0], failed);
unsafe_put_user(PPC_INST_SC, &mctx->mc_pad[1], failed); unsafe_put_user(PPC_INST_SC, &mctx->mc_pad[1], failed);
asm("dcbst %y0; sync; icbi %y0; sync" :: "Z" (mctx->mc_pad[0]));
} }
user_write_access_end(); user_access_end();
if (tramp == (unsigned long)mctx->mc_pad)
flush_icache_range(tramp, tramp + 2 * sizeof(unsigned long));
regs->link = tramp; regs->link = tramp;
...@@ -935,7 +931,7 @@ int handle_signal32(struct ksignal *ksig, sigset_t *oldset, ...@@ -935,7 +931,7 @@ int handle_signal32(struct ksignal *ksig, sigset_t *oldset,
return 0; return 0;
failed: failed:
user_write_access_end(); user_access_end();
badframe: badframe:
signal_fault(tsk, regs, "handle_signal32", frame); signal_fault(tsk, regs, "handle_signal32", frame);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment