summaryrefslogtreecommitdiffstats
path: root/include/asm-i386/system.h
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>1995-11-14 08:00:00 +0000
committer <ralf@linux-mips.org>1995-11-14 08:00:00 +0000
commite7c2a72e2680827d6a733931273a93461c0d8d1b (patch)
treec9abeda78ef7504062bb2e816bcf3e3c9d680112 /include/asm-i386/system.h
parentec6044459060a8c9ce7f64405c465d141898548c (diff)
Import of Linux/MIPS 1.3.0
Diffstat (limited to 'include/asm-i386/system.h')
-rw-r--r--include/asm-i386/system.h184
1 files changed, 156 insertions, 28 deletions
diff --git a/include/asm-i386/system.h b/include/asm-i386/system.h
index 23af2e513..b4108d511 100644
--- a/include/asm-i386/system.h
+++ b/include/asm-i386/system.h
@@ -3,23 +3,125 @@
#include <asm/segment.h>
-#define move_to_user_mode() \
-__asm__ __volatile__ ("movl %%esp,%%eax\n\t" \
- "pushl %0\n\t" \
- "pushl %%eax\n\t" \
- "pushfl\n\t" \
- "pushl %1\n\t" \
- "pushl $1f\n\t" \
- "iret\n" \
- "1:\tmovl %0,%%eax\n\t" \
- "mov %%ax,%%ds\n\t" \
- "mov %%ax,%%es\n\t" \
- "mov %%ax,%%fs\n\t" \
- "mov %%ax,%%gs" \
- : /* no outputs */ :"i" (USER_DS), "i" (USER_CS):"ax")
+/*
+ * Entry into gdt where to find first TSS. GDT layout:
+ * 0 - nul
+ * 1 - kernel code segment
+ * 2 - kernel data segment
+ * 3 - user code segment
+ * 4 - user data segment
+ * ...
+ * 8 - TSS #0
+ * 9 - LDT #0
+ * 10 - TSS #1
+ * 11 - LDT #1
+ */
+#define FIRST_TSS_ENTRY 8
+#define FIRST_LDT_ENTRY (FIRST_TSS_ENTRY+1)
+#define _TSS(n) ((((unsigned long) n)<<4)+(FIRST_TSS_ENTRY<<3))
+#define _LDT(n) ((((unsigned long) n)<<4)+(FIRST_LDT_ENTRY<<3))
+#define load_TR(n) __asm__("ltr %%ax": /* no output */ :"a" (_TSS(n)))
+#define load_ldt(n) __asm__("lldt %%ax": /* no output */ :"a" (_LDT(n)))
+#define store_TR(n) \
+__asm__("str %%ax\n\t" \
+ "subl %2,%%eax\n\t" \
+ "shrl $4,%%eax" \
+ :"=a" (n) \
+ :"0" (0),"i" (FIRST_TSS_ENTRY<<3))
+
+/* This special macro can be used to load a debugging register */
+
+#define loaddebug(register) \
+ __asm__("movl %0,%%edx\n\t" \
+ "movl %%edx,%%db" #register "\n\t" \
+ : /* no output */ \
+ :"m" (current->debugreg[register]) \
+ :"dx");
+
+
+/*
+ * switch_to(n) should switch tasks to task nr n, first
+ * checking that n isn't the current task, in which case it does nothing.
+ * This also clears the TS-flag if the task we switched to has used
+ * the math co-processor latest.
+ *
+ * It also reloads the debug regs if necessary..
+ */
+#define switch_to(tsk) do { \
+__asm__("cli\n\t" \
+ "xchgl %%ecx,_current\n\t" \
+ "ljmp %0\n\t" \
+ "sti\n\t" \
+ "cmpl %%ecx,_last_task_used_math\n\t" \
+ "jne 1f\n\t" \
+ "clts\n" \
+ "1:" \
+ : /* no output */ \
+ :"m" (*(((char *)&tsk->tss.tr)-4)), \
+ "c" (tsk) \
+ :"cx"); \
+ /* Now maybe reload the debug registers */ \
+ if(current->debugreg[7]){ \
+ loaddebug(0); \
+ loaddebug(1); \
+ loaddebug(2); \
+ loaddebug(3); \
+ loaddebug(6); \
+ } \
+} while (0)
+
+#define _set_base(addr,base) \
+__asm__("movw %%dx,%0\n\t" \
+ "rorl $16,%%edx\n\t" \
+ "movb %%dl,%1\n\t" \
+ "movb %%dh,%2" \
+ : /* no output */ \
+ :"m" (*((addr)+2)), \
+ "m" (*((addr)+4)), \
+ "m" (*((addr)+7)), \
+ "d" (base) \
+ :"dx")
+
+#define _set_limit(addr,limit) \
+__asm__("movw %%dx,%0\n\t" \
+ "rorl $16,%%edx\n\t" \
+ "movb %1,%%dh\n\t" \
+ "andb $0xf0,%%dh\n\t" \
+ "orb %%dh,%%dl\n\t" \
+ "movb %%dl,%1" \
+ : /* no output */ \
+ :"m" (*(addr)), \
+ "m" (*((addr)+6)), \
+ "d" (limit) \
+ :"dx")
+
+#define set_base(ldt,base) _set_base( ((char *)&(ldt)) , base )
+#define set_limit(ldt,limit) _set_limit( ((char *)&(ldt)) , (limit-1)>>12 )
+
+static inline unsigned long _get_base(char * addr)
+{
+ unsigned long __base;
+ __asm__("movb %3,%%dh\n\t"
+ "movb %2,%%dl\n\t"
+ "shll $16,%%edx\n\t"
+ "movw %1,%%dx"
+ :"=&d" (__base)
+ :"m" (*((addr)+2)),
+ "m" (*((addr)+4)),
+ "m" (*((addr)+7)));
+ return __base;
+}
+
+#define get_base(ldt) _get_base( ((char *)&(ldt)) )
+
+static inline unsigned long get_limit(unsigned long segment)
+{
+ unsigned long __limit;
+ __asm__("lsll %1,%0"
+ :"=r" (__limit):"r" (segment));
+ return __limit+1;
+}
-#define sti() __asm__ __volatile__ ("sti": : :"memory")
-#define cli() __asm__ __volatile__ ("cli": : :"memory")
#define nop() __asm__ __volatile__ ("nop")
/*
@@ -36,23 +138,37 @@ __asm__ __volatile__ ( \
:"ax")
+extern inline unsigned long xchg_u8(char * m, unsigned long val)
+{
+ __asm__("xchgb %b0,%1":"=q" (val),"=m" (*m):"0" (val):"memory");
+ return val;
+}
+
+extern inline unsigned long xchg_u16(short * m, unsigned long val)
+{
+ __asm__("xchgw %w0,%1":"=r" (val),"=m" (*m):"0" (val):"memory");
+ return val;
+}
+
+extern inline unsigned long xchg_u32(int * m, unsigned long val)
+{
+ __asm__("xchgl %0,%1":"=r" (val),"=m" (*m):"0" (val):"memory");
+ return val;
+}
+
extern inline int tas(char * m)
{
- char res;
+ return xchg_u8(m,1);
+}
- __asm__("xchgb %0,%1":"=q" (res),"=m" (*m):"0" (0x1));
- return res;
+extern inline void * xchg_ptr(void * m, void * val)
+{
+ return (void *) xchg_u32(m, (unsigned long) val);
}
-/*
- * atomic exchange
- */
-#define atomic_exchange(m,r) \
- __asm__ __volatile__( \
- "xchgl %0,%2" \
- : "=r" ((r)) \
- : "0" ((r)), "m" (*(m)) \
- : "memory");
+#define mb() __asm__ __volatile__ ("" : : :"memory")
+#define sti() __asm__ __volatile__ ("sti": : :"memory")
+#define cli() __asm__ __volatile__ ("cli": : :"memory")
#define save_flags(x) \
__asm__ __volatile__("pushfl ; popl %0":"=r" (x): /* no input */ :"memory")
@@ -113,5 +229,17 @@ __asm__ __volatile__ ("movw $" #limit ",%1\n\t" \
#define set_ldt_desc(n,addr,size) \
_set_tssldt_desc(((char *) (n)),((int)(addr)),((size << 3) - 1),"0x82")
+/*
+ * This is the ldt that every process will get unless we need
+ * something other than this.
+ */
+extern struct desc_struct default_ldt;
+
+/*
+ * disable hlt during certain critical i/o operations
+ */
+#define HAVE_DISABLE_HLT
+void disable_hlt(void);
+void enable_hlt(void);
#endif