X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?p=palacios.git;a=blobdiff_plain;f=geekos%2Fsrc%2Fgeekos%2Fgdt.c;fp=geekos%2Fsrc%2Fgeekos%2Fgdt.c;h=707e34a2a4ea08d46b22ee2497a32151bbccf7f9;hp=0000000000000000000000000000000000000000;hb=ddc16b0737cf58f7aa90a69c6652cdf4090aec51;hpb=626595465a2c6987606a6bc697df65130ad8c2d3 diff --git a/geekos/src/geekos/gdt.c b/geekos/src/geekos/gdt.c new file mode 100644 index 0000000..707e34a --- /dev/null +++ b/geekos/src/geekos/gdt.c @@ -0,0 +1,179 @@ +/* + * Initialize kernel GDT. + * Copyright (c) 2001,2004 David H. Hovemeyer + * $Revision: 1.4 $ + * + * This is free software. You are permitted to use, + * redistribute, and modify it as specified in the file "COPYING". + */ + +#include +#include +#include +#include +#include +#include + +#include + +/* + * This is defined in lowlevel.asm. + */ +extern void Load_GDTR(ushort_t* limitAndBase); + +/* ---------------------------------------------------------------------- + * Data + * ---------------------------------------------------------------------- */ + +/* + * Number of entries in the kernel GDT. + */ +#define NUM_GDT_ENTRIES 16 + +/* + * This is the kernel's global descriptor table. + */ +struct Segment_Descriptor s_GDT[NUM_GDT_ENTRIES]; +/* + * Number of allocated GDT entries. + */ +static int s_numAllocated = 0; + + + + + +void DumpGDT() +{ + int i; + PrintBoth("GDT Contents:\n"); + + for (i=0;iavail) { + ++s_numAllocated; + desc->avail = 0; + result = desc; + break; + } + } + + End_Int_Atomic(iflag); + + return result; +} + +/* + * Free a segment descriptor. + */ +void Free_Segment_Descriptor(struct Segment_Descriptor* desc) +{ + bool iflag = Begin_Int_Atomic(); + + KASSERT(!desc->avail); + + Init_Null_Segment_Descriptor(desc); + desc->avail = 1; + --s_numAllocated; + + End_Int_Atomic(iflag); +} + +/* + * Get the index (int the GDT) of given segment descriptor. + */ +int Get_Descriptor_Index(struct Segment_Descriptor* desc) +{ + return (int) (desc - s_GDT); +} + +/* + * Initialize the kernel's GDT. + */ +void Init_GDT(void) +{ + ushort_t limitAndBase[3]; + ulong_t gdtBaseAddr = (ulong_t) s_GDT; + struct Segment_Descriptor* desc; + int i; + + + KASSERT(sizeof(struct Segment_Descriptor) == 8); + + /* Clear out entries. */ + for (i = 0; i < NUM_GDT_ENTRIES; ++i) { + desc = &s_GDT[ i ]; + Init_Null_Segment_Descriptor(desc); + desc->avail = 1; + } + + /* Kernel code segment. */ + desc = Allocate_Segment_Descriptor(); + Init_Code_Segment_Descriptor( + desc, + 0, /* base address */ + 0x100000, /* num pages (== 2^20) */ + 0 /* privilege level (0 == kernel) */ + ); + KASSERT(Get_Descriptor_Index(desc) == (KERNEL_CS >> 3)); + + /* Kernel data segment. */ + desc = Allocate_Segment_Descriptor(); + Init_Data_Segment_Descriptor( + desc, + 0, /* base address */ + 0x100000, /* num pages (== 2^20) */ + 0 /* privilege level (0 == kernel) */ + ); + KASSERT(Get_Descriptor_Index(desc) == (KERNEL_DS >> 3)); + + Print("GDT: Base=0x%.8x, limit=%d\n", (uint_t)gdtBaseAddr, (uint_t)(sizeof(struct Segment_Descriptor) * NUM_GDT_ENTRIES)); + + /* Activate the kernel GDT. */ + limitAndBase[0] = sizeof(struct Segment_Descriptor) * NUM_GDT_ENTRIES; + limitAndBase[1] = gdtBaseAddr & 0xffff; + limitAndBase[2] = gdtBaseAddr >> 16; + Load_GDTR(limitAndBase); +}