]> git.lizzy.rs Git - plan9front.git/blob - sys/src/9/pc64/main.c
17a766137cf6e8063964a7616330db449971eba6
[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         cpuidentify();
187         meminit0();
188         archinit();
189         if(arch->clockinit)
190                 arch->clockinit();
191         meminit();
192         ramdiskinit();
193         confinit();
194         xinit();
195         if(i8237alloc != nil)
196                 i8237alloc();
197         pcicfginit();
198         bootscreeninit();
199         trapinit();
200         printinit();
201         cpuidprint();
202         mmuinit();
203         if(arch->intrinit)
204                 arch->intrinit();
205         timersinit();
206         mathinit();
207         if(arch->clockenable)
208                 arch->clockenable();
209         procinit0();
210         initseg();
211         if(delaylink){
212                 bootlinks();
213         }else
214                 links();
215         chandevreset();
216         preallocpages();
217         pageinit();
218         userinit();
219         schedinit();
220 }
221
222 static void
223 rebootjump(uintptr entry, uintptr code, ulong size)
224 {
225         void (*f)(uintptr, uintptr, ulong);
226         uintptr *pte;
227
228         splhi();
229         arch->introff();
230
231         /*
232          * This allows the reboot code to turn off the page mapping
233          */
234         *mmuwalk(m->pml4, 0, 3, 0) = *mmuwalk(m->pml4, KZERO, 3, 0);
235         *mmuwalk(m->pml4, 0, 2, 0) = *mmuwalk(m->pml4, KZERO, 2, 0);
236
237         if((pte = mmuwalk(m->pml4, REBOOTADDR, 1, 0)) != nil)
238                 *pte &= ~PTENOEXEC;
239         if((pte = mmuwalk(m->pml4, REBOOTADDR, 0, 0)) != nil)
240                 *pte &= ~PTENOEXEC;
241
242         mmuflushtlb();
243
244         /* setup reboot trampoline function */
245         f = (void*)REBOOTADDR;
246         memmove(f, rebootcode, sizeof(rebootcode));
247
248         /* off we go - never to return */
249         coherence();
250         (*f)(entry, code, size);
251
252         for(;;);
253 }
254
255
256 void
257 exit(int)
258 {
259         cpushutdown();
260         if(m->machno)
261                 rebootjump(0, 0, 0);
262         arch->reset();
263 }
264
265 void
266 reboot(void *entry, void *code, ulong size)
267 {
268         writeconf();
269         vmxshutdown();
270
271         /*
272          * the boot processor is cpu0.  execute this function on it
273          * so that the new kernel has the same cpu0.  this only matters
274          * because the hardware has a notion of which processor was the
275          * boot processor and we look at it at start up.
276          */
277         if (m->machno != 0) {
278                 procwired(up, 0);
279                 sched();
280         }
281         cpushutdown();
282         delay(1000);
283         splhi();
284
285         /* turn off buffered serial console */
286         serialoq = nil;
287
288         /* shutdown devices */
289         chandevshutdown();
290
291         /* disable pci devices */
292         pcireset();
293
294         rebootjump((uintptr)entry & (ulong)~0xF0000000UL, PADDR(code), size);
295 }
296
297 void
298 procsetup(Proc *p)
299 {
300         fpuprocsetup(p);
301
302         /* clear debug registers */
303         memset(p->dr, 0, sizeof(p->dr));
304         if(m->dr7 != 0){
305                 m->dr7 = 0;
306                 putdr7(0);
307         }
308 }
309
310 void
311 procfork(Proc *p)
312 {
313         fpuprocfork(p);
314 }
315
316 void
317 procrestore(Proc *p)
318 {
319         if(p->dr[7] != 0){
320                 m->dr7 = p->dr[7];
321                 putdr(p->dr);
322         }
323         
324         if(p->vmx != nil)
325                 vmxprocrestore(p);
326
327         fpuprocrestore(p);
328 }
329
330 void
331 procsave(Proc *p)
332 {
333         if(m->dr7 != 0){
334                 m->dr7 = 0;
335                 putdr7(0);
336         }
337         if(p->state == Moribund)
338                 p->dr[7] = 0;
339
340         fpuprocsave(p);
341
342         /*
343          * While this processor is in the scheduler, the process could run
344          * on another processor and exit, returning the page tables to
345          * the free list where they could be reallocated and overwritten.
346          * When this processor eventually has to get an entry from the
347          * trashed page tables it will crash.
348          *
349          * If there's only one processor, this can't happen.
350          * You might think it would be a win not to do this in that case,
351          * especially on VMware, but it turns out not to matter.
352          */
353         mmuflushtlb();
354 }