arch/s390/kernel/idle.c

Source file repositories/reference/linux-study-clean/arch/s390/kernel/idle.c

File Facts

System
Linux kernel
Corpus path
arch/s390/kernel/idle.c
Extension
.c
Size
3940 bytes
Lines
160
Domain
Architecture Layer
Bucket
arch/s390
Inferred role
Architecture Layer: exported/initcall integration point
Status
integration implementation candidate

Why This File Exists

CPU and platform-specific kernel glue: boot entry, traps, syscall entry, interrupts, page tables, context switch, and low-level barriers.

Dependency Surface

Detected Declarations

Annotated Snippet

// SPDX-License-Identifier: GPL-2.0
/*
 * Idle functions for s390.
 *
 * Copyright IBM Corp. 2014
 *
 * Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com>
 */

#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>
#include <linux/export.h>
#include <trace/events/power.h>
#include <asm/cpu_mf.h>
#include <asm/cputime.h>
#include <asm/idle.h>
#include <asm/nmi.h>
#include <asm/smp.h>

DEFINE_PER_CPU(struct s390_idle_data, s390_idle);

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 = idle->clock_idle_exit.tod - idle->clock_idle_enter.tod;
	account_idle_time(cputime_to_nsecs(idle_time));
}

static __always_inline void __account_idle_time_setup(void)
{
	struct s390_idle_data *idle = this_cpu_ptr(&s390_idle);

	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));
}
EXPORT_SYMBOL_GPL(arch_kcpustat_field_idle);

u64 arch_kcpustat_field_iowait(int cpu)
{

Annotation

Implementation Notes