Revision: 399 Author: nieklinnenbank Date: Mon Oct 18 16:41:04 2010 Log: Added functions for managing per-CPU Global Descriptor Table. http://code.google.com/p/freenos/source/detail?r=399 Added: /branches/scratch/include/x86/gdt.h /branches/scratch/system/x86/pc/gdt.c /branches/scratch/system/x86/pc/gdt_load.S ======================================= --- /dev/null +++ /branches/scratch/include/x86/gdt.h Mon Oct 18 16:41:04 2010 @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2010 Niek Linnenbank + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef __GDT_H +#define __GDT_H + +#include "types.h" +#include "macro.h" + +#define GDT_TYPE_CODE0 0x9a +#define GDT_TYPE_CODE3 0xfa +#define GDT_TYPE_DATA0 0x92 +#define GDT_TYPE_DATA3 0xf2 +#define GDT_TYPE_TSS0 0x89 + +#define GDT_MODE_32 (1 << 2) +#define GDT_GRAN_4K (1 << 3) + +typedef struct gdt_entry +{ + u16 limit_low; + u16 base_low; + u8 base_high1; + u8 type; + u8 limit_high:4; + u8 flags:4; + u8 base_high2; +} +PACKED gdt_entry_t; + +typedef struct gdt +{ + gdt_entry_t entries[6]; +} +PACKED gdt_t; + +typedef struct gdt_ptr +{ + u16 limit; + u32 base; +} +PACKED gdt_ptr_t; + +extern void gdt_init(void); +extern void gdt_load(gdt_ptr_t *ptr); +extern void gdt_set_entry(uint index, addr_t base, uint limit, uint type); + +#endif /* __GDT_H */ ======================================= --- /dev/null +++ /branches/scratch/system/x86/pc/gdt.c Mon Oct 18 16:41:04 2010 @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2010 Niek Linnenbank + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <FreeNOS/gdt.h> +#include <FreeNOS/tss.h> +#include <FreeNOS/smp.h> +#include <FreeNOS/cpu.h> +#include <FreeNOS/virt_memory.h> + +static gdt_t ALIGN(PAGE_SIZE) gdt[SMP_MAX]; +static gdt_ptr_t ALIGN(PAGE_SIZE) gdt_ptr[SMP_MAX]; + +void gdt_init(void) +{ + gdt_ptr_t *ptr = &gdt_ptr[smp_id()]; + + /* Setup GDT entries. */ + gdt_set_entry(0, 0, 0, 0); + gdt_set_entry(1, 0, 0xffffffff, GDT_TYPE_CODE0); + gdt_set_entry(2, 0, 0xffffffff, GDT_TYPE_DATA0); + gdt_set_entry(3, 0, 0xffffffff, GDT_TYPE_CODE3); + gdt_set_entry(4, 0, 0xffffffff, GDT_TYPE_DATA3); + gdt_set_entry(5, (addr_t)tss_get(), + sizeof(tss_t), GDT_TYPE_TSS0); + + /* Set GDT pointer. */ + ptr->base = (addr_t) &gdt[smp_id()]; + ptr->limit = sizeof(gdt_t); + + /* Load the GDT. */ + gdt_load(&gdt_ptr[smp_id()]); +} + +void gdt_set_entry(uint index, addr_t base, uint limit, uint type) +{ + gdt_entry_t *g = &(gdt[smp_id()].entries[index]); + + g->limit_low = (limit / 4096) & 0xffff; + g->limit_high = ((limit / 4096) >> 16) & 0xf; + g->base_low = base & 0xffff; + g->base_high1 = (base >> 16) & 0xff; + g->base_high2 = (base >> 24) & 0xff; + g->type = type; + + if (type != 0) + g->flags = GDT_GRAN_4K | GDT_MODE_32; +} ======================================= --- /dev/null +++ /branches/scratch/system/x86/pc/gdt_load.S Mon Oct 18 16:41:04 2010 @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2010 Niek Linnenbank + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + */ + +#include <FreeNOS/virt_memory.h> +#include <FreeNOS/cpu.h> + +.global gdt_load + +.section ".text" +.code32 + +/* + * gdt_load(gdt_ptr_t *ptr) + */ +gdt_load: + + /* Disable interrupts. */ + cli + + /* Load GDT. */ + movl 4(%esp), %eax + lgdtl (%eax) + + /* Setup segments. */ + movl $KERN_DS_SEL, %edx + movl %edx, %ds + movl %edx, %es + movl %edx, %fs + movl %edx, %gs + + /* Reload CS. */ + ljmpl $KERN_CS_SEL, $gdt_load2 + +gdt_load2: + ret