📄 cpu.c
字号:
/*- * Copyright (c) 2005, Kohsuke Ohtani * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the author nor the names of any co-contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. *//* * cpu.c - cpu dependent routines for Intel x86 */#include <kernel.h>#include <page.h>#include "cpu.h"extern void trap_default(), syscall_entry();extern void intr_0(), intr_1(), intr_2(), intr_3(), intr_4(), intr_5(), intr_6(), intr_7(), intr_8(), intr_9(), intr_10(), intr_11(), intr_12(), intr_13(), intr_14(), intr_15();extern void trap_0(), trap_1(), trap_2(), trap_3(), trap_4(), trap_5(), trap_6(), trap_7(), trap_8(), trap_9(), trap_10(), trap_11(), trap_12(), trap_13(), trap_14(), trap_15(), trap_16(), trap_17(), trap_18();/* * Descriptors */static struct seg_desc gdt[NR_GDT];static struct gate_desc idt[NR_IDT];static struct tss tss;/* * Interrupt table */static void *const intr_table[] = { intr_0, intr_1, intr_2, intr_3, intr_4, intr_5, intr_6, intr_7, intr_8, intr_9, intr_10, intr_11, intr_12, intr_13, intr_14, intr_15};/* * Trap table */static void *const trap_table[] = { trap_0, trap_1, trap_2, trap_3, trap_4, trap_5, trap_6, trap_7, trap_8, trap_9, trap_10, trap_11, trap_12, trap_13, trap_14, trap_15, trap_16, trap_17, trap_18};#define NR_TRAP (sizeof(trap_table) / sizeof(void *))/* * Set kernel stack pointer in TSS (task state segment). * An actual value of the register is automatically set when * CPU enters kernel mode next time. */void tss_set(u_long kstack){ tss.esp0 = kstack;}/* * tss_get() returns current esp0 value for trap handler. */u_long tss_get(void){ return tss.esp0;}/* * Set GDT (global descriptor table) members into specified vector */static void gdt_set(int vec, void *base, size_t limit, int type, int size){ struct seg_desc *seg = &gdt[vec]; if (limit > 0xfffff) { limit >>= 12; size |= SIZE_4K; } seg->limit_lo = limit; seg->base_lo = (int)base; seg->type = type | ST_PRESENT; seg->limit_hi = limit >> 16; seg->size = size; seg->base_hi = (int)base >> 24;}/* * Set IDT (interrupt descriptor table) members into specified vector */static void idt_set(int vec, void *off, int sel, int type){ struct gate_desc *gate = &idt[vec]; gate->offset_lo = (int)off; gate->selector = sel; gate->nr_copy = 0; gate->type = type | ST_PRESENT; gate->offset_hi = (int)off >> 16;}/* * Setup the GDT and load it. */static void gdt_init(void){ struct desc_p gdt_p; /* Set system vectors */ gdt_set(KERNEL_CS / 8, 0, 0xffffffff, ST_KERN | ST_CODE_R, SIZE_32); gdt_set(KERNEL_DS / 8, 0, 0xffffffff, ST_KERN | ST_DATA_W, SIZE_32); gdt_set(USER_CS / 8, 0, 0xffffffff, ST_USER | ST_CODE_R, SIZE_32); gdt_set(USER_DS / 8, 0, 0xffffffff, ST_USER | ST_DATA_W, SIZE_32); /* Clear TSS Busy */ gdt[KERNEL_TSS / 8].type &= ~ST_TSS_BUSY; /* Load GDT */ gdt_p.limit = sizeof(gdt) - 1; gdt_p.base = (u_long)&gdt; lgdt(&gdt_p); /* Reset code, data and stack selectors */ set_cs(KERNEL_CS); set_ds(KERNEL_DS);}/* * Setup the interrupt descriptor table and load it. * * IDT layout: * 0x00 - 0x12 ... S/W trap * 0x13 - 0x1f ... Intel reserved * 0x20 - 0x3f ... H/W interrupt * 0x40 ... System call trap */static void idt_init(void){ struct desc_p idt_p; int i; /* Fill all vectors with default handler */ for (i = 0; i < NR_IDT; i++) idt_set(i, trap_default, KERNEL_CS, ST_KERN | ST_TRAP_GATE); /* Setup trap handlers */ for (i = 0; i < NR_TRAP; i++) idt_set(i, trap_table[i], KERNEL_CS, ST_KERN | ST_TRAP_GATE); /* Setup interrupt handlers */ for (i = 0; i < 16; i++) idt_set(0x20 + i, intr_table[i], KERNEL_CS, ST_KERN | ST_INTR_GATE); /* Setup debug trap */ idt_set(3, trap_3, KERNEL_CS, ST_USER | ST_TRAP_GATE); /* Setup system call handler */ idt_set(SYSCALL_INT, syscall_entry, KERNEL_CS, ST_USER | ST_TRAP_GATE); /* Load IDT */ idt_p.limit = sizeof(idt) - 1; idt_p.base = (u_long)&idt; lidt(&idt_p);}/* * Initialize the task state segment. * Only one static TSS is used for all contexts. */static void tss_init(void){ gdt_set(KERNEL_TSS / 8, &tss, sizeof(struct tss) - 1, ST_KERN | ST_TSS, 0); /* Setup TSS */ memset(&tss, 0, sizeof(struct tss)); tss.ss0 = KERNEL_DS; tss.esp0 = (u_long)phys_to_virt(BOOT_STACK + BOOT_STACK_SIZE - 1); tss.cs = USER_CS | 3; tss.ds = tss.es = tss.ss = tss.fs = tss.gs = USER_CS | 3; tss.io_bitmap_offset = INVALID_IO_BITMAP; ltr(KERNEL_TSS);}#ifdef CONFIG_GDB/* * Set trap handler for GDB */void trap_set(int vec, void *handler){ struct desc_p idt_p; idt_set(vec, handler, KERNEL_CS, ST_KERN | ST_TRAP_GATE); idt_p.limit = sizeof(idt) - 1; idt_p.base = (u_long)&idt; lidt(&idt_p);}#endif/* * Initialize CPU state. * Setup segment and interrupt descriptor. */void cpu_init(void){ /* Enable write protection from kernel code */ set_cr0(get_cr0() | CR0_WP); /* * Setup flag register. * Interrupt disable, clear direction, clear nested * task, i/o privilege 0 */ set_eflags(get_eflags() & ~(EFL_IF | EFL_DF | EFL_NT | EFL_IOPL)); /* Initialize descriptors. */ gdt_init(); idt_init(); tss_init();}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -