blob: 55e21da96e7a239534075b87c556f7ca50e52999 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001#ifndef X86_64_PDA_H
2#define X86_64_PDA_H
3
4#ifndef __ASSEMBLY__
5#include <linux/stddef.h>
6#include <linux/types.h>
7#include <linux/cache.h>
Jan Beulichb556b352006-01-11 22:43:00 +01008#include <asm/page.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -07009
10/* Per processor datastructure. %gs points to it while the kernel runs */
11struct x8664_pda {
12 struct task_struct *pcurrent; /* Current process */
13 unsigned long data_offset; /* Per cpu data offset from linker address */
Linus Torvalds1da177e2005-04-16 15:20:36 -070014 unsigned long kernelstack; /* top of kernel stack for current */
15 unsigned long oldrsp; /* user rsp for system call */
Jan Beulichb556b352006-01-11 22:43:00 +010016#if DEBUG_STKSZ > EXCEPTION_STKSZ
17 unsigned long debugstack; /* #DB/#BP stack. */
18#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -070019 int irqcount; /* Irq nesting counter. Starts with -1 */
20 int cpunumber; /* Logical CPU number */
21 char *irqstackptr; /* top of irqstack */
Andi Kleen69d81fc2005-11-05 17:25:53 +010022 int nodenumber; /* number of current node */
Linus Torvalds1da177e2005-04-16 15:20:36 -070023 unsigned int __softirq_pending;
24 unsigned int __nmi_count; /* number of NMI on this CPUs */
Linus Torvalds1da177e2005-04-16 15:20:36 -070025 int mmu_state;
Arjan van de Vendf920042006-03-25 16:31:01 +010026 struct mm_struct *active_mm;
Linus Torvalds1da177e2005-04-16 15:20:36 -070027 unsigned apic_timer_irqs;
Andi Kleenb9169112005-09-12 18:49:24 +020028} ____cacheline_aligned_in_smp;
Linus Torvalds1da177e2005-04-16 15:20:36 -070029
Ravikiran G Thirumalai365ba912006-01-11 22:45:42 +010030extern struct x8664_pda *_cpu_pda[];
31extern struct x8664_pda boot_cpu_pda[];
Ravikiran G Thirumalaidf79efd2006-01-11 22:45:39 +010032
Ravikiran G Thirumalai365ba912006-01-11 22:45:42 +010033#define cpu_pda(i) (_cpu_pda[i])
Linus Torvalds1da177e2005-04-16 15:20:36 -070034
35/*
36 * There is no fast way to get the base address of the PDA, all the accesses
37 * have to mention %fs/%gs. So it needs to be done this Torvaldian way.
38 */
Linus Torvalds1da177e2005-04-16 15:20:36 -070039extern void __bad_pda_field(void);
40
Andi Kleen53ee11a2006-09-26 10:52:38 +020041/* proxy_pda doesn't actually exist, but tell gcc it is accessed
42 for all PDA accesses so it gets read/write dependencies right. */
43extern struct x8664_pda _proxy_pda;
44
Linus Torvalds1da177e2005-04-16 15:20:36 -070045#define pda_offset(field) offsetof(struct x8664_pda, field)
46
47#define pda_to_op(op,field,val) do { \
Andi Kleen53ee11a2006-09-26 10:52:38 +020048 typedef typeof(_proxy_pda.field) T__; \
49 switch (sizeof(_proxy_pda.field)) { \
Linus Torvalds1da177e2005-04-16 15:20:36 -070050case 2: \
Andi Kleen53ee11a2006-09-26 10:52:38 +020051asm(op "w %1,%%gs:%P2" : "+m" (_proxy_pda.field) : \
52 "ri" ((T__)val),"i"(pda_offset(field))); break; \
Linus Torvalds1da177e2005-04-16 15:20:36 -070053case 4: \
Andi Kleen53ee11a2006-09-26 10:52:38 +020054asm(op "l %1,%%gs:%P2" : "+m" (_proxy_pda.field) : \
55 "ri" ((T__)val),"i"(pda_offset(field))); break; \
Linus Torvalds1da177e2005-04-16 15:20:36 -070056case 8: \
Andi Kleen53ee11a2006-09-26 10:52:38 +020057asm(op "q %1,%%gs:%P2": "+m" (_proxy_pda.field) : \
58 "ri" ((T__)val),"i"(pda_offset(field))); break; \
59default: __bad_pda_field(); \
Linus Torvalds1da177e2005-04-16 15:20:36 -070060 } \
61 } while (0)
62
Linus Torvalds1da177e2005-04-16 15:20:36 -070063#define pda_from_op(op,field) ({ \
Andi Kleen53ee11a2006-09-26 10:52:38 +020064 typeof(_proxy_pda.field) ret__; \
65 switch (sizeof(_proxy_pda.field)) { \
Linus Torvalds1da177e2005-04-16 15:20:36 -070066case 2: \
Andi Kleen53ee11a2006-09-26 10:52:38 +020067asm(op "w %%gs:%P1,%0":"=r" (ret__):\
68 "i" (pda_offset(field)), "m" (_proxy_pda.field)); break;\
Linus Torvalds1da177e2005-04-16 15:20:36 -070069case 4: \
Andi Kleen53ee11a2006-09-26 10:52:38 +020070asm(op "l %%gs:%P1,%0":"=r" (ret__):\
71 "i" (pda_offset(field)), "m" (_proxy_pda.field)); break;\
Linus Torvalds1da177e2005-04-16 15:20:36 -070072case 8: \
Andi Kleen53ee11a2006-09-26 10:52:38 +020073asm(op "q %%gs:%P1,%0":"=r" (ret__):\
74 "i" (pda_offset(field)), "m" (_proxy_pda.field)); break;\
75default: __bad_pda_field(); \
Linus Torvalds1da177e2005-04-16 15:20:36 -070076 } \
77 ret__; })
78
79
80#define read_pda(field) pda_from_op("mov",field)
81#define write_pda(field,val) pda_to_op("mov",field,val)
82#define add_pda(field,val) pda_to_op("add",field,val)
83#define sub_pda(field,val) pda_to_op("sub",field,val)
Andi Kleen3f744782005-09-12 18:49:24 +020084#define or_pda(field,val) pda_to_op("or",field,val)
Linus Torvalds1da177e2005-04-16 15:20:36 -070085
86#endif
87
88#define PDA_STACKOFFSET (5*8)
89
90#endif