mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-12-20 09:34:44 +08:00
c6622f63db
This implements accurate task and cpu time accounting for 64-bit powerpc kernels. Instead of accounting a whole jiffy of time to a task on a timer interrupt because that task happened to be running at the time, we now account time in units of timebase ticks according to the actual time spent by the task in user mode and kernel mode. We also count the time spent processing hardware and software interrupts accurately. This is conditional on CONFIG_VIRT_CPU_ACCOUNTING. If that is not set, we do tick-based approximate accounting as before. To get this accurate information, we read either the PURR (processor utilization of resources register) on POWER5 machines, or the timebase on other machines on * each entry to the kernel from usermode * each exit to usermode * transitions between process context, hard irq context and soft irq context in kernel mode * context switches. On POWER5 systems with shared-processor logical partitioning we also read both the PURR and the timebase at each timer interrupt and context switch in order to determine how much time has been taken by the hypervisor to run other partitions ("steal" time). Unfortunately, since we need values of the PURR on both threads at the same time to accurately calculate the steal time, and since we can only calculate steal time on a per-core basis, the apportioning of the steal time between idle time (time which we ceded to the hypervisor in the idle loop) and actual stolen time is somewhat approximate at the moment. This is all based quite heavily on what s390 does, and it uses the generic interfaces that were added by the s390 developers, i.e. account_system_time(), account_user_time(), etc. This patch doesn't add any new interfaces between the kernel and userspace, and doesn't change the units in which time is reported to userspace by things such as /proc/stat, /proc/<pid>/stat, getrusage(), times(), etc. Internally the various task and cpu times are stored in timebase units, but they are converted to USER_HZ units (1/100th of a second) when reported to userspace. Some precision is therefore lost but there should not be any accumulating error, since the internal accumulation is at full precision. Signed-off-by: Paul Mackerras <paulus@samba.org>
110 lines
3.4 KiB
C
110 lines
3.4 KiB
C
/*
|
|
* include/asm-powerpc/paca.h
|
|
*
|
|
* This control block defines the PACA which defines the processor
|
|
* specific data for each logical processor on the system.
|
|
* There are some pointers defined that are utilized by PLIC.
|
|
*
|
|
* C 2001 PPC 64 Team, IBM Corp
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation; either version
|
|
* 2 of the License, or (at your option) any later version.
|
|
*/
|
|
#ifndef _ASM_POWERPC_PACA_H
|
|
#define _ASM_POWERPC_PACA_H
|
|
#ifdef __KERNEL__
|
|
|
|
#include <linux/config.h>
|
|
#include <asm/types.h>
|
|
#include <asm/lppaca.h>
|
|
#include <asm/mmu.h>
|
|
|
|
register struct paca_struct *local_paca asm("r13");
|
|
#define get_paca() local_paca
|
|
#define get_lppaca() (get_paca()->lppaca_ptr)
|
|
|
|
struct task_struct;
|
|
|
|
/*
|
|
* Defines the layout of the paca.
|
|
*
|
|
* This structure is not directly accessed by firmware or the service
|
|
* processor except for the first two pointers that point to the
|
|
* lppaca area and the ItLpRegSave area for this CPU. The lppaca
|
|
* object is currently contained within the PACA but it doesn't need
|
|
* to be.
|
|
*/
|
|
struct paca_struct {
|
|
/*
|
|
* Because hw_cpu_id, unlike other paca fields, is accessed
|
|
* routinely from other CPUs (from the IRQ code), we stick to
|
|
* read-only (after boot) fields in the first cacheline to
|
|
* avoid cacheline bouncing.
|
|
*/
|
|
|
|
/*
|
|
* MAGIC: These first two pointers can't be moved - they're
|
|
* accessed by the firmware
|
|
*/
|
|
struct lppaca *lppaca_ptr; /* Pointer to LpPaca for PLIC */
|
|
#ifdef CONFIG_PPC_ISERIES
|
|
void *reg_save_ptr; /* Pointer to LpRegSave for PLIC */
|
|
#endif /* CONFIG_PPC_ISERIES */
|
|
|
|
/*
|
|
* MAGIC: the spinlock functions in arch/powerpc/lib/locks.c
|
|
* load lock_token and paca_index with a single lwz
|
|
* instruction. They must travel together and be properly
|
|
* aligned.
|
|
*/
|
|
u16 lock_token; /* Constant 0x8000, used in locks */
|
|
u16 paca_index; /* Logical processor number */
|
|
|
|
u64 kernel_toc; /* Kernel TOC address */
|
|
u64 stab_real; /* Absolute address of segment table */
|
|
u64 stab_addr; /* Virtual address of segment table */
|
|
void *emergency_sp; /* pointer to emergency stack */
|
|
u64 data_offset; /* per cpu data offset */
|
|
s16 hw_cpu_id; /* Physical processor number */
|
|
u8 cpu_start; /* At startup, processor spins until */
|
|
/* this becomes non-zero. */
|
|
|
|
/*
|
|
* Now, starting in cacheline 2, the exception save areas
|
|
*/
|
|
/* used for most interrupts/exceptions */
|
|
u64 exgen[10] __attribute__((aligned(0x80)));
|
|
u64 exmc[10]; /* used for machine checks */
|
|
u64 exslb[10]; /* used for SLB/segment table misses
|
|
* on the linear mapping */
|
|
#ifdef CONFIG_PPC_64K_PAGES
|
|
pgd_t *pgdir;
|
|
#endif /* CONFIG_PPC_64K_PAGES */
|
|
|
|
mm_context_t context;
|
|
u16 slb_cache[SLB_CACHE_ENTRIES];
|
|
u16 slb_cache_ptr;
|
|
|
|
/*
|
|
* then miscellaneous read-write fields
|
|
*/
|
|
struct task_struct *__current; /* Pointer to current */
|
|
u64 kstack; /* Saved Kernel stack addr */
|
|
u64 stab_rr; /* stab/slb round-robin counter */
|
|
u64 saved_r1; /* r1 save for RTAS calls */
|
|
u64 saved_msr; /* MSR saved here by enter_rtas */
|
|
u8 proc_enabled; /* irq soft-enable flag */
|
|
|
|
/* Stuff for accurate time accounting */
|
|
u64 user_time; /* accumulated usermode TB ticks */
|
|
u64 system_time; /* accumulated system TB ticks */
|
|
u64 startpurr; /* PURR/TB value snapshot */
|
|
};
|
|
|
|
extern struct paca_struct paca[];
|
|
|
|
#endif /* __KERNEL__ */
|
|
#endif /* _ASM_POWERPC_PACA_H */
|