Commit a0872417 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull more s390 updates from Heiko Carstens:
 "This is mainly to decouple udelay() and arch_cpu_idle() and simplify
  both of them.

  Summary:

   - Always initialize kernel stack backchain when entering the kernel,
     so that unwinding works properly.

   - Fix stack unwinder test case to avoid rare interrupt stack
     corruption.

   - Simplify udelay() and just let it busy loop instead of implementing
     a complex logic.

   - arch_cpu_idle() cleanup.

   - Some other minor improvements"

* tag 's390-5.11-2' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux:
  s390/zcrypt: convert comma to semicolon
  s390/idle: allow arch_cpu_idle() to be kprobed
  s390/idle: remove raw_local_irq_save()/restore() from arch_cpu_idle()
  s390/idle: merge enabled_wait() and arch_cpu_idle()
  s390/delay: remove udelay_simple()
  s390/irq: select HAVE_IRQ_EXIT_ON_IRQ_STACK
  s390/delay: simplify udelay
  s390/test_unwind: use timer instead of udelay
  s390/test_unwind: fix CALL_ON_STACK tests
  s390: make calls to TRACE_IRQS_OFF/TRACE_IRQS_ON balanced
  s390: always clear kernel stack backchain before calling functions
parents 5ba836eb dfdc6e73
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -150,6 +150,7 @@ config S390
	select HAVE_FUTEX_CMPXCHG if FUTEX
	select HAVE_GCC_PLUGINS
	select HAVE_GENERIC_VDSO
	select HAVE_IRQ_EXIT_ON_IRQ_STACK
	select HAVE_KERNEL_BZIP2
	select HAVE_KERNEL_GZIP
	select HAVE_KERNEL_LZ4
+5 −7
Original line number Diff line number Diff line
@@ -13,14 +13,12 @@
#ifndef _S390_DELAY_H
#define _S390_DELAY_H

void udelay_enable(void);
void __ndelay(unsigned long long nsecs);
void __udelay(unsigned long long usecs);
void udelay_simple(unsigned long long usecs);
void __ndelay(unsigned long nsecs);
void __udelay(unsigned long usecs);
void __delay(unsigned long loops);

#define ndelay(n) __ndelay((unsigned long long) (n))
#define udelay(n) __udelay((unsigned long long) (n))
#define mdelay(n) __udelay((unsigned long long) (n) * 1000)
#define ndelay(n) __ndelay((unsigned long)(n))
#define udelay(n) __udelay((unsigned long)(n))
#define mdelay(n) __udelay((unsigned long)(n) * 1000)

#endif /* defined(_S390_DELAY_H) */
+0 −7
Original line number Diff line number Diff line
@@ -16,14 +16,12 @@

#define CIF_NOHZ_DELAY		2	/* delay HZ disable for a tick */
#define CIF_FPU			3	/* restore FPU registers */
#define CIF_IGNORE_IRQ		4	/* ignore interrupt (for udelay) */
#define CIF_ENABLED_WAIT	5	/* in enabled wait state */
#define CIF_MCCK_GUEST		6	/* machine check happening in guest */
#define CIF_DEDICATED_CPU	7	/* this CPU is dedicated */

#define _CIF_NOHZ_DELAY		BIT(CIF_NOHZ_DELAY)
#define _CIF_FPU		BIT(CIF_FPU)
#define _CIF_IGNORE_IRQ		BIT(CIF_IGNORE_IRQ)
#define _CIF_ENABLED_WAIT	BIT(CIF_ENABLED_WAIT)
#define _CIF_MCCK_GUEST		BIT(CIF_MCCK_GUEST)
#define _CIF_DEDICATED_CPU	BIT(CIF_DEDICATED_CPU)
@@ -292,11 +290,6 @@ static inline unsigned long __rewind_psw(psw_t psw, unsigned long ilc)
	return (psw.addr - ilc) & mask;
}

/*
 * Function to stop a processor until the next interrupt occurs
 */
void enabled_wait(void);

/*
 * Function to drop a processor into disabled wait state
 */
+6 −10
Original line number Diff line number Diff line
@@ -414,6 +414,7 @@ ENTRY(system_call)
	mvc	__PT_PSW(16,%r11),__LC_SVC_OLD_PSW
	mvc	__PT_INT_CODE(4,%r11),__LC_SVC_ILC
	stg	%r14,__PT_FLAGS(%r11)
	xc	__SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15)
	ENABLE_INTS
.Lsysc_do_svc:
	# clear user controlled register to prevent speculative use
@@ -430,7 +431,6 @@ ENTRY(system_call)
	jnl	.Lsysc_nr_ok
	slag	%r8,%r1,3
.Lsysc_nr_ok:
	xc	__SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15)
	stg	%r2,__PT_ORIG_GPR2(%r11)
	stg	%r7,STACK_FRAME_OVERHEAD(%r15)
	lg	%r9,0(%r8,%r10)			# get system call add.
@@ -699,8 +699,8 @@ ENTRY(pgm_check_handler)
	mvc	__THREAD_per_address(8,%r14),__LC_PER_ADDRESS
	mvc	__THREAD_per_cause(2,%r14),__LC_PER_CODE
	mvc	__THREAD_per_paid(1,%r14),__LC_PER_ACCESS_ID
6:	RESTORE_SM_CLEAR_PER
	xc	__SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15)
6:	xc	__SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15)
	RESTORE_SM_CLEAR_PER
	larl	%r1,pgm_check_table
	llgh	%r10,__PT_INT_CODE+2(%r11)
	nill	%r10,0x007f
@@ -731,8 +731,8 @@ ENTRY(pgm_check_handler)
# PER event in supervisor state, must be kprobes
#
.Lpgm_kprobe:
	RESTORE_SM_CLEAR_PER
	xc	__SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15)
	RESTORE_SM_CLEAR_PER
	lgr	%r2,%r11		# pass pointer to pt_regs
	brasl	%r14,do_per_trap
	j	.Lpgm_return
@@ -778,10 +778,8 @@ ENTRY(io_int_handler)
.Lio_skip_asce:
	mvc	__PT_INT_CODE(12,%r11),__LC_SUBCHANNEL_ID
	xc	__PT_FLAGS(8,%r11),__PT_FLAGS(%r11)
	TSTMSK	__LC_CPU_FLAGS,_CIF_IGNORE_IRQ
	jo	.Lio_restore
	TRACE_IRQS_OFF
	xc	__SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15)
	TRACE_IRQS_OFF
.Lio_loop:
	lgr	%r2,%r11		# pass pointer to pt_regs
	lghi	%r3,IO_INTERRUPT
@@ -966,10 +964,8 @@ ENTRY(ext_int_handler)
	mvc	__PT_INT_PARM(4,%r11),__LC_EXT_PARAMS
	mvc	__PT_INT_PARM_LONG(8,%r11),0(%r1)
	xc	__PT_FLAGS(8,%r11),__PT_FLAGS(%r11)
	TSTMSK	__LC_CPU_FLAGS,_CIF_IGNORE_IRQ
	jo	.Lio_restore
	TRACE_IRQS_OFF
	xc	__SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15)
	TRACE_IRQS_OFF
	lgr	%r2,%r11		# pass pointer to pt_regs
	lghi	%r3,EXT_INTERRUPT
	brasl	%r14,do_IRQ
+4 −14
Original line number Diff line number Diff line
@@ -9,7 +9,6 @@

#include <linux/kernel.h>
#include <linux/kernel_stat.h>
#include <linux/kprobes.h>
#include <linux/notifier.h>
#include <linux/init.h>
#include <linux/cpu.h>
@@ -21,22 +20,19 @@

static DEFINE_PER_CPU(struct s390_idle_data, s390_idle);

void enabled_wait(void)
void arch_cpu_idle(void)
{
	struct s390_idle_data *idle = this_cpu_ptr(&s390_idle);
	unsigned long long idle_time;
	unsigned long psw_mask, flags;

	unsigned long psw_mask;

	/* Wait for external, I/O or machine check interrupt. */
	psw_mask = PSW_KERNEL_BITS | PSW_MASK_WAIT | PSW_MASK_DAT |
		PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK;
	clear_cpu_flag(CIF_NOHZ_DELAY);

	raw_local_irq_save(flags);
	/* Call the assembler magic in entry.S */
	/* psw_idle() returns with interrupts disabled. */
	psw_idle(idle, psw_mask);
	raw_local_irq_restore(flags);

	/* Account time spent with enabled wait psw loaded as idle time. */
	raw_write_seqcount_begin(&idle->seqcount);
@@ -46,8 +42,8 @@ void enabled_wait(void)
	idle->idle_count++;
	account_idle_time(cputime_to_nsecs(idle_time));
	raw_write_seqcount_end(&idle->seqcount);
	raw_local_irq_enable();
}
NOKPROBE_SYMBOL(enabled_wait);

static ssize_t show_idle_count(struct device *dev,
				struct device_attribute *attr, char *buf)
@@ -120,12 +116,6 @@ void arch_cpu_idle_enter(void)
{
}

void arch_cpu_idle(void)
{
	enabled_wait();
	raw_local_irq_enable();
}

void arch_cpu_idle_exit(void)
{
}
Loading