Annotation of prex-old/sys/arch/i386/include/cpu.h, Revision 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