From 9365965db0c7ca7fc81eee27c21d8522d7102c32 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Fri, 4 Dec 2020 17:56:57 +0100 Subject: s390: always clear kernel stack backchain before calling functions Clear the kernel stack backchain before potentially calling the lockdep trace_hardirqs_off/on functions. Without this walking the kernel backchain, e.g. during a panic, might stop too early. Signed-off-by: Heiko Carstens --- arch/s390/kernel/entry.S | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'arch') diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S index 8bb9ebb71c4b..aa445203f5a5 100644 --- a/arch/s390/kernel/entry.S +++ b/arch/s390/kernel/entry.S @@ -413,6 +413,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 @@ -429,7 +430,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. @@ -698,8 +698,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 @@ -730,8 +730,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 @@ -777,10 +777,10 @@ ENTRY(io_int_handler) .Lio_skip_asce: mvc __PT_INT_CODE(12,%r11),__LC_SUBCHANNEL_ID xc __PT_FLAGS(8,%r11),__PT_FLAGS(%r11) + xc __SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15) TSTMSK __LC_CPU_FLAGS,_CIF_IGNORE_IRQ jo .Lio_restore TRACE_IRQS_OFF - xc __SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15) .Lio_loop: lgr %r2,%r11 # pass pointer to pt_regs lghi %r3,IO_INTERRUPT @@ -965,10 +965,10 @@ 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) + xc __SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15) TSTMSK __LC_CPU_FLAGS,_CIF_IGNORE_IRQ jo .Lio_restore TRACE_IRQS_OFF - xc __SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15) lgr %r2,%r11 # pass pointer to pt_regs lghi %r3,EXT_INTERRUPT brasl %r14,do_IRQ -- cgit v1.2.3 From f0c7cf13a3d77b3c6071ab179b583435847747e9 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Fri, 4 Dec 2020 18:01:22 +0100 Subject: s390: make calls to TRACE_IRQS_OFF/TRACE_IRQS_ON balanced In case of udelay CIF_IGNORE_IRQ is set. This leads to an unbalanced call of TRACE_IRQS_OFF and TRACE_IRQS_ON. That is: from lockdep's point of view TRACE_IRQS_ON is called one time too often. This doesn't fix any real bug, just makes the calls balanced. Signed-off-by: Heiko Carstens --- arch/s390/kernel/entry.S | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S index aa445203f5a5..2cc338aa3f65 100644 --- a/arch/s390/kernel/entry.S +++ b/arch/s390/kernel/entry.S @@ -778,9 +778,9 @@ ENTRY(io_int_handler) mvc __PT_INT_CODE(12,%r11),__LC_SUBCHANNEL_ID xc __PT_FLAGS(8,%r11),__PT_FLAGS(%r11) xc __SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15) + TRACE_IRQS_OFF TSTMSK __LC_CPU_FLAGS,_CIF_IGNORE_IRQ jo .Lio_restore - TRACE_IRQS_OFF .Lio_loop: lgr %r2,%r11 # pass pointer to pt_regs lghi %r3,IO_INTERRUPT @@ -966,9 +966,9 @@ ENTRY(ext_int_handler) mvc __PT_INT_PARM_LONG(8,%r11),0(%r1) xc __PT_FLAGS(8,%r11),__PT_FLAGS(%r11) xc __SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15) + TRACE_IRQS_OFF TSTMSK __LC_CPU_FLAGS,_CIF_IGNORE_IRQ jo .Lio_restore - TRACE_IRQS_OFF lgr %r2,%r11 # pass pointer to pt_regs lghi %r3,EXT_INTERRUPT brasl %r14,do_IRQ -- cgit v1.2.3 From f22b9c219a798e1bf11110a3d2733d883e6da059 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Sun, 13 Dec 2020 18:05:56 +0100 Subject: s390/test_unwind: fix CALL_ON_STACK tests The CALL_ON_STACK tests use the no_dat stack to switch to a different stack for unwinding tests. If an interrupt or machine check happens while using that stack, and previously being on the async stack, the interrupt / machine check entry code (SWITCH_ASYNC) will assume that the previous context did not use the async stack and happily use the async stack again. This will lead to stack corruption of the previous context. To solve this disable both interrupts and machine checks before switching to the no_dat stack. Fixes: 7868249fbbc8 ("s390/test_unwind: add CALL_ON_STACK tests") Signed-off-by: Heiko Carstens --- arch/s390/lib/test_unwind.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/s390/lib/test_unwind.c b/arch/s390/lib/test_unwind.c index 7c988994931f..6bad84c372dc 100644 --- a/arch/s390/lib/test_unwind.c +++ b/arch/s390/lib/test_unwind.c @@ -205,12 +205,15 @@ static noinline int unwindme_func3(struct unwindme *u) /* This function must appear in the backtrace. */ static noinline int unwindme_func2(struct unwindme *u) { + unsigned long flags; int rc; if (u->flags & UWM_SWITCH_STACK) { - preempt_disable(); + local_irq_save(flags); + local_mcck_disable(); rc = CALL_ON_STACK(unwindme_func3, S390_lowcore.nodat_stack, 1, u); - preempt_enable(); + local_mcck_enable(); + local_irq_restore(flags); return rc; } else { return unwindme_func3(u); -- cgit v1.2.3 From 91c2bad6aec98a51663ce9eec7c4825c1ca0b870 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Wed, 9 Dec 2020 22:09:16 +0100 Subject: s390/test_unwind: use timer instead of udelay Instead of registering an external interrupt handler and relying on the udelay implementation, simply use a timer to get into irq context. Acked-by: Ilya Leoshkevich Signed-off-by: Heiko Carstens --- arch/s390/lib/test_unwind.c | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) (limited to 'arch') diff --git a/arch/s390/lib/test_unwind.c b/arch/s390/lib/test_unwind.c index 6bad84c372dc..dcd8946255be 100644 --- a/arch/s390/lib/test_unwind.c +++ b/arch/s390/lib/test_unwind.c @@ -9,12 +9,12 @@ #include #include #include +#include #include #include #include #include #include -#include #define BT_BUF_SIZE (PAGE_SIZE * 4) @@ -226,31 +226,27 @@ static noinline int unwindme_func1(void *u) return unwindme_func2((struct unwindme *)u); } -static void unwindme_irq_handler(struct ext_code ext_code, - unsigned int param32, - unsigned long param64) +static void unwindme_timer_fn(struct timer_list *unused) { struct unwindme *u = READ_ONCE(unwindme); - if (u && u->task == current) { + if (u) { unwindme = NULL; u->task = NULL; u->ret = unwindme_func1(u); + complete(&u->task_ready); } } +static struct timer_list unwind_timer; + static int test_unwind_irq(struct unwindme *u) { - preempt_disable(); - if (register_external_irq(EXT_IRQ_CLK_COMP, unwindme_irq_handler)) { - pr_info("Couldn't register external interrupt handler"); - return -1; - } - u->task = current; unwindme = u; - udelay(1); - unregister_external_irq(EXT_IRQ_CLK_COMP, unwindme_irq_handler); - preempt_enable(); + init_completion(&u->task_ready); + timer_setup(&unwind_timer, unwindme_timer_fn, 0); + mod_timer(&unwind_timer, jiffies + 1); + wait_for_completion(&u->task_ready); return u->ret; } -- cgit v1.2.3 From dd6cfe553212b6311cac27ecd2f67621857fb10a Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Fri, 4 Dec 2020 12:32:42 +0100 Subject: s390/delay: simplify udelay udelay is implemented by using quite subtle details to make it possible to load an idle psw and waiting for an interrupt even in irq context or when interrupts are disabled. Also handling (or better: no handling) of softirqs is taken into account. All this is done to optimize for something which should in normal circumstances never happen: calling udelay to busy wait. Therefore get rid of the whole complexity and just busy loop like other architectures are doing it also. It could have been possible to use diag 0x44 instead of cpu_relax() in the busy loop, however we have seen too many bad things happen with diag 0x44 that it seems to be better to simply busy loop. Also note that with this new implementation kernel preemption does work when within the udelay loop. This did not work before. To get a feeling what the former code optimizes for: IPL'ing a kernel with 'defconfig' and afterwards compiling a kernel ends with a total of zero udelay calls. Signed-off-by: Heiko Carstens --- arch/s390/include/asm/delay.h | 12 ++--- arch/s390/include/asm/processor.h | 2 - arch/s390/kernel/entry.S | 4 -- arch/s390/lib/delay.c | 99 +++++++-------------------------------- 4 files changed, 23 insertions(+), 94 deletions(-) (limited to 'arch') diff --git a/arch/s390/include/asm/delay.h b/arch/s390/include/asm/delay.h index 4a08379cd1eb..b566be6f13f3 100644 --- a/arch/s390/include/asm/delay.h +++ b/arch/s390/include/asm/delay.h @@ -14,13 +14,13 @@ #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 udelay_simple(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) */ diff --git a/arch/s390/include/asm/processor.h b/arch/s390/include/asm/processor.h index 6b7269f51f83..85dfbb20467e 100644 --- a/arch/s390/include/asm/processor.h +++ b/arch/s390/include/asm/processor.h @@ -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) diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S index 2cc338aa3f65..87e83164c330 100644 --- a/arch/s390/kernel/entry.S +++ b/arch/s390/kernel/entry.S @@ -779,8 +779,6 @@ ENTRY(io_int_handler) xc __PT_FLAGS(8,%r11),__PT_FLAGS(%r11) xc __SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15) TRACE_IRQS_OFF - TSTMSK __LC_CPU_FLAGS,_CIF_IGNORE_IRQ - jo .Lio_restore .Lio_loop: lgr %r2,%r11 # pass pointer to pt_regs lghi %r3,IO_INTERRUPT @@ -967,8 +965,6 @@ ENTRY(ext_int_handler) xc __PT_FLAGS(8,%r11),__PT_FLAGS(%r11) xc __SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15) TRACE_IRQS_OFF - TSTMSK __LC_CPU_FLAGS,_CIF_IGNORE_IRQ - jo .Lio_restore lgr %r2,%r11 # pass pointer to pt_regs lghi %r3,EXT_INTERRUPT brasl %r14,do_IRQ diff --git a/arch/s390/lib/delay.c b/arch/s390/lib/delay.c index 68d61f2835df..928b1dbe182c 100644 --- a/arch/s390/lib/delay.c +++ b/arch/s390/lib/delay.c @@ -39,79 +39,24 @@ void __delay(unsigned long loops) } EXPORT_SYMBOL(__delay); -static void __udelay_disabled(unsigned long long usecs) +static void delay_loop(unsigned long delta, bool simple) { - unsigned long cr0, cr0_new, psw_mask; - struct s390_idle_data idle; - u64 end; + unsigned long end; - end = get_tod_clock() + (usecs << 12); - __ctl_store(cr0, 0, 0); - cr0_new = cr0 & ~CR0_IRQ_SUBCLASS_MASK; - cr0_new |= (1UL << (63 - 52)); /* enable clock comparator irq */ - __ctl_load(cr0_new, 0, 0); - psw_mask = __extract_psw() | PSW_MASK_EXT | PSW_MASK_WAIT; - set_clock_comparator(end); - set_cpu_flag(CIF_IGNORE_IRQ); - psw_idle(&idle, psw_mask); - trace_hardirqs_off(); - clear_cpu_flag(CIF_IGNORE_IRQ); - set_clock_comparator(S390_lowcore.clock_comparator); - __ctl_load(cr0, 0, 0); + if (static_branch_likely(&udelay_ready) && !simple) { + end = get_tod_clock_monotonic() + delta; + while (!tod_after(get_tod_clock_monotonic(), end)) + cpu_relax(); + } else { + end = get_tod_clock() + delta; + while (!tod_after(get_tod_clock(), end)) + cpu_relax(); + } } -static void __udelay_enabled(unsigned long long usecs) +void __udelay(unsigned long usecs) { - u64 clock_saved, end; - - end = get_tod_clock_fast() + (usecs << 12); - do { - clock_saved = 0; - if (tod_after(S390_lowcore.clock_comparator, end)) { - clock_saved = local_tick_disable(); - set_clock_comparator(end); - } - enabled_wait(); - if (clock_saved) - local_tick_enable(clock_saved); - } while (get_tod_clock_fast() < end); -} - -/* - * Waits for 'usecs' microseconds using the TOD clock comparator. - */ -void __udelay(unsigned long long usecs) -{ - unsigned long flags; - - if (!static_branch_likely(&udelay_ready)) { - udelay_simple(usecs); - return; - } - - preempt_disable(); - local_irq_save(flags); - if (in_irq()) { - __udelay_disabled(usecs); - goto out; - } - if (in_softirq()) { - if (raw_irqs_disabled_flags(flags)) - __udelay_disabled(usecs); - else - __udelay_enabled(usecs); - goto out; - } - if (raw_irqs_disabled_flags(flags)) { - local_bh_disable(); - __udelay_disabled(usecs); - _local_bh_enable(); - goto out; - } - __udelay_enabled(usecs); -out: - local_irq_restore(flags); - preempt_enable(); + delay_loop(usecs << 12, 0); } EXPORT_SYMBOL(__udelay); @@ -119,25 +64,15 @@ EXPORT_SYMBOL(__udelay); * Simple udelay variant. To be used on startup and reboot * when the interrupt handler isn't working. */ -void udelay_simple(unsigned long long usecs) +void udelay_simple(unsigned long usecs) { - u64 end; - - end = get_tod_clock_fast() + (usecs << 12); - while (get_tod_clock_fast() < end) - cpu_relax(); + delay_loop(usecs << 12, 1); } -void __ndelay(unsigned long long nsecs) +void __ndelay(unsigned long nsecs) { - u64 end; - nsecs <<= 9; do_div(nsecs, 125); - end = get_tod_clock_fast() + nsecs; - if (nsecs & ~0xfffUL) - __udelay(nsecs >> 12); - while (get_tod_clock_fast() < end) - barrier(); + delay_loop(nsecs, 0); } EXPORT_SYMBOL(__ndelay); -- cgit v1.2.3 From 9ceed9988a8e6a1656ed2bdaa30501cf0f3dd925 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Thu, 10 Dec 2020 22:30:09 +0100 Subject: s390/irq: select HAVE_IRQ_EXIT_ON_IRQ_STACK irq_exit() is always called on async stack. Therefore select HAVE_IRQ_EXIT_ON_IRQ_STACK and get a tiny optimization in invoke_softirq(). Signed-off-by: Heiko Carstens --- arch/s390/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'arch') diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig index a60cc523d810..9e8895cb9ee7 100644 --- a/arch/s390/Kconfig +++ b/arch/s390/Kconfig @@ -153,6 +153,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 -- cgit v1.2.3 From e0d62dcb20beac18a412ef9355208d9058c674d3 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Mon, 14 Dec 2020 21:44:39 +0100 Subject: s390/delay: remove udelay_simple() udelay_simple() callers can make use of the now simplified udelay() implementation. No need to keep it. Signed-off-by: Heiko Carstens --- arch/s390/include/asm/delay.h | 2 -- arch/s390/kernel/ipl.c | 2 +- arch/s390/kernel/setup.c | 1 - arch/s390/lib/delay.c | 34 ++++++---------------------------- drivers/s390/cio/device.c | 2 +- 5 files changed, 8 insertions(+), 33 deletions(-) (limited to 'arch') diff --git a/arch/s390/include/asm/delay.h b/arch/s390/include/asm/delay.h index b566be6f13f3..21a8fe18fe66 100644 --- a/arch/s390/include/asm/delay.h +++ b/arch/s390/include/asm/delay.h @@ -13,10 +13,8 @@ #ifndef _S390_DELAY_H #define _S390_DELAY_H -void udelay_enable(void); void __ndelay(unsigned long nsecs); void __udelay(unsigned long usecs); -void udelay_simple(unsigned long usecs); void __delay(unsigned long loops); #define ndelay(n) __ndelay((unsigned long)(n)) diff --git a/arch/s390/kernel/ipl.c b/arch/s390/kernel/ipl.c index 98b3aca1de8e..7a21eca498aa 100644 --- a/arch/s390/kernel/ipl.c +++ b/arch/s390/kernel/ipl.c @@ -1512,7 +1512,7 @@ static void diag308_dump(void *dump_block) while (1) { if (diag308(DIAG308_LOAD_NORMAL_DUMP, NULL) != 0x302) break; - udelay_simple(USEC_PER_SEC); + udelay(USEC_PER_SEC); } } diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c index 1f16a03be995..1fbed91c73bc 100644 --- a/arch/s390/kernel/setup.c +++ b/arch/s390/kernel/setup.c @@ -335,7 +335,6 @@ int __init arch_early_irq_init(void) if (!stack) panic("Couldn't allocate async stack"); S390_lowcore.async_stack = stack + STACK_INIT_OFFSET; - udelay_enable(); return 0; } diff --git a/arch/s390/lib/delay.c b/arch/s390/lib/delay.c index 928b1dbe182c..f289afeb3f31 100644 --- a/arch/s390/lib/delay.c +++ b/arch/s390/lib/delay.c @@ -19,13 +19,6 @@ #include #include -static DEFINE_STATIC_KEY_FALSE(udelay_ready); - -void __init udelay_enable(void) -{ - static_branch_enable(&udelay_ready); -} - void __delay(unsigned long loops) { /* @@ -39,40 +32,25 @@ void __delay(unsigned long loops) } EXPORT_SYMBOL(__delay); -static void delay_loop(unsigned long delta, bool simple) +static void delay_loop(unsigned long delta) { unsigned long end; - if (static_branch_likely(&udelay_ready) && !simple) { - end = get_tod_clock_monotonic() + delta; - while (!tod_after(get_tod_clock_monotonic(), end)) - cpu_relax(); - } else { - end = get_tod_clock() + delta; - while (!tod_after(get_tod_clock(), end)) - cpu_relax(); - } + end = get_tod_clock_monotonic() + delta; + while (!tod_after(get_tod_clock_monotonic(), end)) + cpu_relax(); } void __udelay(unsigned long usecs) { - delay_loop(usecs << 12, 0); + delay_loop(usecs << 12); } EXPORT_SYMBOL(__udelay); -/* - * Simple udelay variant. To be used on startup and reboot - * when the interrupt handler isn't working. - */ -void udelay_simple(unsigned long usecs) -{ - delay_loop(usecs << 12, 1); -} - void __ndelay(unsigned long nsecs) { nsecs <<= 9; do_div(nsecs, 125); - delay_loop(nsecs, 0); + delay_loop(nsecs); } EXPORT_SYMBOL(__ndelay); diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c index e0005a4fc978..9e3c8b4e7fa8 100644 --- a/drivers/s390/cio/device.c +++ b/drivers/s390/cio/device.c @@ -1668,7 +1668,7 @@ void ccw_device_wait_idle(struct ccw_device *cdev) cio_tsch(sch); if (sch->schib.scsw.cmd.actl == 0) break; - udelay_simple(100); + udelay(100); } } #endif -- cgit v1.2.3 From 44292c868473ed6389a78cfa366895b341845579 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Mon, 14 Dec 2020 22:33:39 +0100 Subject: s390/idle: merge enabled_wait() and arch_cpu_idle() The only caller of enabled_wait() besides arch_cpu_idle() was udelay(). Since that call doesn't exist anymore, merge enabled_wait() and arch_cpu_idle(). Signed-off-by: Heiko Carstens --- arch/s390/include/asm/processor.h | 5 ----- arch/s390/kernel/idle.c | 11 +++-------- 2 files changed, 3 insertions(+), 13 deletions(-) (limited to 'arch') diff --git a/arch/s390/include/asm/processor.h b/arch/s390/include/asm/processor.h index 85dfbb20467e..2058a435add4 100644 --- a/arch/s390/include/asm/processor.h +++ b/arch/s390/include/asm/processor.h @@ -290,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 */ diff --git a/arch/s390/kernel/idle.c b/arch/s390/kernel/idle.c index 2b85096964f8..bbf6b7d959c2 100644 --- a/arch/s390/kernel/idle.c +++ b/arch/s390/kernel/idle.c @@ -21,7 +21,7 @@ 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; @@ -46,8 +46,9 @@ 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); +NOKPROBE_SYMBOL(arch_cpu_idle); static ssize_t show_idle_count(struct device *dev, struct device_attribute *attr, char *buf) @@ -120,12 +121,6 @@ void arch_cpu_idle_enter(void) { } -void arch_cpu_idle(void) -{ - enabled_wait(); - raw_local_irq_enable(); -} - void arch_cpu_idle_exit(void) { } -- cgit v1.2.3 From 7494755a9ad62be7e389b535c77e85ed9c66bece Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Mon, 14 Dec 2020 22:36:03 +0100 Subject: s390/idle: remove raw_local_irq_save()/restore() from arch_cpu_idle() arch_cpu_idle() gets called with interrupts disabled, and psw_idle() returns with interrupts disabled. No reason to use raw_local_irq_save() / restore(). Signed-off-by: Heiko Carstens --- arch/s390/kernel/idle.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'arch') diff --git a/arch/s390/kernel/idle.c b/arch/s390/kernel/idle.c index bbf6b7d959c2..ae27e9fb5d94 100644 --- a/arch/s390/kernel/idle.c +++ b/arch/s390/kernel/idle.c @@ -25,18 +25,15 @@ 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); -- cgit v1.2.3 From 8d93b7011831edc42760aa5d2f0727edda7257d5 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Mon, 14 Dec 2020 22:39:01 +0100 Subject: s390/idle: allow arch_cpu_idle() to be kprobed Remove NOKPROBE_SYMBOL() for arch_cpu_idle(). This might have made sense when enabled_wait() (aka arch_cpu_idle()) was called from udelay. But now there shouldn't be a reason why s390 should be the only architecture which doesn't allow arch_cpu_idle() to be probed. Signed-off-by: Heiko Carstens --- arch/s390/kernel/idle.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'arch') diff --git a/arch/s390/kernel/idle.c b/arch/s390/kernel/idle.c index ae27e9fb5d94..a5d4d80d6ede 100644 --- a/arch/s390/kernel/idle.c +++ b/arch/s390/kernel/idle.c @@ -9,7 +9,6 @@ #include #include -#include #include #include #include @@ -45,7 +44,6 @@ void arch_cpu_idle(void) raw_write_seqcount_end(&idle->seqcount); raw_local_irq_enable(); } -NOKPROBE_SYMBOL(arch_cpu_idle); static ssize_t show_idle_count(struct device *dev, struct device_attribute *attr, char *buf) -- cgit v1.2.3