acore.c 7.0 KB

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