/* * 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); }