Commit 8dc7f022 authored by Nicholas Piggin's avatar Nicholas Piggin Committed by Michael Ellerman

powerpc: remove partial register save logic

All subarchitectures always save all GPRs to pt_regs interrupt frames
now. Remove FULL_REGS and associated bits.
Signed-off-by: default avatarNicholas Piggin <npiggin@gmail.com>
Signed-off-by: default avatarMichael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/20210316104206.407354-11-npiggin@gmail.com
parent c45ba4f4
...@@ -188,29 +188,16 @@ static inline void regs_set_return_value(struct pt_regs *regs, unsigned long rc) ...@@ -188,29 +188,16 @@ static inline void regs_set_return_value(struct pt_regs *regs, unsigned long rc)
#ifdef __powerpc64__ #ifdef __powerpc64__
#define TRAP_FLAGS_MASK 0x10 #define TRAP_FLAGS_MASK 0x10
#define TRAP(regs) ((regs)->trap & ~TRAP_FLAGS_MASK) #define TRAP(regs) ((regs)->trap & ~TRAP_FLAGS_MASK)
#define FULL_REGS(regs) true
#define SET_FULL_REGS(regs) do { } while (0)
#define CHECK_FULL_REGS(regs) do { } while (0)
#define NV_REG_POISON 0xdeadbeefdeadbeefUL
#else #else
/* /*
* We use the least-significant bit of the trap field to indicate * On 4xx we use bit 1 in the trap word to indicate whether the exception
* whether we have saved the full set of registers, or only a
* partial set. A 1 there means the partial set.
* On 4xx we use the next bit to indicate whether the exception
* is a critical exception (1 means it is). * is a critical exception (1 means it is).
*/ */
#define TRAP_FLAGS_MASK 0x1F #define TRAP_FLAGS_MASK 0x1E
#define TRAP(regs) ((regs)->trap & ~TRAP_FLAGS_MASK) #define TRAP(regs) ((regs)->trap & ~TRAP_FLAGS_MASK)
#define FULL_REGS(regs) true
#define SET_FULL_REGS(regs) do { } while (0)
#define IS_CRITICAL_EXC(regs) (((regs)->trap & 2) != 0) #define IS_CRITICAL_EXC(regs) (((regs)->trap & 2) != 0)
#define IS_MCHECK_EXC(regs) (((regs)->trap & 4) != 0) #define IS_MCHECK_EXC(regs) (((regs)->trap & 4) != 0)
#define IS_DEBUG_EXC(regs) (((regs)->trap & 8) != 0) #define IS_DEBUG_EXC(regs) (((regs)->trap & 8) != 0)
#define NV_REG_POISON 0xdeadbeef
#define CHECK_FULL_REGS(regs) \
do { \
} while (0)
#endif /* __powerpc64__ */ #endif /* __powerpc64__ */
static __always_inline void set_trap(struct pt_regs *regs, unsigned long val) static __always_inline void set_trap(struct pt_regs *regs, unsigned long val)
......
...@@ -304,12 +304,6 @@ int fix_alignment(struct pt_regs *regs) ...@@ -304,12 +304,6 @@ int fix_alignment(struct pt_regs *regs)
struct instruction_op op; struct instruction_op op;
int r, type; int r, type;
/*
* We require a complete register set, if not, then our assembly
* is broken
*/
CHECK_FULL_REGS(regs);
if (is_kernel_addr(regs->nip)) if (is_kernel_addr(regs->nip))
r = probe_kernel_read_inst(&instr, (void *)regs->nip); r = probe_kernel_read_inst(&instr, (void *)regs->nip);
else else
......
...@@ -51,7 +51,6 @@ notrace long system_call_exception(long r3, long r4, long r5, ...@@ -51,7 +51,6 @@ notrace long system_call_exception(long r3, long r4, long r5,
if (!IS_ENABLED(CONFIG_BOOKE) && !IS_ENABLED(CONFIG_40x)) if (!IS_ENABLED(CONFIG_BOOKE) && !IS_ENABLED(CONFIG_40x))
BUG_ON(!(regs->msr & MSR_RI)); BUG_ON(!(regs->msr & MSR_RI));
BUG_ON(!(regs->msr & MSR_PR)); BUG_ON(!(regs->msr & MSR_PR));
BUG_ON(!FULL_REGS(regs));
BUG_ON(arch_irq_disabled_regs(regs)); BUG_ON(arch_irq_disabled_regs(regs));
#ifdef CONFIG_PPC_PKEY #ifdef CONFIG_PPC_PKEY
...@@ -365,7 +364,6 @@ notrace unsigned long interrupt_exit_user_prepare(struct pt_regs *regs, unsigned ...@@ -365,7 +364,6 @@ notrace unsigned long interrupt_exit_user_prepare(struct pt_regs *regs, unsigned
if (!IS_ENABLED(CONFIG_BOOKE) && !IS_ENABLED(CONFIG_40x)) if (!IS_ENABLED(CONFIG_BOOKE) && !IS_ENABLED(CONFIG_40x))
BUG_ON(!(regs->msr & MSR_RI)); BUG_ON(!(regs->msr & MSR_RI));
BUG_ON(!(regs->msr & MSR_PR)); BUG_ON(!(regs->msr & MSR_PR));
BUG_ON(!FULL_REGS(regs));
BUG_ON(arch_irq_disabled_regs(regs)); BUG_ON(arch_irq_disabled_regs(regs));
CT_WARN_ON(ct_state() == CONTEXT_USER); CT_WARN_ON(ct_state() == CONTEXT_USER);
...@@ -445,7 +443,6 @@ notrace unsigned long interrupt_exit_kernel_prepare(struct pt_regs *regs, unsign ...@@ -445,7 +443,6 @@ notrace unsigned long interrupt_exit_kernel_prepare(struct pt_regs *regs, unsign
unlikely(!(regs->msr & MSR_RI))) unlikely(!(regs->msr & MSR_RI)))
unrecoverable_exception(regs); unrecoverable_exception(regs);
BUG_ON(regs->msr & MSR_PR); BUG_ON(regs->msr & MSR_PR);
BUG_ON(!FULL_REGS(regs));
/* /*
* CT_WARN_ON comes here via program_check_exception, * CT_WARN_ON comes here via program_check_exception,
* so avoid recursion. * so avoid recursion.
......
...@@ -1448,11 +1448,9 @@ static void print_msr_bits(unsigned long val) ...@@ -1448,11 +1448,9 @@ static void print_msr_bits(unsigned long val)
#ifdef CONFIG_PPC64 #ifdef CONFIG_PPC64
#define REG "%016lx" #define REG "%016lx"
#define REGS_PER_LINE 4 #define REGS_PER_LINE 4
#define LAST_VOLATILE 13
#else #else
#define REG "%08lx" #define REG "%08lx"
#define REGS_PER_LINE 8 #define REGS_PER_LINE 8
#define LAST_VOLATILE 12
#endif #endif
static void __show_regs(struct pt_regs *regs) static void __show_regs(struct pt_regs *regs)
...@@ -1488,8 +1486,6 @@ static void __show_regs(struct pt_regs *regs) ...@@ -1488,8 +1486,6 @@ static void __show_regs(struct pt_regs *regs)
if ((i % REGS_PER_LINE) == 0) if ((i % REGS_PER_LINE) == 0)
pr_cont("\nGPR%02d: ", i); pr_cont("\nGPR%02d: ", i);
pr_cont(REG " ", regs->gpr[i]); pr_cont(REG " ", regs->gpr[i]);
if (i == LAST_VOLATILE && !FULL_REGS(regs))
break;
} }
pr_cont("\n"); pr_cont("\n");
/* /*
...@@ -1692,7 +1688,6 @@ int copy_thread(unsigned long clone_flags, unsigned long usp, ...@@ -1692,7 +1688,6 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
} else { } else {
/* user thread */ /* user thread */
struct pt_regs *regs = current_pt_regs(); struct pt_regs *regs = current_pt_regs();
CHECK_FULL_REGS(regs);
*childregs = *regs; *childregs = *regs;
if (usp) if (usp)
childregs->gpr[1] = usp; childregs->gpr[1] = usp;
...@@ -1797,13 +1792,6 @@ void start_thread(struct pt_regs *regs, unsigned long start, unsigned long sp) ...@@ -1797,13 +1792,6 @@ void start_thread(struct pt_regs *regs, unsigned long start, unsigned long sp)
regs->ccr = 0; regs->ccr = 0;
regs->gpr[1] = sp; regs->gpr[1] = sp;
/*
* We have just cleared all the nonvolatile GPRs, so make
* FULL_REGS(regs) return true. This is necessary to allow
* ptrace to examine the thread immediately after exec.
*/
SET_FULL_REGS(regs);
#ifdef CONFIG_PPC32 #ifdef CONFIG_PPC32
regs->mq = 0; regs->mq = 0;
regs->nip = start; regs->nip = start;
......
...@@ -221,17 +221,9 @@ static int gpr_get(struct task_struct *target, const struct user_regset *regset, ...@@ -221,17 +221,9 @@ static int gpr_get(struct task_struct *target, const struct user_regset *regset,
#ifdef CONFIG_PPC64 #ifdef CONFIG_PPC64
struct membuf to_softe = membuf_at(&to, offsetof(struct pt_regs, softe)); struct membuf to_softe = membuf_at(&to, offsetof(struct pt_regs, softe));
#endif #endif
int i;
if (target->thread.regs == NULL) if (target->thread.regs == NULL)
return -EIO; return -EIO;
if (!FULL_REGS(target->thread.regs)) {
/* We have a partial register set. Fill 14-31 with bogus values */
for (i = 14; i < 32; i++)
target->thread.regs->gpr[i] = NV_REG_POISON;
}
membuf_write(&to, target->thread.regs, sizeof(struct user_pt_regs)); membuf_write(&to, target->thread.regs, sizeof(struct user_pt_regs));
membuf_store(&to_msr, get_user_msr(target)); membuf_store(&to_msr, get_user_msr(target));
...@@ -252,8 +244,6 @@ static int gpr_set(struct task_struct *target, const struct user_regset *regset, ...@@ -252,8 +244,6 @@ static int gpr_set(struct task_struct *target, const struct user_regset *regset,
if (target->thread.regs == NULL) if (target->thread.regs == NULL)
return -EIO; return -EIO;
CHECK_FULL_REGS(target->thread.regs);
ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
target->thread.regs, target->thread.regs,
0, PT_MSR * sizeof(reg)); 0, PT_MSR * sizeof(reg));
...@@ -729,19 +719,9 @@ static int gpr32_get(struct task_struct *target, ...@@ -729,19 +719,9 @@ static int gpr32_get(struct task_struct *target,
const struct user_regset *regset, const struct user_regset *regset,
struct membuf to) struct membuf to)
{ {
int i;
if (target->thread.regs == NULL) if (target->thread.regs == NULL)
return -EIO; return -EIO;
if (!FULL_REGS(target->thread.regs)) {
/*
* We have a partial register set.
* Fill 14-31 with bogus values.
*/
for (i = 14; i < 32; i++)
target->thread.regs->gpr[i] = NV_REG_POISON;
}
return gpr32_get_common(target, regset, to, return gpr32_get_common(target, regset, to,
&target->thread.regs->gpr[0]); &target->thread.regs->gpr[0]);
} }
...@@ -754,7 +734,6 @@ static int gpr32_set(struct task_struct *target, ...@@ -754,7 +734,6 @@ static int gpr32_set(struct task_struct *target,
if (target->thread.regs == NULL) if (target->thread.regs == NULL)
return -EIO; return -EIO;
CHECK_FULL_REGS(target->thread.regs);
return gpr32_set_common(target, regset, pos, count, kbuf, ubuf, return gpr32_set_common(target, regset, pos, count, kbuf, ubuf,
&target->thread.regs->gpr[0]); &target->thread.regs->gpr[0]);
} }
......
...@@ -59,7 +59,6 @@ long arch_ptrace(struct task_struct *child, long request, ...@@ -59,7 +59,6 @@ long arch_ptrace(struct task_struct *child, long request,
if ((addr & (sizeof(long) - 1)) || !child->thread.regs) if ((addr & (sizeof(long) - 1)) || !child->thread.regs)
break; break;
CHECK_FULL_REGS(child->thread.regs);
if (index < PT_FPR0) if (index < PT_FPR0)
ret = ptrace_get_reg(child, (int) index, &tmp); ret = ptrace_get_reg(child, (int) index, &tmp);
else else
...@@ -81,7 +80,6 @@ long arch_ptrace(struct task_struct *child, long request, ...@@ -81,7 +80,6 @@ long arch_ptrace(struct task_struct *child, long request,
if ((addr & (sizeof(long) - 1)) || !child->thread.regs) if ((addr & (sizeof(long) - 1)) || !child->thread.regs)
break; break;
CHECK_FULL_REGS(child->thread.regs);
if (index < PT_FPR0) if (index < PT_FPR0)
ret = ptrace_put_reg(child, index, data); ret = ptrace_put_reg(child, index, data);
else else
......
...@@ -83,7 +83,6 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request, ...@@ -83,7 +83,6 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
if ((addr & 3) || (index > PT_FPSCR32)) if ((addr & 3) || (index > PT_FPSCR32))
break; break;
CHECK_FULL_REGS(child->thread.regs);
if (index < PT_FPR0) { if (index < PT_FPR0) {
ret = ptrace_get_reg(child, index, &tmp); ret = ptrace_get_reg(child, index, &tmp);
if (ret) if (ret)
...@@ -133,7 +132,6 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request, ...@@ -133,7 +132,6 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
if ((addr & 3) || numReg > PT_FPSCR) if ((addr & 3) || numReg > PT_FPSCR)
break; break;
CHECK_FULL_REGS(child->thread.regs);
if (numReg >= PT_FPR0) { if (numReg >= PT_FPR0) {
flush_fp_to_thread(child); flush_fp_to_thread(child);
/* get 64 bit FPR */ /* get 64 bit FPR */
...@@ -187,7 +185,6 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request, ...@@ -187,7 +185,6 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
if ((addr & 3) || (index > PT_FPSCR32)) if ((addr & 3) || (index > PT_FPSCR32))
break; break;
CHECK_FULL_REGS(child->thread.regs);
if (index < PT_FPR0) { if (index < PT_FPR0) {
ret = ptrace_put_reg(child, index, data); ret = ptrace_put_reg(child, index, data);
} else { } else {
...@@ -226,7 +223,6 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request, ...@@ -226,7 +223,6 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
*/ */
if ((addr & 3) || (numReg > PT_FPSCR)) if ((addr & 3) || (numReg > PT_FPSCR))
break; break;
CHECK_FULL_REGS(child->thread.regs);
if (numReg < PT_FPR0) { if (numReg < PT_FPR0) {
unsigned long freg; unsigned long freg;
ret = ptrace_get_reg(child, numReg, &freg); ret = ptrace_get_reg(child, numReg, &freg);
......
...@@ -94,8 +94,6 @@ __unsafe_save_general_regs(struct pt_regs *regs, struct mcontext __user *frame) ...@@ -94,8 +94,6 @@ __unsafe_save_general_regs(struct pt_regs *regs, struct mcontext __user *frame)
elf_greg_t64 *gregs = (elf_greg_t64 *)regs; elf_greg_t64 *gregs = (elf_greg_t64 *)regs;
int val, i; int val, i;
WARN_ON(!FULL_REGS(regs));
for (i = 0; i <= PT_RESULT; i ++) { for (i = 0; i <= PT_RESULT; i ++) {
/* Force usr to alway see softe as 1 (interrupts enabled) */ /* Force usr to alway see softe as 1 (interrupts enabled) */
if (i == PT_SOFTE) if (i == PT_SOFTE)
...@@ -147,7 +145,6 @@ __unsafe_restore_general_regs(struct pt_regs *regs, struct mcontext __user *sr) ...@@ -147,7 +145,6 @@ __unsafe_restore_general_regs(struct pt_regs *regs, struct mcontext __user *sr)
static __always_inline int static __always_inline int
__unsafe_save_general_regs(struct pt_regs *regs, struct mcontext __user *frame) __unsafe_save_general_regs(struct pt_regs *regs, struct mcontext __user *frame)
{ {
WARN_ON(!FULL_REGS(regs));
unsafe_copy_to_user(&frame->mc_gregs, regs, GP_REGS_SIZE, failed); unsafe_copy_to_user(&frame->mc_gregs, regs, GP_REGS_SIZE, failed);
return 0; return 0;
......
...@@ -172,7 +172,6 @@ static long notrace __unsafe_setup_sigcontext(struct sigcontext __user *sc, ...@@ -172,7 +172,6 @@ static long notrace __unsafe_setup_sigcontext(struct sigcontext __user *sc,
} }
#endif /* CONFIG_VSX */ #endif /* CONFIG_VSX */
unsafe_put_user(&sc->gp_regs, &sc->regs, efault_out); unsafe_put_user(&sc->gp_regs, &sc->regs, efault_out);
WARN_ON(!FULL_REGS(regs));
unsafe_copy_to_user(&sc->gp_regs, regs, GP_REGS_SIZE, efault_out); unsafe_copy_to_user(&sc->gp_regs, regs, GP_REGS_SIZE, efault_out);
unsafe_put_user(msr, &sc->gp_regs[PT_MSR], efault_out); unsafe_put_user(msr, &sc->gp_regs[PT_MSR], efault_out);
unsafe_put_user(softe, &sc->gp_regs[PT_SOFTE], efault_out); unsafe_put_user(softe, &sc->gp_regs[PT_SOFTE], efault_out);
...@@ -309,7 +308,6 @@ static long setup_tm_sigcontexts(struct sigcontext __user *sc, ...@@ -309,7 +308,6 @@ static long setup_tm_sigcontexts(struct sigcontext __user *sc,
err |= __put_user(&sc->gp_regs, &sc->regs); err |= __put_user(&sc->gp_regs, &sc->regs);
err |= __put_user(&tm_sc->gp_regs, &tm_sc->regs); err |= __put_user(&tm_sc->gp_regs, &tm_sc->regs);
WARN_ON(!FULL_REGS(regs));
err |= __copy_to_user(&tm_sc->gp_regs, regs, GP_REGS_SIZE); err |= __copy_to_user(&tm_sc->gp_regs, regs, GP_REGS_SIZE);
err |= __copy_to_user(&sc->gp_regs, err |= __copy_to_user(&sc->gp_regs,
&tsk->thread.ckpt_regs, GP_REGS_SIZE); &tsk->thread.ckpt_regs, GP_REGS_SIZE);
......
...@@ -1318,7 +1318,6 @@ static int emulate_instruction(struct pt_regs *regs) ...@@ -1318,7 +1318,6 @@ static int emulate_instruction(struct pt_regs *regs)
if (!user_mode(regs)) if (!user_mode(regs))
return -EINVAL; return -EINVAL;
CHECK_FULL_REGS(regs);
if (get_user(instword, (u32 __user *)(regs->nip))) if (get_user(instword, (u32 __user *)(regs->nip)))
return -EFAULT; return -EFAULT;
......
...@@ -1401,10 +1401,6 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs, ...@@ -1401,10 +1401,6 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
break; break;
} }
/* Following cases refer to regs->gpr[], so we need all regs */
if (!FULL_REGS(regs))
return -1;
rd = (word >> 21) & 0x1f; rd = (word >> 21) & 0x1f;
ra = (word >> 16) & 0x1f; ra = (word >> 16) & 0x1f;
rb = (word >> 11) & 0x1f; rb = (word >> 11) & 0x1f;
......
...@@ -1815,25 +1815,16 @@ static void prregs(struct pt_regs *fp) ...@@ -1815,25 +1815,16 @@ static void prregs(struct pt_regs *fp)
} }
#ifdef CONFIG_PPC64 #ifdef CONFIG_PPC64
if (FULL_REGS(fp)) { #define R_PER_LINE 2
for (n = 0; n < 16; ++n)
printf("R%.2d = "REG" R%.2d = "REG"\n",
n, fp->gpr[n], n+16, fp->gpr[n+16]);
} else {
for (n = 0; n < 7; ++n)
printf("R%.2d = "REG" R%.2d = "REG"\n",
n, fp->gpr[n], n+7, fp->gpr[n+7]);
}
#else #else
#define R_PER_LINE 4
#endif
for (n = 0; n < 32; ++n) { for (n = 0; n < 32; ++n) {
printf("R%.2d = %.8lx%s", n, fp->gpr[n], printf("R%.2d = "REG"%s", n, fp->gpr[n],
(n & 3) == 3? "\n": " "); (n % R_PER_LINE) == R_PER_LINE - 1 ? "\n" : " ");
if (n == 12 && !FULL_REGS(fp)) {
printf("\n");
break;
}
} }
#endif
printf("pc = "); printf("pc = ");
xmon_print_symbol(fp->nip, " ", "\n"); xmon_print_symbol(fp->nip, " ", "\n");
if (!trap_is_syscall(fp) && cpu_has_feature(CPU_FTR_CFAR)) { if (!trap_is_syscall(fp) && cpu_has_feature(CPU_FTR_CFAR)) {
......
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