2 * General data structures and routines for segmentation
3 * Copyright (c) 2001, David H. Hovemeyer <daveho@cs.umd.edu>
6 * This is free software. You are permitted to use,
7 * redistribute, and modify it as specified in the file "COPYING".
11 * Source: _Protected Mode Software Architecture_ by Tom Shanley,
15 #include <geekos/kassert.h>
16 #include <geekos/string.h>
17 #include <geekos/tss.h>
18 #include <geekos/segment.h>
20 static __inline__ void Set_Size_And_Base_Pages(
21 struct Segment_Descriptor* desc,
27 * There are 20 bits in the size fields of a segment descriptor.
28 * The maximum possible value is thus 0xFFFFF, which in terms of
29 * pages is one page less than 4GB. So, I conclude that the
30 * number of pages in the segment is one greater than the
31 * value specified in the descriptor.
33 KASSERT(numPages > 0);
36 desc->sizeLow = numPages & 0xFFFF;
37 desc->sizeHigh = (numPages >> 16) & 0x0F;
38 desc->baseLow = baseAddr & 0xFFFFFF;
39 desc->baseHigh = (baseAddr >> 24) & 0xFF;
40 desc->granularity = 1; /* size in pages */
43 static __inline__ void Set_Size_And_Base_Bytes(
44 struct Segment_Descriptor* desc,
49 desc->sizeLow = numBytes & 0xFFFF;
50 desc->sizeHigh = (numBytes >> 16) & 0x0F;
51 desc->baseLow = baseAddr & 0xFFFFFF;
52 desc->baseHigh = (baseAddr >> 24) & 0xFF;
53 desc->granularity = 0; /* size in bytes */
57 * Initialize an unused segment descriptor.
59 void Init_Null_Segment_Descriptor(struct Segment_Descriptor* desc)
61 memset(desc, '\0', sizeof(*desc));
65 * Initialize a code segment descriptor.
67 void Init_Code_Segment_Descriptor(
68 struct Segment_Descriptor* desc,
74 KASSERT(privilegeLevel >= 0 && privilegeLevel <= 3);
76 Set_Size_And_Base_Pages(desc, baseAddr, numPages);
77 desc->type = 0x0A; /* 1010b: code, !conforming, readable, !accessed */
79 desc->dpl = privilegeLevel;
82 desc->dbBit = 1; /* 32 bit code segment */
86 * Initialize a data segment descriptor.
88 void Init_Data_Segment_Descriptor(
89 struct Segment_Descriptor* desc,
95 KASSERT(privilegeLevel >= 0 && privilegeLevel <= 3);
97 Set_Size_And_Base_Pages(desc, baseAddr, numPages);
98 desc->type = 0x02; /* 0010b: data, expand-up, writable, !accessed */
100 desc->dpl = privilegeLevel;
103 desc->dbBit = 1; /* 32 bit operands */
107 * Initialize a TSS descriptor.
109 void Init_TSS_Descriptor(struct Segment_Descriptor* desc, struct TSS* theTSS)
111 Set_Size_And_Base_Bytes(desc, (ulong_t) theTSS, sizeof(struct TSS));
112 desc->type = 0x09; /* 1001b: 32 bit, !busy */
117 desc->dbBit = 0; /* must be 0 in TSS */
121 * Initialize an LDT (Local Descriptor Table) descriptor.
123 void Init_LDT_Descriptor(
124 struct Segment_Descriptor* desc,
125 struct Segment_Descriptor theLDT[],
129 Set_Size_And_Base_Bytes(
130 desc, (ulong_t) theLDT, sizeof(struct Segment_Descriptor) * numEntries);
132 desc->type = 0x02; /* 0010b */