diff options
| author | Alexander Gordeev <agordeev@linux.ibm.com> | 2026-06-16 16:21:46 +0200 |
|---|---|---|
| committer | Alexander Gordeev <agordeev@linux.ibm.com> | 2026-06-16 16:21:46 +0200 |
| commit | 9fb519794ecb2af57eff63ad82fdfcaf12e7b4b4 (patch) | |
| tree | 8fc23c3158a062bd85cd1faac75cc1788e57ed9a | |
| parent | 25a01b5155d207e72bdd31b138406f37788403cb (diff) | |
| parent | 968ec3f960d013fc74d3a9bed3ae9ab9a44cb951 (diff) | |
| download | lwn-9fb519794ecb2af57eff63ad82fdfcaf12e7b4b4.tar.gz lwn-9fb519794ecb2af57eff63ad82fdfcaf12e7b4b4.zip | |
Merge branch 'idle-time-acc' into features
Heiko Carstens says:
===================
This is supposed to improve s390 idle time accounting, and brings it
back to the state it was before arch_cpu_idle_time() was removed from
s390 [3].
In result all cpu time accounting is done by the s390 architecture backend
again, instead of having a mix of architecure specific and common code
accounting (common code: idle, s390 architecture: everything else).
===================
Signed-off-by: Alexander Gordeev <agordeev@linux.ibm.com>
| -rw-r--r-- | arch/s390/include/asm/idle.h | 14 | ||||
| -rw-r--r-- | arch/s390/include/asm/lowcore.h | 4 | ||||
| -rw-r--r-- | arch/s390/include/asm/timex.h | 20 | ||||
| -rw-r--r-- | arch/s390/include/asm/tod_types.h | 30 | ||||
| -rw-r--r-- | arch/s390/include/asm/vtime.h | 4 | ||||
| -rw-r--r-- | arch/s390/kernel/asm-offsets.c | 7 | ||||
| -rw-r--r-- | arch/s390/kernel/entry.S | 14 | ||||
| -rw-r--r-- | arch/s390/kernel/idle.c | 125 | ||||
| -rw-r--r-- | arch/s390/kernel/irq.c | 7 | ||||
| -rw-r--r-- | arch/s390/kernel/smp.c | 33 | ||||
| -rw-r--r-- | arch/s390/kernel/vtime.c | 55 | ||||
| -rw-r--r-- | drivers/s390/cio/qdio_main.c | 2 | ||||
| -rw-r--r-- | drivers/s390/cio/qdio_thinint.c | 2 | ||||
| -rw-r--r-- | include/linux/kernel_stat.h | 27 | ||||
| -rw-r--r-- | include/linux/vtime.h | 6 | ||||
| -rw-r--r-- | kernel/sched/cputime.c | 4 |
16 files changed, 201 insertions, 153 deletions
diff --git a/arch/s390/include/asm/idle.h b/arch/s390/include/asm/idle.h index e4ad09a22400..07819f11987c 100644 --- a/arch/s390/include/asm/idle.h +++ b/arch/s390/include/asm/idle.h @@ -10,20 +10,18 @@ #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; +#ifdef CONFIG_NO_HZ_COMMON + bool in_idle; +#endif unsigned long timer_idle_enter; unsigned long mt_cycles_enter[8]; + union tod_clock clock_idle_enter; + union tod_clock clock_idle_exit; }; DECLARE_PER_CPU(struct s390_idle_data, s390_idle); -extern struct device_attribute dev_attr_idle_count; -extern struct device_attribute dev_attr_idle_time_us; - #endif /* _S390_IDLE_H */ diff --git a/arch/s390/include/asm/lowcore.h b/arch/s390/include/asm/lowcore.h index cd1ddfdb5d35..3b3ecc647993 100644 --- a/arch/s390/include/asm/lowcore.h +++ b/arch/s390/include/asm/lowcore.h @@ -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 */ diff --git a/arch/s390/include/asm/timex.h b/arch/s390/include/asm/timex.h index 49447b40f038..ac3ab6c29912 100644 --- a/arch/s390/include/asm/timex.h +++ b/arch/s390/include/asm/timex.h @@ -12,6 +12,7 @@ #include <linux/preempt.h> #include <linux/time64.h> +#include <asm/tod_types.h> #include <asm/lowcore.h> #include <asm/machine.h> #include <asm/asm.h> @@ -21,25 +22,6 @@ extern u64 clock_comparator_max; -union tod_clock { - __uint128_t val; - struct { - __uint128_t ei : 8; /* epoch index */ - __uint128_t tod : 64; /* bits 0-63 of tod clock */ - __uint128_t : 40; - __uint128_t pf : 16; /* programmable field */ - }; - struct { - __uint128_t eitod : 72; /* epoch index + bits 0-63 tod clock */ - __uint128_t : 56; - }; - struct { - __uint128_t us : 60; /* micro-seconds */ - __uint128_t sus : 12; /* sub-microseconds */ - __uint128_t : 56; - }; -} __packed; - /* Inline functions for clock register access. */ static inline int set_tod_clock(__u64 time) { diff --git a/arch/s390/include/asm/tod_types.h b/arch/s390/include/asm/tod_types.h new file mode 100644 index 000000000000..976fa0a1e895 --- /dev/null +++ b/arch/s390/include/asm/tod_types.h @@ -0,0 +1,30 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +#ifndef _ASM_S390_TOD_TYPES_H +#define _ASM_S390_TOD_TYPES_H + +#include <linux/types.h> + +#ifndef __ASSEMBLER__ + +union tod_clock { + __uint128_t val; + struct { + __uint128_t ei : 8; /* epoch index */ + __uint128_t tod : 64; /* bits 0-63 of tod clock */ + __uint128_t : 40; + __uint128_t pf : 16; /* programmable field */ + }; + struct { + __uint128_t eitod : 72; /* epoch index + bits 0-63 tod clock */ + __uint128_t : 56; + }; + struct { + __uint128_t us : 60; /* micro-seconds */ + __uint128_t sus : 12; /* sub-microseconds */ + __uint128_t : 56; + }; +} __packed; + +#endif +#endif diff --git a/arch/s390/include/asm/vtime.h b/arch/s390/include/asm/vtime.h index b1db75d14e9d..da116a93d3b6 100644 --- a/arch/s390/include/asm/vtime.h +++ b/arch/s390/include/asm/vtime.h @@ -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; } diff --git a/arch/s390/kernel/asm-offsets.c b/arch/s390/kernel/asm-offsets.c index fbd26f3e9f96..f6dd2b67dcee 100644 --- a/arch/s390/kernel/asm-offsets.c +++ b/arch/s390/kernel/asm-offsets.c @@ -11,9 +11,11 @@ #include <linux/purgatory.h> #include <linux/pgtable.h> #include <linux/ftrace_regs.h> +#include <linux/kernel_stat.h> #include <asm/kvm_host_types.h> #include <asm/stacktrace.h> #include <asm/ptrace.h> +#include <asm/idle.h> int main(void) { @@ -128,6 +130,7 @@ int main(void) OFFSET(__LC_LAST_UPDATE_CLOCK, lowcore, last_update_clock); OFFSET(__LC_INT_CLOCK, lowcore, int_clock); OFFSET(__LC_CURRENT, lowcore, current_task); + OFFSET(__LC_PERCPU_OFFSET, lowcore, percpu_offset); OFFSET(__LC_KERNEL_STACK, lowcore, kernel_stack); OFFSET(__LC_ASYNC_STACK, lowcore, async_stack); OFFSET(__LC_NODAT_STACK, lowcore, nodat_stack); @@ -180,6 +183,10 @@ int main(void) DEFINE(OLDMEM_SIZE, PARMAREA + offsetof(struct parmarea, oldmem_size)); DEFINE(COMMAND_LINE, PARMAREA + offsetof(struct parmarea, command_line)); DEFINE(MAX_COMMAND_LINE_SIZE, PARMAREA + offsetof(struct parmarea, max_command_line_size)); + OFFSET(__IDLE_CLOCK_EXIT, s390_idle_data, clock_idle_exit); +#ifdef CONFIG_NO_HZ_COMMON + OFFSET(__KCPUSTAT_SEQUENCE, kernel_cpustat, idle_sleeptime_seq); +#endif OFFSET(__FTRACE_REGS_PT_REGS, __arch_ftrace_regs, regs); DEFINE(__FTRACE_REGS_SIZE, sizeof(struct __arch_ftrace_regs)); diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S index bb806d1ddae0..79a45efae23d 100644 --- a/arch/s390/kernel/entry.S +++ b/arch/s390/kernel/entry.S @@ -379,8 +379,19 @@ 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) +#ifdef CONFIG_NO_HZ_COMMON + larl %r12,kernel_cpustat + ag %r12,__LC_PERCPU_OFFSET(%r13) + asi __KCPUSTAT_SEQUENCE(%r12),1 +#endif + stcke __LC_INT_CLOCK(%r13) stpt __LC_SYS_ENTER_TIMER(%r13) + larl %r10,s390_idle + ag %r10,__LC_PERCPU_OFFSET(%r13) + mvc __IDLE_CLOCK_EXIT(16,%r10),__LC_INT_CLOCK(%r13) +#ifdef CONFIG_NO_HZ_COMMON + asi __KCPUSTAT_SEQUENCE(%r12),1 +#endif STBEAR __LC_LAST_BREAK(%r13) BPOFF lmg %r8,%r9,\lc_old_psw(%r13) @@ -407,7 +418,6 @@ SYM_CODE_START(\name) xgr %r5,%r5 xgr %r6,%r6 xgr %r7,%r7 - xgr %r10,%r10 xgr %r12,%r12 xc __PT_FLAGS(8,%r11),__PT_FLAGS(%r11) mvc __PT_R8(64,%r11),__LC_SAVE_AREA(%r13) diff --git a/arch/s390/kernel/idle.c b/arch/s390/kernel/idle.c index 4685d7c5bc51..7f7851c001e0 100644 --- a/arch/s390/kernel/idle.c +++ b/arch/s390/kernel/idle.c @@ -9,6 +9,7 @@ #include <linux/kernel.h> #include <linux/kernel_stat.h> +#include <linux/sched/stat.h> #include <linux/notifier.h> #include <linux/init.h> #include <linux/cpu.h> @@ -21,22 +22,109 @@ DEFINE_PER_CPU(struct s390_idle_data, s390_idle); -void account_idle_time_irq(void) +static __always_inline 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 = idle->clock_idle_exit.tod - idle->clock_idle_enter.tod; + account_idle_time(cputime_to_nsecs(idle_time)); +} - /* Account time spent with enabled wait psw loaded as idle time. */ - __atomic64_add(idle_time, &idle->idle_time); - __atomic64_add_const(1, &idle->idle_count); +static __always_inline void __account_idle_time_setup(void) +{ + struct s390_idle_data *idle = this_cpu_ptr(&s390_idle); - /* Dyntick idle time accounted by nohz/scheduler */ - if (!idle->idle_dyntick) - account_idle_time(cputime_to_nsecs(idle_time)); + store_tod_clock_ext(&idle->clock_idle_enter); + idle->timer_idle_enter = get_cpu_timer(); + idle->clock_idle_exit = idle->clock_idle_enter; } +#ifdef CONFIG_NO_HZ_COMMON + +static u64 arch_cpu_in_idle_time(int cpu) +{ + struct s390_idle_data *idle = &per_cpu(s390_idle, cpu); + union tod_clock now; + u64 idle_time; + + if (!idle->in_idle) + return 0; + store_tod_clock_ext(&now); + if (tod_after(idle->clock_idle_exit.tod, idle->clock_idle_enter.tod)) + idle_time = idle->clock_idle_exit.tod - idle->clock_idle_enter.tod; + else + idle_time = now.tod - idle->clock_idle_enter.tod; + return cputime_to_nsecs(idle_time); +} + +static u64 arch_cpu_idle_time(int cpu, enum cpu_usage_stat idx, bool compute_delta) +{ + struct kernel_cpustat *kc = &kcpustat_cpu(cpu); + u64 *cpustat = kc->cpustat; + unsigned int seq; + u64 idle_time; + + /* + * The open coded seqcount writer in entry.S relies on the + * raw counting mechanism without any writer protection. + */ + typecheck(typeof(kc->idle_sleeptime_seq), seqcount_t); + do { + seq = read_seqcount_begin(&kc->idle_sleeptime_seq); + idle_time = cpustat[idx]; + if (compute_delta) + idle_time += arch_cpu_in_idle_time(cpu); + } while (read_seqcount_retry(&kc->idle_sleeptime_seq, seq)); + return idle_time; +} + +u64 arch_kcpustat_field_idle(int cpu) +{ + return arch_cpu_idle_time(cpu, CPUTIME_IDLE, !nr_iowait_cpu(cpu)); +} + +u64 arch_kcpustat_field_iowait(int cpu) +{ + return arch_cpu_idle_time(cpu, CPUTIME_IOWAIT, nr_iowait_cpu(cpu)); +} + +void account_idle_time_irq(void) +{ + struct s390_idle_data *idle = this_cpu_ptr(&s390_idle); + struct kernel_cpustat *kc = kcpustat_this_cpu; + + write_seqcount_begin(&kc->idle_sleeptime_seq); + idle->in_idle = false; + __account_idle_time_irq(); + write_seqcount_end(&kc->idle_sleeptime_seq); +} + +static __always_inline void account_idle_time_setup(void) +{ + struct s390_idle_data *idle = this_cpu_ptr(&s390_idle); + struct kernel_cpustat *kc = kcpustat_this_cpu; + + raw_write_seqcount_begin(&kc->idle_sleeptime_seq); + idle->in_idle = true; + __account_idle_time_setup(); + raw_write_seqcount_end(&kc->idle_sleeptime_seq); +} + +#else /* CONFIG_NO_HZ_COMMON */ + +void account_idle_time_irq(void) +{ + __account_idle_time_irq(); +} + +static __always_inline void account_idle_time_setup(void) +{ + __account_idle_time_setup(); +} + +#endif /* CONFIG_NO_HZ_COMMON */ + void noinstr arch_cpu_idle(void) { struct s390_idle_data *idle = this_cpu_ptr(&s390_idle); @@ -49,30 +137,11 @@ 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(); - idle->timer_idle_enter = get_cpu_timer(); + account_idle_time_setup(); bpon(); __load_psw_mask(psw_mask); } -static ssize_t show_idle_count(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct s390_idle_data *idle = &per_cpu(s390_idle, dev->id); - - return sysfs_emit(buf, "%lu\n", READ_ONCE(idle->idle_count)); -} -DEVICE_ATTR(idle_count, 0444, show_idle_count, NULL); - -static ssize_t show_idle_time(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct s390_idle_data *idle = &per_cpu(s390_idle, dev->id); - - return sysfs_emit(buf, "%lu\n", READ_ONCE(idle->idle_time) >> 12); -} -DEVICE_ATTR(idle_time_us, 0444, show_idle_time, NULL); - void arch_cpu_idle_enter(void) { } diff --git a/arch/s390/kernel/irq.c b/arch/s390/kernel/irq.c index efb988833c88..04d528639b94 100644 --- a/arch/s390/kernel/irq.c +++ b/arch/s390/kernel/irq.c @@ -104,9 +104,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); } diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c index 50bb499cf3e5..0ba7f89b8161 100644 --- a/arch/s390/kernel/smp.c +++ b/arch/s390/kernel/smp.c @@ -54,7 +54,6 @@ #include <asm/debug.h> #include <asm/os_info.h> #include <asm/sigp.h> -#include <asm/idle.h> #include <asm/nmi.h> #include <asm/stacktrace.h> #include <asm/topology.h> @@ -1085,31 +1084,6 @@ static struct attribute_group cpu_common_attr_group = { .attrs = cpu_common_attrs, }; -static struct attribute *cpu_online_attrs[] = { - &dev_attr_idle_count.attr, - &dev_attr_idle_time_us.attr, - NULL, -}; - -static struct attribute_group cpu_online_attr_group = { - .attrs = cpu_online_attrs, -}; - -static int smp_cpu_online(unsigned int cpu) -{ - struct cpu *c = per_cpu_ptr(&cpu_devices, cpu); - - return sysfs_create_group(&c->dev.kobj, &cpu_online_attr_group); -} - -static int smp_cpu_pre_down(unsigned int cpu) -{ - struct cpu *c = per_cpu_ptr(&cpu_devices, cpu); - - sysfs_remove_group(&c->dev.kobj, &cpu_online_attr_group); - return 0; -} - bool arch_cpu_is_hotpluggable(int cpu) { return !!cpu; @@ -1175,18 +1149,13 @@ static DEVICE_ATTR_WO(rescan); static int __init s390_smp_init(void) { struct device *dev_root; - int rc; + int rc = 0; dev_root = bus_get_dev_root(&cpu_subsys); if (dev_root) { rc = device_create_file(dev_root, &dev_attr_rescan); put_device(dev_root); - if (rc) - return rc; } - rc = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "s390/smp:online", - smp_cpu_online, smp_cpu_pre_down); - rc = rc <= 0 ? rc : 0; return rc; } subsys_initcall(s390_smp_init); diff --git a/arch/s390/kernel/vtime.c b/arch/s390/kernel/vtime.c index d1102a6f80bd..d804e1140c2e 100644 --- a/arch/s390/kernel/vtime.c +++ b/arch/s390/kernel/vtime.c @@ -140,8 +140,6 @@ static int do_account_vtime(struct task_struct *tsk) if (hardirq_count()) lc->hardirq_timer += timer; - else if (in_serving_softirq()) - lc->softirq_timer += timer; else lc->system_timer += timer; @@ -241,62 +239,13 @@ EXPORT_SYMBOL_GPL(vtime_account_kernel); void vtime_account_softirq(struct task_struct *tsk) { - if (!__this_cpu_read(s390_idle.idle_dyntick)) - get_lowcore()->softirq_timer += vtime_delta(); - else - vtime_flush(tsk); + get_lowcore()->softirq_timer += vtime_delta(); } void vtime_account_hardirq(struct task_struct *tsk) { - if (!__this_cpu_read(s390_idle.idle_dyntick)) { - get_lowcore()->hardirq_timer += vtime_delta(); - } else { - /* - * In dynticks mode, the idle cputime is accounted by the nohz - * subsystem. Therefore the s390 timer/clocks are reset on IRQ - * entry and steal time must be accounted now. - */ - vtime_flush(tsk); - } -} - -#ifdef CONFIG_NO_HZ_COMMON -/** - * vtime_reset - Fast forward vtime entry clocks - * - * Called from dynticks idle IRQ entry to fast-forward the clocks to current time - * so that the IRQ time is still accounted by vtime while nohz cputime is paused. - */ -void vtime_reset(void) -{ - vtime_reset_last_update(get_lowcore()); -} - -/** - * vtime_dyntick_start - Inform vtime about entry to idle-dynticks - * - * Called when idle enters in dyntick mode. The idle cputime that elapsed so far - * is flushed and the tick subsystem takes over the idle cputime accounting. - */ -void vtime_dyntick_start(void) -{ - __this_cpu_write(s390_idle.idle_dyntick, true); - vtime_flush(current); -} - -/** - * vtime_dyntick_stop - Inform vtime about exit from idle-dynticks - * - * Called when idle exits from dyntick mode. The vtime entry clocks are - * fast-forward to current time and idle accounting resumes. - */ -void vtime_dyntick_stop(void) -{ - vtime_reset_last_update(get_lowcore()); - __this_cpu_write(s390_idle.idle_dyntick, false); + get_lowcore()->hardirq_timer += vtime_delta(); } -#endif /* CONFIG_NO_HZ_COMMON */ /* * Sorted add to a list. List is linear searched until first bigger diff --git a/drivers/s390/cio/qdio_main.c b/drivers/s390/cio/qdio_main.c index 7e594a800525..c1e09fa34e77 100644 --- a/drivers/s390/cio/qdio_main.c +++ b/drivers/s390/cio/qdio_main.c @@ -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, diff --git a/drivers/s390/cio/qdio_thinint.c b/drivers/s390/cio/qdio_thinint.c index 85ca8650adeb..e167aa75c3df 100644 --- a/drivers/s390/cio/qdio_thinint.c +++ b/drivers/s390/cio/qdio_thinint.c @@ -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; diff --git a/include/linux/kernel_stat.h b/include/linux/kernel_stat.h index fce1392e2140..9ca6c2259dfe 100644 --- a/include/linux/kernel_stat.h +++ b/include/linux/kernel_stat.h @@ -107,6 +107,30 @@ static inline unsigned long kstat_cpu_irqs_sum(unsigned int cpu) } #ifdef CONFIG_NO_HZ_COMMON + +#ifdef CONFIG_HAVE_VIRT_CPU_ACCOUNTING_IDLE + +static inline void kcpustat_dyntick_start(u64 now) { } +static inline void kcpustat_dyntick_stop(u64 now) { } +static inline void kcpustat_irq_enter(u64 now) { } +static inline void kcpustat_irq_exit(u64 now) { } +static inline bool kcpustat_idle_dyntick(void) { return false; } + +extern u64 arch_kcpustat_field_idle(int cpu); +extern u64 arch_kcpustat_field_iowait(int cpu); + +static inline u64 kcpustat_field_idle(int cpu) +{ + return arch_kcpustat_field_idle(cpu); +} + +static inline u64 kcpustat_field_iowait(int cpu) +{ + return arch_kcpustat_field_iowait(cpu); +} + +#else /* !CONFIG_HAVE_VIRT_CPU_ACCOUNTING_IDLE */ + extern void kcpustat_dyntick_start(u64 now); extern void kcpustat_dyntick_stop(u64 now); extern void kcpustat_irq_enter(u64 now); @@ -118,6 +142,9 @@ static inline bool kcpustat_idle_dyntick(void) { return __this_cpu_read(kernel_cpustat.idle_dyntick); } + +#endif /* !CONFIG_HAVE_VIRT_CPU_ACCOUNTING_IDLE */ + #else static inline u64 kcpustat_field_idle(int cpu) { diff --git a/include/linux/vtime.h b/include/linux/vtime.h index 9dc25b04a119..82825e775499 100644 --- a/include/linux/vtime.h +++ b/include/linux/vtime.h @@ -42,9 +42,15 @@ extern void vtime_account_irq(struct task_struct *tsk, unsigned int offset); extern void vtime_account_softirq(struct task_struct *tsk); extern void vtime_account_hardirq(struct task_struct *tsk); extern void vtime_flush(struct task_struct *tsk); +#ifdef CONFIG_HAVE_VIRT_CPU_ACCOUNTING_IDLE +static inline void vtime_reset(void) { } +static inline void vtime_dyntick_start(void) { } +static inline void vtime_dyntick_stop(void) { } +#else extern void vtime_reset(void); extern void vtime_dyntick_start(void); extern void vtime_dyntick_stop(void); +#endif #else /* !CONFIG_VIRT_CPU_ACCOUNTING_NATIVE */ static inline void vtime_account_irq(struct task_struct *tsk, unsigned int offset) { } static inline void vtime_account_softirq(struct task_struct *tsk) { } diff --git a/kernel/sched/cputime.c b/kernel/sched/cputime.c index 679ac65be6b0..06bddaa738e5 100644 --- a/kernel/sched/cputime.c +++ b/kernel/sched/cputime.c @@ -421,7 +421,7 @@ static inline void irqtime_account_process_tick(struct task_struct *p, int user_ int nr_ticks) { } #endif /* !CONFIG_IRQ_TIME_ACCOUNTING */ -#ifdef CONFIG_NO_HZ_COMMON +#if defined(CONFIG_NO_HZ_COMMON) && !defined(CONFIG_HAVE_VIRT_CPU_ACCOUNTING_IDLE) static void kcpustat_idle_stop(struct kernel_cpustat *kc, u64 now) { u64 *cpustat = kc->cpustat; @@ -560,7 +560,7 @@ static u64 kcpustat_field_dyntick(int cpu, enum cpu_usage_stat idx, { return kcpustat_cpu(cpu).cpustat[idx]; } -#endif /* CONFIG_NO_HZ_COMMON */ +#endif /* CONFIG_NO_HZ_COMMON && !CONFIG_HAVE_VIRT_CPU_ACCOUNTING_IDLE */ static u64 get_cpu_sleep_time_us(int cpu, enum cpu_usage_stat idx, bool compute_delta, u64 *last_update_time) |
