1 #ifndef X86_64_PDA_H 2 #define X86_64_PDA_H 3 4 #include <linux/cache.h> 5 6 /* Per processor datastructure. %gs points to it while the kernel runs */ 7 /* To use a new field with the *_pda macros it needs to be added to tools/offset.c */ 8 struct x8664_pda { 9 unsigned long kernelstack; /* TOS for current process */ 10 unsigned long oldrsp; /* user rsp for system call */ 11 unsigned long irqrsp; /* Old rsp for interrupts. */ 12 struct task_struct *pcurrent; /* Current process */ 13 int irqcount; /* Irq nesting counter. Starts with -1 */ 14 int cpunumber; /* Logical CPU number */ 15 /* XXX: could be a single list */ 16 unsigned long *pgd_quick; 17 unsigned long *pmd_quick; 18 unsigned long *pte_quick; 19 unsigned long pgtable_cache_sz; 20 char *irqstackptr; /* top of irqstack */ 21 unsigned long volatile *level4_pgt; 22 } ____cacheline_aligned; 23 24 #define PDA_STACKOFFSET (5*8) 25 26 #define IRQSTACK_ORDER 2 27 #define IRQSTACKSIZE (PAGE_SIZE << IRQSTACK_ORDER) 28 29 extern struct x8664_pda cpu_pda[]; 30 31 /* 32 * There is no fast way to get the base address of the PDA, all the accesses 33 * have to mention %fs/%gs. So it needs to be done this Torvaldian way. 34 */ 35 #define sizeof_field(type,field) (sizeof(((type *)0)->field)) 36 #define typeof_field(type,field) typeof(((type *)0)->field) 37 38 extern void __bad_pda_field(void); 39 /* Don't use offsetof because it requires too much infrastructure */ 40 #define pda_offset(field) ((unsigned long)&((struct x8664_pda *)0)->field) 41 42 #define pda_to_op(op,field,val) do { \ 43 switch (sizeof_field(struct x8664_pda, field)) { \ 44 case 2: asm volatile(op "w %0,%%gs:%P1" :: "r" (val), "i"(pda_offset(field)):"memory"); break; \ 45 case 4: asm volatile(op "l %0,%%gs:%P1" :: "r" (val), "i"(pda_offset(field)):"memory"); break; \ 46 case 8: asm volatile(op "q %0,%%gs:%P1" :: "r" (val), "i"(pda_offset(field)):"memory"); break; \ 47 default: __bad_pda_field(); \ 48 } \ 49 } while (0) 50 51 52 #define pda_from_op(op,field) ({ \ 53 typedef typeof_field(struct x8664_pda, field) T__; T__ ret__; \ 54 switch (sizeof_field(struct x8664_pda, field)) { \ 55 case 2: asm volatile(op "w %%gs:%P1,%0":"=r" (ret__): "i" (pda_offset(field)):"memory"); break; \ 56 case 4: asm volatile(op "l %%gs:%P1,%0":"=r" (ret__): "i" (pda_offset(field)):"memory"); break; \ 57 case 8: asm volatile(op "q %%gs:%P1,%0":"=r" (ret__): "i" (pda_offset(field)):"memory"); break; \ 58 default: __bad_pda_field(); \ 59 } \ 60 ret__; }) 61 62 63 #define read_pda(field) pda_from_op("mov",field) 64 #define write_pda(field,val) pda_to_op("mov",field,val) 65 #define add_pda(field,val) pda_to_op("add",field,val) 66 #define sub_pda(field,val) pda_to_op("sub",field,val) 67 68 #endif 69