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