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