2005-04-17 00:20:36 +02:00
|
|
|
/*
|
2005-11-09 03:38:01 +01:00
|
|
|
* This control block defines the PACA which defines the processor
|
|
|
|
* specific data for each logical processor on the system.
|
2005-04-17 00:20:36 +02:00
|
|
|
* 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.
|
2005-11-09 03:38:01 +01:00
|
|
|
*/
|
|
|
|
#ifndef _ASM_POWERPC_PACA_H
|
|
|
|
#define _ASM_POWERPC_PACA_H
|
2005-12-16 22:43:46 +01:00
|
|
|
#ifdef __KERNEL__
|
2005-04-17 00:20:36 +02:00
|
|
|
|
2010-01-28 14:23:22 +01:00
|
|
|
#ifdef CONFIG_PPC64
|
|
|
|
|
|
|
|
#include <linux/init.h>
|
2009-07-24 01:15:42 +02:00
|
|
|
#include <asm/types.h>
|
|
|
|
#include <asm/lppaca.h>
|
|
|
|
#include <asm/mmu.h>
|
|
|
|
#include <asm/page.h>
|
|
|
|
#include <asm/exception-64e.h>
|
2010-01-08 02:58:03 +01:00
|
|
|
#ifdef CONFIG_KVM_BOOK3S_64_HANDLER
|
2010-04-16 00:11:32 +02:00
|
|
|
#include <asm/kvm_book3s_asm.h>
|
2010-01-08 02:58:03 +01:00
|
|
|
#endif
|
2005-04-17 00:20:36 +02:00
|
|
|
|
|
|
|
register struct paca_struct *local_paca asm("r13");
|
2006-10-31 19:44:54 +01:00
|
|
|
|
|
|
|
#if defined(CONFIG_DEBUG_PREEMPT) && defined(CONFIG_SMP)
|
|
|
|
extern unsigned int debug_smp_processor_id(void); /* from linux/smp.h */
|
|
|
|
/*
|
|
|
|
* Add standard checks that preemption cannot occur when using get_paca():
|
|
|
|
* otherwise the paca_struct it points to may be the wrong one just after.
|
|
|
|
*/
|
|
|
|
#define get_paca() ((void) debug_smp_processor_id(), local_paca)
|
|
|
|
#else
|
2005-04-17 00:20:36 +02:00
|
|
|
#define get_paca() local_paca
|
2006-10-31 19:44:54 +01:00
|
|
|
#endif
|
|
|
|
|
2006-01-13 00:26:42 +01:00
|
|
|
#define get_lppaca() (get_paca()->lppaca_ptr)
|
2006-08-07 08:19:19 +02:00
|
|
|
#define get_slb_shadow() (get_paca()->slb_shadow_ptr)
|
2005-04-17 00:20:36 +02:00
|
|
|
|
|
|
|
struct task_struct;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Defines the layout of the paca.
|
|
|
|
*
|
|
|
|
* This structure is not directly accessed by firmware or the service
|
2008-04-10 08:43:47 +02:00
|
|
|
* processor.
|
2005-04-17 00:20:36 +02:00
|
|
|
*/
|
|
|
|
struct paca_struct {
|
2009-06-02 23:17:41 +02:00
|
|
|
#ifdef CONFIG_PPC_BOOK3S
|
2005-04-17 00:20:36 +02:00
|
|
|
/*
|
|
|
|
* 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.
|
|
|
|
*/
|
|
|
|
|
|
|
|
struct lppaca *lppaca_ptr; /* Pointer to LpPaca for PLIC */
|
2009-06-02 23:17:41 +02:00
|
|
|
#endif /* CONFIG_PPC_BOOK3S */
|
2005-04-17 00:20:36 +02:00
|
|
|
/*
|
2006-01-23 17:58:20 +01:00
|
|
|
* MAGIC: the spinlock functions in arch/powerpc/lib/locks.c
|
2005-04-17 00:20:36 +02:00
|
|
|
* 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 */
|
2008-08-30 03:40:24 +02:00
|
|
|
u64 kernelbase; /* Base address of kernel */
|
|
|
|
u64 kernel_msr; /* MSR while running in kernel */
|
2009-06-02 23:17:41 +02:00
|
|
|
#ifdef CONFIG_PPC_STD_MMU_64
|
2005-04-17 00:20:36 +02:00
|
|
|
u64 stab_real; /* Absolute address of segment table */
|
|
|
|
u64 stab_addr; /* Virtual address of segment table */
|
2009-06-02 23:17:41 +02:00
|
|
|
#endif /* CONFIG_PPC_STD_MMU_64 */
|
2005-04-17 00:20:36 +02:00
|
|
|
void *emergency_sp; /* pointer to emergency stack */
|
[PATCH] powerpc/64: per cpu data optimisations
The current ppc64 per cpu data implementation is quite slow. eg:
lhz 11,18(13) /* smp_processor_id() */
ld 9,.LC63-.LCTOC1(30) /* per_cpu__variable_name */
ld 8,.LC61-.LCTOC1(30) /* __per_cpu_offset */
sldi 11,11,3 /* form index into __per_cpu_offset */
mr 10,9
ldx 9,11,8 /* __per_cpu_offset[smp_processor_id()] */
ldx 0,10,9 /* load per cpu data */
5 loads for something that is supposed to be fast, pretty awful. One
reason for the large number of loads is that we have to synthesize 2
64bit constants (per_cpu__variable_name and __per_cpu_offset).
By putting __per_cpu_offset into the paca we can avoid the 2 loads
associated with it:
ld 11,56(13) /* paca->data_offset */
ld 9,.LC59-.LCTOC1(30) /* per_cpu__variable_name */
ldx 0,9,11 /* load per cpu data
Longer term we can should be able to do even better than 3 loads.
If per_cpu__variable_name wasnt a 64bit constant and paca->data_offset
was in a register we could cut it down to one load. A suggestion from
Rusty is to use gcc's __thread extension here. In order to do this we
would need to free up r13 (the __thread register and where the paca
currently is). So far Ive had a few unsuccessful attempts at doing that :)
The patch also allocates per cpu memory node local on NUMA machines.
This patch from Rusty has been sitting in my queue _forever_ but stalled
when I hit the compiler bug. Sorry about that.
Finally I also only allocate per cpu data for possible cpus, which comes
straight out of the x86-64 port. On a pseries kernel (with NR_CPUS == 128)
and 4 possible cpus we see some nice gains:
total used free shared buffers cached
Mem: 4012228 212860 3799368 0 0 162424
total used free shared buffers cached
Mem: 4016200 212984 3803216 0 0 162424
A saving of 3.75MB. Quite nice for smaller machines. Note: we now have
to be careful of per cpu users that touch data for !possible cpus.
At this stage it might be worth making the NUMA and possible cpu
optimisations generic, but per cpu init is done so early we have to be
careful that all architectures have their possible map setup correctly.
Signed-off-by: Anton Blanchard <anton@samba.org>
Signed-off-by: Paul Mackerras <paulus@samba.org>
2006-01-11 03:16:44 +01:00
|
|
|
u64 data_offset; /* per cpu data offset */
|
2005-04-17 00:20:36 +02:00
|
|
|
s16 hw_cpu_id; /* Physical processor number */
|
|
|
|
u8 cpu_start; /* At startup, processor spins until */
|
|
|
|
/* this becomes non-zero. */
|
2010-05-13 21:40:11 +02:00
|
|
|
u8 kexec_state; /* set when kexec down has irqs off */
|
2009-06-02 23:17:41 +02:00
|
|
|
#ifdef CONFIG_PPC_STD_MMU_64
|
2007-03-16 07:47:07 +01:00
|
|
|
struct slb_shadow *slb_shadow_ptr;
|
powerpc: Account time using timebase rather than PURR
Currently, when CONFIG_VIRT_CPU_ACCOUNTING is enabled, we use the
PURR register for measuring the user and system time used by
processes, as well as other related times such as hardirq and
softirq times. This turns out to be quite confusing for users
because it means that a program will often be measured as taking
less time when run on a multi-threaded processor (SMT2 or SMT4 mode)
than it does when run on a single-threaded processor (ST mode), even
though the program takes longer to finish. The discrepancy is
accounted for as stolen time, which is also confusing, particularly
when there are no other partitions running.
This changes the accounting to use the timebase instead, meaning that
the reported user and system times are the actual number of real-time
seconds that the program was executing on the processor thread,
regardless of which SMT mode the processor is in. Thus a program will
generally show greater user and system times when run on a
multi-threaded processor than on a single-threaded processor.
On pSeries systems on POWER5 or later processors, we measure the
stolen time (time when this partition wasn't running) using the
hypervisor dispatch trace log. We check for new entries in the
log on every entry from user mode and on every transition from
kernel process context to soft or hard IRQ context (i.e. when
account_system_vtime() gets called). So that we can correctly
distinguish time stolen from user time and time stolen from system
time, without having to check the log on every exit to user mode,
we store separate timestamps for exit to user mode and entry from
user mode.
On systems that have a SPURR (POWER6 and POWER7), we read the SPURR
in account_system_vtime() (as before), and then apportion the SPURR
ticks since the last time we read it between scaled user time and
scaled system time according to the relative proportions of user
time and system time over the same interval. This avoids having to
read the SPURR on every kernel entry and exit. On systems that have
PURR but not SPURR (i.e., POWER5), we do the same using the PURR
rather than the SPURR.
This disables the DTL user interface in /sys/debug/kernel/powerpc/dtl
for now since it conflicts with the use of the dispatch trace log
by the time accounting code.
Signed-off-by: Paul Mackerras <paulus@samba.org>
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
2010-08-26 21:56:43 +02:00
|
|
|
struct dtl_entry *dispatch_log;
|
|
|
|
struct dtl_entry *dispatch_log_end;
|
2005-04-17 00:20:36 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Now, starting in cacheline 2, the exception save areas
|
|
|
|
*/
|
2005-11-07 01:06:55 +01:00
|
|
|
/* 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 */
|
2009-06-02 23:17:41 +02:00
|
|
|
/* SLB related definitions */
|
2006-06-15 02:45:18 +02:00
|
|
|
u16 vmalloc_sllp;
|
2005-04-17 00:20:36 +02:00
|
|
|
u16 slb_cache_ptr;
|
2007-05-08 08:27:27 +02:00
|
|
|
u16 slb_cache[SLB_CACHE_ENTRIES];
|
2009-06-02 23:17:41 +02:00
|
|
|
#endif /* CONFIG_PPC_STD_MMU_64 */
|
|
|
|
|
2009-07-24 01:15:42 +02:00
|
|
|
#ifdef CONFIG_PPC_BOOK3E
|
|
|
|
pgd_t *pgd; /* Current PGD */
|
|
|
|
pgd_t *kernel_pgd; /* Kernel PGD */
|
|
|
|
u64 exgen[8] __attribute__((aligned(0x80)));
|
|
|
|
u64 extlb[EX_TLB_SIZE*3] __attribute__((aligned(0x80)));
|
|
|
|
u64 exmc[8]; /* used for machine checks */
|
|
|
|
u64 excrit[8]; /* used for crit interrupts */
|
|
|
|
u64 exdbg[8]; /* used for debug interrupts */
|
|
|
|
|
|
|
|
/* Kernel stack pointers for use by special exceptions */
|
|
|
|
void *mc_kstack;
|
|
|
|
void *crit_kstack;
|
|
|
|
void *dbg_kstack;
|
|
|
|
#endif /* CONFIG_PPC_BOOK3E */
|
|
|
|
|
2009-06-02 23:17:41 +02:00
|
|
|
mm_context_t context;
|
2005-04-17 00:20:36 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* 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 */
|
2011-01-24 08:42:41 +01:00
|
|
|
u64 saved_r1; /* r1 save for RTAS calls or PM */
|
2005-04-17 00:20:36 +02:00
|
|
|
u64 saved_msr; /* MSR saved here by enter_rtas */
|
2007-04-23 17:11:55 +02:00
|
|
|
u16 trap_save; /* Used when bad stack is encountered */
|
[POWERPC] Lazy interrupt disabling for 64-bit machines
This implements a lazy strategy for disabling interrupts. This means
that local_irq_disable() et al. just clear the 'interrupts are
enabled' flag in the paca. If an interrupt comes along, the interrupt
entry code notices that interrupts are supposed to be disabled, and
clears the EE bit in SRR1, clears the 'interrupts are hard-enabled'
flag in the paca, and returns. This means that interrupts only
actually get disabled in the processor when an interrupt comes along.
When interrupts are enabled by local_irq_enable() et al., the code
sets the interrupts-enabled flag in the paca, and then checks whether
interrupts got hard-disabled. If so, it also sets the EE bit in the
MSR to hard-enable the interrupts.
This has the potential to improve performance, and also makes it
easier to make a kernel that can boot on iSeries and on other 64-bit
machines, since this lazy-disable strategy is very similar to the
soft-disable strategy that iSeries already uses.
This version renames paca->proc_enabled to paca->soft_enabled, and
changes a couple of soft-disables in the kexec code to hard-disables,
which should fix the crash that Michael Ellerman saw. This doesn't
yet use a reserved CR field for the soft_enabled and hard_enabled
flags. This applies on top of Stephen Rothwell's patches to make it
possible to build a combined iSeries/other kernel.
Signed-off-by: Paul Mackerras <paulus@samba.org>
2006-10-04 08:47:49 +02:00
|
|
|
u8 soft_enabled; /* irq soft-enable flag */
|
|
|
|
u8 hard_enabled; /* set if irqs are enabled in MSR */
|
2006-09-13 14:08:26 +02:00
|
|
|
u8 io_sync; /* writel() needs spin_unlock sync */
|
2010-10-14 08:01:34 +02:00
|
|
|
u8 irq_work_pending; /* IRQ_WORK interrupt while soft-disable */
|
powerpc: Implement accurate task and CPU time accounting
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>
2006-02-24 00:06:59 +01:00
|
|
|
|
|
|
|
/* Stuff for accurate time accounting */
|
|
|
|
u64 user_time; /* accumulated usermode TB ticks */
|
|
|
|
u64 system_time; /* accumulated system TB ticks */
|
powerpc: Account time using timebase rather than PURR
Currently, when CONFIG_VIRT_CPU_ACCOUNTING is enabled, we use the
PURR register for measuring the user and system time used by
processes, as well as other related times such as hardirq and
softirq times. This turns out to be quite confusing for users
because it means that a program will often be measured as taking
less time when run on a multi-threaded processor (SMT2 or SMT4 mode)
than it does when run on a single-threaded processor (ST mode), even
though the program takes longer to finish. The discrepancy is
accounted for as stolen time, which is also confusing, particularly
when there are no other partitions running.
This changes the accounting to use the timebase instead, meaning that
the reported user and system times are the actual number of real-time
seconds that the program was executing on the processor thread,
regardless of which SMT mode the processor is in. Thus a program will
generally show greater user and system times when run on a
multi-threaded processor than on a single-threaded processor.
On pSeries systems on POWER5 or later processors, we measure the
stolen time (time when this partition wasn't running) using the
hypervisor dispatch trace log. We check for new entries in the
log on every entry from user mode and on every transition from
kernel process context to soft or hard IRQ context (i.e. when
account_system_vtime() gets called). So that we can correctly
distinguish time stolen from user time and time stolen from system
time, without having to check the log on every exit to user mode,
we store separate timestamps for exit to user mode and entry from
user mode.
On systems that have a SPURR (POWER6 and POWER7), we read the SPURR
in account_system_vtime() (as before), and then apportion the SPURR
ticks since the last time we read it between scaled user time and
scaled system time according to the relative proportions of user
time and system time over the same interval. This avoids having to
read the SPURR on every kernel entry and exit. On systems that have
PURR but not SPURR (i.e., POWER5), we do the same using the PURR
rather than the SPURR.
This disables the DTL user interface in /sys/debug/kernel/powerpc/dtl
for now since it conflicts with the use of the dispatch trace log
by the time accounting code.
Signed-off-by: Paul Mackerras <paulus@samba.org>
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
2010-08-26 21:56:43 +02:00
|
|
|
u64 user_time_scaled; /* accumulated usermode SPURR ticks */
|
|
|
|
u64 starttime; /* TB value snapshot */
|
|
|
|
u64 starttime_user; /* TB value on exit to usermode */
|
2007-10-18 12:06:37 +02:00
|
|
|
u64 startspurr; /* SPURR value snapshot */
|
powerpc: Account time using timebase rather than PURR
Currently, when CONFIG_VIRT_CPU_ACCOUNTING is enabled, we use the
PURR register for measuring the user and system time used by
processes, as well as other related times such as hardirq and
softirq times. This turns out to be quite confusing for users
because it means that a program will often be measured as taking
less time when run on a multi-threaded processor (SMT2 or SMT4 mode)
than it does when run on a single-threaded processor (ST mode), even
though the program takes longer to finish. The discrepancy is
accounted for as stolen time, which is also confusing, particularly
when there are no other partitions running.
This changes the accounting to use the timebase instead, meaning that
the reported user and system times are the actual number of real-time
seconds that the program was executing on the processor thread,
regardless of which SMT mode the processor is in. Thus a program will
generally show greater user and system times when run on a
multi-threaded processor than on a single-threaded processor.
On pSeries systems on POWER5 or later processors, we measure the
stolen time (time when this partition wasn't running) using the
hypervisor dispatch trace log. We check for new entries in the
log on every entry from user mode and on every transition from
kernel process context to soft or hard IRQ context (i.e. when
account_system_vtime() gets called). So that we can correctly
distinguish time stolen from user time and time stolen from system
time, without having to check the log on every exit to user mode,
we store separate timestamps for exit to user mode and entry from
user mode.
On systems that have a SPURR (POWER6 and POWER7), we read the SPURR
in account_system_vtime() (as before), and then apportion the SPURR
ticks since the last time we read it between scaled user time and
scaled system time according to the relative proportions of user
time and system time over the same interval. This avoids having to
read the SPURR on every kernel entry and exit. On systems that have
PURR but not SPURR (i.e., POWER5), we do the same using the PURR
rather than the SPURR.
This disables the DTL user interface in /sys/debug/kernel/powerpc/dtl
for now since it conflicts with the use of the dispatch trace log
by the time accounting code.
Signed-off-by: Paul Mackerras <paulus@samba.org>
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
2010-08-26 21:56:43 +02:00
|
|
|
u64 utime_sspurr; /* ->user_time when ->startspurr set */
|
|
|
|
u64 stolen_time; /* TB ticks taken by hypervisor */
|
|
|
|
u64 dtl_ridx; /* read index in dispatch log */
|
|
|
|
struct dtl_entry *dtl_curr; /* pointer corresponding to dtl_ridx */
|
2009-10-30 06:47:22 +01:00
|
|
|
|
2010-04-16 00:11:41 +02:00
|
|
|
#ifdef CONFIG_KVM_BOOK3S_HANDLER
|
2010-01-08 02:58:03 +01:00
|
|
|
/* We use this to store guest state in */
|
|
|
|
struct kvmppc_book3s_shadow_vcpu shadow_vcpu;
|
2009-10-30 06:47:22 +01:00
|
|
|
#endif
|
2005-04-17 00:20:36 +02:00
|
|
|
};
|
|
|
|
|
2010-01-28 14:23:22 +01:00
|
|
|
extern struct paca_struct *paca;
|
|
|
|
extern __initdata struct paca_struct boot_paca;
|
|
|
|
extern void initialise_paca(struct paca_struct *new_paca, int cpu);
|
2010-07-07 23:55:37 +02:00
|
|
|
extern void setup_paca(struct paca_struct *new_paca);
|
2010-01-28 14:23:22 +01:00
|
|
|
extern void allocate_pacas(void);
|
|
|
|
extern void free_unused_pacas(void);
|
|
|
|
|
|
|
|
#else /* CONFIG_PPC64 */
|
|
|
|
|
|
|
|
static inline void allocate_pacas(void) { };
|
|
|
|
static inline void free_unused_pacas(void) { };
|
|
|
|
|
|
|
|
#endif /* CONFIG_PPC64 */
|
2005-04-17 00:20:36 +02:00
|
|
|
|
2005-12-16 22:43:46 +01:00
|
|
|
#endif /* __KERNEL__ */
|
2005-11-09 03:38:01 +01:00
|
|
|
#endif /* _ASM_POWERPC_PACA_H */
|