00001 #include "userprog/gdt.h"
00002
00003 #include <debug.h>
00004 #include "userprog/tss.h"
00005 #include "threads/palloc.h"
00006 #include "threads/vaddr.h"
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 static uint64_t gdt[SEL_CNT];
00027
00028
00029 static uint64_t make_code_desc (int dpl);
00030 static uint64_t make_data_desc (int dpl);
00031 static uint64_t make_tss_desc (void *laddr);
00032 static uint64_t make_gdtr_operand (uint16_t limit, void *base);
00033
00034
00035
00036 void
00037 gdt_init (void)
00038 {
00039 uint64_t gdtr_operand;
00040
00041
00042 gdt[SEL_NULL / sizeof *gdt] = 0;
00043 gdt[SEL_KCSEG / sizeof *gdt] = make_code_desc (0);
00044 gdt[SEL_KDSEG / sizeof *gdt] = make_data_desc (0);
00045 gdt[SEL_UCSEG / sizeof *gdt] = make_code_desc (3);
00046 gdt[SEL_UDSEG / sizeof *gdt] = make_data_desc (3);
00047 gdt[SEL_TSS / sizeof *gdt] = make_tss_desc (tss_get ());
00048
00049
00050
00051
00052 gdtr_operand = make_gdtr_operand (sizeof gdt - 1, gdt);
00053 asm volatile ("lgdt %0" : : "m" (gdtr_operand));
00054 asm volatile ("ltr %w0" : : "q" (SEL_TSS));
00055 }
00056
00057
00058 enum seg_class
00059 {
00060 CLS_SYSTEM = 0,
00061 CLS_CODE_DATA = 1
00062 };
00063
00064
00065 enum seg_granularity
00066 {
00067 GRAN_BYTE = 0,
00068 GRAN_PAGE = 1
00069 };
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082 static uint64_t
00083 make_seg_desc (uint32_t base,
00084 uint32_t limit,
00085 enum seg_class class,
00086 int type,
00087 int dpl,
00088 enum seg_granularity granularity)
00089 {
00090 uint32_t e0, e1;
00091
00092 ASSERT (limit <= 0xfffff);
00093 ASSERT (class == CLS_SYSTEM || class == CLS_CODE_DATA);
00094 ASSERT (type >= 0 && type <= 15);
00095 ASSERT (dpl >= 0 && dpl <= 3);
00096 ASSERT (granularity == GRAN_BYTE || granularity == GRAN_PAGE);
00097
00098 e0 = ((limit & 0xffff)
00099 | (base << 16));
00100
00101 e1 = (((base >> 16) & 0xff)
00102 | (type << 8)
00103 | (class << 12)
00104 | (dpl << 13)
00105 | (1 << 15)
00106 | (limit & 0xf0000)
00107 | (1 << 22)
00108 | (granularity << 23)
00109 | (base & 0xff000000));
00110
00111 return e0 | ((uint64_t) e1 << 32);
00112 }
00113
00114
00115
00116 static uint64_t
00117 make_code_desc (int dpl)
00118 {
00119 return make_seg_desc (0, 0xfffff, CLS_CODE_DATA, 10, dpl, GRAN_PAGE);
00120 }
00121
00122
00123
00124 static uint64_t
00125 make_data_desc (int dpl)
00126 {
00127 return make_seg_desc (0, 0xfffff, CLS_CODE_DATA, 2, dpl, GRAN_PAGE);
00128 }
00129
00130
00131
00132
00133
00134 static uint64_t
00135 make_tss_desc (void *laddr)
00136 {
00137 return make_seg_desc ((uint32_t) laddr, 0x67, CLS_SYSTEM, 9, 0, GRAN_BYTE);
00138 }
00139
00140
00141
00142
00143 static uint64_t
00144 make_gdtr_operand (uint16_t limit, void *base)
00145 {
00146 return limit | ((uint64_t) (uint32_t) base << 16);
00147 }