]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
s390/irq/idle: Use stcke instead of stckf for time stamps
authorHeiko Carstens <hca@linux.ibm.com>
Wed, 13 May 2026 14:01:27 +0000 (16:01 +0200)
committerAlexander Gordeev <agordeev@linux.ibm.com>
Mon, 15 Jun 2026 14:33:40 +0000 (16:33 +0200)
The upcoming cpu idle time accounting rework involves comparing and
subtracting cross cpu time stamps. Time stamps created with the stckf
instruction monotonic with respect to the local cpu. For cross cpu
monotonic time stamps the slightly slower stcke instruction has to
be used [1].

Convert the idle time accounting relevant usages of stckf to stcke.

[1] Principles of Operation - Setting and Inspecting the Clock

Signed-off-by: Heiko Carstens <hca@linux.ibm.com>
Acked-by: Frederic Weisbecker <frederic@kernel.org>
Signed-off-by: Alexander Gordeev <agordeev@linux.ibm.com>
arch/s390/include/asm/idle.h
arch/s390/include/asm/lowcore.h
arch/s390/include/asm/vtime.h
arch/s390/kernel/entry.S
arch/s390/kernel/idle.c
arch/s390/kernel/irq.c
drivers/s390/cio/qdio_main.c
drivers/s390/cio/qdio_thinint.c

index e4ad09a22400b4d5c80d3efa2f1e4005af5e53e1..6963e92b60a1dba959a4efc02fdf1f371744d81b 100644 (file)
 #include <linux/percpu-defs.h>
 #include <linux/types.h>
 #include <linux/device.h>
+#include <asm/tod_types.h>
 
 struct s390_idle_data {
        bool          idle_dyntick;
        unsigned long idle_count;
        unsigned long idle_time;
-       unsigned long clock_idle_enter;
        unsigned long timer_idle_enter;
        unsigned long mt_cycles_enter[8];
+       union tod_clock clock_idle_enter;
 };
 
 DECLARE_PER_CPU(struct s390_idle_data, s390_idle);
index 50ffe75adeb477947357b90d22a809d703e76cbb..b7720484b2f72740ad0c22819f9c0cfa5484b646 100644 (file)
@@ -10,6 +10,7 @@
 #define _ASM_S390_LOWCORE_H
 
 #include <linux/types.h>
+#include <asm/tod_types.h>
 #include <asm/machine.h>
 #include <asm/ptrace.h>
 #include <asm/ctlreg.h>
@@ -125,8 +126,7 @@ struct lowcore {
        __u64   avg_steal_timer;                /* 0x0300 */
        __u64   last_update_timer;              /* 0x0308 */
        __u64   last_update_clock;              /* 0x0310 */
-       __u64   int_clock;                      /* 0x0318 */
-       __u8    pad_0x0320[0x0328-0x0320];      /* 0x0320 */
+       union tod_clock int_clock;              /* 0x0318 */
        __u64   clock_comparator;               /* 0x0328 */
        __u8    pad_0x0330[0x0340-0x0330];      /* 0x0330 */
 
index b1db75d14e9dc2145d0d557f7cbc9a688cd22deb..da116a93d3b6cd04901253524017a4f3fca4e5ca 100644 (file)
@@ -48,8 +48,8 @@ static inline void update_timer_idle(void)
         * The accounted CPU times will be subtracted again from steal_timer
         * when accumulated steal time is calculated in do_account_vtime().
         */
-       lc->steal_timer += idle->clock_idle_enter - lc->last_update_clock;
-       lc->last_update_clock = lc->int_clock;
+       lc->steal_timer += idle->clock_idle_enter.tod - lc->last_update_clock;
+       lc->last_update_clock = lc->int_clock.tod;
        lc->system_timer += lc->last_update_timer - idle->timer_idle_enter;
        lc->last_update_timer = lc->sys_enter_timer;
 }
index bb806d1ddae0164665fd287e56cfed1e897ed0d1..7147f3e51acec62f83aecb3d3ca2d90d68b16074 100644 (file)
@@ -379,7 +379,7 @@ SYM_CODE_END(pgm_check_handler)
 SYM_CODE_START(\name)
        STMG_LC %r8,%r15,__LC_SAVE_AREA
        GET_LC  %r13
-       stckf   __LC_INT_CLOCK(%r13)
+       stcke   __LC_INT_CLOCK(%r13)
        stpt    __LC_SYS_ENTER_TIMER(%r13)
        STBEAR  __LC_LAST_BREAK(%r13)
        BPOFF
index 4685d7c5bc5189e04691222c78c425537448bbe3..36020dffb86be2e2d93c877d0d192f684d6994a0 100644 (file)
@@ -26,7 +26,7 @@ void account_idle_time_irq(void)
        struct s390_idle_data *idle = this_cpu_ptr(&s390_idle);
        unsigned long idle_time;
 
-       idle_time = get_lowcore()->int_clock - idle->clock_idle_enter;
+       idle_time = get_lowcore()->int_clock.tod - idle->clock_idle_enter.tod;
 
        /* Account time spent with enabled wait psw loaded as idle time. */
        __atomic64_add(idle_time, &idle->idle_time);
@@ -49,7 +49,7 @@ void noinstr arch_cpu_idle(void)
        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();
+       store_tod_clock_ext(&idle->clock_idle_enter);
        idle->timer_idle_enter = get_cpu_timer();
        bpon();
        __load_psw_mask(psw_mask);
index d10a17e6531dae0d42fac6cd7ffef77f6cb2b131..24f44f4a3aac1bd8ea2359ca497036e39e6d7632 100644 (file)
@@ -103,9 +103,10 @@ static const struct irq_class irqclass_sub_desc[] = {
 
 static void do_IRQ(struct pt_regs *regs, int irq)
 {
-       if (tod_after_eq(get_lowcore()->int_clock,
-                        get_lowcore()->clock_comparator))
-               /* Serve timer interrupts first. */
+       struct lowcore *lc = get_lowcore();
+
+       /* Serve timer interrupts first */
+       if (tod_after_eq(lc->int_clock.tod, lc->clock_comparator))
                clock_comparator_work();
        generic_handle_irq(irq);
 }
index 7e594a800525ee987198aafe5d7e3f0a41dfbbcb..c1e09fa34e7745ec4467b65387c94b7aee666434 100644 (file)
@@ -695,7 +695,7 @@ static void qdio_int_handler_pci(struct qdio_irq *irq_ptr)
                return;
 
        qdio_deliver_irq(irq_ptr);
-       irq_ptr->last_data_irq_time = get_lowcore()->int_clock;
+       irq_ptr->last_data_irq_time = get_lowcore()->int_clock.tod;
 }
 
 static void qdio_handle_activate_check(struct qdio_irq *irq_ptr,
index 85ca8650adebf0a9c45a6c4e35b2b762fdc04ff2..e167aa75c3dff72037a6eb838cb459de80bc2546 100644 (file)
@@ -99,7 +99,7 @@ static inline u32 clear_shared_ind(void)
 static void tiqdio_thinint_handler(struct airq_struct *airq,
                                   struct tpi_info *tpi_info)
 {
-       u64 irq_time = get_lowcore()->int_clock;
+       u64 irq_time = get_lowcore()->int_clock.tod;
        u32 si_used = clear_shared_ind();
        struct qdio_irq *irq;