Annotation of prex-old/sys/arch/i386/include/cpu.h, Revision 1.1.1.1
1.1 nbrk 1: /*
2: * Copyright (c) 2005, Kohsuke Ohtani
3: * All rights reserved.
4: *
5: * Redistribution and use in source and binary forms, with or without
6: * modification, are permitted provided that the following conditions
7: * are met:
8: * 1. Redistributions of source code must retain the above copyright
9: * notice, this list of conditions and the following disclaimer.
10: * 2. Redistributions in binary form must reproduce the above copyright
11: * notice, this list of conditions and the following disclaimer in the
12: * documentation and/or other materials provided with the distribution.
13: * 3. Neither the name of the author nor the names of any co-contributors
14: * may be used to endorse or promote products derived from this software
15: * without specific prior written permission.
16: *
17: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20: * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27: * SUCH DAMAGE.
28: */
29:
30: #ifndef _I386_CPU_H
31: #define _I386_CPU_H
32:
33: #include <sys/cdefs.h> /* for __packed */
34:
35: /*
36: * GDTs
37: */
38: #define KERNEL_CS 0x10
39: #define KERNEL_DS 0x18
40: #define USER_CS 0x20
41: #define USER_DS 0x28
42: #define KERNEL_TSS 0x38
43:
44: #define NGDTS 8
45:
46: /*
47: * IDTs
48: */
49: #define NIDTS 0x41
50: #define SYSCALL_INT 0x40
51: #define INVALID_INT 0xFF
52:
53:
54: #ifndef __ASSEMBLY__
55:
56: /*
57: * Segment Descriptor
58: */
59: struct seg_desc {
60: int limit_lo:16; /* segment limit (lsb) */
61: int base_lo:24; /* segment base address (lsb) */
62: int type:8; /* type */
63: int limit_hi:4; /* segment limit (msb) */
64: int size:4; /* size */
65: int base_hi:8; /* segment base address (msb) */
66: } __packed;
67:
68: /*
69: * Gate Descriptor
70: */
71: struct gate_desc {
72: int offset_lo:16; /* gate offset (lsb) */
73: int selector:16; /* gate segment selector */
74: int nr_copy:8; /* stack copy count */
75: int type:8; /* type */
76: int offset_hi:16; /* gate offset (msb) */
77: } __packed;
78:
79: /*
80: * Linear memory description for lgdt and lidt instructions.
81: */
82: struct desc_p {
83: u_short limit;
84: u_long base;
85: } __packed;
86:
87: /*
88: * Segment size
89: */
90: #define SIZE_32 0x4 /* 32-bit segment */
91: #define SIZE_16 0x0 /* 16-bit segment */
92: #define SIZE_4K 0x8 /* 4K limit field */
93:
94: /*
95: * Segment type
96: */
97: #define ST_ACC 0x01 /* accessed */
98: #define ST_LDT 0x02 /* LDT */
99: #define ST_CALL_GATE_16 0x04 /* 16-bit call gate */
100: #define ST_TASK_GATE 0x05 /* task gate */
101: #define ST_TSS 0x09 /* task segment */
102: #define ST_CALL_GATE 0x0c /* call gate */
103: #define ST_INTR_GATE 0x0e /* interrupt gate */
104: #define ST_TRAP_GATE 0x0f /* trap gate */
105:
106: #define ST_TSS_BUSY 0x02 /* task busy */
107:
108: #define ST_DATA 0x10 /* data */
109: #define ST_DATA_W 0x12 /* data, writable */
110: #define ST_DATA_E 0x14 /* data, expand-down */
111: #define ST_DATA_EW 0x16 /* data, expand-down, writable */
112:
113: #define ST_CODE 0x18 /* code */
114: #define ST_CODE_R 0x1a /* code, readable */
115: #define ST_CODE_C 0x1c /* code, conforming */
116: #define ST_CODE_CR 0x1e /* code, conforming, readable */
117:
118: #define ST_KERN 0x00 /* kernel access only */
119: #define ST_USER 0x60 /* user access */
120:
121: #define ST_PRESENT 0x80 /* segment present */
122:
123: /*
124: * Task State Segment (TSS)
125: */
126:
127: #define IO_BITMAP_SIZE (65536/8 + 1)
128: #define INVALID_IO_BITMAP 0x8000
129:
130: struct tss {
131: u_long back_link;
132: u_long esp0, ss0;
133: u_long esp1, ss1;
134: u_long esp2, ss2;
135: u_long cr3;
136: u_long eip;
137: u_long eflags;
138: u_long eax, ecx, edx, ebx;
139: u_long esp, ebp, esi, edi;
140: u_long es, cs, ss, ds, fs, gs;
141: u_long ldt;
142: u_short dbg_trace;
143: u_short io_bitmap_offset;
144: #if 0
145: u_long io_bitmap[IO_BITMAP_SIZE/4+1];
146: u_long pad[5];
147: #endif
148: } __packed;
149:
150: /*
151: * i386 flags register
152: */
153: #define EFL_CF 0x00000001 /* Carry */
154: #define EFL_PF 0x00000004 /* Parity */
155: #define EFL_AF 0x00000010 /* Carry */
156: #define EFL_ZF 0x00000040 /* Zero */
157: #define EFL_SF 0x00000080 /* Sign */
158: #define EFL_TF 0x00000100 /* Trap */
159: #define EFL_IF 0x00000200 /* Interrupt enable */
160: #define EFL_DF 0x00000400 /* Direction */
161: #define EFL_OF 0x00000800 /* Overflow */
162: #define EFL_IOPL 0x00003000 /* IO privilege level: */
163: #define EFL_IOPL_KERN 0x00000000 /* Kernel */
164: #define EFL_IOPL_USER 0x00003000 /* User */
165: #define EFL_NT 0x00004000 /* Nested task */
166: #define EFL_RF 0x00010000 /* Resume without tracing */
167: #define EFL_VM 0x00020000 /* Virtual 8086 mode */
168: #define EFL_AC 0x00040000 /* Alignment Check */
169:
170: /*
171: * CR0 register
172: */
173: #define CR0_PG 0x80000000 /* enable paging */
174: #define CR0_CD 0x40000000 /* cache disable */
175: #define CR0_NW 0x20000000 /* no write-through */
176: #define CR0_AM 0x00040000 /* alignment check mask */
177: #define CR0_WP 0x00010000 /* write-protect kernel access */
178: #define CR0_NE 0x00000020 /* handle numeric exceptions */
179: #define CR0_ET 0x00000010 /* extension type is 80387 coprocessor */
180: #define CR0_TS 0x00000008 /* task switch */
181: #define CR0_EM 0x00000004 /* emulate coprocessor */
182: #define CR0_MP 0x00000002 /* monitor coprocessor */
183: #define CR0_PE 0x00000001 /* enable protected mode */
184:
185: /*
186: * Page table (PTE)
187: */
188: typedef long *page_table_t;
189:
190: /*
191: * Page directory entry
192: */
193: #define PDE_PRESENT 0x00000001
194: #define PDE_WRITE 0x00000002
195: #define PDE_USER 0x00000004
196: #define PDE_WTHRU 0x00000008
197: #define PDE_NCACHE 0x00000010
198: #define PDE_ACCESS 0x00000020
199: #define PDE_SIZE 0x00000080
200: #define PDE_AVAIL 0x00000e00
201: #define PDE_ADDRESS 0xfffff000
202:
203: /*
204: * Page table entry
205: */
206: #define PTE_PRESENT 0x00000001
207: #define PTE_WRITE 0x00000002
208: #define PTE_USER 0x00000004
209: #define PTE_WTHRU 0x00000008
210: #define PTE_NCACHE 0x00000010
211: #define PTE_ACCESS 0x00000020
212: #define PTE_DIRTY 0x00000040
213: #define PTE_AVAIL 0x00000e00
214: #define PTE_ADDRESS 0xfffff000
215:
216: /*
217: * Virtual and physical address translation
218: */
219: #define PAGE_DIR(virt) ((((u_long)(virt)) >> 22) & 0x3ff)
220: #define PAGE_TABLE(virt) ((((u_long)(virt)) >> 12) & 0x3ff)
221:
222: #define pte_present(pgd, virt) (pgd[PAGE_DIR(virt)] & PDE_PRESENT)
223:
224: #define page_present(pte, virt) (pte[PAGE_TABLE(virt)] & PTE_PRESENT)
225:
226: #define pgd_to_pte(pgd, virt) \
227: (page_table_t)phys_to_virt((pgd)[PAGE_DIR(virt)] & PDE_ADDRESS)
228:
229: #define pte_to_page(pte, virt) \
230: ((pte)[PAGE_TABLE(virt)] & PTE_ADDRESS)
231:
232:
233: /*
234: * Inline CPU functions
235: */
236:
237: static __inline void
238: ltr(u_int sel)
239: {
240: __asm__ __volatile__(
241: "ltr %%ax\n\t"
242: "jmp 1f\n\t"
243: "1:\n\t"
244: :
245: :"a" (sel));
246: }
247:
248: static __inline void
249: lgdt(void *gdt_ptr)
250: {
251: __asm__ __volatile__(
252: "lgdt (%%eax)\n\t"
253: "jmp 1f\n\t"
254: "1:\n\t"
255: :
256: :"a" (gdt_ptr));
257: }
258:
259: static __inline void
260: lidt(void *idt_ptr)
261: {
262: __asm__ __volatile__(
263: "lidt (%%eax)\n\t"
264: "jmp 1f\n\t"
265: "1:\n\t"
266: :
267: :"a" (idt_ptr));
268: }
269:
270: static __inline void
271: set_cs(u_short sel)
272: {
273: __asm__ __volatile__(
274: "movzx %%ax, %%eax\n\t"
275: "pushl %%eax\n\t"
276: "pushl $1f\n\t"
277: "lret\n\t"
278: "1:\n\t"
279: :
280: :"a" (sel));
281: }
282:
283: static __inline void
284: set_ds(u_short sel)
285: {
286: __asm__ __volatile__(
287: "movw %0, %%ds\n\t"
288: "movw %0, %%es\n\t"
289: "movw %0, %%fs\n\t"
290: "movw %0, %%gs\n\t"
291: "movw %0, %%ss\n\t"
292: :
293: :"r" (sel));
294: }
295:
296: static __inline void
297: set_esp(u_long val)
298: {
299: __asm__ __volatile__(
300: "movl %0, %%esp"
301: :
302: :"r" (val));
303: }
304:
305: static __inline u_long
306: get_esp(void)
307: {
308: register u_long esp;
309: __asm__ __volatile__(
310: "movl %%esp, %0"
311: :"=r" (esp));
312: return esp;
313: }
314:
315: static __inline u_long
316: get_eflags(void)
317: {
318: register u_long eflags;
319: __asm__ __volatile__(
320: "pushfl\n\t"
321: "popl %0\n\t"
322: :"=r" (eflags));
323: return eflags;
324: }
325:
326: static __inline void
327: set_eflags(u_long val)
328: {
329: __asm__ __volatile__(
330: "pushl %0\n\t"
331: "popfl\n\t"
332: :
333: :"r" (val));
334: }
335:
336: static __inline u_long
337: get_cr0(void)
338: {
339: register u_long _cr0;
340: __asm__ __volatile__(
341: "movl %%cr0, %0"
342: :"=r" (_cr0)
343: :);
344: return _cr0;
345: }
346:
347: static __inline void
348: set_cr0(u_long _cr0)
349: {
350: __asm__ __volatile__(
351: "movl %0, %%cr0"
352: :
353: :"r" (_cr0));
354: }
355:
356: static __inline u_long
357: get_cr2(void)
358: {
359: register u_long _cr2;
360: __asm__ __volatile__(
361: "movl %%cr2, %0"
362: :"=r" (_cr2)
363: :);
364: return _cr2;
365: }
366:
367: static __inline u_long
368: get_cr3(void)
369: {
370: register u_long _cr3;
371: __asm__ __volatile__(
372: "movl %%cr3, %0"
373: :"=r" (_cr3)
374: :);
375: return _cr3;
376: }
377:
378: static __inline void
379: set_cr3(u_long _cr3)
380: {
381: __asm__ __volatile__(
382: "movl %0, %%cr3"
383: :
384: :"r" (_cr3));
385: }
386:
387: /*
388: * Enable/disable CPU interrupt
389: */
390: #define sti() __asm__ ("sti"::)
391: #define cli() __asm__ ("cli"::)
392:
393: /*
394: * Flush translation lookaside buffer for
395: * specified page
396: */
397: static __inline void
398: flush_tlb_page(void *pg)
399: {
400: __asm__ __volatile__(
401: "invlpg (%0)"
402: :
403: : "r" (pg)
404: : "memory");
405: }
406:
407: /*
408: * Flush translation lookaside buffer
409: */
410: static __inline void
411: flush_tlb(void)
412: {
413: __asm__ __volatile__(
414: "movl %%cr3, %%eax\n\t"
415: "movl %%eax, %%cr3\n\t"
416: :
417: :
418: : "ax");
419: }
420:
421: /*
422: * Check if CPU supports "invlpg" (TLB flush per page) function.
423: * Return true if supported.
424: *
425: * TODO: I can not test this because I do not have 386 system. :-(
426: */
427: static __inline int
428: check_invlpg(void)
429: {
430: int _i486 = 0;
431:
432: __asm__ __volatile__(
433: "pushfl\n\t"
434: "popl %%eax\n\t"
435: "movl %%eax, %%ecx\n\t"
436: "xorl $0x240000, %%eax\n\t"
437: "pushl %%eax\n\t"
438: "popfl\n\t"
439: "pushfl\n\t"
440: "popl %%eax\n\t"
441: "xorl %%ecx, %%eax\n\t"
442: "pushl %%ecx\n\t"
443: "popfl\n\t"
444: "testl $0x40000, %%eax\n\t"
445: "je 1f\n\t"
446: "movl $1, %0\n\t"
447: "1:\n\t"
448: : "=r" (_i486)
449: :);
450: return _i486;
451: }
452:
453: /*
454: * I/O instructions
455: */
456: static __inline void
457: outb(unsigned char value, int port)
458: {
459: __asm__ __volatile__(
460: "outb %b0, %w1"
461: ::"a" (value),"Nd" (port));
462: }
463:
464: static __inline unsigned char
465: inb(int port)
466: {
467: unsigned char _val;
468: __asm__ __volatile__(
469: "inb %w1, %b0"
470: :"=a" (_val)
471: :"Nd" (port));
472: return _val;
473: }
474:
475: static __inline void
476: outb_p(unsigned char value, int port)
477: {
478: __asm__ __volatile__(
479: "outb %b0, %w1\n\t"
480: "outb %%al, $0x80\n\t"
481: ::"a" (value),"Nd" (port));
482: }
483:
484: static __inline unsigned char
485: inb_p(int port)
486: {
487: unsigned char _val;
488: __asm__ __volatile__(
489: "inb %w1, %b0\n\t"
490: "outb %%al, $0x80\n\t"
491: :"=a" (_val)
492: :"Nd" (port));
493: return _val;
494: }
495:
496: extern void tss_set(u_long kstack);
497: extern u_long tss_get(void);
498: extern void trap_set(int vector, void *handler);
499:
500: extern void cpu_reset(void);
501: extern void cpu_init(void);
502:
503: #endif /* !__ASSEMBLY__ */
504:
505: #endif /* !_I386_CPU_H */
CVSweb