]> git.lizzy.rs Git - plan9front.git/blob - sys/src/9/pc64/main.c
vmx: clean up mksegment, memset only if segment existed (devsegment clears new ones)
[plan9front.git] / sys / src / 9 / pc64 / main.c
1 #include        "u.h"
2 #include        "tos.h"
3 #include        "../port/lib.h"
4 #include        "mem.h"
5 #include        "dat.h"
6 #include        "fns.h"
7 #include        "io.h"
8 #include        "../port/pci.h"
9 #include        "ureg.h"
10 #include        "pool.h"
11 #include        "rebootcode.i"
12
13 Conf conf;
14 int delaylink;
15 int idle_spin;
16
17 extern void (*i8237alloc)(void);
18 extern void bootscreeninit(void);
19
20 void
21 confinit(void)
22 {
23         char *p;
24         int i, userpcnt;
25         ulong kpages;
26
27         if(p = getconf("service")){
28                 if(strcmp(p, "cpu") == 0)
29                         cpuserver = 1;
30                 else if(strcmp(p,"terminal") == 0)
31                         cpuserver = 0;
32         }
33
34         if(p = getconf("*kernelpercent"))
35                 userpcnt = 100 - strtol(p, 0, 0);
36         else
37                 userpcnt = 0;
38
39         conf.npage = 0;
40         for(i=0; i<nelem(conf.mem); i++)
41                 conf.npage += conf.mem[i].npage;
42
43         conf.nproc = 100 + ((conf.npage*BY2PG)/MB)*5;
44         if(cpuserver)
45                 conf.nproc *= 3;
46         if(conf.nproc > 2000)
47                 conf.nproc = 2000;
48         conf.nimage = 200;
49         conf.nswap = conf.nproc*80;
50         conf.nswppo = 4096;
51
52         if(cpuserver) {
53                 if(userpcnt < 10)
54                         userpcnt = 70;
55                 kpages = conf.npage - (conf.npage*userpcnt)/100;
56                 conf.nimage = conf.nproc;
57         } else {
58                 if(userpcnt < 10) {
59                         if(conf.npage*BY2PG < 16*MB)
60                                 userpcnt = 50;
61                         else
62                                 userpcnt = 60;
63                 }
64                 kpages = conf.npage - (conf.npage*userpcnt)/100;
65
66                 /*
67                  * Make sure terminals with low memory get at least
68                  * 4MB on the first Image chunk allocation.
69                  */
70                 if(conf.npage*BY2PG < 16*MB)
71                         imagmem->minarena = 4*MB;
72         }
73
74         /*
75          * can't go past the end of virtual memory.
76          */
77         if(kpages > ((uintptr)-KZERO)/BY2PG)
78                 kpages = ((uintptr)-KZERO)/BY2PG;
79
80         conf.upages = conf.npage - kpages;
81         conf.ialloc = (kpages/2)*BY2PG;
82
83         /*
84          * Guess how much is taken by the large permanent
85          * datastructures. Mntcache and Mntrpc are not accounted for.
86          */
87         kpages *= BY2PG;
88         kpages -= conf.nproc*sizeof(Proc)
89                 + conf.nimage*sizeof(Image)
90                 + conf.nswap
91                 + conf.nswppo*sizeof(Page*);
92         mainmem->maxsize = kpages;
93
94         /*
95          * the dynamic allocation will balance the load properly,
96          * hopefully. be careful with 32-bit overflow.
97          */
98         imagmem->maxsize = kpages - (kpages/10);
99         if(p = getconf("*imagemaxmb")){
100                 imagmem->maxsize = strtol(p, nil, 0)*MB;
101                 if(imagmem->maxsize > mainmem->maxsize)
102                         imagmem->maxsize = mainmem->maxsize;
103         }
104 }
105
106 void
107 machinit(void)
108 {
109         int machno;
110         Segdesc *gdt;
111         uintptr *pml4;
112
113         machno = m->machno;
114         pml4 = m->pml4;
115         gdt = m->gdt;
116         memset(m, 0, sizeof(Mach));
117         m->machno = machno;
118         m->pml4 = pml4;
119         m->gdt = gdt;
120         m->perf.period = 1;
121
122         /*
123          * For polled uart output at boot, need
124          * a default delay constant. 100000 should
125          * be enough for a while. Cpuidentify will
126          * calculate the real value later.
127          */
128         m->loopconst = 100000;
129 }
130
131 void
132 mach0init(void)
133 {
134         conf.nmach = 1;
135
136         MACHP(0) = (Mach*)CPU0MACH;
137
138         m->machno = 0;
139         m->pml4 = (u64int*)CPU0PML4;
140         m->gdt = (Segdesc*)CPU0GDT;
141
142         machinit();
143
144         active.machs[0] = 1;
145         active.exiting = 0;
146 }
147
148 void
149 init0(void)
150 {
151         char buf[2*KNAMELEN], **sp;
152
153         chandevinit();
154
155         if(!waserror()){
156                 snprint(buf, sizeof(buf), "%s %s", arch->id, conffile);
157                 ksetenv("terminal", buf, 0);
158                 ksetenv("cputype", "amd64", 0);
159                 if(cpuserver)
160                         ksetenv("service", "cpu", 0);
161                 else
162                         ksetenv("service", "terminal", 0);
163                 setconfenv();
164                 poperror();
165         }
166         kproc("alarm", alarmkproc, 0);
167
168         sp = (char**)(USTKTOP - sizeof(Tos) - 8 - sizeof(sp[0])*4);
169         sp[3] = sp[2] = nil;
170         strcpy(sp[1] = (char*)&sp[4], "boot");
171         sp[0] = nil;
172         touser(sp);
173 }
174
175 void
176 main(void)
177 {
178         mach0init();
179         bootargsinit();
180         trapinit0();
181         ioinit();
182         i8250console();
183         quotefmtinstall();
184         screeninit();
185         print("\nPlan 9\n");
186         i8253init();
187         cpuidentify();
188         meminit0();
189         archinit();
190         meminit();
191         ramdiskinit();
192         confinit();
193         xinit();
194         if(i8237alloc != nil)
195                 i8237alloc();
196         pcicfginit();
197         bootscreeninit();
198         trapinit();
199         printinit();
200         cpuidprint();
201         mmuinit();
202         if(arch->intrinit)
203                 arch->intrinit();
204         timersinit();
205         mathinit();
206         if(arch->clockenable)
207                 arch->clockenable();
208         procinit0();
209         initseg();
210         if(delaylink){
211                 bootlinks();
212         }else
213                 links();
214         chandevreset();
215         preallocpages();
216         pageinit();
217         userinit();
218         schedinit();
219 }
220
221 static void
222 rebootjump(uintptr entry, uintptr code, ulong size)
223 {
224         void (*f)(uintptr, uintptr, ulong);
225         uintptr *pte;
226
227         splhi();
228         arch->introff();
229
230         /*
231          * This allows the reboot code to turn off the page mapping
232          */
233         *mmuwalk(m->pml4, 0, 3, 0) = *mmuwalk(m->pml4, KZERO, 3, 0);
234         *mmuwalk(m->pml4, 0, 2, 0) = *mmuwalk(m->pml4, KZERO, 2, 0);
235
236         if((pte = mmuwalk(m->pml4, REBOOTADDR, 1, 0)) != nil)
237                 *pte &= ~PTENOEXEC;
238         if((pte = mmuwalk(m->pml4, REBOOTADDR, 0, 0)) != nil)
239                 *pte &= ~PTENOEXEC;
240
241         mmuflushtlb();
242
243         /* setup reboot trampoline function */
244         f = (void*)REBOOTADDR;
245         memmove(f, rebootcode, sizeof(rebootcode));
246
247         /* off we go - never to return */
248         coherence();
249         (*f)(entry, code, size);
250
251         for(;;);
252 }
253
254
255 void
256 exit(int)
257 {
258         cpushutdown();
259         if(m->machno)
260                 rebootjump(0, 0, 0);
261         arch->reset();
262 }
263
264 void
265 reboot(void *entry, void *code, ulong size)
266 {
267         writeconf();
268         vmxshutdown();
269
270         /*
271          * the boot processor is cpu0.  execute this function on it
272          * so that the new kernel has the same cpu0.  this only matters
273          * because the hardware has a notion of which processor was the
274          * boot processor and we look at it at start up.
275          */
276         if (m->machno != 0) {
277                 procwired(up, 0);
278                 sched();
279         }
280         cpushutdown();
281         delay(1000);
282         splhi();
283
284         /* turn off buffered serial console */
285         serialoq = nil;
286
287         /* shutdown devices */
288         chandevshutdown();
289
290         /* disable pci devices */
291         pcireset();
292
293         rebootjump((uintptr)entry & (ulong)~0xF0000000UL, PADDR(code), size);
294 }
295
296 void
297 procsetup(Proc *p)
298 {
299         fpuprocsetup(p);
300
301         /* clear debug registers */
302         memset(p->dr, 0, sizeof(p->dr));
303         if(m->dr7 != 0){
304                 m->dr7 = 0;
305                 putdr7(0);
306         }
307
308         cycles(&p->kentry);
309         p->pcycles = -p->kentry;
310 }
311
312 void
313 procfork(Proc *p)
314 {
315         p->kentry = up->kentry;
316         p->pcycles = -p->kentry;
317
318         fpuprocfork(p);
319 }
320
321 void
322 procrestore(Proc *p)
323 {
324         uvlong t;
325         
326         if(p->dr[7] != 0){
327                 m->dr7 = p->dr[7];
328                 putdr(p->dr);
329         }
330         
331         if(p->vmx != nil)
332                 vmxprocrestore(p);
333
334         fpuprocrestore(p);
335
336         if(p->kp)
337                 return;
338
339         cycles(&t);
340         p->kentry += t;
341         p->pcycles -= t;
342 }
343
344 void
345 procsave(Proc *p)
346 {
347         uvlong t;
348         
349         cycles(&t);
350         p->kentry -= t;
351         p->pcycles += t;
352
353         if(m->dr7 != 0){
354                 m->dr7 = 0;
355                 putdr7(0);
356         }
357         if(p->state == Moribund)
358                 p->dr[7] = 0;
359
360         fpuprocsave(p);
361
362         /*
363          * While this processor is in the scheduler, the process could run
364          * on another processor and exit, returning the page tables to
365          * the free list where they could be reallocated and overwritten.
366          * When this processor eventually has to get an entry from the
367          * trashed page tables it will crash.
368          *
369          * If there's only one processor, this can't happen.
370          * You might think it would be a win not to do this in that case,
371          * especially on VMware, but it turns out not to matter.
372          */
373         mmuflushtlb();
374 }