acore.c 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343
  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 "../port/lib.h"
  11. #include "mem.h"
  12. #include "dat.h"
  13. #include "fns.h"
  14. #include <tos.h>
  15. #include <pool.h>
  16. #include "ureg.h"
  17. #include "io.h"
  18. #include "../port/pmc.h"
  19. /*
  20. * NIX code run at the AC.
  21. * This is the "AC kernel".
  22. */
  23. /*
  24. * FPU:
  25. *
  26. * The TC handles the FPU by keeping track of the state for the
  27. * current process. If it has been used and must be saved, it is saved, etc.
  28. * When a process gets to the AC, we handle the FPU directly, and save its
  29. * state before going back to the TC (or the TC state would be stale).
  30. *
  31. * Because of this, each time the process comes back to the AC and
  32. * uses the FPU it will get a device not available trap and
  33. * the state will be restored. This could be optimized because the AC
  34. * is single-process, and we do not have to disable the FPU while
  35. * saving, so it does not have to be restored.
  36. */
  37. extern char* acfpunm(Ureg* ureg, void *unused_voidp);
  38. extern char* acfpumf(Ureg* ureg, void *unused_voidp);
  39. extern char* acfpuxf(Ureg* ureg, void *unused_voidp);
  40. extern void acfpusysprocsetup(Proc*);
  41. extern void _acsysret(void);
  42. extern void _actrapret(void);
  43. ACVctl *acvctl[256];
  44. /*
  45. * Test inter core calls by calling a cores to print something, and then
  46. * waiting for it to complete.
  47. */
  48. static void
  49. testiccfn(void)
  50. {
  51. print("called: %s\n", ( char *)machp()->NIX.icc->data);
  52. }
  53. void
  54. testicc(int i)
  55. {
  56. Mach *mp;
  57. if((mp = sys->machptr[i]) != nil && mp->online != 0){
  58. if(mp->NIX.nixtype != NIXAC){
  59. print("testicc: core %d is not an AC\n", i);
  60. return;
  61. }
  62. print("calling core %d... ", i);
  63. mp->NIX.icc->flushtlb = 0;
  64. snprint(( char *)mp->NIX.icc->data, ICCLNSZ, "<%d>", i);
  65. mfence();
  66. mp->NIX.icc->fn = testiccfn;
  67. mwait(&mp->NIX.icc->fn);
  68. }
  69. }
  70. /*
  71. * Check if the AC kernel (mach) stack has more than 4*KiB free.
  72. * Do not call panic, the stack is gigantic.
  73. */
  74. static void
  75. acstackok(void)
  76. {
  77. char dummy;
  78. char *sstart;
  79. sstart = (char *)machp() - PGSZ - 4*PTSZ - MACHSTKSZ;
  80. if(&dummy < sstart + 4*KiB){
  81. print("ac kernel stack overflow, cpu%d stopped\n", machp()->machno);
  82. DONE();
  83. }
  84. }
  85. /*
  86. * Main scheduling loop done by the application core.
  87. * Some of functions run will not return.
  88. * The system call handler will reset the stack and
  89. * call acsched again.
  90. * We loop because some functions may return and we should
  91. * wait for another call.
  92. */
  93. void
  94. acsched(void)
  95. {
  96. acmmuswitch();
  97. for(;;){
  98. acstackok();
  99. mwait(&machp()->NIX.icc->fn);
  100. if(machp()->NIX.icc->flushtlb)
  101. acmmuswitch();
  102. DBG("acsched: cpu%d: fn %#p\n", machp()->machno, machp()->NIX.icc->fn);
  103. machp()->NIX.icc->fn();
  104. DBG("acsched: cpu%d: idle\n", machp()->machno);
  105. mfence();
  106. machp()->NIX.icc->fn = nil;
  107. }
  108. }
  109. void
  110. acmmuswitch(void)
  111. {
  112. extern Page mach0pml4;
  113. DBG("acmmuswitch mpl4 %#p mach0pml4 %#p m0pml4 %#p\n", machp()->MMU.pml4->pa, mach0pml4.pa, sys->machptr[0]->MMU.pml4->pa);
  114. rootput(machp()->MMU.pml4->pa);
  115. }
  116. /*
  117. * Beware: up is not set when this function is called.
  118. */
  119. void
  120. actouser(void)
  121. {
  122. #if 0
  123. void xactouser(uint64_t);
  124. Ureg *u;
  125. acfpusysprocsetup(m->proc);
  126. u = m->proc->dbgreg;
  127. DBG("cpu%d: touser usp = %#p entry %#p\n", machp()->machno, u->sp, u->ip);
  128. xactouser(u->sp);
  129. #endif
  130. panic("actouser");
  131. }
  132. void
  133. actrapret(void)
  134. {
  135. /* done by actrap() */
  136. }
  137. /*
  138. * Entered in AP core context, upon traps (system calls go through acsyscall)
  139. * using up->dbgreg means cores MUST be homogeneous.
  140. *
  141. * BUG: We should setup some trapenable() mechanism for the AC,
  142. * so that code like fpu.c could arrange for handlers specific for
  143. * the AC, instead of doint that by hand here.
  144. *
  145. * All interrupts are masked while in the "kernel"
  146. */
  147. void
  148. actrap(Ureg *u)
  149. {
  150. panic("actrap");
  151. #if 0
  152. char *n;
  153. ACVctl *v;
  154. n = nil;
  155. _pmcupdate(m);
  156. if(m->proc != nil){
  157. m->proc->nactrap++;
  158. m->proc->actime1 = fastticks(nil);
  159. }
  160. if(u->type < nelem(acvctl)){
  161. v = acvctl[u->type];
  162. if(v != nil){
  163. DBG("actrap: cpu%d: %llu\n", machp()->machno, u->type);
  164. n = v->f(u, v->a);
  165. if(n != nil)
  166. goto Post;
  167. return;
  168. }
  169. }
  170. switch(u->type){
  171. case IdtDF:
  172. print("AC: double fault\n");
  173. dumpregs(u);
  174. ndnr();
  175. case IdtIPI:
  176. m->intr++;
  177. DBG("actrap: cpu%d: IPI\n", machp()->machno);
  178. apiceoi(IdtIPI);
  179. break;
  180. case IdtTIMER:
  181. apiceoi(IdtTIMER);
  182. panic("timer interrupt in an AC");
  183. break;
  184. case IdtPF:
  185. /* this case is here for debug only */
  186. m->pfault++;
  187. DBG("actrap: cpu%d: PF cr2 %#llx\n", machp()->machno, cr2get());
  188. break;
  189. default:
  190. print("actrap: cpu%d: %llu\n", machp()->machno, u->type);
  191. }
  192. Post:
  193. m->NIX.icc->rc = ICCTRAP;
  194. m->cr2 = cr2get();
  195. memmove(m->proc->dbgreg, u, sizeof *u);
  196. m->NIX.icc->note = n;
  197. fpuprocsave(m->proc);
  198. _pmcupdate(m);
  199. mfence();
  200. m->NIX.icc->fn = nil;
  201. ready(m->proc);
  202. mwait(&m->NIX.icc->fn);
  203. if(m->NIX.icc->flushtlb)
  204. acmmuswitch();
  205. if(m->NIX.icc->fn != actrapret)
  206. acsched();
  207. DBG("actrap: ret\n");
  208. memmove(u, m->proc->dbgreg, sizeof *u);
  209. if(m->proc)
  210. m->proc->actime += fastticks2us(fastticks(nil) - m->proc->actime1);
  211. #endif
  212. }
  213. void
  214. acsyscall(void)
  215. {
  216. panic("acsyscall");
  217. #if 0
  218. Proc *p;
  219. /*
  220. * If we saved the Ureg into m->proc->dbgregs,
  221. * There's nothing else we have to do.
  222. * Otherwise, we should m->proc->dbgregs = u;
  223. */
  224. DBG("acsyscall: cpu%d\n", machp()->machno);
  225. _pmcupdate(m);
  226. p = m->proc;
  227. p->actime1 = fastticks(nil);
  228. m->syscall++; /* would also count it in the TS core */
  229. m->NIX.icc->rc = ICCSYSCALL;
  230. m->cr2 = cr2get();
  231. fpuprocsave(p);
  232. _pmcupdate(m);
  233. mfence();
  234. m->NIX.icc->fn = nil;
  235. ready(p);
  236. /*
  237. * The next call is probably going to make us jmp
  238. * into user code, forgetting all our state in this
  239. * stack, upon the next syscall.
  240. * We don't nest calls in the current stack for too long.
  241. */
  242. acsched();
  243. #endif
  244. }
  245. /*
  246. * Called in AP core context, to return from system call.
  247. */
  248. void
  249. acsysret(void)
  250. {
  251. panic("acsysret");
  252. #if 0
  253. DBG("acsysret\n");
  254. if(m->proc != nil)
  255. m->proc->actime += fastticks2us(fastticks(nil) - m->proc->actime1);
  256. _acsysret();
  257. #endif
  258. }
  259. void
  260. dumpreg(void *u)
  261. {
  262. print("reg is %p\n", u);
  263. ndnr();
  264. }
  265. char *rolename[] =
  266. {
  267. [NIXAC] = "AC",
  268. [NIXTC] = "TC",
  269. [NIXKC] = "KC",
  270. [NIXXC] = "XC",
  271. };
  272. void
  273. acmodeset(int mode)
  274. {
  275. switch(mode){
  276. case NIXAC:
  277. case NIXKC:
  278. case NIXTC:
  279. case NIXXC:
  280. break;
  281. default:
  282. panic("acmodeset: bad mode %d", mode);
  283. }
  284. machp()->NIX.nixtype = mode;
  285. }
  286. void
  287. acinit(void)
  288. {
  289. Mach *mp;
  290. Proc *pp;
  291. /*
  292. * Lower the priority of the apic to 0,
  293. * to accept interrupts.
  294. * Raise it later if needed to disable them.
  295. */
  296. panic("apicpri");
  297. //apicpri(0);
  298. /*
  299. * Be sure a few assembler assumptions still hold.
  300. * Someone moved m->stack and I had fun debugging...
  301. */
  302. mp = 0;
  303. pp = 0;
  304. assert((uintptr)&mp->proc == 16);
  305. assert((uintptr)&pp->dbgreg == 24);
  306. assert((uintptr)&mp->stack == 24);
  307. }