kexec.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467
  1. /*
  2. * This file is part of the UCB release of Plan 9. It is subject to the license
  3. * terms in the LICENSE file found in the top-level directory of this
  4. * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
  5. * part of the UCB release of Plan 9, including this file, may be copied,
  6. * modified, propagated, or distributed except according to the terms contained
  7. * in the LICENSE file.
  8. */
  9. #include "u.h"
  10. #include "tos.h"
  11. #include "../port/lib.h"
  12. #include "mem.h"
  13. #include "dat.h"
  14. #include "fns.h"
  15. #include "../port/error.h"
  16. #include "../port/edf.h"
  17. #include <a.out.h>
  18. #include "kexec.h"
  19. /* XXX: MOVE ME TO K10 */
  20. enum {
  21. Maxslot = 32,
  22. };
  23. static uint64_t
  24. vl2be(uint64_t v)
  25. {
  26. uint8_t *p;
  27. p = (uint8_t*)&v;
  28. return ((uint64_t)((p[0]<<24)|(p[1]<<16)|(p[2]<<8)|p[3])<<32)
  29. |((uint64_t)(p[4]<<24)|(p[5]<<16)|(p[6]<<8)|p[7]);
  30. }
  31. static uint32_t
  32. l2be(int32_t l)
  33. {
  34. uint8_t *cp;
  35. cp = (uint8_t*)&l;
  36. return (cp[0]<<24) | (cp[1]<<16) | (cp[2]<<8) | cp[3];
  37. }
  38. typedef struct {
  39. Exec;
  40. uint64_t hdr[1];
  41. } Khdr;
  42. enum {
  43. AsmNONE = 0,
  44. AsmMEMORY = 1,
  45. AsmRESERVED = 2,
  46. AsmACPIRECLAIM = 3,
  47. AsmACPINVS = 4,
  48. AsmDEV = 5,
  49. };
  50. Proc*
  51. setupseg(int core)
  52. {
  53. Mach *m = machp();
  54. Segment *s;
  55. uintptr_t ka;
  56. Proc *p;
  57. static Pgrp *kpgrp;
  58. // XXX: we're going to need this for locality domains.
  59. USED(core);
  60. p = newproc();
  61. p->psstate = 0;
  62. p->procmode = 0640;
  63. p->kp = 1;
  64. p->noswap = 1;
  65. p->scallnr = m->externup->scallnr;
  66. memmove(p->arg, m->externup->arg, sizeof(m->externup->arg));
  67. p->nerrlab = 0;
  68. p->slash = m->externup->slash;
  69. p->dot = m->externup->dot;
  70. if(p->dot)
  71. incref(p->dot);
  72. memmove(p->note, m->externup->note, sizeof(p->note));
  73. p->nnote = m->externup->nnote;
  74. p->notified = 0;
  75. p->lastnote = m->externup->lastnote;
  76. p->notify = m->externup->notify;
  77. p->ureg = 0;
  78. p->dbgreg = 0;
  79. kstrdup(&p->user, eve);
  80. if(kpgrp == 0)
  81. kpgrp = newpgrp();
  82. p->pgrp = kpgrp;
  83. incref(kpgrp);
  84. memset(p->time, 0, sizeof(p->time));
  85. p->time[TReal] = sys->ticks;
  86. procpriority(p, PriKproc, 0);
  87. // XXX: kluge 4 pages of address space for this.
  88. // how will it expand up? gives us <50 kprocs as is.
  89. /*
  90. * we create the color and core at allocation time, not execution. This
  91. * is probably not the best idea but it's a start.
  92. */
  93. // XXX: now that we are asmalloc we are no long proc.
  94. ka = (uintptr_t)KADDR(asmalloc(0, BIGPGSZ, AsmMEMORY, 1));
  95. s = newseg(SG_TEXT|SG_RONLY, ka, 1);
  96. p->seg[TSEG] = s;
  97. // s->color = acpicorecolor(core);
  98. /* Data. Shared. */
  99. // XXX; Now that the address space is all funky how are we going to handle shared data segments?
  100. ka = (uintptr_t)KADDR(asmalloc(0, BIGPGSZ, AsmMEMORY, 2));
  101. s = newseg(SG_DATA, ka, 1);
  102. p->seg[DSEG] = s;
  103. s->color = p->seg[TSEG]->color;
  104. /* BSS. Uses asm from data map. */
  105. p->seg[BSEG] = newseg(SG_BSS, ka+BIGPGSZ, 1);
  106. p->seg[BSEG]->color= m->externup->seg[TSEG]->color;
  107. /* Stack */
  108. ka = (uintptr_t)KADDR(asmalloc(0, BIGPGSZ, AsmMEMORY, 1));
  109. p->seg[SSEG] = newseg(SG_STACK, ka, 1);
  110. nixprepage(-1);
  111. return p;
  112. }
  113. void
  114. kforkexecac(Proc *p, int core, char *ufile, char **argv)
  115. {
  116. Mach *m = machp();
  117. Khdr hdr;
  118. Tos *tos;
  119. Chan *chan;
  120. int argc, i, n;
  121. char *a, *elem, *file, *args;
  122. int32_t hdrsz, magic, textsz, datasz, bsssz;
  123. uintptr_t textlim, datalim, bsslim, entry, tbase, tsize, dbase, dsize, bbase, bsize, sbase, ssize, stack;
  124. Mach *mp;
  125. // static Pgrp *kpgrp;
  126. DBG("kexec on core %d\n", core);
  127. // XXX: since this is kernel code we can't do attachimage,
  128. // we should be reading the file into kernel memory.
  129. // this only matters if we are using ufile.
  130. // YYY: look at dev reboot for help.
  131. file = nil;
  132. elem = nil;
  133. chan = nil;
  134. mp = nil;
  135. USED(chan);
  136. if(waserror()){
  137. DBG("kforkexecac: failing: %s\n", m->externup->errstr);
  138. if(file)
  139. free(file);
  140. if(elem)
  141. free(elem);
  142. if(chan)
  143. cclose(chan);
  144. if(core > 0 && mp != nil)
  145. mp->proc = nil;
  146. if(core != 0)
  147. p->ac = nil;
  148. nexterror();
  149. }
  150. if(core != 0)
  151. p->ac = getac(p, core);
  152. argc = 0;
  153. if(ufile != nil){
  154. panic("ufile not implemented yet");
  155. file = validnamedup(ufile, 1);
  156. DBG("kforkexecac: up %#p file %s\n", m->externup, file);
  157. chan = namec(file, Aopen, OEXEC, 0);
  158. kstrdup(&elem, m->externup->genbuf);
  159. hdrsz = chan->dev->read(chan, &hdr, sizeof(Khdr), 0);
  160. DBG("wrote ufile\n");
  161. if(hdrsz < 2)
  162. error(Ebadexec);
  163. }else{
  164. /* somebody already wrote in our text segment */
  165. hdr = *(Khdr*)p->seg[TSEG]->base;
  166. hdrsz = sizeof(Khdr);
  167. }
  168. // p = (char*)&hdr;
  169. magic = l2be(hdr.magic);
  170. DBG("badexec3\n");
  171. if(hdrsz != sizeof(Khdr) || magic != AOUT_MAGIC)
  172. error(Ebadexec);
  173. if(magic & HDR_MAGIC){
  174. entry = vl2be(hdr.hdr[0]);
  175. hdrsz = sizeof(Khdr);
  176. }
  177. else{
  178. entry = l2be(hdr.entry);
  179. hdrsz = sizeof(Exec);
  180. }
  181. textsz = l2be(hdr.text);
  182. datasz = l2be(hdr.data);
  183. bsssz = l2be(hdr.bss);
  184. tbase = p->seg[TSEG]->base;
  185. tsize = tbase - p->seg[TSEG]->top;
  186. dbase = p->seg[DSEG]->base;
  187. dsize = dbase - p->seg[DSEG]->top;
  188. bbase = p->seg[BSEG]->base;
  189. bsize = bbase - p->seg[BSEG]->top;
  190. sbase = p->seg[SSEG]->base;
  191. ssize = sbase - p->seg[SSEG]->top;
  192. // XXX: we are no longer contiguous.
  193. textlim = ROUNDUP(hdrsz+textsz, BIGPGSZ);
  194. // XXX: we are going to be at least two pages here.
  195. datalim = BIGPGROUND(datasz);
  196. bsslim = BIGPGROUND(datalim+bsssz);
  197. // XXX: this is pretty fragile
  198. memmove((void*)dbase, (void*)(entry+textsz), datasz);
  199. DBG("writing data dbase %#p tbase %#p textsz %ld datasz %ld\n", dbase, tbase, textsz, datasz);
  200. // memmove((void*)dbase, (void*)"testing data", 13);
  201. /*
  202. * Check the binary header for consistency,
  203. * e.g. the entry point is within the text segment and
  204. * the segments don't overlap each other.
  205. */
  206. // XXX: max instruction size on amd64 is 15 bytes provide a check for consistency.
  207. DBG("kexec: entry %#p tbase %#p hdrsz %ld textsz %ld\n", entry, tbase, hdrsz, textsz);
  208. if(entry < tbase+hdrsz || entry >= tbase+hdrsz+textsz)
  209. error(Ebadexec);
  210. // XXX: what about the kernel stack we are making here?
  211. DBG("kexec: testing if sizes overflow limits\n");
  212. if(textsz >= textlim || datasz > datalim || bsssz > bsslim)
  213. error(Ebadexec);
  214. DBG("kexec: do the top of the segments overflow limits?\n");
  215. if(textlim >= tbase+tsize || datalim >= dbase+dsize || bsslim >= bbase+bsize)
  216. error(Ebadexec);
  217. DBG("kexec: is bss below data?\n");
  218. if(bsslim < datalim)
  219. error(Ebadexec);
  220. /*
  221. Interesting thought, the previously allocated segments for
  222. data and text are shared and constant. The BSS and the stack
  223. are not. What you really want is the ability to make an
  224. executable text and data and then create child executables on
  225. top of that. This will lower external fragmentation and allow
  226. a bunch of communicating shared memory processes (ie. go) in
  227. kernel space.
  228. Fundamentally this means that the allocation of the text and
  229. the data should be separate from the bss and the stack. This
  230. will require that you change the linkers as well to allow the
  231. separation of data and bss sections.
  232. */
  233. /*
  234. * Stack is a pointer into the temporary stack
  235. * segment, and will move as items are pushed.
  236. */
  237. // need to work something out here with the stack.
  238. stack = sbase+ssize-sizeof(Tos);
  239. /*
  240. * XXX: When we are linking this how do we set the tos? We will need to change trap right?
  241. */
  242. tos = (Tos*)stack;
  243. tos->cyclefreq = m->cyclefreq;
  244. cycles((uint64_t*)&tos->pcycles);
  245. tos->pcycles = -tos->pcycles;
  246. tos->kcycles = tos->pcycles;
  247. tos->clock = 0;
  248. DBG("kexec: argument processing\n");
  249. if(0)
  250. for(i = 0;; i++, argv++){
  251. a = *(char**)validaddr(argv, sizeof(char**), 0);
  252. if(a == nil)
  253. break;
  254. a = validaddr(a, 1, 0);
  255. n = ((char*)vmemchr(a, 0, 0x7fffffff) - a) + 1;
  256. if(argc > 0 && i == 0)
  257. continue;
  258. stack -= n;
  259. if(stack < sbase+ssize-4096)
  260. error(Enovmem);
  261. args = UINT2PTR(stack);
  262. memmove(args, a, n);
  263. args[n-1] = 0;
  264. argc++;
  265. }
  266. // DBG("kexec: ensuring we have argc\n");
  267. if(0)
  268. if(argc < 1)
  269. error(Ebadexec);
  270. a = args = UINT2PTR(stack);
  271. stack = sysexecstack(stack, argc);
  272. // XXX: look through math on this. look at ../../9/port/ exec.c
  273. // YYY: this looks like a Jimism for 9k.
  274. // DBG("kexec: ensuring the stack \n");
  275. if(0)
  276. if(stack-(argc+1)*sizeof(char**)-BIGPGSZ < sbase+ssize-4096)
  277. error(Ebadexec);
  278. argv = (char**)stack;
  279. *--argv = nil;
  280. // XXX: replace USTKTOP with a new variable representing the top of stack.
  281. if(0)
  282. for(i = 0; i < argc; i++){
  283. *--argv = args + (USTKTOP-sbase+ssize);
  284. args += strlen(args) + 1;
  285. }
  286. DBG("argsing\n");
  287. n = args - a;
  288. if(0)
  289. if(n <= 0)
  290. error(Egreg);
  291. if(n > 128)
  292. n = 128;
  293. DBG("kexec: allocating args\n");
  294. // XXX: hangs in smalloc, not sure why.
  295. // args = smalloc(n);
  296. // if(waserror()){
  297. // DBG("erroring\n");
  298. // free(args);
  299. // nexterror();
  300. // }
  301. // DBG("kexec: moving args\n");
  302. // memmove(args, a, n);
  303. // if(0)
  304. // while(n > 0 && (args[n-1] & 0xc0) == 0x80)
  305. // n--;
  306. // args[n-1] = '\0';
  307. kstrdup(&p->text, "kexecproc");
  308. p->args = nil;
  309. //elem;
  310. // elem = nil;
  311. // p->args = args;
  312. // p->nargs = n;
  313. poperror(); /* p (m->externup->args) */
  314. /*
  315. qlock(&p->debug);
  316. sysprocsetup(p);
  317. qunlock(&p->debug);
  318. */
  319. // why is this sched and not ureg?
  320. p->sched.pc = entry;
  321. // the real question here is how do you set up the stack?
  322. p->sched.sp = PTR2UINT(stack-BY2SE);
  323. p->sched.sp = STACKALIGN(p->sched.sp);
  324. // XXX: what does it imply if you have a kproc that runs on an ac?
  325. if(core > 0){
  326. DBG("kexec: coring %d\n", core);
  327. mp = p->ac;
  328. mp->icc->flushtlb = 1;
  329. mp->icc->rc = ICCOK;
  330. DBG("kexec: exotic proc on cpu%d\n", mp->machno);
  331. qlock(&p->debug);
  332. if(waserror()){
  333. DBG("kexec: had error");
  334. qunlock(&p->debug);
  335. nexterror();
  336. }
  337. p->nicc++;
  338. p->state = Exotic;
  339. p->psstate = 0;
  340. DBG("kexec: unlocking");
  341. qunlock(&p->debug);
  342. poperror();
  343. mfence();
  344. mp->icc->fn = (void*)entry;
  345. sched();
  346. }else{
  347. DBG("kexec: readying\n");
  348. ready(p);
  349. p->newtlb = 1;
  350. mmuflush();
  351. }
  352. DBG("kforkexecac up %#p done\n"
  353. "textsz %lx datasz %lx bsssz %lx hdrsz %lx\n"
  354. "textlim %ullx datalim %ullx bsslim %ullx\n", m->externup,
  355. textsz, datasz, bsssz, hdrsz, textlim, datalim, bsslim);
  356. }
  357. void
  358. syskforkexecac(Ar0* ar0, ...)
  359. {
  360. // int core;
  361. // uintptr base, size;
  362. // char *file, **argv;
  363. va_list list;
  364. va_start(list, ar0);
  365. //XXX: get system call working.
  366. USED(ar0); USED(list);
  367. // XXX: fix sysexecregs
  368. panic("syskforkexecac: don't call me yet");
  369. /*
  370. * void* syskforkexecac(uintptr base, size, int core, char *ufile, char **argv)
  371. */
  372. // base = va_arg(list, uintptr);
  373. // size = va_arg(list, uintptr);
  374. // core = va_arg(list, unsigned int);
  375. // file = va_arg(list, char*);
  376. // file = validaddr(file, 1, 0);
  377. // argv = va_arg(list, char**);
  378. va_end(list);
  379. // evenaddr(PTR2UINT(argv));
  380. // XXX: going to need to setup segs here.
  381. //kforkexecac(p, core, file, argv);
  382. // this is not going to work. I need to think about it.
  383. // ar0->v = sysexecregs(entry, stack - PTR2UINT(argv), argc);
  384. }
  385. void
  386. printhello(void)
  387. {
  388. print("hello\n");
  389. }
  390. void
  391. printargs(char *arg)
  392. {
  393. print("%#p %s\n", arg, arg);
  394. }