kernel-ark/include/asm-x86_64/pda.h
Arjan van de Ven 0a42540580 [PATCH] Add the canary field to the PDA area and the task struct
This patch adds the per thread cookie field to the task struct and the PDA.
Also it makes sure that the PDA value gets the new cookie value at context
switch, and that a new task gets a new cookie at task creation time.

Signed-off-by: Arjan van Ven <arjan@linux.intel.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Andi Kleen <ak@suse.de>
CC: Andi Kleen <ak@suse.de>
2006-09-26 10:52:38 +02:00

94 lines
2.9 KiB
C

#ifndef X86_64_PDA_H
#define X86_64_PDA_H
#ifndef __ASSEMBLY__
#include <linux/stddef.h>
#include <linux/types.h>
#include <linux/cache.h>
#include <asm/page.h>
/* Per processor datastructure. %gs points to it while the kernel runs */
struct x8664_pda {
struct task_struct *pcurrent; /* 0 Current process */
unsigned long data_offset; /* 8 Per cpu data offset from linker
address */
unsigned long kernelstack; /* 16 top of kernel stack for current */
unsigned long oldrsp; /* 24 user rsp for system call */
int irqcount; /* 32 Irq nesting counter. Starts with -1 */
int cpunumber; /* 36 Logical CPU number */
#ifdef CONFIG_CC_STACKPROTECTOR
unsigned long stack_canary; /* 40 stack canary value */
/* gcc-ABI: this canary MUST be at
offset 40!!! */
#endif
char *irqstackptr;
int nodenumber; /* number of current node */
unsigned int __softirq_pending;
unsigned int __nmi_count; /* number of NMI on this CPUs */
int mmu_state;
struct mm_struct *active_mm;
unsigned apic_timer_irqs;
} ____cacheline_aligned_in_smp;
extern struct x8664_pda *_cpu_pda[];
extern struct x8664_pda boot_cpu_pda[];
#define cpu_pda(i) (_cpu_pda[i])
/*
* There is no fast way to get the base address of the PDA, all the accesses
* have to mention %fs/%gs. So it needs to be done this Torvaldian way.
*/
extern void __bad_pda_field(void);
/* proxy_pda doesn't actually exist, but tell gcc it is accessed
for all PDA accesses so it gets read/write dependencies right. */
extern struct x8664_pda _proxy_pda;
#define pda_offset(field) offsetof(struct x8664_pda, field)
#define pda_to_op(op,field,val) do { \
typedef typeof(_proxy_pda.field) T__; \
switch (sizeof(_proxy_pda.field)) { \
case 2: \
asm(op "w %1,%%gs:%P2" : "+m" (_proxy_pda.field) : \
"ri" ((T__)val),"i"(pda_offset(field))); break; \
case 4: \
asm(op "l %1,%%gs:%P2" : "+m" (_proxy_pda.field) : \
"ri" ((T__)val),"i"(pda_offset(field))); break; \
case 8: \
asm(op "q %1,%%gs:%P2": "+m" (_proxy_pda.field) : \
"ri" ((T__)val),"i"(pda_offset(field))); break; \
default: __bad_pda_field(); \
} \
} while (0)
#define pda_from_op(op,field) ({ \
typeof(_proxy_pda.field) ret__; \
switch (sizeof(_proxy_pda.field)) { \
case 2: \
asm(op "w %%gs:%P1,%0":"=r" (ret__):\
"i" (pda_offset(field)), "m" (_proxy_pda.field)); break;\
case 4: \
asm(op "l %%gs:%P1,%0":"=r" (ret__):\
"i" (pda_offset(field)), "m" (_proxy_pda.field)); break;\
case 8: \
asm(op "q %%gs:%P1,%0":"=r" (ret__):\
"i" (pda_offset(field)), "m" (_proxy_pda.field)); break;\
default: __bad_pda_field(); \
} \
ret__; })
#define read_pda(field) pda_from_op("mov",field)
#define write_pda(field,val) pda_to_op("mov",field,val)
#define add_pda(field,val) pda_to_op("add",field,val)
#define sub_pda(field,val) pda_to_op("sub",field,val)
#define or_pda(field,val) pda_to_op("or",field,val)
#endif
#define PDA_STACKOFFSET (5*8)
#endif