/* * General data structures and routines for segmentation * Copyright (c) 2001, David H. Hovemeyer * $Revision: 1.1 $ * * This is free software. You are permitted to use, * redistribute, and modify it as specified in the file "COPYING". */ /* * Source: _Protected Mode Software Architecture_ by Tom Shanley, * ISBN 020155447X. */ #include #include #include #include static __inline__ void Set_Size_And_Base_Pages( struct Segment_Descriptor* desc, ulong_t baseAddr, ulong_t numPages ) { /* * There are 20 bits in the size fields of a segment descriptor. * The maximum possible value is thus 0xFFFFF, which in terms of * pages is one page less than 4GB. So, I conclude that the * number of pages in the segment is one greater than the * value specified in the descriptor. */ KASSERT(numPages > 0); numPages -= 1; desc->sizeLow = numPages & 0xFFFF; desc->sizeHigh = (numPages >> 16) & 0x0F; desc->baseLow = baseAddr & 0xFFFFFF; desc->baseHigh = (baseAddr >> 24) & 0xFF; desc->granularity = 1; /* size in pages */ } static __inline__ void Set_Size_And_Base_Bytes( struct Segment_Descriptor* desc, ulong_t baseAddr, ulong_t numBytes ) { desc->sizeLow = numBytes & 0xFFFF; desc->sizeHigh = (numBytes >> 16) & 0x0F; desc->baseLow = baseAddr & 0xFFFFFF; desc->baseHigh = (baseAddr >> 24) & 0xFF; desc->granularity = 0; /* size in bytes */ } /* * Initialize an unused segment descriptor. */ void Init_Null_Segment_Descriptor(struct Segment_Descriptor* desc) { memset(desc, '\0', sizeof(*desc)); } /* * Initialize a code segment descriptor. */ void Init_Code_Segment_Descriptor( struct Segment_Descriptor* desc, ulong_t baseAddr, ulong_t numPages, int privilegeLevel ) { KASSERT(privilegeLevel >= 0 && privilegeLevel <= 3); Set_Size_And_Base_Pages(desc, baseAddr, numPages); desc->type = 0x0A; /* 1010b: code, !conforming, readable, !accessed */ desc->system = 1; desc->dpl = privilegeLevel; desc->present = 1; desc->reserved = 0; desc->dbBit = 1; /* 32 bit code segment */ } /* * Initialize a data segment descriptor. */ void Init_Data_Segment_Descriptor( struct Segment_Descriptor* desc, ulong_t baseAddr, ulong_t numPages, int privilegeLevel ) { KASSERT(privilegeLevel >= 0 && privilegeLevel <= 3); Set_Size_And_Base_Pages(desc, baseAddr, numPages); desc->type = 0x02; /* 0010b: data, expand-up, writable, !accessed */ desc->system = 1; desc->dpl = privilegeLevel; desc->present = 1; desc->reserved = 0; desc->dbBit = 1; /* 32 bit operands */ } /* * Initialize a TSS descriptor. */ void Init_TSS_Descriptor(struct Segment_Descriptor* desc, struct TSS* theTSS) { Set_Size_And_Base_Bytes(desc, (ulong_t) theTSS, sizeof(struct TSS)); desc->type = 0x09; /* 1001b: 32 bit, !busy */ desc->system = 0; desc->dpl = 0; desc->present = 1; desc->reserved = 0; desc->dbBit = 0; /* must be 0 in TSS */ } /* * Initialize an LDT (Local Descriptor Table) descriptor. */ void Init_LDT_Descriptor( struct Segment_Descriptor* desc, struct Segment_Descriptor theLDT[], int numEntries ) { Set_Size_And_Base_Bytes( desc, (ulong_t) theLDT, sizeof(struct Segment_Descriptor) * numEntries); desc->type = 0x02; /* 0010b */ desc->system = 0; desc->dpl = 0; desc->present = 1; desc->reserved = 0; desc->dbBit = 0; }