This commit was manufactured by cvs2svn to create branch 'vserver'.
[linux-2.6.git] / include / asm-i386 / pda.h
diff --git a/include/asm-i386/pda.h b/include/asm-i386/pda.h
new file mode 100644 (file)
index 0000000..2ba2736
--- /dev/null
@@ -0,0 +1,100 @@
+/*
+   Per-processor Data Areas
+   Jeremy Fitzhardinge <jeremy@goop.org> 2006
+   Based on asm-x86_64/pda.h by Andi Kleen.
+ */
+#ifndef _I386_PDA_H
+#define _I386_PDA_H
+
+#include <linux/stddef.h>
+#include <linux/types.h>
+
+struct i386_pda
+{
+       struct i386_pda *_pda;          /* pointer to self */
+
+       int cpu_number;
+       struct task_struct *pcurrent;   /* current process */
+       struct pt_regs *irq_regs;
+};
+
+extern struct i386_pda *_cpu_pda[];
+
+#define cpu_pda(i)     (_cpu_pda[i])
+
+#define pda_offset(field) offsetof(struct i386_pda, field)
+
+extern void __bad_pda_field(void);
+
+/* This variable is never instantiated.  It is only used as a stand-in
+   for the real per-cpu PDA memory, so that gcc can understand what
+   memory operations the inline asms() below are performing.  This
+   eliminates the need to make the asms volatile or have memory
+   clobbers, so gcc can readily analyse them. */
+extern struct i386_pda _proxy_pda;
+
+#define pda_to_op(op,field,val)                                                \
+       do {                                                            \
+               typedef typeof(_proxy_pda.field) T__;                   \
+               if (0) { T__ tmp__; tmp__ = (val); }                    \
+               switch (sizeof(_proxy_pda.field)) {                     \
+               case 1:                                                 \
+                       asm(op "b %1,%%gs:%c2"                          \
+                           : "+m" (_proxy_pda.field)                   \
+                           :"ri" ((T__)val),                           \
+                            "i"(pda_offset(field)));                   \
+                       break;                                          \
+               case 2:                                                 \
+                       asm(op "w %1,%%gs:%c2"                          \
+                           : "+m" (_proxy_pda.field)                   \
+                           :"ri" ((T__)val),                           \
+                            "i"(pda_offset(field)));                   \
+                       break;                                          \
+               case 4:                                                 \
+                       asm(op "l %1,%%gs:%c2"                          \
+                           : "+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 1:                                                 \
+                       asm(op "b %%gs:%c1,%0"                          \
+                           : "=r" (ret__)                              \
+                           : "i" (pda_offset(field)),                  \
+                             "m" (_proxy_pda.field));                  \
+                       break;                                          \
+               case 2:                                                 \
+                       asm(op "w %%gs:%c1,%0"                          \
+                           : "=r" (ret__)                              \
+                           : "i" (pda_offset(field)),                  \
+                             "m" (_proxy_pda.field));                  \
+                       break;                                          \
+               case 4:                                                 \
+                       asm(op "l %%gs:%c1,%0"                          \
+                           : "=r" (ret__)                              \
+                           : "i" (pda_offset(field)),                  \
+                             "m" (_proxy_pda.field));                  \
+                       break;                                          \
+               default: __bad_pda_field();                             \
+               }                                                       \
+               ret__; })
+
+/* Return a pointer to a pda field */
+#define pda_addr(field)                                                        \
+       ((typeof(_proxy_pda.field) *)((unsigned char *)read_pda(_pda) + \
+                                     pda_offset(field)))
+
+#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 /* _I386_PDA_H */