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