SimpleOS

LXR

Navigation



Site hébergé par : enix

The LXR Cross Referencer for SOS

source navigation ]
diff markup ]
identifier search ]
general search ]
 
 
Article:1 ] [ 2 ] [ 3 ] [ 4 ] [ 5 ] [ 6 ] [ 6.5 ] [ 7 ] [ 7.5 ] [ 8 ] [ 9 ] [ 9.5 ]

001 /* Copyright (C) 2004  David Decotigny
002    Copyright (C) 2003  Thomas Petazzoni
003 
004    This program is free software; you can redistribute it and/or
005    modify it under the terms of the GNU General Public License
006    as published by the Free Software Foundation; either version 2
007    of the License, or (at your option) any later version.
008    
009    This program is distributed in the hope that it will be useful,
010    but WITHOUT ANY WARRANTY; without even the implied warranty of
011    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
012    GNU General Public License for more details.
013    
014    You should have received a copy of the GNU General Public License
015    along with this program; if not, write to the Free Software
016    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
017    USA. 
018 */
019 #include "segment.h"
020 
021 #include "gdt.h"
022 
023 
024 /**
025  * The sructure of a segment descriptor.
026  *
027  * @see Intel x86 doc, Vol 3, section 3.4.3, figure 3-8. For segment
028  * types, see section 3.5
029  */
030 struct x86_segment_descriptor
031 {
032   /* Lowest dword */
033   sos_ui16_t limit_15_0;            /* Segment limit, bits 15..0 */
034   sos_ui16_t base_paged_addr_15_0;  /* Base address, bits 15..0 */
035 
036   /* Highest dword */
037   sos_ui8_t  base_paged_addr_23_16; /* Base address bits 23..16 */
038   sos_ui8_t  segment_type:4;        /* Section 3.4.3.1 (code/data)
039                                        and 3.5 (system) of Intel x86 vol 3 */
040   sos_ui8_t  descriptor_type:1;     /* 0=system, 1=Code/Data */
041   sos_ui8_t  dpl:2;                 /* Descriptor privilege level */
042   sos_ui8_t  present:1;
043 
044   sos_ui8_t  limit_19_16:4;         /* Segment limit, bits 19..16 */
045   sos_ui8_t  custom:1;
046   sos_ui8_t  zero:1;
047   sos_ui8_t  op_size:1;             /* 0=16bits instructions, 1=32bits */
048   sos_ui8_t  granularity:1;         /* 0=limit in bytes, 1=limit in pages */
049   
050   sos_ui8_t  base_paged_addr_31_24; /* Base address bits 31..24 */
051 } __attribute__ ((packed, aligned(8)));
052 
053 
054 /**
055  * The GDT register, which stores the address and size of the
056  * GDT.
057  *
058  * @see Intel x86 doc vol 3, section 2.4, figure 2-4; and section
059  * 3.5.1
060  */
061 struct x86_gdt_register {
062   /** Intel doc says that the real GDT register (ie the "limit" field)
063       should be odd-word aligned. That's why we add a padding here.
064       Credits to Romain for having signalled this to us. */
065   sos_ui16_t  padding;
066 
067   /** The maximum GDT offset allowed to access an entry in the GDT */
068   sos_ui16_t  limit;
069   
070   /**
071    * This is not exactly a "virtual" address, ie an adddress such as
072    * those of instructions and data; this is a "linear" address, ie an
073    * address in the paged memory. However, in SOS we configure the
074    * segmented memory as a "flat" space: the 0-4GB segment-based (ie
075    * "virtual") addresses directly map to the 0-4GB paged memory (ie
076    * "linear"), so that the "linear" addresses are numerically equal
077    * to the "virtual" addresses: this base_addr will thus be the same
078    * as the address of the gdt array
079    */
080     sos_ui32_t base_addr;
081 } __attribute__((packed, aligned(4)));
082 
083 
084 /**
085  * Helper macro that builds a Segment descriptor for the virtual
086  * 0..4GB addresses to be mapped to the linear 0..4GB linear
087  * addresses.
088  */
089 #define BUILD_GDTE(descr_privilege_level,is_code)               \
090   ((struct x86_segment_descriptor) {                            \
091       .limit_15_0=            0xffff,                           \
092       .base_paged_addr_15_0=  0,                                \
093       .base_paged_addr_23_16= 0,                                \
094       .segment_type=          ((is_code)?0xb:0x3),              \
095              /* With descriptor_type (below) = 1 (code/data),   \
096               * see Figure 3-1 of section 3.4.3.1 in Intel      \
097               * x86 vol 3:                                      \
098               *   - Code (bit 3 = 1):                           \
099               *     bit 0: 1=Accessed                           \
100               *     bit 1: 1=Readable                           \
101               *     bit 2: 0=Non-Conforming                     \
102               *   - Data (bit 3 = 0):                           \
103               *     bit 0: 1=Accessed                           \
104               *     bit 1: 1=Writable                           \
105               *     bit 2: 0=Expand up (stack-related)          \
106               * For Conforming/non conforming segments, see     \
107               * Intel x86 Vol 3 section 4.8.1.1                 \
108               */                                                \
109       .descriptor_type=       1,  /* 1=Code/Data */             \
110       .dpl=                   ((descr_privilege_level) & 0x3),  \
111       .present=               1,                                \
112       .limit_19_16=           0xf,                              \
113       .custom=                0,                                \
114       .zero=                  0,                                \
115       .op_size=               1,  /* 32 bits instr/data */      \
116       .granularity=           1,  /* limit is in 4kB Pages */   \
117       .base_paged_addr_31_24= 0                                 \
118   })
119 
120 
121 /** The actual GDT */
122 static struct x86_segment_descriptor gdt[] = {
123   [SOS_SEG_NULL]  = (struct x86_segment_descriptor){ 0, },
124   [SOS_SEG_KCODE] = BUILD_GDTE(0, 1),
125   [SOS_SEG_KDATA] = BUILD_GDTE(0, 0),
126   [SOS_SEG_UCODE] = BUILD_GDTE(3, 1),
127   [SOS_SEG_UDATA] = BUILD_GDTE(3, 0),
128   [SOS_SEG_KERNEL_TSS] = { 0, } /* Initialized by
129                                    register_kernel_tss */
130 };
131 
132 
133 sos_ret_t sos_gdt_subsystem_setup(void)
134 {
135   struct x86_gdt_register gdtr;
136 
137   /* Put some garbage in the padding field of the GDTR */
138   gdtr.padding   = ~0;
139 
140   /* Address of the GDT */
141   gdtr.base_addr = (sos_ui32_t) gdt;
142 
143   /* The limit is the maximum offset in bytes from the base address of
144      the GDT */
145   gdtr.limit     = sizeof(gdt) - 1;
146 
147   /* Commit the GDT into the CPU, and update the segment
148      registers. The CS register may only be updated with a long jump
149      to an absolute address in the given segment (see Intel x86 doc
150      vol 3, section 4.8.1). */
151   asm volatile ("lgdt %0          \n\
152                  ljmp %1,$1f      \n\
153                  1:               \n\
154                  movw %2, %%ax    \n\
155                  movw %%ax,  %%ss \n\
156                  movw %%ax,  %%ds \n\
157                  movw %%ax,  %%es \n\
158                  movw %%ax,  %%fs \n\
159                  movw %%ax,  %%gs"
160                 :
161                 :"m"(gdtr.limit) /* The real beginning of the GDT
162                                     register is /after/ the "padding"
163                                     field, ie at the "limit"
164                                     field. */,
165                  "i"(SOS_BUILD_SEGMENT_REG_VALUE(0, FALSE, SOS_SEG_KCODE)),
166                  "i"(SOS_BUILD_SEGMENT_REG_VALUE(0, FALSE, SOS_SEG_KDATA))
167                 :"memory","eax");
168 
169   return SOS_OK;
170 }
171 
172 
173 sos_ret_t sos_gdt_register_kernel_tss(sos_vaddr_t tss_vaddr)
174 {
175   sos_ui16_t regval_tss;
176 
177   /* Initialize the GDT entry */
178   gdt[SOS_SEG_KERNEL_TSS]
179     = (struct x86_segment_descriptor) {
180       .limit_15_0=            0x67, /* See Intel x86 vol 3 section 6.2.2 */
181       .base_paged_addr_15_0=  (tss_vaddr) & 0xffff,
182       .base_paged_addr_23_16= (tss_vaddr >> 16) & 0xff,
183       .segment_type=          0x9,  /* See Intel x86 vol 3 figure 6-3 */
184       .descriptor_type=       0,    /* (idem) */
185       .dpl=                   3,    /* Allowed for CPL3 tasks */
186       .present=               1,
187       .limit_19_16=           0,    /* Size of a TSS is < 2^16 ! */
188       .custom=                0,    /* Unused */
189       .zero=                  0,
190       .op_size=               0,    /* See Intel x86 vol 3 figure 6-3 */
191       .granularity=           1,    /* limit is in Bytes */
192       .base_paged_addr_31_24= (tss_vaddr >> 24) & 0xff
193     };
194 
195   /* Load the TSS register into the processor */
196   regval_tss = SOS_BUILD_SEGMENT_REG_VALUE(0, FALSE,
197                                            SOS_SEG_KERNEL_TSS);
198   asm ("ltr %0" : :"r"(regval_tss));
199   
200   return SOS_OK;     
201 }
202 
203 

source navigation ] diff markup ] identifier search ] general search ]