xref: /xv6-public/x86.h (revision 8a8be1b8)
1 static __inline void breakpoint(void) __attribute__((always_inline));
2 static __inline uchar inb(int port) __attribute__((always_inline));
3 static __inline void insb(int port, void *addr, int cnt) __attribute__((always_inline));
4 static __inline ushort inw(int port) __attribute__((always_inline));
5 static __inline void insw(int port, void *addr, int cnt) __attribute__((always_inline));
6 static __inline uint inl(int port) __attribute__((always_inline));
7 static __inline void insl(int port, void *addr, int cnt) __attribute__((always_inline));
8 static __inline void outb(int port, uchar data) __attribute__((always_inline));
9 static __inline void outsb(int port, const void *addr, int cnt) __attribute__((always_inline));
10 static __inline void outw(int port, ushort data) __attribute__((always_inline));
11 static __inline void outsw(int port, const void *addr, int cnt) __attribute__((always_inline));
12 static __inline void outsl(int port, const void *addr, int cnt) __attribute__((always_inline));
13 static __inline void outl(int port, uint data) __attribute__((always_inline));
14 static __inline void invlpg(void *addr) __attribute__((always_inline));
15 struct segdesc;
16 static __inline void lgdt(struct segdesc *p, int) __attribute__((always_inline));
17 struct gatedesc;
18 static __inline void lidt(struct gatedesc *p, int) __attribute__((always_inline));
19 static __inline void lldt(ushort sel) __attribute__((always_inline));
20 static __inline void ltr(ushort sel) __attribute__((always_inline));
21 static __inline void lcr0(uint val) __attribute__((always_inline));
22 static __inline uint rcr0(void) __attribute__((always_inline));
23 static __inline uint rcr2(void) __attribute__((always_inline));
24 static __inline void lcr3(uint val) __attribute__((always_inline));
25 static __inline uint rcr3(void) __attribute__((always_inline));
26 static __inline void lcr4(uint val) __attribute__((always_inline));
27 static __inline uint rcr4(void) __attribute__((always_inline));
28 static __inline void tlbflush(void) __attribute__((always_inline));
29 static __inline uint read_eflags(void) __attribute__((always_inline));
30 static __inline void write_eflags(uint eflags) __attribute__((always_inline));
31 static __inline uint read_ebp(void) __attribute__((always_inline));
32 static __inline uint read_esp(void) __attribute__((always_inline));
33 static __inline void cpuid(uint info, uint *eaxp, uint *ebxp, uint *ecxp, uint *edxp);
34 static __inline void cli(void) __attribute__((always_inline));
35 static __inline void sti(void) __attribute__((always_inline));
36 
37 static __inline void
38 breakpoint(void)
39 {
40 	__asm __volatile("int3");
41 }
42 
43 static __inline uchar
44 inb(int port)
45 {
46 	uchar data;
47 	__asm __volatile("inb %w1,%0" : "=a" (data) : "d" (port));
48 	return data;
49 }
50 
51 static __inline void
52 insb(int port, void *addr, int cnt)
53 {
54 	__asm __volatile("cld\n\trepne\n\tinsb"			:
55 			 "=D" (addr), "=c" (cnt)		:
56 			 "d" (port), "0" (addr), "1" (cnt)	:
57 			 "memory", "cc");
58 }
59 
60 static __inline ushort
61 inw(int port)
62 {
63 	ushort data;
64 	__asm __volatile("inw %w1,%0" : "=a" (data) : "d" (port));
65 	return data;
66 }
67 
68 static __inline void
69 insw(int port, void *addr, int cnt)
70 {
71 	__asm __volatile("cld\n\trepne\n\tinsw"			:
72 			 "=D" (addr), "=c" (cnt)		:
73 			 "d" (port), "0" (addr), "1" (cnt)	:
74 			 "memory", "cc");
75 }
76 
77 static __inline uint
78 inl(int port)
79 {
80 	uint data;
81 	__asm __volatile("inl %w1,%0" : "=a" (data) : "d" (port));
82 	return data;
83 }
84 
85 static __inline void
86 insl(int port, void *addr, int cnt)
87 {
88 	__asm __volatile("cld\n\trepne\n\tinsl"			:
89 			 "=D" (addr), "=c" (cnt)		:
90 			 "d" (port), "0" (addr), "1" (cnt)	:
91 			 "memory", "cc");
92 }
93 
94 static __inline void
95 outb(int port, uchar data)
96 {
97 	__asm __volatile("outb %0,%w1" : : "a" (data), "d" (port));
98 }
99 
100 static __inline void
101 outsb(int port, const void *addr, int cnt)
102 {
103 	__asm __volatile("cld\n\trepne\n\toutsb"		:
104 			 "=S" (addr), "=c" (cnt)		:
105 			 "d" (port), "0" (addr), "1" (cnt)	:
106 			 "cc");
107 }
108 
109 static __inline void
110 outw(int port, ushort data)
111 {
112 	__asm __volatile("outw %0,%w1" : : "a" (data), "d" (port));
113 }
114 
115 static __inline void
116 outsw(int port, const void *addr, int cnt)
117 {
118 	__asm __volatile("cld\n\trepne\n\toutsw"		:
119 			 "=S" (addr), "=c" (cnt)		:
120 			 "d" (port), "0" (addr), "1" (cnt)	:
121 			 "cc");
122 }
123 
124 static __inline void
125 outsl(int port, const void *addr, int cnt)
126 {
127 	__asm __volatile("cld\n\trepne\n\toutsl"		:
128 			 "=S" (addr), "=c" (cnt)		:
129 			 "d" (port), "0" (addr), "1" (cnt)	:
130 			 "cc");
131 }
132 
133 static __inline void
134 outl(int port, uint data)
135 {
136 	__asm __volatile("outl %0,%w1" : : "a" (data), "d" (port));
137 }
138 
139 static __inline void
140 invlpg(void *addr)
141 {
142 	__asm __volatile("invlpg (%0)" : : "r" (addr) : "memory");
143 }
144 
145 static __inline void
146 lgdt(struct segdesc *p, int size)
147 {
148 	volatile ushort pd[3];
149 
150 	pd[0] = size-1;
151 	pd[1] = (uint)p;
152 	pd[2] = (uint)p >> 16;
153 
154 	asm volatile("lgdt (%0)" : : "g" (pd));
155 }
156 
157 static __inline void
158 lidt(struct gatedesc *p, int size)
159 {
160 	volatile ushort pd[3];
161 
162 	pd[0] = size-1;
163 	pd[1] = (uint)p;
164 	pd[2] = (uint)p >> 16;
165 
166 	asm volatile("lidt (%0)" : : "g" (pd));
167 }
168 
169 static __inline void
170 lldt(ushort sel)
171 {
172 	__asm __volatile("lldt %0" : : "r" (sel));
173 }
174 
175 static __inline void
176 ltr(ushort sel)
177 {
178 	__asm __volatile("ltr %0" : : "r" (sel));
179 }
180 
181 static __inline void
182 lcr0(uint val)
183 {
184 	__asm __volatile("movl %0,%%cr0" : : "r" (val));
185 }
186 
187 static __inline uint
188 rcr0(void)
189 {
190 	uint val;
191 	__asm __volatile("movl %%cr0,%0" : "=r" (val));
192 	return val;
193 }
194 
195 static __inline uint
196 rcr2(void)
197 {
198 	uint val;
199 	__asm __volatile("movl %%cr2,%0" : "=r" (val));
200 	return val;
201 }
202 
203 static __inline void
204 lcr3(uint val)
205 {
206 	__asm __volatile("movl %0,%%cr3" : : "r" (val));
207 }
208 
209 static __inline uint
210 rcr3(void)
211 {
212 	uint val;
213 	__asm __volatile("movl %%cr3,%0" : "=r" (val));
214 	return val;
215 }
216 
217 static __inline void
218 lcr4(uint val)
219 {
220 	__asm __volatile("movl %0,%%cr4" : : "r" (val));
221 }
222 
223 static __inline uint
224 rcr4(void)
225 {
226 	uint cr4;
227 	__asm __volatile("movl %%cr4,%0" : "=r" (cr4));
228 	return cr4;
229 }
230 
231 static __inline void
232 tlbflush(void)
233 {
234 	uint cr3;
235 	__asm __volatile("movl %%cr3,%0" : "=r" (cr3));
236 	__asm __volatile("movl %0,%%cr3" : : "r" (cr3));
237 }
238 
239 static __inline uint
240 read_eflags(void)
241 {
242         uint eflags;
243         __asm __volatile("pushfl; popl %0" : "=r" (eflags));
244         return eflags;
245 }
246 
247 static __inline void
248 write_eflags(uint eflags)
249 {
250         __asm __volatile("pushl %0; popfl" : : "r" (eflags));
251 }
252 
253 static __inline uint
254 read_ebp(void)
255 {
256         uint ebp;
257         __asm __volatile("movl %%ebp,%0" : "=r" (ebp));
258         return ebp;
259 }
260 
261 static __inline uint
262 read_esp(void)
263 {
264         uint esp;
265         __asm __volatile("movl %%esp,%0" : "=r" (esp));
266         return esp;
267 }
268 
269 static __inline uint
270 read_esi(void)
271 {
272         uint esi;
273         __asm __volatile("movl %%esi,%0" : "=r" (esi));
274         return esi;
275 }
276 
277 static __inline uint
278 read_edi(void)
279 {
280         uint edi;
281         __asm __volatile("movl %%edi,%0" : "=r" (edi));
282         return edi;
283 }
284 
285 static __inline uint
286 read_ebx(void)
287 {
288         uint ebx;
289         __asm __volatile("movl %%ebx,%0" : "=r" (ebx));
290         return ebx;
291 }
292 
293 static __inline void
294 cpuid(uint info, uint *eaxp, uint *ebxp, uint *ecxp, uint *edxp)
295 {
296 	uint eax, ebx, ecx, edx;
297 	asm volatile("cpuid"
298 		: "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx)
299 		: "a" (info));
300 	if (eaxp)
301 		*eaxp = eax;
302 	if (ebxp)
303 		*ebxp = ebx;
304 	if (ecxp)
305 		*ecxp = ecx;
306 	if (edxp)
307 		*edxp = edx;
308 }
309 
310 static __inline uint
311 cmpxchg(uint oldval, uint newval, volatile uint* lock_addr)
312 {
313   uint result;
314   __asm__ __volatile__(
315 		       "lock; cmpxchgl %2, %0"
316 		       :"+m" (*lock_addr), "=a" (result) : "r"(newval), "1"(oldval) : "cc"
317 		       );
318   return result;
319 }
320 
321 static __inline void
322 cli(void)
323 {
324 	__asm__ volatile("cli");
325 }
326 
327 static __inline void
328 sti(void)
329 {
330 	__asm__ volatile("sti");
331 }
332 
333 struct trapframe {
334     /* registers as pushed by pusha */
335     uint edi;
336     uint esi;
337     uint ebp;
338     uint oesp;      /* Useless */
339     uint ebx;
340     uint edx;
341     uint ecx;
342     uint eax;
343     /* rest of trap frame */
344     ushort es;
345     ushort padding1;
346     ushort ds;
347     ushort padding2;
348     uint trapno;
349     /* below here defined by x86 hardware */
350     uint err;
351     uint eip;
352     ushort cs;
353     ushort padding3;
354     uint eflags;
355     /* below here only when crossing rings, such as from user to kernel */
356     uint esp;
357     ushort ss;
358     ushort padding4;
359 };
360 
361 #define MAX_IRQS	16	// Number of IRQs
362 
363 #define IRQ_OFFSET      32	// IRQ 0 corresponds to int IRQ_OFFSET
364 
365 #define IRQ_KBD         1
366 #define IRQ_IDE         14
367 #define IRQ_ERROR       19
368 #define IRQ_SPURIOUS    31
369