Skip to content

Commit

Permalink
powerpc/64s: system call support for scv/rfscv instructions
Browse files Browse the repository at this point in the history
Add support for the scv instruction on POWER9 and later CPUs.

For now this implements the zeroth scv vector 'scv 0', as identical to
'sc' system calls, with the exception that LR is not preserved, nor
are volatile CR registers, and error is not indicated with CR0[SO],
but by returning a negative errno.

rfscv is implemented to return from scv type system calls. It can not
be used to return from sc system calls because those are defined to
preserve LR.

getpid syscall throughput on POWER9 is improved by 26% (428 to 318
cycles), largely due to reducing mtmsr and mtspr.

Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
[mpe: Fix ppc64e build]
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/20200611081203.995112-3-npiggin@gmail.com
  • Loading branch information
npiggin authored and mpe committed Jul 22, 2020
1 parent b2dc297 commit 7fa95f9
Show file tree
Hide file tree
Showing 20 changed files with 421 additions and 44 deletions.
42 changes: 30 additions & 12 deletions Documentation/powerpc/syscall64-abi.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,23 +5,39 @@ Power Architecture 64-bit Linux system call ABI
syscall
=======

Invocation
----------
The syscall is made with the sc instruction, and returns with execution
continuing at the instruction following the sc instruction.

If PPC_FEATURE2_SCV appears in the AT_HWCAP2 ELF auxiliary vector, the
scv 0 instruction is an alternative that may provide better performance,
with some differences to calling sequence.

syscall calling sequence\ [1]_ matches the Power Architecture 64-bit ELF ABI
specification C function calling sequence, including register preservation
rules, with the following differences.

.. [1] Some syscalls (typically low-level management functions) may have
different calling sequences (e.g., rt_sigreturn).
Parameters and return value
---------------------------
Parameters
----------
The system call number is specified in r0.

There is a maximum of 6 integer parameters to a syscall, passed in r3-r8.

Both a return value and a return error code are returned. cr0.SO is the return
error code, and r3 is the return value or error code. When cr0.SO is clear,
the syscall succeeded and r3 is the return value. When cr0.SO is set, the
syscall failed and r3 is the error code that generally corresponds to errno.
Return value
------------
- For the sc instruction, both a value and an error condition are returned.
cr0.SO is the error condition, and r3 is the return value. When cr0.SO is
clear, the syscall succeeded and r3 is the return value. When cr0.SO is set,
the syscall failed and r3 is the error value (that normally corresponds to
errno).

- For the scv 0 instruction, the return value indicates failure if it is
-4095..-1 (i.e., it is >= -MAX_ERRNO (-4095) as an unsigned comparison),
in which case the error value is the negated return value.

Stack
-----
Expand All @@ -34,22 +50,23 @@ Register preservation rules match the ELF ABI calling sequence with the
following differences:

=========== ============= ========================================
--- For the sc instruction, differences with the ELF ABI ---
r0 Volatile (System call number.)
r3 Volatile (Parameter 1, and return value.)
r4-r8 Volatile (Parameters 2-6.)
cr0 Volatile (cr0.SO is the return error condition)
cr0 Volatile (cr0.SO is the return error condition.)
cr1, cr5-7 Nonvolatile
lr Nonvolatile

--- For the scv 0 instruction, differences with the ELF ABI ---
r0 Volatile (System call number.)
r3 Volatile (Parameter 1, and return value.)
r4-r8 Volatile (Parameters 2-6.)
=========== ============= ========================================

All floating point and vector data registers as well as control and status
registers are nonvolatile.

Invocation
----------
The syscall is performed with the sc instruction, and returns with execution
continuing at the instruction following the sc instruction.

Transactional Memory
--------------------
Syscall behavior can change if the processor is in transactional or suspended
Expand All @@ -75,6 +92,7 @@ auxiliary vector.
returning to the caller. This case is not well defined or supported, so this
behavior should not be relied upon.

scv 0 syscalls will always behave as PPC_FEATURE2_HTM_NOSC.

vsyscall
========
Expand Down
2 changes: 1 addition & 1 deletion arch/powerpc/include/asm/asm-prototypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ unsigned long __init early_init(unsigned long dt_ptr);
void __init machine_init(u64 dt_ptr);
#endif
long system_call_exception(long r3, long r4, long r5, long r6, long r7, long r8, unsigned long r0, struct pt_regs *regs);
notrace unsigned long syscall_exit_prepare(unsigned long r3, struct pt_regs *regs);
notrace unsigned long syscall_exit_prepare(unsigned long r3, struct pt_regs *regs, long scv);
notrace unsigned long interrupt_exit_user_prepare(struct pt_regs *regs, unsigned long msr);
notrace unsigned long interrupt_exit_kernel_prepare(struct pt_regs *regs, unsigned long msr);

Expand Down
6 changes: 6 additions & 0 deletions arch/powerpc/include/asm/exception-64s.h
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,12 @@
hrfid; \
b hrfi_flush_fallback

#define RFSCV_TO_USER \
STF_EXIT_BARRIER_SLOT; \
RFI_FLUSH_SLOT; \
RFSCV; \
b rfscv_flush_fallback

#endif /* __ASSEMBLY__ */

#endif /* _ASM_POWERPC_EXCEPTION_H */
2 changes: 1 addition & 1 deletion arch/powerpc/include/asm/head-64.h
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ end_##sname:
.if ((start) % (size) != 0); \
.error "Fixed section exception vector misalignment"; \
.endif; \
.if ((size) != 0x20) && ((size) != 0x80) && ((size) != 0x100); \
.if ((size) != 0x20) && ((size) != 0x80) && ((size) != 0x100) && ((size) != 0x1000); \
.error "Fixed section exception vector bad size"; \
.endif; \
.if (start) < sname##_start; \
Expand Down
2 changes: 2 additions & 0 deletions arch/powerpc/include/asm/ppc_asm.h
Original file line number Diff line number Diff line change
Expand Up @@ -755,6 +755,8 @@ END_FTR_SECTION_NESTED(CPU_FTR_CELL_TB_BUG, CPU_FTR_CELL_TB_BUG, 96)
#define N_SLINE 68
#define N_SO 100

#define RFSCV .long 0x4c0000a4

/*
* Create an endian fixup trampoline
*
Expand Down
7 changes: 6 additions & 1 deletion arch/powerpc/include/asm/ptrace.h
Original file line number Diff line number Diff line change
Expand Up @@ -222,9 +222,14 @@ static inline void set_trap(struct pt_regs *regs, unsigned long val)
regs->trap = (regs->trap & TRAP_FLAGS_MASK) | (val & ~TRAP_FLAGS_MASK);
}

static inline bool trap_is_scv(struct pt_regs *regs)
{
return (IS_ENABLED(CONFIG_PPC_BOOK3S_64) && TRAP(regs) == 0x3000);
}

static inline bool trap_is_syscall(struct pt_regs *regs)
{
return TRAP(regs) == 0xc00;
return (trap_is_scv(regs) || TRAP(regs) == 0xc00);
}

static inline bool trap_norestart(struct pt_regs *regs)
Expand Down
4 changes: 2 additions & 2 deletions arch/powerpc/include/asm/setup.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,12 @@ void setup_panic(void);
#define ARCH_PANIC_TIMEOUT 180

#ifdef CONFIG_PPC_PSERIES
extern void pseries_enable_reloc_on_exc(void);
extern bool pseries_enable_reloc_on_exc(void);
extern void pseries_disable_reloc_on_exc(void);
extern void pseries_big_endian_exceptions(void);
extern void pseries_little_endian_exceptions(void);
#else
static inline void pseries_enable_reloc_on_exc(void) {}
static inline bool pseries_enable_reloc_on_exc(void) { return false; }
static inline void pseries_disable_reloc_on_exc(void) {}
static inline void pseries_big_endian_exceptions(void) {}
static inline void pseries_little_endian_exceptions(void) {}
Expand Down
1 change: 1 addition & 0 deletions arch/powerpc/include/asm/sstep.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ enum instruction_type {
CACHEOP,
BARRIER,
SYSCALL,
SYSCALL_VECTORED_0,
MFMSR,
MTMSR,
RFI,
Expand Down
10 changes: 8 additions & 2 deletions arch/powerpc/kernel/cpu_setup_power.S
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ _GLOBAL(__setup_cpu_power10)

_GLOBAL(__setup_cpu_power9)
mflr r11
bl __init_FSCR
bl __init_FSCR_power9
1: bl __init_PMU
bl __init_hvmode_206
mtlr r11
Expand Down Expand Up @@ -128,7 +128,7 @@ _GLOBAL(__restore_cpu_power10)

_GLOBAL(__restore_cpu_power9)
mflr r11
bl __init_FSCR
bl __init_FSCR_power9
1: bl __init_PMU
mfmsr r3
rldicl. r0,r3,4,63
Expand Down Expand Up @@ -198,6 +198,12 @@ __init_FSCR_power10:
mtspr SPRN_FSCR, r3
// fall through

__init_FSCR_power9:
mfspr r3, SPRN_FSCR
ori r3, r3, FSCR_SCV
mtspr SPRN_FSCR, r3
// fall through

__init_FSCR:
mfspr r3,SPRN_FSCR
ori r3,r3,FSCR_TAR|FSCR_EBB
Expand Down
3 changes: 2 additions & 1 deletion arch/powerpc/kernel/cputable.c
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,8 @@ extern void __restore_cpu_e6500(void);
#define COMMON_USER2_POWER9 (COMMON_USER2_POWER8 | \
PPC_FEATURE2_ARCH_3_00 | \
PPC_FEATURE2_HAS_IEEE128 | \
PPC_FEATURE2_DARN )
PPC_FEATURE2_DARN | \
PPC_FEATURE2_SCV)
#define COMMON_USER_POWER10 COMMON_USER_POWER9
#define COMMON_USER2_POWER10 (COMMON_USER2_POWER9 | \
PPC_FEATURE2_ARCH_3_1 | \
Expand Down
1 change: 1 addition & 0 deletions arch/powerpc/kernel/dt_cpu_ftrs.c
Original file line number Diff line number Diff line change
Expand Up @@ -587,6 +587,7 @@ static struct dt_cpu_feature_match __initdata
{"little-endian", feat_enable_le, CPU_FTR_REAL_LE},
{"smt", feat_enable_smt, 0},
{"interrupt-facilities", feat_enable, 0},
{"system-call-vectored", feat_enable, 0},
{"timer-facilities", feat_enable, 0},
{"timer-facilities-v3", feat_enable, 0},
{"debug-facilities", feat_enable, 0},
Expand Down
Loading

0 comments on commit 7fa95f9

Please sign in to comment.