mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-06 10:57:46 +00:00
powerpc/64: remove system call instruction emulation
emulate_step() instruction emulation including sc instruction emulation initially appeared in xmon. It was then moved into sstep.c where kprobes could use it too, and later hw_breakpoint and uprobes started to use it. Until uprobes, the only instruction emulation users were for kernel mode instructions. - xmon only steps / breaks on kernel addresses. - kprobes is kernel only. - hw_breakpoint only emulates kernel instructions, single steps user. At one point, there was support for the kernel to execute sc instructions, although that is long removed and it's not clear whether there were any in-tree users. So system call emulation is not required by the above users. uprobes uses emulate_step and it appears possible to emulate sc instruction in userspace. Userspace system call emulation is broken and it's not clear it ever worked well. The big complication is that userspace takes an interrupt to the kernel to emulate the instruction. The user->kernel interrupt sets up registers and interrupt stack frame expecting to return to userspace, then system call instruction emulation re-directs that stack frame to the kernel, early in the system call interrupt handler. This means the interrupt return code takes the kernel->kernel restore path, which does not restore everything as the system call interrupt handler would expect coming from userspace. regs->iamr appears to get lost for example, because the kernel->kernel return does not restore the user iamr. Accounting such as irqflags tracing and CPU accounting does not get flipped back to user mode as the system call handler expects, so those appear to enter the kernel twice without returning to userspace. These things may be individually fixable with various complication, but it is a big complexity for unclear real benefit. Furthermore, it is not possible to single step a system call instruction since it causes an interrupt. As such, a separate patch disables probing on system call instructions. This patch removes system call emulation and disables stepping system calls. Signed-off-by: Nicholas Piggin <npiggin@gmail.com> [minor commit log edit, and also get rid of '#ifdef CONFIG_PPC64'] Signed-off-by: Naveen N. Rao <naveen.n.rao@linux.vnet.ibm.com> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au> Link: https://lore.kernel.org/r/a412e3b3791ed83de18704c8d90f492e7a0049c0.1648648712.git.naveen.n.rao@linux.vnet.ibm.com
This commit is contained in:
parent
54cdacd7d3
commit
a553476c44
2 changed files with 10 additions and 46 deletions
|
@ -219,16 +219,6 @@ system_call_vectored common 0x3000
|
||||||
*/
|
*/
|
||||||
system_call_vectored sigill 0x7ff0
|
system_call_vectored sigill 0x7ff0
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Entered via kernel return set up by kernel/sstep.c, must match entry regs
|
|
||||||
*/
|
|
||||||
.globl system_call_vectored_emulate
|
|
||||||
system_call_vectored_emulate:
|
|
||||||
_ASM_NOKPROBE_SYMBOL(system_call_vectored_emulate)
|
|
||||||
li r10,IRQS_ALL_DISABLED
|
|
||||||
stb r10,PACAIRQSOFTMASK(r13)
|
|
||||||
b system_call_vectored_common
|
|
||||||
#endif /* CONFIG_PPC_BOOK3S */
|
#endif /* CONFIG_PPC_BOOK3S */
|
||||||
|
|
||||||
.balign IFETCH_ALIGN_BYTES
|
.balign IFETCH_ALIGN_BYTES
|
||||||
|
|
|
@ -15,9 +15,6 @@
|
||||||
#include <asm/cputable.h>
|
#include <asm/cputable.h>
|
||||||
#include <asm/disassemble.h>
|
#include <asm/disassemble.h>
|
||||||
|
|
||||||
extern char system_call_common[];
|
|
||||||
extern char system_call_vectored_emulate[];
|
|
||||||
|
|
||||||
#ifdef CONFIG_PPC64
|
#ifdef CONFIG_PPC64
|
||||||
/* Bits in SRR1 that are copied from MSR */
|
/* Bits in SRR1 that are copied from MSR */
|
||||||
#define MSR_MASK 0xffffffff87c0ffffUL
|
#define MSR_MASK 0xffffffff87c0ffffUL
|
||||||
|
@ -1376,7 +1373,6 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
|
||||||
if (branch_taken(word, regs, op))
|
if (branch_taken(word, regs, op))
|
||||||
op->type |= BRTAKEN;
|
op->type |= BRTAKEN;
|
||||||
return 1;
|
return 1;
|
||||||
#ifdef CONFIG_PPC64
|
|
||||||
case 17: /* sc */
|
case 17: /* sc */
|
||||||
if ((word & 0xfe2) == 2)
|
if ((word & 0xfe2) == 2)
|
||||||
op->type = SYSCALL;
|
op->type = SYSCALL;
|
||||||
|
@ -1388,7 +1384,6 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
|
||||||
} else
|
} else
|
||||||
op->type = UNKNOWN;
|
op->type = UNKNOWN;
|
||||||
return 0;
|
return 0;
|
||||||
#endif
|
|
||||||
case 18: /* b */
|
case 18: /* b */
|
||||||
op->type = BRANCH | BRTAKEN;
|
op->type = BRANCH | BRTAKEN;
|
||||||
imm = word & 0x03fffffc;
|
imm = word & 0x03fffffc;
|
||||||
|
@ -3643,43 +3638,22 @@ int emulate_step(struct pt_regs *regs, ppc_inst_t instr)
|
||||||
regs_set_return_msr(regs, (regs->msr & ~op.val) | (val & op.val));
|
regs_set_return_msr(regs, (regs->msr & ~op.val) | (val & op.val));
|
||||||
goto instr_done;
|
goto instr_done;
|
||||||
|
|
||||||
#ifdef CONFIG_PPC64
|
|
||||||
case SYSCALL: /* sc */
|
case SYSCALL: /* sc */
|
||||||
/*
|
/*
|
||||||
* N.B. this uses knowledge about how the syscall
|
* Per ISA v3.1, section 7.5.15 'Trace Interrupt', we can't
|
||||||
* entry code works. If that is changed, this will
|
* single step a system call instruction:
|
||||||
* need to be changed also.
|
*
|
||||||
|
* Successful completion for an instruction means that the
|
||||||
|
* instruction caused no other interrupt. Thus a Trace
|
||||||
|
* interrupt never occurs for a System Call or System Call
|
||||||
|
* Vectored instruction, or for a Trap instruction that
|
||||||
|
* traps.
|
||||||
*/
|
*/
|
||||||
if (IS_ENABLED(CONFIG_PPC_FAST_ENDIAN_SWITCH) &&
|
return -1;
|
||||||
cpu_has_feature(CPU_FTR_REAL_LE) &&
|
|
||||||
regs->gpr[0] == 0x1ebe) {
|
|
||||||
regs_set_return_msr(regs, regs->msr ^ MSR_LE);
|
|
||||||
goto instr_done;
|
|
||||||
}
|
|
||||||
regs->gpr[9] = regs->gpr[13];
|
|
||||||
regs->gpr[10] = MSR_KERNEL;
|
|
||||||
regs->gpr[11] = regs->nip + 4;
|
|
||||||
regs->gpr[12] = regs->msr & MSR_MASK;
|
|
||||||
regs->gpr[13] = (unsigned long) get_paca();
|
|
||||||
regs_set_return_ip(regs, (unsigned long) &system_call_common);
|
|
||||||
regs_set_return_msr(regs, MSR_KERNEL);
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
#ifdef CONFIG_PPC_BOOK3S_64
|
|
||||||
case SYSCALL_VECTORED_0: /* scv 0 */
|
case SYSCALL_VECTORED_0: /* scv 0 */
|
||||||
regs->gpr[9] = regs->gpr[13];
|
return -1;
|
||||||
regs->gpr[10] = MSR_KERNEL;
|
|
||||||
regs->gpr[11] = regs->nip + 4;
|
|
||||||
regs->gpr[12] = regs->msr & MSR_MASK;
|
|
||||||
regs->gpr[13] = (unsigned long) get_paca();
|
|
||||||
regs_set_return_ip(regs, (unsigned long) &system_call_vectored_emulate);
|
|
||||||
regs_set_return_msr(regs, MSR_KERNEL);
|
|
||||||
return 1;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
case RFI:
|
case RFI:
|
||||||
return -1;
|
return -1;
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue