changelog shortlog tags branches changeset files revisions annotate raw help

Mercurial > hg > plan9front / sys/src/9/bcm64/main.c

changeset 7235: b1dc95374307
parent: 19de954d8073
child: 889b634159e5
author: cinap_lenrek@felloff.net
date: Mon, 13 May 2019 19:20:21 +0200
permissions: -rw-r--r--
description: bcm64: implement reboot support
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 "../port/error.h"
8 #include "io.h"
9 #include "init.h"
10 #include "sysreg.h"
11 #include "reboot.h"
12 
13 #include <pool.h>
14 #include <libsec.h>
15 
16 Conf conf;
17 
18 /*
19  * starting place for first process
20  */
21 void
22 init0(void)
23 {
24  char buf[2*KNAMELEN], **sp;
25 
26  up->nerrlab = 0;
27  spllo();
28 
29  /*
30  * These are o.k. because rootinit is null.
31  * Then early kproc's will have a root and dot.
32  */
33  up->slash = namec("#/", Atodir, 0, 0);
34  pathclose(up->slash->path);
35  up->slash->path = newpath("/");
36  up->dot = cclone(up->slash);
37  chandevinit();
38 
39  if(!waserror()){
40  snprint(buf, sizeof(buf), "%s %s", "ARM64", conffile);
41  ksetenv("terminal", buf, 0);
42  ksetenv("cputype", "arm64", 0);
43  if(cpuserver)
44  ksetenv("service", "cpu", 0);
45  else
46  ksetenv("service", "terminal", 0);
47  snprint(buf, sizeof(buf), "-a %s", getethermac());
48  ksetenv("etherargs", buf, 0);
49 
50  /* convert plan9.ini variables to #e and #ec */
51  setconfenv();
52  poperror();
53  }
54  kproc("alarm", alarmkproc, 0);
55 
56  sp = (char**)(USTKTOP-sizeof(Tos) - 8 - sizeof(sp[0])*4);
57  sp[3] = sp[2] = sp[1] = nil;
58  strcpy(sp[1] = (char*)&sp[4], "boot");
59  sp[0] = (void*)&sp[1];
60 
61  touser((uintptr)sp);
62 
63  assert(0); /* shouldn't have returned */
64 }
65 
66 /*
67  * create the first process
68  */
69 void
70 userinit(void)
71 {
72  Proc *p;
73  Segment *s;
74  KMap *k;
75  Page *pg;
76 
77  /* no processes yet */
78  up = nil;
79 
80  p = newproc();
81  p->pgrp = newpgrp();
82  p->egrp = smalloc(sizeof(Egrp));
83  p->egrp->ref = 1;
84  p->fgrp = dupfgrp(nil);
85  p->rgrp = newrgrp();
86  p->procmode = 0640;
87 
88  kstrdup(&eve, "");
89  kstrdup(&p->text, "*init*");
90  kstrdup(&p->user, eve);
91 
92  /*
93  * Kernel Stack
94  */
95  p->sched.pc = (uintptr)init0;
96  p->sched.sp = (uintptr)p->kstack+KSTACK-sizeof(up->s.args)-sizeof(uintptr);
97  p->sched.sp = STACKALIGN(p->sched.sp);
98  *(void**)p->sched.sp = kproc; // fake
99 
100  /*
101  * User Stack
102  *
103  * Technically, newpage can't be called here because it
104  * should only be called when in a user context as it may
105  * try to sleep if there are no pages available, but that
106  * shouldn't be the case here.
107  */
108  s = newseg(SG_STACK, USTKTOP-USTKSIZE, USTKSIZE/BY2PG);
109  s->flushme++;
110  p->seg[SSEG] = s;
111  pg = newpage(1, 0, USTKTOP-BY2PG);
112  segpage(s, pg);
113  k = kmap(pg);
114  memset((void*)VA(k), 0, BY2PG);
115  kunmap(k);
116 
117  /*
118  * Text
119  */
120  s = newseg(SG_TEXT, UTZERO, 1);
121  p->seg[TSEG] = s;
122  pg = newpage(1, 0, UTZERO);
123  pg->txtflush = ~0;
124  segpage(s, pg);
125  k = kmap(pg);
126  memmove((void*)VA(k), initcode, sizeof initcode);
127  kunmap(k);
128 
129  ready(p);
130 }
131 
132 void
133 confinit(void)
134 {
135  int i, userpcnt;
136  ulong kpages, memsize = 0;
137  uintptr pa;
138  char *p;
139 
140  if(p = getconf("service")){
141  if(strcmp(p, "cpu") == 0)
142  cpuserver = 1;
143  else if(strcmp(p,"terminal") == 0)
144  cpuserver = 0;
145  }
146 
147  if(p = getconf("*kernelpercent"))
148  userpcnt = 100 - strtol(p, 0, 0);
149  else
150  userpcnt = 0;
151 
152  if(p = getconf("*maxmem"))
153  memsize = strtoul(p, 0, 0) - PHYSDRAM;
154  if (memsize < 16*MB) /* sanity */
155  memsize = 16*MB;
156  getramsize(&conf.mem[0]);
157  if(conf.mem[0].limit == 0){
158  conf.mem[0].base = PHYSDRAM;
159  conf.mem[0].limit = PHYSDRAM + memsize;
160  }else if(p != nil)
161  conf.mem[0].limit = conf.mem[0].base + memsize;
162 
163  conf.npage = 0;
164  pa = PADDR(PGROUND((uintptr)end));
165 
166  /*
167  * we assume that the kernel is at the beginning of one of the
168  * contiguous chunks of memory and fits therein.
169  */
170  for(i=0; i<nelem(conf.mem); i++){
171  /* take kernel out of allocatable space */
172  if(pa > conf.mem[i].base && pa < conf.mem[i].limit)
173  conf.mem[i].base = pa;
174 
175  conf.mem[i].npage = (conf.mem[i].limit - conf.mem[i].base)/BY2PG;
176  conf.npage += conf.mem[i].npage;
177  }
178 
179  if(userpcnt < 10)
180  userpcnt = 60 + cpuserver*10;
181  kpages = conf.npage - (conf.npage*userpcnt)/100;
182 
183  /*
184  * can't go past the end of virtual memory
185  * (uintptr)-KZERO is 2^32 - KZERO
186  */
187  if(kpages > ((uintptr)-KZERO)/BY2PG)
188  kpages = ((uintptr)-KZERO)/BY2PG;
189 
190  conf.upages = conf.npage - kpages;
191  conf.ialloc = (kpages/2)*BY2PG;
192 
193  conf.nmach = getncpus();
194 
195  /* set up other configuration parameters */
196  conf.nproc = 100 + ((conf.npage*BY2PG)/MB)*5;
197  if(cpuserver)
198  conf.nproc *= 3;
199  if(conf.nproc > 2000)
200  conf.nproc = 2000;
201  conf.nswap = conf.npage*3;
202  conf.nswppo = 4096;
203  conf.nimage = 200;
204 
205  conf.copymode = conf.nmach > 1;
206 
207  /*
208  * Guess how much is taken by the large permanent
209  * datastructures. Mntcache and Mntrpc are not accounted for.
210  */
211  kpages = conf.npage - conf.upages;
212  kpages *= BY2PG;
213  kpages -= conf.upages*sizeof(Page)
214  + conf.nproc*sizeof(Proc)
215  + conf.nimage*sizeof(Image)
216  + conf.nswap
217  + conf.nswppo*sizeof(Page*);
218  mainmem->maxsize = kpages;
219  if(!cpuserver)
220  /*
221  * give terminals lots of image memory, too; the dynamic
222  * allocation will balance the load properly, hopefully.
223  * be careful with 32-bit overflow.
224  */
225  imagmem->maxsize = kpages;
226 }
227 
228 void
229 machinit(void)
230 {
231  m->ticks = 1;
232  m->perf.period = 1;
233  active.machs[m->machno] = 1;
234 }
235 
236 void
237 mpinit(void)
238 {
239  extern void _start(void);
240  int i;
241 
242  for(i = 0; i < MAXMACH; i++)
243  ((uintptr*)SPINTABLE)[i] = 0;
244 
245  for(i = 1; i < conf.nmach; i++)
246  MACHP(i)->machno = i;
247 
248  coherence();
249 
250  for(i = 1; i < conf.nmach; i++)
251  ((uintptr*)SPINTABLE)[i] = PADDR(_start);
252 
253  cachedwbinvse((void*)SPINTABLE, MAXMACH*8);
254  sev();
255  delay(100);
256  sev();
257  synccycles();
258 
259  for(i = 0; i < MAXMACH; i++)
260  ((uintptr*)SPINTABLE)[i] = 0;
261 }
262 
263 void
264 main(void)
265 {
266  machinit();
267  if(m->machno){
268  trapinit();
269  fpuinit();
270  clockinit();
271  cpuidprint();
272  synccycles();
273  timersinit();
274  flushtlb();
275  mmu1init();
276  m->ticks = MACHP(0)->ticks;
277  schedinit();
278  return;
279  }
280  quotefmtinstall();
281  bootargsinit();
282  confinit();
283  xinit();
284  printinit();
285  uartconsinit();
286  screeninit();
287  print("\nPlan 9\n");
288  xsummary();
289 
290  /* set clock rate to arm_freq from config.txt */
291  setclkrate(ClkArm, 0);
292 
293  trapinit();
294  fpuinit();
295  clockinit();
296  cpuidprint();
297  timersinit();
298  pageinit();
299  procinit0();
300  initseg();
301  links();
302  chandevreset();
303  userinit();
304  mpinit();
305  mmu0clear((uintptr*)L1);
306  flushtlb();
307  mmu1init();
308  schedinit();
309 }
310 
311 static void
312 rebootjump(void *entry, void *code, ulong size)
313 {
314  void (*f)(void*, void*, ulong);
315 
316  intrsoff();
317  intrcpushutdown();
318 
319  /* redo identity map */
320  mmuidmap((uintptr*)L1);
321 
322  /* setup reboot trampoline function */
323  f = (void*)REBOOTADDR;
324  memmove(f, rebootcode, sizeof(rebootcode));
325  cachedwbinvse(f, sizeof(rebootcode));
326  cacheiinvse(f, sizeof(rebootcode));
327 
328  (*f)(entry, code, size);
329 
330  for(;;);
331 }
332 
333 void
334 exit(int)
335 {
336  cpushutdown();
337  splfhi();
338  if(m->machno == 0)
339  archreboot();
340  rebootjump(0, 0, 0);
341 }
342 
343 void
344 reboot(void *entry, void *code, ulong size)
345 {
346  writeconf();
347  while(m->machno != 0){
348  procwired(up, 0);
349  sched();
350  }
351 
352  cpushutdown();
353  delay(2000);
354 
355  splfhi();
356 
357  /* turn off buffered serial console */
358  serialoq = nil;
359 
360  /* shutdown devices */
361  chandevshutdown();
362 
363  /* stop the clock (and watchdog if any) */
364  clockshutdown();
365  wdogoff();
366 
367  /* off we go - never to return */
368  rebootjump(entry, code, size);
369 }
370 
371 /*
372  * stub for ../omap/devether.c
373  */
374 int
375 isaconfig(char *, int, ISAConf *)
376 {
377  return 0;
378 }