|
[ 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 /** Intel doc says that the real GDT registe 062 /** Intel doc says that the real GDT register (ie the "limit" field) 063 should be odd-word aligned. That's why w 063 should be odd-word aligned. That's why we add a padding here. 064 Credits to Romain for having signalled t 064 Credits to Romain for having signalled this to us. */ 065 sos_ui16_t padding; 065 sos_ui16_t padding; 066 066 067 /** The maximum GDT offset allowed to access 067 /** The maximum GDT offset allowed to access an entry in the GDT */ 068 sos_ui16_t limit; 068 sos_ui16_t limit; 069 069 070 /** 070 /** 071 * This is not exactly a "virtual" address, 071 * This is not exactly a "virtual" address, ie an adddress such as 072 * those of instructions and data; this is a 072 * those of instructions and data; this is a "linear" address, ie an 073 * address in the paged memory. However, in 073 * address in the paged memory. However, in SOS we configure the 074 * segmented memory as a "flat" space: the 0 074 * segmented memory as a "flat" space: the 0-4GB segment-based (ie 075 * "virtual") addresses directly map to the 075 * "virtual") addresses directly map to the 0-4GB paged memory (ie 076 * "linear"), so that the "linear" addresses 076 * "linear"), so that the "linear" addresses are numerically equal 077 * to the "virtual" addresses: this base_add 077 * to the "virtual" addresses: this base_addr will thus be the same 078 * as the address of the gdt array 078 * as the address of the gdt array 079 */ 079 */ 080 sos_ui32_t base_addr; 080 sos_ui32_t base_addr; 081 } __attribute__((packed, aligned(4))); 081 } __attribute__((packed, aligned(4))); 082 082 083 083 084 /** 084 /** 085 * Helper macro that builds a Segment descript 085 * Helper macro that builds a Segment descriptor for the virtual 086 * 0..4GB addresses to be mapped to the linear 086 * 0..4GB addresses to be mapped to the linear 0..4GB linear 087 * addresses. 087 * addresses. 088 */ 088 */ 089 #define BUILD_GDTE(descr_privilege_level,is_co 089 #define BUILD_GDTE(descr_privilege_level,is_code) \ 090 ((struct x86_segment_descriptor) { 090 ((struct x86_segment_descriptor) { \ 091 .limit_15_0= 0xffff, 091 .limit_15_0= 0xffff, \ 092 .base_paged_addr_15_0= 0, 092 .base_paged_addr_15_0= 0, \ 093 .base_paged_addr_23_16= 0, 093 .base_paged_addr_23_16= 0, \ 094 .segment_type= ((is_code)?0xb:0 094 .segment_type= ((is_code)?0xb:0x3), \ 095 /* With descriptor_type (below) = 095 /* With descriptor_type (below) = 1 (code/data), \ 096 * see Figure 3-1 of section 3.4. 096 * see Figure 3-1 of section 3.4.3.1 in Intel \ 097 * x86 vol 3: 097 * x86 vol 3: \ 098 * - Code (bit 3 = 1): 098 * - Code (bit 3 = 1): \ 099 * bit 0: 1=Accessed 099 * bit 0: 1=Accessed \ 100 * bit 1: 1=Readable 100 * bit 1: 1=Readable \ 101 * bit 2: 0=Non-Conforming 101 * bit 2: 0=Non-Conforming \ 102 * - Data (bit 3 = 0): 102 * - Data (bit 3 = 0): \ 103 * bit 0: 1=Accessed 103 * bit 0: 1=Accessed \ 104 * bit 1: 1=Writable 104 * bit 1: 1=Writable \ 105 * bit 2: 0=Expand up (stack- 105 * bit 2: 0=Expand up (stack-related) \ 106 * For Conforming/non conforming 106 * For Conforming/non conforming segments, see \ 107 * Intel x86 Vol 3 section 4.8.1. 107 * Intel x86 Vol 3 section 4.8.1.1 \ 108 */ 108 */ \ 109 .descriptor_type= 1, /* 1=Code/Da 109 .descriptor_type= 1, /* 1=Code/Data */ \ 110 .dpl= ((descr_privileg 110 .dpl= ((descr_privilege_level) & 0x3), \ 111 .present= 1, 111 .present= 1, \ 112 .limit_19_16= 0xf, 112 .limit_19_16= 0xf, \ 113 .custom= 0, 113 .custom= 0, \ 114 .zero= 0, 114 .zero= 0, \ 115 .op_size= 1, /* 32 bits i 115 .op_size= 1, /* 32 bits instr/data */ \ 116 .granularity= 1, /* limit is 116 .granularity= 1, /* limit is in 4kB Pages */ \ 117 .base_paged_addr_31_24= 0 117 .base_paged_addr_31_24= 0 \ 118 }) 118 }) 119 119 120 120 121 /** The actual GDT */ 121 /** The actual GDT */ 122 static struct x86_segment_descriptor gdt[] = { 122 static struct x86_segment_descriptor gdt[] = { 123 [SOS_SEG_NULL] = (struct x86_segment_descri 123 [SOS_SEG_NULL] = (struct x86_segment_descriptor){ 0, }, 124 [SOS_SEG_KCODE] = BUILD_GDTE(0, 1), 124 [SOS_SEG_KCODE] = BUILD_GDTE(0, 1), 125 [SOS_SEG_KDATA] = BUILD_GDTE(0, 0), 125 [SOS_SEG_KDATA] = BUILD_GDTE(0, 0), 126 [SOS_SEG_UCODE] = BUILD_GDTE(3, 1), 126 [SOS_SEG_UCODE] = BUILD_GDTE(3, 1), 127 [SOS_SEG_UDATA] = BUILD_GDTE(3, 0), 127 [SOS_SEG_UDATA] = BUILD_GDTE(3, 0), 128 [SOS_SEG_KERNEL_TSS] = { 0, } /* Initialized 128 [SOS_SEG_KERNEL_TSS] = { 0, } /* Initialized by 129 register_ke 129 register_kernel_tss */ 130 }; 130 }; 131 131 132 132 133 sos_ret_t sos_gdt_subsystem_setup(void) 133 sos_ret_t sos_gdt_subsystem_setup(void) 134 { 134 { 135 struct x86_gdt_register gdtr; 135 struct x86_gdt_register gdtr; 136 136 137 /* Put some garbage in the padding field of 137 /* Put some garbage in the padding field of the GDTR */ 138 gdtr.padding = ~0; 138 gdtr.padding = ~0; 139 139 140 /* Address of the GDT */ 140 /* Address of the GDT */ 141 gdtr.base_addr = (sos_ui32_t) gdt; 141 gdtr.base_addr = (sos_ui32_t) gdt; 142 142 143 /* The limit is the maximum offset in bytes 143 /* The limit is the maximum offset in bytes from the base address of 144 the GDT */ 144 the GDT */ 145 gdtr.limit = sizeof(gdt) - 1; 145 gdtr.limit = sizeof(gdt) - 1; 146 146 147 /* Commit the GDT into the CPU, and update t 147 /* Commit the GDT into the CPU, and update the segment 148 registers. The CS register may only be up 148 registers. The CS register may only be updated with a long jump 149 to an absolute address in the given segme 149 to an absolute address in the given segment (see Intel x86 doc 150 vol 3, section 4.8.1). */ 150 vol 3, section 4.8.1). */ 151 asm volatile ("lgdt %0 \n\ 151 asm volatile ("lgdt %0 \n\ 152 ljmp %1,$1f \n\ 152 ljmp %1,$1f \n\ 153 1: \n\ 153 1: \n\ 154 movw %2, %%ax \n\ 154 movw %2, %%ax \n\ 155 movw %%ax, %%ss \n\ 155 movw %%ax, %%ss \n\ 156 movw %%ax, %%ds \n\ 156 movw %%ax, %%ds \n\ 157 movw %%ax, %%es \n\ 157 movw %%ax, %%es \n\ 158 movw %%ax, %%fs \n\ 158 movw %%ax, %%fs \n\ 159 movw %%ax, %%gs" 159 movw %%ax, %%gs" 160 : 160 : 161 :"m"(gdtr.limit) /* The real b 161 :"m"(gdtr.limit) /* The real beginning of the GDT 162 register i 162 register is /after/ the "padding" 163 field, ie 163 field, ie at the "limit" 164 field. */, 164 field. */, 165 "i"(SOS_BUILD_SEGMENT_REG_VAL 165 "i"(SOS_BUILD_SEGMENT_REG_VALUE(0, FALSE, SOS_SEG_KCODE)), 166 "i"(SOS_BUILD_SEGMENT_REG_VAL 166 "i"(SOS_BUILD_SEGMENT_REG_VALUE(0, FALSE, SOS_SEG_KDATA)) 167 :"memory","eax"); 167 :"memory","eax"); 168 168 169 return SOS_OK; 169 return SOS_OK; 170 } 170 } 171 171 172 172 173 sos_ret_t sos_gdt_register_kernel_tss(sos_vadd 173 sos_ret_t sos_gdt_register_kernel_tss(sos_vaddr_t tss_vaddr) 174 { 174 { 175 sos_ui16_t regval_tss; 175 sos_ui16_t regval_tss; 176 176 177 /* Initialize the GDT entry */ 177 /* Initialize the GDT entry */ 178 gdt[SOS_SEG_KERNEL_TSS] 178 gdt[SOS_SEG_KERNEL_TSS] 179 = (struct x86_segment_descriptor) { 179 = (struct x86_segment_descriptor) { 180 .limit_15_0= 0x67, /* See Int 180 .limit_15_0= 0x67, /* See Intel x86 vol 3 section 6.2.2 */ 181 .base_paged_addr_15_0= (tss_vaddr) & 0x 181 .base_paged_addr_15_0= (tss_vaddr) & 0xffff, 182 .base_paged_addr_23_16= (tss_vaddr >> 16 182 .base_paged_addr_23_16= (tss_vaddr >> 16) & 0xff, 183 .segment_type= 0x9, /* See Int 183 .segment_type= 0x9, /* See Intel x86 vol 3 figure 6-3 */ 184 .descriptor_type= 0, /* (idem) 184 .descriptor_type= 0, /* (idem) */ 185 .dpl= 3, /* Allowed 185 .dpl= 3, /* Allowed for CPL3 tasks */ 186 .present= 1, 186 .present= 1, 187 .limit_19_16= 0, /* Size of 187 .limit_19_16= 0, /* Size of a TSS is < 2^16 ! */ 188 .custom= 0, /* Unused 188 .custom= 0, /* Unused */ 189 .zero= 0, 189 .zero= 0, 190 .op_size= 0, /* See Int 190 .op_size= 0, /* See Intel x86 vol 3 figure 6-3 */ 191 .granularity= 1, /* limit i 191 .granularity= 1, /* limit is in Bytes */ 192 .base_paged_addr_31_24= (tss_vaddr >> 24 192 .base_paged_addr_31_24= (tss_vaddr >> 24) & 0xff 193 }; 193 }; 194 194 195 /* Load the TSS register into the processor 195 /* Load the TSS register into the processor */ 196 regval_tss = SOS_BUILD_SEGMENT_REG_VALUE(0, 196 regval_tss = SOS_BUILD_SEGMENT_REG_VALUE(0, FALSE, 197 SOS 197 SOS_SEG_KERNEL_TSS); 198 asm ("ltr %0" : :"r"(regval_tss)); 198 asm ("ltr %0" : :"r"(regval_tss)); 199 199 200 return SOS_OK; 200 return SOS_OK; 201 } 201 } 202 202 203 203
[ source navigation ] | [ diff markup ] | [ identifier search ] | [ general search ] |