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