[BACK]Return to cpu.h CVS log [TXT][DIR] Up to [local] / prex-old / sys / arch / i386 / include

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