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