| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1 | #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> | 
 | 8 |  | 
 | 9 | /* Per processor datastructure. %gs points to it while the kernel runs */  | 
 | 10 | struct x8664_pda { | 
 | 11 | 	struct task_struct *pcurrent;	/* Current process */ | 
 | 12 | 	unsigned long data_offset;	/* Per cpu data offset from linker address */ | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 13 | 	unsigned long kernelstack;  /* top of kernel stack for current */  | 
 | 14 | 	unsigned long oldrsp; 	    /* user rsp for system call */ | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 15 |         int irqcount;		    /* Irq nesting counter. Starts with -1 */  	 | 
 | 16 | 	int cpunumber;		    /* Logical CPU number */ | 
 | 17 | 	char *irqstackptr;	/* top of irqstack */ | 
 | 18 | 	unsigned int __softirq_pending; | 
 | 19 | 	unsigned int __nmi_count;	/* number of NMI on this CPUs */ | 
 | 20 | 	struct mm_struct *active_mm; | 
 | 21 | 	int mmu_state;      | 
 | 22 | 	unsigned apic_timer_irqs; | 
| Andi Kleen | b916911 | 2005-09-12 18:49:24 +0200 | [diff] [blame] | 23 | } ____cacheline_aligned_in_smp; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 24 |  | 
 | 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 |  | 
 | 40 | #define pda_offset(field) offsetof(struct x8664_pda, field) | 
 | 41 |  | 
 | 42 | #define pda_to_op(op,field,val) do { \ | 
| Andi Kleen | 3f74478 | 2005-09-12 18:49:24 +0200 | [diff] [blame] | 43 | 	typedef typeof_field(struct x8664_pda, field) T__; \ | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 44 |        switch (sizeof_field(struct x8664_pda, field)) { 		\ | 
 | 45 | case 2: \ | 
| Andi Kleen | 3f74478 | 2005-09-12 18:49:24 +0200 | [diff] [blame] | 46 | asm volatile(op "w %0,%%gs:%P1"::"ri" ((T__)val),"i"(pda_offset(field)):"memory"); break; \ | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 47 | case 4: \ | 
| Andi Kleen | 3f74478 | 2005-09-12 18:49:24 +0200 | [diff] [blame] | 48 | asm volatile(op "l %0,%%gs:%P1"::"ri" ((T__)val),"i"(pda_offset(field)):"memory"); break; \ | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 49 | case 8: \ | 
| Andi Kleen | 3f74478 | 2005-09-12 18:49:24 +0200 | [diff] [blame] | 50 | asm volatile(op "q %0,%%gs:%P1"::"ri" ((T__)val),"i"(pda_offset(field)):"memory"); break; \ | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 51 |        default: __bad_pda_field(); 					\ | 
 | 52 |        } \ | 
 | 53 |        } while (0) | 
 | 54 |  | 
 | 55 | /*  | 
 | 56 |  * AK: PDA read accesses should be neither volatile nor have an memory clobber. | 
 | 57 |  * Unfortunately removing them causes all hell to break lose currently. | 
 | 58 |  */ | 
 | 59 | #define pda_from_op(op,field) ({ \ | 
| Andi Kleen | 3f74478 | 2005-09-12 18:49:24 +0200 | [diff] [blame] | 60 |        typeof_field(struct x8664_pda, field) ret__; \ | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 61 |        switch (sizeof_field(struct x8664_pda, field)) { 		\ | 
 | 62 | case 2: \ | 
 | 63 | asm volatile(op "w %%gs:%P1,%0":"=r" (ret__):"i"(pda_offset(field)):"memory"); break;\ | 
 | 64 | case 4: \ | 
 | 65 | asm volatile(op "l %%gs:%P1,%0":"=r" (ret__):"i"(pda_offset(field)):"memory"); break;\ | 
 | 66 | case 8: \ | 
 | 67 | asm volatile(op "q %%gs:%P1,%0":"=r" (ret__):"i"(pda_offset(field)):"memory"); break;\ | 
 | 68 |        default: __bad_pda_field(); 					\ | 
 | 69 |        } \ | 
 | 70 |        ret__; }) | 
 | 71 |  | 
 | 72 |  | 
 | 73 | #define read_pda(field) pda_from_op("mov",field) | 
 | 74 | #define write_pda(field,val) pda_to_op("mov",field,val) | 
 | 75 | #define add_pda(field,val) pda_to_op("add",field,val) | 
 | 76 | #define sub_pda(field,val) pda_to_op("sub",field,val) | 
| Andi Kleen | 3f74478 | 2005-09-12 18:49:24 +0200 | [diff] [blame] | 77 | #define or_pda(field,val) pda_to_op("or",field,val) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 78 |  | 
 | 79 | #endif | 
 | 80 |  | 
 | 81 | #define PDA_STACKOFFSET (5*8) | 
 | 82 |  | 
 | 83 | #endif |