s390/idle: Rewrite psw_idle() in C
authorSven Schnelle <svens@linux.ibm.com>
Tue, 30 Apr 2024 14:29:59 +0000 (16:29 +0200)
committerAlexander Gordeev <agordeev@linux.ibm.com>
Tue, 14 May 2024 11:37:07 +0000 (13:37 +0200)
To ease maintenance and further enhancements, convert
the psw_idle() function to C.

Reviewed-by: Heiko Carstens <hca@linux.ibm.com>
Signed-off-by: Sven Schnelle <svens@linux.ibm.com>
Signed-off-by: Alexander Gordeev <agordeev@linux.ibm.com>
arch/s390/include/asm/processor.h
arch/s390/kernel/asm-offsets.c
arch/s390/kernel/entry.S
arch/s390/kernel/idle.c

index bbbdc5abe2b2ce618a66f8a6a7114d8ff404c50a..1e2fc6d6963c36cb868c6ba8fa7c1b11629a7e9e 100644 (file)
@@ -40,6 +40,7 @@
 #include <asm/setup.h>
 #include <asm/runtime_instr.h>
 #include <asm/irqflags.h>
+#include <asm/alternative.h>
 
 typedef long (*sys_call_ptr_t)(struct pt_regs *regs);
 
@@ -92,6 +93,14 @@ static inline void get_cpu_id(struct cpuid *ptr)
        asm volatile("stidp %0" : "=Q" (*ptr));
 }
 
+static __always_inline unsigned long get_cpu_timer(void)
+{
+       unsigned long timer;
+
+       asm volatile("stpt      %[timer]" : [timer] "=Q" (timer));
+       return timer;
+}
+
 void s390_adjust_jiffies(void);
 void s390_update_cpu_mhz(void);
 void cpu_detect_mhz_feature(void);
@@ -394,6 +403,11 @@ static __always_inline bool regs_irqs_disabled(struct pt_regs *regs)
        return arch_irqs_disabled_flags(regs->psw.mask);
 }
 
+static __always_inline void bpon(void)
+{
+       asm volatile(ALTERNATIVE("nop", ".insn  rrf,0xb2e80000,0,0,13,0", 82));
+}
+
 #endif /* __ASSEMBLY__ */
 
 #endif /* __ASM_S390_PROCESSOR_H */
index 2f65bca2f3f1c84f23df2f0d7dd9fc2f34c54c21..f55979f64d4996de797339bab62d0a90bde8fb06 100644 (file)
@@ -13,7 +13,6 @@
 #include <linux/purgatory.h>
 #include <linux/pgtable.h>
 #include <linux/ftrace.h>
-#include <asm/idle.h>
 #include <asm/gmap.h>
 #include <asm/stacktrace.h>
 
@@ -71,11 +70,6 @@ int main(void)
        OFFSET(__SFVDSO_RETURN_ADDRESS, stack_frame_vdso_wrapper, return_address);
        DEFINE(STACK_FRAME_VDSO_OVERHEAD, sizeof(struct stack_frame_vdso_wrapper));
        BLANK();
-       /* idle data offsets */
-       OFFSET(__CLOCK_IDLE_ENTER, s390_idle_data, clock_idle_enter);
-       OFFSET(__TIMER_IDLE_ENTER, s390_idle_data, timer_idle_enter);
-       OFFSET(__MT_CYCLES_ENTER, s390_idle_data, mt_cycles_enter);
-       BLANK();
        /* hardware defined lowcore locations 0x000 - 0x1ff */
        OFFSET(__LC_EXT_PARAMS, lowcore, ext_params);
        OFFSET(__LC_EXT_CPU_ADDR, lowcore, ext_cpu_addr);
index 6a1e0fbbaa15b325c898548afe1189905d4b0520..60cf917a7122d9a7da3c7f1b14ac6879304477d5 100644 (file)
@@ -440,29 +440,6 @@ SYM_CODE_END(\name)
 INT_HANDLER ext_int_handler,__LC_EXT_OLD_PSW,do_ext_irq
 INT_HANDLER io_int_handler,__LC_IO_OLD_PSW,do_io_irq
 
-/*
- * Load idle PSW.
- */
-SYM_FUNC_START(psw_idle)
-       stg     %r14,(__SF_GPRS+8*8)(%r15)
-       stg     %r3,__SF_EMPTY(%r15)
-       larl    %r1,psw_idle_exit
-       stg     %r1,__SF_EMPTY+8(%r15)
-       larl    %r1,smp_cpu_mtid
-       llgf    %r1,0(%r1)
-       ltgr    %r1,%r1
-       jz      .Lpsw_idle_stcctm
-       .insn   rsy,0xeb0000000017,%r1,5,__MT_CYCLES_ENTER(%r2)
-.Lpsw_idle_stcctm:
-       oi      __LC_CPU_FLAGS+7,_CIF_ENABLED_WAIT
-       BPON
-       stckf   __CLOCK_IDLE_ENTER(%r2)
-       stpt    __TIMER_IDLE_ENTER(%r2)
-       lpswe   __SF_EMPTY(%r15)
-SYM_INNER_LABEL(psw_idle_exit, SYM_L_GLOBAL)
-       BR_EX   %r14
-SYM_FUNC_END(psw_idle)
-
 /*
  * Machine check handler routines
  */
index e7239aaf428b0a6674e081940d1930592f191ece..af9c97c0ad73052327e15de68cd618d3bca1fc24 100644 (file)
@@ -57,9 +57,13 @@ void noinstr arch_cpu_idle(void)
        psw_mask = PSW_KERNEL_BITS | PSW_MASK_WAIT |
                   PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK;
        clear_cpu_flag(CIF_NOHZ_DELAY);
-
-       /* psw_idle() returns with interrupts disabled. */
-       psw_idle(idle, psw_mask);
+       set_cpu_flag(CIF_ENABLED_WAIT);
+       if (smp_cpu_mtid)
+               stcctm(MT_DIAG, smp_cpu_mtid, (u64 *)&idle->mt_cycles_enter);
+       idle->clock_idle_enter = get_tod_clock_fast();
+       idle->timer_idle_enter = get_cpu_timer();
+       bpon();
+       __load_psw_mask(psw_mask);
 }
 
 static ssize_t show_idle_count(struct device *dev,