arch.c 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  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. /*
  10. * EPISODE 12B
  11. * How to recognise different types of trees from quite a long way away.
  12. * NO. 1
  13. * THE LARCH
  14. */
  15. #include "u.h"
  16. #include "../port/lib.h"
  17. #include "mem.h"
  18. #include "dat.h"
  19. #include "fns.h"
  20. #include "../port/error.h"
  21. #include "ureg.h"
  22. #include "encoding.h"
  23. /* the rules are different for different compilers. We need to define up. */
  24. // Initialize it to force it into data.
  25. // That way, if we set them in assembly, they won't get zero'd by the bss init in main
  26. // N.B. There was an interesting hack in plan 9 c. You could grab up to two registers for your
  27. // program. In the case of Plan 9, m was r15, and up was r14. Very slick, and if there is a way to do
  28. // this in gcc or clang I don't know it. This also nicely handled per cpu info; R15/14 were always right for
  29. // your core and context.
  30. //Mach *m = (void *)0;
  31. int
  32. incref(Ref *r)
  33. {
  34. int x;
  35. lock(&r->l);
  36. x = ++r->ref;
  37. unlock(&r->l);
  38. return x;
  39. }
  40. int
  41. decref(Ref *r)
  42. {
  43. int x;
  44. lock(&r->l);
  45. x = --r->ref;
  46. unlock(&r->l);
  47. if(x < 0)
  48. panic("decref pc=%#p", getcallerpc());
  49. return x;
  50. }
  51. void fpuprocrestore(Proc *p)
  52. {
  53. if (0)print("NOT DOING fpuprocrestore");
  54. }
  55. void
  56. procrestore(Proc *p)
  57. {
  58. uint64_t t;
  59. if(p->kp)
  60. return;
  61. cycles(&t);
  62. p->pcycles -= t;
  63. fpuprocrestore(p);
  64. }
  65. void
  66. fpuprocsave(Proc *p)
  67. {
  68. print("fpuprocsave -- NEED TO IMPLEMENT");
  69. }
  70. /*
  71. * Save the mach dependent part of the process state.
  72. * NB: the caller should mmuflushtlb after procsave().
  73. * procsave/procrestore don't touch the mmu, they
  74. * care about fpu, mostly.
  75. */
  76. void
  77. procsave(Proc *p)
  78. {
  79. uint64_t t;
  80. cycles(&t);
  81. p->pcycles += t;
  82. fpuprocsave(p);
  83. }
  84. static void
  85. linkproc(void)
  86. {
  87. Proc *up = externup();
  88. spllo();
  89. up->kpfun(up->kparg);
  90. pexit("kproc dying", 0);
  91. }
  92. void
  93. kprocchild(Proc* p, void (*func)(void*), void* arg)
  94. {
  95. /*
  96. * gotolabel() needs a word on the stack in
  97. * which to place the return PC used to jump
  98. * to linkproc().
  99. */
  100. p->sched.pc = PTR2UINT(linkproc);
  101. p->sched.sp = PTR2UINT(p->kstack+KSTACK-BY2SE);
  102. p->sched.sp = STACKALIGN(p->sched.sp);
  103. p->kpfun = func;
  104. p->kparg = arg;
  105. }
  106. /*
  107. * put the processor in the halt state if we've no processes to run.
  108. * an interrupt will get us going again.
  109. * The boot TC in nix can't halt, because it must stay alert in
  110. * case an AC makes a handler process ready.
  111. * We should probably use mwait in that case.
  112. */
  113. void
  114. idlehands(void)
  115. {
  116. uint32_t sip = 0;
  117. int i;
  118. extern uint64_t *mtimecmp;
  119. extern uint64_t *mtime;
  120. //print("idlehands, mtime is 0x%llx mtimecmp is 0x%llx\n", *mtime, *mtimecmp);
  121. //print("spin waiting for an interrupt or until mtimecmp passes mtime. \n");
  122. /* toolchain is broken. Again. Puts an sret in for a wfi. Bad idea.
  123. if(machp()->NIX.nixtype != NIXAC)
  124. __asm__ __volatile__("wfi\n");
  125. if (*mtimecmp < *mtime)
  126. timerset(0);
  127. */
  128. sip = (uint32_t)read_csr(sip);
  129. for(i = 0; *mtimecmp < *mtime; i++) {
  130. if (sip & 0x666)
  131. break;
  132. sip = (uint32_t)read_csr(sip);
  133. }
  134. //print("idlehands, mtime is 0x%llx mtimecmp is 0x%llx\n", *mtime, *mtimecmp);
  135. //print("Leaving idlehands. sip is 0x%x, i is %d\n", sip, i);
  136. }
  137. #if 0
  138. void
  139. ureg2gdb(Ureg *u, uintptr_t *g)
  140. {
  141. g[GDB_AX] = u->ax;
  142. g[GDB_BX] = u->bx;
  143. g[GDB_CX] = u->cx;
  144. g[GDB_DX] = u->dx;
  145. g[GDB_SI] = u->si;
  146. g[GDB_DI] = u->di;
  147. g[GDB_BP] = u->bp;
  148. g[GDB_SP] = u->sp;
  149. g[GDB_R8] = u->r8;
  150. g[GDB_R9] = u->r9;
  151. g[GDB_R10] = u->r10;
  152. g[GDB_R11] = u->r11;
  153. g[GDB_R12] = u->r12;
  154. g[GDB_R13] = u->r13;
  155. g[GDB_R14] = u->r14;
  156. g[GDB_R15] = u->r15;
  157. g[GDB_PC] = u->ip;
  158. /* it's weird, docs say 5 32-bit fields
  159. * but I count 4 if we pack these. Fix me
  160. */
  161. g[GDB_PS] = 0; // u->PS;
  162. g[GDB_CS] = 0; // u->CS;
  163. g[GDB_SS] = 0; // u->SS;
  164. g[GDB_DS] = 0; // u->DS;
  165. g[GDB_ES] = 0; // u->ES;
  166. g[GDB_FS] = 0; // u->FS;
  167. g[GDB_GS] = 0; // u->GS;
  168. }
  169. void
  170. gdb2ureg(uintptr_t *g, Ureg *u)
  171. {
  172. u->ax = g[GDB_AX];
  173. u->bx = g[GDB_BX];
  174. u->cx = g[GDB_CX];
  175. u->dx = g[GDB_DX];
  176. u->si = g[GDB_SI];
  177. u->di = g[GDB_DI];
  178. u->bp = g[GDB_BP];
  179. u->sp = g[GDB_SP];
  180. u->r8 = g[GDB_R8];
  181. u->r9 = g[GDB_R9];
  182. u->r10 = g[GDB_R10];
  183. u->r11 = g[GDB_R11];
  184. u->r12 = g[GDB_R12];
  185. u->r13 = g[GDB_R13];
  186. u->r14 = g[GDB_R14];
  187. u->r15 = g[GDB_R15];
  188. u->ip = g[GDB_PC];
  189. /* it's weird but gdb seems to have no way to
  190. * express the sp. Hmm.
  191. */
  192. u->flags = g[GDB_PS];
  193. /* is there any point to this? */
  194. u->cs = g[GDB_CS];
  195. u->ss = g[GDB_SS];
  196. }
  197. #endif