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

Annotation of prex-old/sys/arch/i386/i386/cpu.c, Revision 1.1.1.1.2.1

1.1       nbrk        1: /*-
                      2:  * Copyright (c) 2005-2007, 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: /*
                     31:  * cpu.c - cpu dependent routines for Intel x86
                     32:  */
                     33:
                     34: #include <kernel.h>
                     35: #include <page.h>
                     36: #include <cpu.h>
                     37: #include <locore.h>
                     38:
                     39: typedef void (*trapfn_t)(void);
                     40:
                     41: /*
                     42:  * Descriptors
                     43:  */
                     44: static struct seg_desc gdt[NGDTS];
                     45: static struct gate_desc idt[NIDTS];
                     46: static struct tss tss;
                     47:
                     48: /*
                     49:  * Interrupt table
                     50:  */
                     51: static const trapfn_t intr_table[] = {
                     52:        intr_0, intr_1, intr_2, intr_3, intr_4, intr_5, intr_6,
                     53:        intr_7, intr_8, intr_9, intr_10, intr_11, intr_12, intr_13,
                     54:        intr_14, intr_15
                     55: };
                     56:
                     57: /*
                     58:  * Trap table
                     59:  */
                     60: static const trapfn_t trap_table[] = {
                     61:        trap_0, trap_1, trap_2, trap_3, trap_4, trap_5, trap_6,
                     62:        trap_7, trap_8, trap_9, trap_10, trap_11, trap_12, trap_13,
                     63:        trap_14, trap_15, trap_16, trap_17, trap_18
                     64: };
                     65: #define NTRAPS (int)(sizeof(trap_table) / sizeof(void *))
                     66:
                     67: /*
                     68:  * Set kernel stack pointer in TSS (task state segment).
                     69:  * An actual value of the register is automatically set when
                     70:  * CPU enters kernel mode next time.
                     71:  */
                     72: void
1.1.1.1.2.1! nbrk       73: tss_set(uint32_t kstack)
1.1       nbrk       74: {
                     75:
                     76:        tss.esp0 = kstack;
                     77: }
                     78:
                     79: /*
                     80:  * tss_get() returns current esp0 value for trap handler.
                     81:  */
1.1.1.1.2.1! nbrk       82: uint32_t
1.1       nbrk       83: tss_get(void)
                     84: {
                     85:
                     86:        return tss.esp0;
                     87: }
                     88:
                     89: /*
                     90:  * Set GDT (global descriptor table) members into specified vector
                     91:  */
                     92: static void
1.1.1.1.2.1! nbrk       93: gdt_set(int vec, void *base, size_t limit, int type, u_int size)
1.1       nbrk       94: {
                     95:        struct seg_desc *seg = &gdt[vec];
                     96:
                     97:        if (limit > 0xfffff) {
                     98:                limit >>= 12;
                     99:                size |= SIZE_4K;
                    100:        }
                    101:        seg->limit_lo = limit;
1.1.1.1.2.1! nbrk      102:        seg->base_lo = (u_int)base & 0xffff;
        !           103:        seg->base_mid = ((u_int)base >> 16) & 0xff;
1.1       nbrk      104:        seg->limit_hi = limit >> 16;
1.1.1.1.2.1! nbrk      105:        seg->base_hi = (u_int)base >> 24;
        !           106:        seg->type = (u_int)type | ST_PRESENT;
1.1       nbrk      107:        seg->size = size;
                    108: }
                    109:
                    110: /*
                    111:  * Set IDT (interrupt descriptor table) members into specified vector
                    112:  */
                    113: static void
1.1.1.1.2.1! nbrk      114: idt_set(int vec, trapfn_t off, u_int sel, int type)
1.1       nbrk      115: {
                    116:        struct gate_desc *gate = &idt[vec];
                    117:
1.1.1.1.2.1! nbrk      118:        gate->offset_lo = (u_int)off & 0xffff;
1.1       nbrk      119:        gate->selector = sel;
                    120:        gate->nr_copy = 0;
1.1.1.1.2.1! nbrk      121:        gate->type = (u_int)type | ST_PRESENT;
        !           122:        gate->offset_hi = (u_int)off >> 16;
1.1       nbrk      123: }
                    124:
                    125: /*
                    126:  * Setup the GDT and load it.
                    127:  */
                    128: static void
                    129: gdt_init(void)
                    130: {
                    131:        struct desc_p gdt_p;
                    132:
                    133:        /* Set system vectors */
                    134:        gdt_set(KERNEL_CS / 8, 0, 0xffffffff, ST_KERN | ST_CODE_R, SIZE_32);
                    135:        gdt_set(KERNEL_DS / 8, 0, 0xffffffff, ST_KERN | ST_DATA_W, SIZE_32);
                    136:        gdt_set(USER_CS / 8, 0, 0xffffffff, ST_USER | ST_CODE_R, SIZE_32);
                    137:        gdt_set(USER_DS / 8, 0, 0xffffffff, ST_USER | ST_DATA_W, SIZE_32);
                    138:
                    139:        /* Clear TSS Busy */
                    140:        gdt[KERNEL_TSS / 8].type &= ~ST_TSS_BUSY;
                    141:
                    142:        /* Load GDT */
1.1.1.1.2.1! nbrk      143:        gdt_p.limit = (uint16_t)(sizeof(gdt) - 1);
        !           144:        gdt_p.base = (uint32_t)&gdt;
1.1       nbrk      145:        lgdt(&gdt_p);
                    146: }
                    147:
                    148: /*
                    149:  * Setup the interrupt descriptor table and load it.
                    150:  *
                    151:  * IDT layout:
                    152:  *  0x00 - 0x12 ... S/W trap
                    153:  *  0x13 - 0x1f ... Intel reserved
                    154:  *  0x20 - 0x3f ... H/W interrupt
                    155:  *  0x40        ... System call trap
                    156:  */
                    157: static void
                    158: idt_init(void)
                    159: {
                    160:        struct desc_p idt_p;
                    161:        int i;
                    162:
                    163:        /* Fill all vectors with default handler */
                    164:        for (i = 0; i < NIDTS; i++)
                    165:                idt_set(i, trap_default, KERNEL_CS, ST_KERN | ST_TRAP_GATE);
                    166:
                    167:        /* Setup trap handlers */
                    168:        for (i = 0; i < NTRAPS; i++)
                    169:                idt_set(i, trap_table[i], KERNEL_CS, ST_KERN | ST_TRAP_GATE);
                    170:
                    171:        /* Setup interrupt handlers */
                    172:        for (i = 0; i < 16; i++)
                    173:                idt_set(0x20 + i, intr_table[i], KERNEL_CS,
                    174:                        ST_KERN | ST_INTR_GATE);
                    175:
                    176:        /* Setup debug trap */
                    177:        idt_set(3, trap_3, KERNEL_CS, ST_USER | ST_TRAP_GATE);
                    178:
                    179:        /* Setup system call handler */
                    180:        idt_set(SYSCALL_INT, syscall_entry, KERNEL_CS,
                    181:                ST_USER | ST_TRAP_GATE);
                    182:
                    183:        /* Load IDT */
1.1.1.1.2.1! nbrk      184:        idt_p.limit = (uint16_t)(sizeof(idt) - 1);
        !           185:        idt_p.base = (uint32_t)&idt;
1.1       nbrk      186:        lidt(&idt_p);
                    187: }
                    188:
                    189: /*
                    190:  * Initialize the task state segment.
                    191:  * Only one static TSS is used for all contexts.
                    192:  */
                    193: static void
                    194: tss_init(void)
                    195: {
                    196:
                    197:        gdt_set(KERNEL_TSS / 8, &tss, sizeof(struct tss) - 1,
                    198:                ST_KERN | ST_TSS, 0);
                    199:        /* Setup TSS */
                    200:        memset(&tss, 0, sizeof(struct tss));
                    201:        tss.ss0 = KERNEL_DS;
1.1.1.1.2.1! nbrk      202:        tss.esp0 = (uint32_t)phys_to_virt(BOOT_STACK + 0x800 - 1);
        !           203:        tss.cs = (uint32_t)USER_CS | 3;
        !           204:        tss.ds = tss.es = tss.ss = tss.fs = tss.gs = (uint32_t)USER_CS | 3;
1.1       nbrk      205:        tss.io_bitmap_offset = INVALID_IO_BITMAP;
                    206:        ltr(KERNEL_TSS);
                    207: }
                    208:
                    209: /*
                    210:  * Set trap handler for GDB
                    211:  */
                    212: void
1.1.1.1.2.1! nbrk      213: trap_set(int vec, void (*handler)(void))
1.1       nbrk      214: {
                    215:        struct desc_p idt_p;
                    216:
                    217:        idt_set(vec, (trapfn_t)handler, KERNEL_CS, ST_KERN | ST_TRAP_GATE);
1.1.1.1.2.1! nbrk      218:        idt_p.limit = (uint16_t)(sizeof(idt) - 1);
        !           219:        idt_p.base = (uint32_t)&idt;
1.1       nbrk      220:        lidt(&idt_p);
                    221: }
                    222:
                    223: /*
                    224:  * Initialize CPU state.
                    225:  * Setup segment and interrupt descriptor.
                    226:  */
                    227: void
                    228: cpu_init(void)
                    229: {
                    230:
                    231:        /* Enable write protection from kernel code */
                    232:        set_cr0(get_cr0() | CR0_WP);
                    233:
                    234:        /*
                    235:         * Setup flag register.
                    236:         * Interrupt disable, clear direction, clear nested
                    237:         * task, i/o privilege 0
                    238:         */
                    239:        set_eflags(get_eflags() & ~(EFL_IF | EFL_DF | EFL_NT | EFL_IOPL));
                    240:
                    241:        /*
                    242:         * Initialize descriptors.
                    243:         * Setup segment and interrupt descriptor.
                    244:         */
                    245:        gdt_init();
                    246:        idt_init();
                    247:        tss_init();
                    248: }

CVSweb