xref: /xv6-public/x86.h (revision 31085bb4)
1 // Special assembly routines to access x86-specific
2 // hardware instructions.
3 
4 static __inline uchar
5 inb(int port)
6 {
7   uchar data;
8   __asm __volatile("inb %w1,%0" : "=a" (data) : "d" (port));
9   return data;
10 }
11 
12 static __inline void
13 insl(int port, void *addr, int cnt)
14 {
15   __asm __volatile("cld\n\trepne\n\tinsl"     :
16                    "=D" (addr), "=c" (cnt)    :
17                    "d" (port), "0" (addr), "1" (cnt)  :
18                    "memory", "cc");
19 }
20 
21 static __inline void
22 outb(int port, uchar data)
23 {
24   __asm __volatile("outb %0,%w1" : : "a" (data), "d" (port));
25 }
26 
27 static __inline void
28 outw(int port, ushort data)
29 {
30   __asm __volatile("outw %0,%w1" : : "a" (data), "d" (port));
31 }
32 
33 static __inline void
34 outsl(int port, const void *addr, int cnt)
35 {
36   __asm __volatile("cld\n\trepne\n\toutsl"    :
37                    "=S" (addr), "=c" (cnt)    :
38                    "d" (port), "0" (addr), "1" (cnt)  :
39                    "cc");
40 }
41 
42 struct segdesc;
43 
44 static __inline void
45 lgdt(struct segdesc *p, int size)
46 {
47   volatile ushort pd[3];
48 
49   pd[0] = size-1;
50   pd[1] = (uint)p;
51   pd[2] = (uint)p >> 16;
52 
53   asm volatile("lgdt (%0)" : : "g" (pd));
54 }
55 
56 struct gatedesc;
57 
58 static __inline void
59 lidt(struct gatedesc *p, int size)
60 {
61   volatile ushort pd[3];
62 
63   pd[0] = size-1;
64   pd[1] = (uint)p;
65   pd[2] = (uint)p >> 16;
66 
67   asm volatile("lidt (%0)" : : "g" (pd));
68 }
69 
70 static __inline void
71 ltr(ushort sel)
72 {
73   __asm __volatile("ltr %0" : : "r" (sel));
74 }
75 
76 static __inline uint
77 read_eflags(void)
78 {
79   uint eflags;
80   __asm __volatile("pushfl; popl %0" : "=r" (eflags));
81   return eflags;
82 }
83 
84 static __inline void
85 write_eflags(uint eflags)
86 {
87   __asm __volatile("pushl %0; popfl" : : "r" (eflags));
88 }
89 
90 static __inline void
91 cpuid(uint info, uint *eaxp, uint *ebxp, uint *ecxp, uint *edxp)
92 {
93   uint eax, ebx, ecx, edx;
94   asm volatile("cpuid" :
95                "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx) :
96                "a" (info));
97   if(eaxp)
98     *eaxp = eax;
99   if(ebxp)
100     *ebxp = ebx;
101   if(ecxp)
102     *ecxp = ecx;
103   if(edxp)
104     *edxp = edx;
105 }
106 
107 static __inline uint
108 cmpxchg(uint oldval, uint newval, volatile uint* lock_addr)
109 {
110   uint result;
111   __asm__ __volatile__("lock; cmpxchgl %2, %0" :
112                        "+m" (*lock_addr), "=a" (result) :
113                        "r"(newval), "1"(oldval) :
114                        "cc");
115   return result;
116 }
117 
118 static __inline void
119 cli(void)
120 {
121   __asm__ volatile("cli");
122 }
123 
124 static __inline void
125 sti(void)
126 {
127   __asm__ volatile("sti");
128 }
129 
130 // Layout of the trap frame on the stack upon entry to trap.
131 struct trapframe {
132   // registers as pushed by pusha
133   uint edi;
134   uint esi;
135   uint ebp;
136   uint oesp;      // useless & ignored
137   uint ebx;
138   uint edx;
139   uint ecx;
140   uint eax;
141 
142   // rest of trap frame
143   ushort es;
144   ushort padding1;
145   ushort ds;
146   ushort padding2;
147   uint trapno;
148 
149   // below here defined by x86 hardware
150   uint err;
151   uint eip;
152   ushort cs;
153   ushort padding3;
154   uint eflags;
155 
156   // below here only when crossing rings, such as from user to kernel
157   uint esp;
158   ushort ss;
159   ushort padding4;
160 };
161