| Jeremy Fitzhardinge | 9ca3610 | 2006-12-07 02:14:02 +0100 | [diff] [blame] | 1 | /* | 
 | 2 |    Per-processor Data Areas | 
 | 3 |    Jeremy Fitzhardinge <jeremy@goop.org> 2006 | 
 | 4 |    Based on asm-x86_64/pda.h by Andi Kleen. | 
 | 5 |  */ | 
 | 6 | #ifndef _I386_PDA_H | 
 | 7 | #define _I386_PDA_H | 
 | 8 |  | 
 | 9 | #include <linux/stddef.h> | 
| Jeremy Fitzhardinge | ec7fcaa | 2006-12-07 02:14:03 +0100 | [diff] [blame] | 10 | #include <linux/types.h> | 
| Jeremy Fitzhardinge | 9ca3610 | 2006-12-07 02:14:02 +0100 | [diff] [blame] | 11 |  | 
 | 12 | struct i386_pda | 
 | 13 | { | 
 | 14 | 	struct i386_pda *_pda;		/* pointer to self */ | 
| Jeremy Fitzhardinge | b2938f8 | 2006-12-07 02:14:03 +0100 | [diff] [blame] | 15 |  | 
 | 16 | 	int cpu_number; | 
| Jeremy Fitzhardinge | ec7fcaa | 2006-12-07 02:14:03 +0100 | [diff] [blame] | 17 | 	struct task_struct *pcurrent;	/* current process */ | 
| Jeremy Fitzhardinge | 70463da | 2006-12-07 02:14:03 +0100 | [diff] [blame] | 18 | 	struct pt_regs *irq_regs; | 
| Jeremy Fitzhardinge | 9ca3610 | 2006-12-07 02:14:02 +0100 | [diff] [blame] | 19 | }; | 
 | 20 |  | 
 | 21 | extern struct i386_pda *_cpu_pda[]; | 
 | 22 |  | 
 | 23 | #define cpu_pda(i)	(_cpu_pda[i]) | 
 | 24 |  | 
 | 25 | #define pda_offset(field) offsetof(struct i386_pda, field) | 
 | 26 |  | 
 | 27 | extern void __bad_pda_field(void); | 
 | 28 |  | 
 | 29 | /* This variable is never instantiated.  It is only used as a stand-in | 
 | 30 |    for the real per-cpu PDA memory, so that gcc can understand what | 
 | 31 |    memory operations the inline asms() below are performing.  This | 
 | 32 |    eliminates the need to make the asms volatile or have memory | 
 | 33 |    clobbers, so gcc can readily analyse them. */ | 
 | 34 | extern struct i386_pda _proxy_pda; | 
 | 35 |  | 
 | 36 | #define pda_to_op(op,field,val)						\ | 
 | 37 | 	do {								\ | 
 | 38 | 		typedef typeof(_proxy_pda.field) T__;			\ | 
 | 39 | 		if (0) { T__ tmp__; tmp__ = (val); }			\ | 
 | 40 | 		switch (sizeof(_proxy_pda.field)) {			\ | 
 | 41 | 		case 1:							\ | 
 | 42 | 			asm(op "b %1,%%gs:%c2"				\ | 
 | 43 | 			    : "+m" (_proxy_pda.field)			\ | 
 | 44 | 			    :"ri" ((T__)val),				\ | 
 | 45 | 			     "i"(pda_offset(field)));			\ | 
 | 46 | 			break;						\ | 
 | 47 | 		case 2:							\ | 
 | 48 | 			asm(op "w %1,%%gs:%c2"				\ | 
 | 49 | 			    : "+m" (_proxy_pda.field)			\ | 
 | 50 | 			    :"ri" ((T__)val),				\ | 
 | 51 | 			     "i"(pda_offset(field)));			\ | 
 | 52 | 			break;						\ | 
 | 53 | 		case 4:							\ | 
 | 54 | 			asm(op "l %1,%%gs:%c2"				\ | 
 | 55 | 			    : "+m" (_proxy_pda.field)			\ | 
 | 56 | 			    :"ri" ((T__)val),				\ | 
 | 57 | 			     "i"(pda_offset(field)));			\ | 
 | 58 | 			break;						\ | 
 | 59 | 		default: __bad_pda_field();				\ | 
 | 60 | 		}							\ | 
 | 61 | 	} while (0) | 
 | 62 |  | 
 | 63 | #define pda_from_op(op,field)						\ | 
 | 64 | 	({								\ | 
 | 65 | 		typeof(_proxy_pda.field) ret__;				\ | 
 | 66 | 		switch (sizeof(_proxy_pda.field)) {			\ | 
 | 67 | 		case 1:							\ | 
 | 68 | 			asm(op "b %%gs:%c1,%0"				\ | 
 | 69 | 			    : "=r" (ret__)				\ | 
 | 70 | 			    : "i" (pda_offset(field)),			\ | 
 | 71 | 			      "m" (_proxy_pda.field));			\ | 
 | 72 | 			break;						\ | 
 | 73 | 		case 2:							\ | 
 | 74 | 			asm(op "w %%gs:%c1,%0"				\ | 
 | 75 | 			    : "=r" (ret__)				\ | 
 | 76 | 			    : "i" (pda_offset(field)),			\ | 
 | 77 | 			      "m" (_proxy_pda.field));			\ | 
 | 78 | 			break;						\ | 
 | 79 | 		case 4:							\ | 
 | 80 | 			asm(op "l %%gs:%c1,%0"				\ | 
 | 81 | 			    : "=r" (ret__)				\ | 
 | 82 | 			    : "i" (pda_offset(field)),			\ | 
 | 83 | 			      "m" (_proxy_pda.field));			\ | 
 | 84 | 			break;						\ | 
 | 85 | 		default: __bad_pda_field();				\ | 
 | 86 | 		}							\ | 
 | 87 | 		ret__; }) | 
 | 88 |  | 
 | 89 | /* Return a pointer to a pda field */ | 
 | 90 | #define pda_addr(field)							\ | 
 | 91 | 	((typeof(_proxy_pda.field) *)((unsigned char *)read_pda(_pda) + \ | 
 | 92 | 				      pda_offset(field))) | 
 | 93 |  | 
 | 94 | #define read_pda(field) pda_from_op("mov",field) | 
 | 95 | #define write_pda(field,val) pda_to_op("mov",field,val) | 
 | 96 | #define add_pda(field,val) pda_to_op("add",field,val) | 
 | 97 | #define sub_pda(field,val) pda_to_op("sub",field,val) | 
 | 98 | #define or_pda(field,val) pda_to_op("or",field,val) | 
 | 99 |  | 
 | 100 | #endif	/* _I386_PDA_H */ |