Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


(no commit message)
[palacios.git] / palacios / src / geekos / segment.c
1 /*
2  * General data structures and routines for segmentation
3  * Copyright (c) 2001, David H. Hovemeyer <daveho@cs.umd.edu>
4  * $Revision: 1.1.1.1 $
5  * 
6  * This is free software.  You are permitted to use,
7  * redistribute, and modify it as specified in the file "COPYING".
8  */
9
10 /*
11  * Source: _Protected Mode Software Architecture_ by Tom Shanley,
12  * ISBN 020155447X.
13  */
14
15 #include <geekos/kassert.h>
16 #include <geekos/string.h>
17 #include <geekos/tss.h>
18 #include <geekos/segment.h>
19
20 static __inline__ void Set_Size_And_Base_Pages(
21     struct Segment_Descriptor* desc,
22     ulong_t baseAddr,
23     ulong_t numPages
24 )
25 {
26     /*
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.
32      */
33     KASSERT(numPages > 0);
34     numPages -= 1;
35
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 */
41 }
42
43 static __inline__ void Set_Size_And_Base_Bytes(
44     struct Segment_Descriptor* desc,
45     ulong_t baseAddr,
46     ulong_t numBytes
47 )
48 {
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 */
54 }
55
56 /*
57  * Initialize an unused segment descriptor.
58  */
59 void Init_Null_Segment_Descriptor(struct Segment_Descriptor* desc)
60 {
61     memset(desc, '\0', sizeof(*desc));
62 }
63
64 /*
65  * Initialize a code segment descriptor.
66  */
67 void Init_Code_Segment_Descriptor(
68     struct Segment_Descriptor* desc,
69     ulong_t baseAddr,
70     ulong_t numPages,
71     int privilegeLevel
72 )
73 {
74     KASSERT(privilegeLevel >= 0 && privilegeLevel <= 3);
75
76     Set_Size_And_Base_Pages(desc, baseAddr, numPages);
77     desc->type     = 0x0A;   /* 1010b: code, !conforming, readable, !accessed */
78     desc->system   = 1;
79     desc->dpl      = privilegeLevel;
80     desc->present  = 1;
81     desc->reserved = 0;
82     desc->dbBit    = 1;  /* 32 bit code segment */
83 }
84
85 /*
86  * Initialize a data segment descriptor.
87  */
88 void Init_Data_Segment_Descriptor(
89     struct Segment_Descriptor* desc,
90     ulong_t baseAddr,
91     ulong_t numPages,
92     int privilegeLevel
93 )
94 {
95     KASSERT(privilegeLevel >= 0 && privilegeLevel <= 3);
96
97     Set_Size_And_Base_Pages(desc, baseAddr, numPages);
98     desc->type     = 0x02;  /* 0010b: data, expand-up, writable, !accessed */
99     desc->system   = 1;
100     desc->dpl      = privilegeLevel;
101     desc->present  = 1;
102     desc->reserved = 0;
103     desc->dbBit    = 1;  /* 32 bit operands */
104 }
105
106 /*
107  * Initialize a TSS descriptor.
108  */
109 void Init_TSS_Descriptor(struct Segment_Descriptor* desc, struct TSS* theTSS)
110 {
111     Set_Size_And_Base_Bytes(desc, (ulong_t) theTSS, sizeof(struct TSS));
112     desc->type     = 0x09;  /* 1001b: 32 bit, !busy */
113     desc->system   = 0;
114     desc->dpl      = 0;
115     desc->present  = 1;
116     desc->reserved = 0;
117     desc->dbBit    = 0;  /* must be 0 in TSS */
118 }
119
120 /*
121  * Initialize an LDT (Local Descriptor Table) descriptor.
122  */
123 void Init_LDT_Descriptor(
124     struct Segment_Descriptor* desc,
125     struct Segment_Descriptor theLDT[],
126     int numEntries
127 )
128 {
129     Set_Size_And_Base_Bytes(
130         desc, (ulong_t) theLDT, sizeof(struct Segment_Descriptor) * numEntries);
131
132     desc->type     = 0x02;  /* 0010b */
133     desc->system   = 0;
134     desc->dpl      = 0;
135     desc->present  = 1;
136     desc->reserved = 0;
137     desc->dbBit    = 0;
138 }