Skip to content

Commit

Permalink
Merge tag 's390-5.5-2' of git://git.kernel.org/pub/scm/linux/kernel/g…
Browse files Browse the repository at this point in the history
…it/s390/linux

Pull more s390 updates from Vasily Gorbik:

 - Make stack unwinder reliable and suitable for livepatching. Add
   unwinder testing module.

 - Fixes for CALL_ON_STACK helper used for stack switching.

 - Fix unwinding from bpf code.

 - Fix getcpu and remove compat support in vdso code.

 - Fix address space control registers initialization.

 - Save KASLR offset for early dumps.

 - Handle new FILTERED_BY_HYPERVISOR reply code in crypto code.

 - Minor perf code cleanup and potential memory leak fix.

 - Add couple of error messages for corner cases during PCI device
   creation.

* tag 's390-5.5-2' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux: (33 commits)
  s390: remove compat vdso code
  s390/livepatch: Implement reliable stack tracing for the consistency model
  s390/unwind: add stack pointer alignment sanity checks
  s390/unwind: filter out unreliable bogus %r14
  s390/unwind: start unwinding from reliable state
  s390/test_unwind: add program check context tests
  s390/test_unwind: add irq context tests
  s390/test_unwind: print verbose unwinding results
  s390/test_unwind: add CALL_ON_STACK tests
  s390: fix register clobbering in CALL_ON_STACK
  s390/test_unwind: require that unwinding ended successfully
  s390/unwind: add a test for the internal API
  s390/unwind: always inline get_stack_pointer
  s390/pci: add error message on device number limit
  s390/pci: add error message for UID collision
  s390/cpum_sf: Check for SDBT and SDB consistency
  s390/cpum_sf: Use TEAR_REG macro consistantly
  s390/cpum_sf: Remove unnecessary check for pending SDBs
  s390/cpum_sf: Replace function name in debug statements
  s390/kaslr: store KASLR offset for early dumps
  ...
  • Loading branch information
Linus Torvalds committed Dec 3, 2019
2 parents 4d7048f + 2115fbf commit 01d1dff
Show file tree
Hide file tree
Showing 35 changed files with 627 additions and 768 deletions.
18 changes: 15 additions & 3 deletions arch/s390/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,7 @@ config S390
select HAVE_PERF_EVENTS
select HAVE_RCU_TABLE_FREE
select HAVE_REGS_AND_STACK_ACCESS_API
select HAVE_RELIABLE_STACKTRACE
select HAVE_RSEQ
select HAVE_SYSCALL_TRACEPOINTS
select HAVE_VIRT_CPU_ACCOUNTING
Expand Down Expand Up @@ -426,9 +427,6 @@ config COMPAT
(and some other stuff like libraries and such) is needed for
executing 31 bit applications. It is safe to say "Y".

config COMPAT_VDSO
def_bool COMPAT && !CC_IS_CLANG

config SYSVIPC_COMPAT
def_bool y if COMPAT && SYSVIPC

Expand Down Expand Up @@ -1018,3 +1016,17 @@ config S390_GUEST
the KVM hypervisor.

endmenu

menu "Selftests"

config S390_UNWIND_SELFTEST
def_tristate n
prompt "Test unwind functions"
help
This option enables s390 specific stack unwinder testing kernel
module. This option is not useful for distributions or general
kernels, but only for kernel developers working on architecture code.

Say N if you are unsure.

endmenu
1 change: 0 additions & 1 deletion arch/s390/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,6 @@ zfcpdump:

vdso_install:
$(Q)$(MAKE) $(build)=arch/$(ARCH)/kernel/vdso64 $@
$(Q)$(MAKE) $(build)=arch/$(ARCH)/kernel/vdso32 $@

archclean:
$(Q)$(MAKE) $(clean)=$(boot)
Expand Down
5 changes: 5 additions & 0 deletions arch/s390/boot/startup.c
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,11 @@ void startup_kernel(void)
handle_relocs(__kaslr_offset);

if (__kaslr_offset) {
/*
* Save KASLR offset for early dumps, before vmcore_info is set.
* Mark as uneven to distinguish from real vmcore_info pointer.
*/
S390_lowcore.vmcore_info = __kaslr_offset | 0x1UL;
/* Clear non-relocated kernel */
if (IS_ENABLED(CONFIG_KERNEL_UNCOMPRESSED))
memset(img, 0, vmlinux.image_size);
Expand Down
2 changes: 1 addition & 1 deletion arch/s390/include/asm/cpu_mf.h
Original file line number Diff line number Diff line change
Expand Up @@ -313,7 +313,7 @@ static inline unsigned long *trailer_entry_ptr(unsigned long v)
return (unsigned long *) ret;
}

/* Return if the entry in the sample data block table (sdbt)
/* Return true if the entry in the sample data block table (sdbt)
* is a link to the next sdbt */
static inline int is_link_entry(unsigned long *s)
{
Expand Down
7 changes: 7 additions & 0 deletions arch/s390/include/asm/perf_event.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

#include <linux/perf_event.h>
#include <linux/device.h>
#include <asm/stacktrace.h>

/* Per-CPU flags for PMU states */
#define PMU_F_RESERVED 0x1000
Expand Down Expand Up @@ -73,4 +74,10 @@ struct perf_sf_sde_regs {
#define SDB_FULL_BLOCKS(hwc) (SAMPL_FLAGS(hwc) & PERF_CPUM_SF_FULL_BLOCKS)
#define SAMPLE_FREQ_MODE(hwc) (SAMPL_FLAGS(hwc) & PERF_CPUM_SF_FREQ_MODE)

#define perf_arch_fetch_caller_regs(regs, __ip) do { \
(regs)->psw.addr = (__ip); \
(regs)->gprs[15] = (unsigned long)__builtin_frame_address(0) - \
offsetof(struct stack_frame, back_chain); \
} while (0)

#endif /* _ASM_S390_PERF_EVENT_H */
2 changes: 1 addition & 1 deletion arch/s390/include/asm/processor.h
Original file line number Diff line number Diff line change
Expand Up @@ -310,7 +310,7 @@ void enabled_wait(void);
/*
* Function to drop a processor into disabled wait state
*/
static inline void __noreturn disabled_wait(void)
static __always_inline void __noreturn disabled_wait(void)
{
psw_t psw;

Expand Down
36 changes: 30 additions & 6 deletions arch/s390/include/asm/stacktrace.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,12 @@ static inline bool on_stack(struct stack_info *info,
return addr >= info->begin && addr + len <= info->end;
}

static inline unsigned long get_stack_pointer(struct task_struct *task,
struct pt_regs *regs)
static __always_inline unsigned long get_stack_pointer(struct task_struct *task,
struct pt_regs *regs)
{
if (regs)
return (unsigned long) kernel_stack_pointer(regs);
if (!task || task == current)
if (task == current)
return current_stack_pointer();
return (unsigned long) task->thread.ksp;
}
Expand All @@ -62,6 +62,17 @@ struct stack_frame {
};
#endif

/*
* Unlike current_stack_pointer() which simply returns current value of %r15
* current_frame_address() returns function stack frame address, which matches
* %r15 upon function invocation. It may differ from %r15 later if function
* allocates stack for local variables or new stack frame to call other
* functions.
*/
#define current_frame_address() \
((unsigned long)__builtin_frame_address(0) - \
offsetof(struct stack_frame, back_chain))

#define CALL_ARGS_0() \
register unsigned long r2 asm("2")
#define CALL_ARGS_1(arg1) \
Expand Down Expand Up @@ -95,20 +106,33 @@ struct stack_frame {

#define CALL_ON_STACK(fn, stack, nr, args...) \
({ \
unsigned long frame = current_frame_address(); \
CALL_ARGS_##nr(args); \
unsigned long prev; \
\
asm volatile( \
" la %[_prev],0(15)\n" \
" la 15,0(%[_stack])\n" \
" stg %[_prev],%[_bc](15)\n" \
" lg 15,%[_stack]\n" \
" stg %[_frame],%[_bc](15)\n" \
" brasl 14,%[_fn]\n" \
" la 15,0(%[_prev])\n" \
: [_prev] "=&a" (prev), CALL_FMT_##nr \
[_stack] "a" (stack), \
[_stack] "R" (stack), \
[_bc] "i" (offsetof(struct stack_frame, back_chain)), \
[_frame] "d" (frame), \
[_fn] "X" (fn) : CALL_CLOBBER_##nr); \
r2; \
})

#define CALL_ON_STACK_NORETURN(fn, stack) \
({ \
asm volatile( \
" la 15,0(%[_stack])\n" \
" xc %[_bc](8,15),%[_bc](15)\n" \
" brasl 14,%[_fn]\n" \
::[_bc] "i" (offsetof(struct stack_frame, back_chain)), \
[_stack] "a" (stack), [_fn] "X" (fn)); \
BUG(); \
})

#endif /* _ASM_S390_STACKTRACE_H */
8 changes: 4 additions & 4 deletions arch/s390/include/asm/unwind.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ struct unwind_state {
struct task_struct *task;
struct pt_regs *regs;
unsigned long sp, ip;
bool reuse_sp;
int graph_idx;
bool reliable;
bool error;
Expand All @@ -59,10 +58,11 @@ static inline bool unwind_error(struct unwind_state *state)
static inline void unwind_start(struct unwind_state *state,
struct task_struct *task,
struct pt_regs *regs,
unsigned long sp)
unsigned long first_frame)
{
sp = sp ? : get_stack_pointer(task, regs);
__unwind_start(state, task, regs, sp);
task = task ?: current;
first_frame = first_frame ?: get_stack_pointer(task, regs);
__unwind_start(state, task, regs, first_frame);
}

static inline struct pt_regs *unwind_get_entry_regs(struct unwind_state *state)
Expand Down
13 changes: 11 additions & 2 deletions arch/s390/include/asm/vdso.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,17 @@ struct vdso_data {
struct vdso_per_cpu_data {
__u64 ectg_timer_base;
__u64 ectg_user_time;
__u32 cpu_nr;
__u32 node_id;
/*
* Note: node_id and cpu_nr must be at adjacent memory locations.
* VDSO userspace must read both values with a single instruction.
*/
union {
__u64 getcpu_val;
struct {
__u32 node_id;
__u32 cpu_nr;
};
};
};

extern struct vdso_data *vdso_data;
Expand Down
1 change: 0 additions & 1 deletion arch/s390/kernel/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -81,4 +81,3 @@ obj-$(CONFIG_TRACEPOINTS) += trace.o

# vdso
obj-y += vdso64/
obj-$(CONFIG_COMPAT_VDSO) += vdso32/
3 changes: 1 addition & 2 deletions arch/s390/kernel/asm-offsets.c
Original file line number Diff line number Diff line change
Expand Up @@ -78,8 +78,7 @@ int main(void)
OFFSET(__VDSO_TS_END, vdso_data, ts_end);
OFFSET(__VDSO_ECTG_BASE, vdso_per_cpu_data, ectg_timer_base);
OFFSET(__VDSO_ECTG_USER, vdso_per_cpu_data, ectg_user_time);
OFFSET(__VDSO_CPU_NR, vdso_per_cpu_data, cpu_nr);
OFFSET(__VDSO_NODE_ID, vdso_per_cpu_data, node_id);
OFFSET(__VDSO_GETCPU_VAL, vdso_per_cpu_data, getcpu_val);
BLANK();
/* constants used by the vdso */
DEFINE(__CLOCK_REALTIME, CLOCK_REALTIME);
Expand Down
7 changes: 4 additions & 3 deletions arch/s390/kernel/dumpstack.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ const char *stack_type_name(enum stack_type type)
return "unknown";
}
}
EXPORT_SYMBOL_GPL(stack_type_name);

static inline bool in_stack(unsigned long sp, struct stack_info *info,
enum stack_type type, unsigned long low,
Expand Down Expand Up @@ -93,7 +94,9 @@ int get_stack_info(unsigned long sp, struct task_struct *task,
if (!sp)
goto unknown;

task = task ? : current;
/* Sanity check: ABI requires SP to be aligned 8 bytes. */
if (sp & 0x7)
goto unknown;

/* Check per-task stack */
if (in_task_stack(sp, task, info))
Expand Down Expand Up @@ -128,8 +131,6 @@ void show_stack(struct task_struct *task, unsigned long *stack)
struct unwind_state state;

printk("Call Trace:\n");
if (!task)
task = current;
unwind_for_each_frame(&state, task, NULL, (unsigned long) stack)
printk(state.reliable ? " [<%016lx>] %pSR \n" :
"([<%016lx>] %pSR)\n",
Expand Down
2 changes: 1 addition & 1 deletion arch/s390/kernel/head64.S
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ ENTRY(startup_continue)
#
larl %r14,init_task
stg %r14,__LC_CURRENT
larl %r15,init_thread_union+THREAD_SIZE-STACK_FRAME_OVERHEAD
larl %r15,init_thread_union+THREAD_SIZE-STACK_FRAME_OVERHEAD-__PT_SIZE
#ifdef CONFIG_KASAN
brasl %r14,kasan_early_init
#endif
Expand Down
4 changes: 3 additions & 1 deletion arch/s390/kernel/machine_kexec.c
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,9 @@ static bool kdump_csum_valid(struct kimage *image)
#ifdef CONFIG_CRASH_DUMP
int rc;

preempt_disable();
rc = CALL_ON_STACK(do_start_kdump, S390_lowcore.nodat_stack, 1, image);
preempt_enable();
return rc == 0;
#else
return false;
Expand Down Expand Up @@ -254,10 +256,10 @@ void arch_crash_save_vmcoreinfo(void)
VMCOREINFO_SYMBOL(lowcore_ptr);
VMCOREINFO_SYMBOL(high_memory);
VMCOREINFO_LENGTH(lowcore_ptr, NR_CPUS);
mem_assign_absolute(S390_lowcore.vmcore_info, paddr_vmcoreinfo_note());
vmcoreinfo_append_str("SDMA=%lx\n", __sdma);
vmcoreinfo_append_str("EDMA=%lx\n", __edma);
vmcoreinfo_append_str("KERNELOFFSET=%lx\n", kaslr_offset());
mem_assign_absolute(S390_lowcore.vmcore_info, paddr_vmcoreinfo_note());
}

void machine_shutdown(void)
Expand Down
Loading

0 comments on commit 01d1dff

Please sign in to comment.