1 /*
2 * Vestigial Segmented Virtual Memory.
3 * To do:
4 * dynamic allocation and free of descriptors;
5 * IST should perhaps point to a different handler;
6 * user-level descriptors (if not dynamic).
7 */
8 #include "u.h"
9 #include "../port/lib.h"
10 #include "mem.h"
11 #include "dat.h"
12 #include "fns.h"
13
14 #include "amd64.h"
15 #include "ureg.h"
16
17 typedef struct Gd Gd;
18 typedef u64int Sd;
19 typedef u16int Ss;
20 typedef struct Tss Tss;
21
22 struct Gd {
23 Sd sd;
24 u64int hi;
25 };
26
27 struct Tss {
28 u32int _0_;
29 u32int rsp0[2];
30 u32int rsp1[2];
31 u32int rsp2[2];
32 u32int _28_[2];
33 u32int ist[14];
34 u16int _92_[5];
35 u16int iomap;
36 };
37
38 enum {
39 Ngdt = 16, /* max. entries in gdt */
40 Nidt = 256, /* max. entries in idt */
41 };
42
43 static Sd gdt64[Ngdt] = {
44 0ull, /* NULL descriptor */
45 SdL|SdP|SdDPL0|SdS|SdCODE, /* CS */
46 SdG|SdD|SdP|SdDPL0|SdS|SdW, /* DS */
47 SdG|SdD|SdP|SdDPL3|SdS|SdCODE|SdR|Sd4G, /* User CS 32-bit */
48 SdG|SdD|SdP|SdDPL3|SdS|SdW|Sd4G, /* User DS */
49 SdL|SdP|SdDPL3|SdS|SdCODE, /* User CS 64-bit */
50
51 0ull, /* FS */
52 0ull, /* GS */
53
54 0ull, /* TSS lower */
55 0ull, /* TSS upper */
56 };
57 static int ngdt64 = 10;
58
59 static Gd idt64[Nidt];
60
61 static Sd
mksd(u64int base,u64int limit,u64int bits,u64int * upper)62 mksd(u64int base, u64int limit, u64int bits, u64int* upper)
63 {
64 Sd sd;
65
66 sd = bits;
67 sd |= (((limit & 0x00000000000f0000ull)>>16)<<48)
68 |(limit & 0x000000000000ffffull);
69 sd |= (((base & 0x00000000ff000000ull)>>24)<<56)
70 |(((base & 0x0000000000ff0000ull)>>16)<<32)
71 |((base & 0x000000000000ffffull)<<16);
72 if(upper != nil)
73 *upper = base>>32;
74
75 return sd;
76 }
77
78 static void
mkgd(Gd * gd,u64int offset,Ss ss,u64int bits,int ist)79 mkgd(Gd* gd, u64int offset, Ss ss, u64int bits, int ist)
80 {
81 Sd sd;
82
83 sd = bits;
84 sd |= (((offset & 0x00000000ffff0000ull)>>16)<<48)
85 |(offset & 0x000000000000ffffull);
86 sd |= ((ss & 0x000000000000ffffull)<<16);
87 sd |= (ist & (SdISTM>>32))<<32;
88 gd->sd = sd;
89 gd->hi = offset>>32;
90 }
91
92 static void
idtinit(void)93 idtinit(void)
94 {
95 Gd *gd;
96 int ist, v;
97 u64int dpl;
98 uintptr offset;
99
100 gd = idt64;
101 offset = PTR2UINT(idthandlers);
102
103 for(v = 0; v < Nidt; v++){
104 ist = 0;
105 dpl = SdP|SdDPL0|SdIG;
106 switch(v){
107 default:
108 break;
109 case IdtBP: /* #BP */
110 dpl = SdP|SdDPL3|SdIG;
111 break;
112 case IdtUD: /* #UD */
113 case IdtDF: /* #DF */
114 ist = 1;
115 break;
116 }
117 mkgd(gd, offset, SSEL(SiCS, SsTIGDT|SsRPL0), dpl, ist);
118 gd++;
119 offset += 6;
120 }
121 }
122
123 void
tssrsp0(uintptr sp)124 tssrsp0(uintptr sp)
125 {
126 Tss *tss;
127
128 tss = m->tss;
129 tss->rsp0[0] = sp;
130 tss->rsp0[1] = sp>>32;
131 }
132
133 static void
tssinit(uintptr sp)134 tssinit(uintptr sp)
135 {
136 int ist;
137 Tss *tss;
138
139 tss = m->tss;
140 memset(tss, 0, sizeof(Tss));
141
142 tssrsp0(sp);
143
144 sp = PTR2UINT(m->vsvm+PGSZ);
145 for(ist = 0; ist < 14; ist += 2){
146 tss->ist[ist] = sp;
147 tss->ist[ist+1] = sp>>32;
148 }
149 tss->iomap = 0xdfff;
150 }
151
152 void
vsvminit(int size)153 vsvminit(int size)
154 {
155 Sd *sd;
156 u64int r;
157
158 if(m->machno == 0)
159 idtinit();
160
161 m->gdt = m->vsvm;
162 memmove(m->gdt, gdt64, sizeof(gdt64));
163 m->tss = &m->vsvm[ROUNDUP(sizeof(gdt64), 16)];
164
165 sd = &((Sd*)m->gdt)[SiTSS];
166 *sd = mksd(PTR2UINT(m->tss), sizeof(Tss)-1, SdP|SdDPL0|SdaTSS, sd+1);
167
168 tssinit(m->stack+size);
169
170 gdtput(sizeof(gdt64)-1, PTR2UINT(m->gdt), SSEL(SiCS, SsTIGDT|SsRPL0));
171 idtput(sizeof(idt64)-1, PTR2UINT(idt64));
172 trput(SSEL(SiTSS, SsTIGDT|SsRPL0));
173
174 wrmsr(FSbase, 0ull);
175 wrmsr(GSbase, PTR2UINT(&sys->machptr[m->machno]));
176 wrmsr(KernelGSbase, 0ull);
177
178 r = rdmsr(Efer);
179 r |= Sce;
180 wrmsr(Efer, r);
181 r = ((u64int)SSEL(SiU32CS, SsRPL3))<<48;
182 r |= ((u64int)SSEL(SiCS, SsRPL0))<<32;
183 wrmsr(Star, r);
184 wrmsr(Lstar, PTR2UINT(syscallentry));
185 wrmsr(Sfmask, If);
186 }
187
188 int
userureg(Ureg * ureg)189 userureg(Ureg* ureg)
190 {
191 return ureg->cs == SSEL(SiUCS, SsRPL3);
192 }
193