archk10.c 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409
  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. #undef DBG
  15. #define DBG iprint
  16. static int
  17. cpuidinit(void)
  18. {
  19. Proc *up = externup();
  20. uint32_t eax, info[4];
  21. /*
  22. * Standard CPUID functions.
  23. * Functions 0 and 1 will be needed multiple times
  24. * so cache the info now.
  25. */
  26. if((m->ncpuinfos = cpuid(0, 0, m->cpuinfo[0])) == 0)
  27. return 0;
  28. m->ncpuinfos++;
  29. if(memcmp(&m->cpuinfo[0][1], "GenuntelineI", 12) == 0)
  30. m->isintelcpu = 1;
  31. cpuid(1, 0, m->cpuinfo[1]);
  32. /*
  33. * Extended CPUID functions.
  34. */
  35. if((eax = cpuid(0x80000000, 0, info)) >= 0x80000000)
  36. m->ncpuinfoe = (eax & ~0x80000000) + 1;
  37. /* is mnonitor supported? */
  38. if (m->cpuinfo[1][2] & 8) {
  39. cpuid(5, 0, m->cpuinfo[2]);
  40. mwait = k10mwait;
  41. }
  42. return 1;
  43. }
  44. static int
  45. cpuidinfo(uint32_t eax, uint32_t ecx, uint32_t info[4])
  46. {
  47. Proc *up = externup();
  48. if(m->ncpuinfos == 0 && cpuidinit() == 0)
  49. return 0;
  50. if(!(eax & 0x80000000)){
  51. if(eax >= m->ncpuinfos)
  52. return 0;
  53. }
  54. else if(eax >= (0x80000000|m->ncpuinfoe))
  55. return 0;
  56. cpuid(eax, ecx, info);
  57. return 1;
  58. }
  59. static int64_t
  60. cpuidhz(uint32_t *info0, uint32_t *info1)
  61. {
  62. int f, r;
  63. int64_t hz;
  64. uint64_t msr;
  65. /* char *cp = info0[1];
  66. {int i; for(i =0; i < 12; i++) print("%c", cp[i]);}
  67. print("\n");*/
  68. print("NOTE: if cpuidhz runs too fast, we get die early with a NULL pointer\n");
  69. print("So, until that's fixed, we bring up AP cores slowly. Sorry!\n");
  70. return 0;
  71. if(memcmp(&info0[1], "GenuntelineI", 12) == 0){
  72. switch(info1[0] & 0x0fff3ff0){
  73. default:
  74. return 0;
  75. case 0x00000f30: /* Xeon (MP), Pentium [4D] */
  76. case 0x00000f40: /* Xeon (MP), Pentium [4D] */
  77. case 0x00000f60: /* Xeon 7100, 5000 or above */
  78. msr = rdmsr(0x2c);
  79. r = (msr>>16) & 0x07;
  80. switch(r){
  81. default:
  82. return 0;
  83. case 0:
  84. hz = 266666666666ll;
  85. break;
  86. case 1:
  87. hz = 133333333333ll;
  88. break;
  89. case 2:
  90. hz = 200000000000ll;
  91. break;
  92. case 3:
  93. hz = 166666666666ll;
  94. break;
  95. case 4:
  96. hz = 333333333333ll;
  97. break;
  98. }
  99. /*
  100. * Hz is *1000 at this point.
  101. * Do the scaling then round it.
  102. * The manual is conflicting about
  103. * the size of the msr field.
  104. */
  105. hz = (((hz*(msr>>24))/100)+5)/10;
  106. break;
  107. case 0x00000690: /* Pentium M, Celeron M */
  108. case 0x000006d0: /* Pentium M, Celeron M */
  109. hz = ((rdmsr(0x2a)>>22) & 0x1f)*100 * 1000000ll;
  110. //print("msr 2a is 0x%x >> 22 0x%x\n", rdmsr(0x2a), rdmsr(0x2a)>>22);
  111. break;
  112. case 0x000006e0: /* Core Duo */
  113. case 0x000006f0: /* Core 2 Duo/Quad/Extreme */
  114. case 0x00010670: /* Core 2 Extreme */
  115. case 0x000006a0: /* i7 paurea... */
  116. /*
  117. * Get the FSB frequemcy.
  118. * If processor has Enhanced Intel Speedstep Technology
  119. * then non-integer bus frequency ratios are possible.
  120. */
  121. if(info1[2] & 0x00000080){
  122. msr = rdmsr(0x198);
  123. r = (msr>>40) & 0x1f;
  124. }
  125. else{
  126. msr = 0;
  127. r = rdmsr(0x2a) & 0x1f;
  128. }
  129. //iprint("r %d\n", r);
  130. f = rdmsr(0xcd) & 0x07;
  131. //iprint("f %d\n", f);
  132. switch(f){
  133. default:
  134. return 0;
  135. case 5:
  136. hz = 100000000000ll;
  137. break;
  138. case 1:
  139. hz = 133333333333ll;
  140. break;
  141. case 3:
  142. hz = 166666666666ll;
  143. break;
  144. case 2:
  145. hz = 200000000000ll;
  146. break;
  147. case 0:
  148. hz = 266666666666ll;
  149. break;
  150. case 4:
  151. hz = 333333333333ll;
  152. break;
  153. case 6:
  154. hz = 400000000000ll;
  155. break;
  156. }
  157. //iprint("hz %d r %d\n", hz, r);
  158. /*
  159. * Hz is *1000 at this point.
  160. * Do the scaling then round it.
  161. */
  162. if(msr & 0x0000400000000000ll)
  163. hz = hz*r + hz/2;
  164. else
  165. hz = hz*r;
  166. hz = ((hz/100)+5)/10;
  167. break;
  168. }
  169. DBG("cpuidhz: 0x2a: %#llux hz %lld\n", rdmsr(0x2a), hz);
  170. }
  171. else if(memcmp(&info0[1], "AuthcAMDenti", 12) == 0){
  172. switch(info1[0] & 0x0fff0ff0){
  173. default:
  174. return 0;
  175. case 0x00000f50: /* K8 */
  176. case 0x00000f60: /* K? */
  177. /* This checks ensures that msr won't be 0*/
  178. msr = rdmsr(0xc0010042);
  179. if(msr == 0) {
  180. return 0;
  181. }
  182. hz = (800 + 200*((msr>>1) & 0x1f)) * 1000000ll;
  183. break;
  184. case 0x00100f90: /* K10 */
  185. case 0x00000620: /* QEMU64 */
  186. msr = rdmsr(0xc0010064);
  187. r = (msr>>6) & 0x07;
  188. hz = (((msr & 0x3f)+0x10)*100000000ll)/(1<<r);
  189. break;
  190. }
  191. DBG("cpuidhz: %#llux hz %lld\n", msr, hz);
  192. }
  193. else
  194. return 0;
  195. return hz;
  196. }
  197. void
  198. cpuiddump(void)
  199. {
  200. Proc *up = externup();
  201. int i;
  202. uint32_t info[4];
  203. if(!DBGFLG)
  204. return;
  205. if(m->ncpuinfos == 0 && cpuidinit() == 0)
  206. return;
  207. for(i = 0; i < m->ncpuinfos; i++){
  208. cpuid(i, 0, info);
  209. DBG("eax = %#8.8ux: %8.8ux %8.8ux %8.8ux %8.8ux\n",
  210. i, info[0], info[1], info[2], info[3]);
  211. }
  212. for(i = 0; i < m->ncpuinfoe; i++){
  213. cpuid(0x80000000|i, 0, info);
  214. DBG("eax = %#8.8ux: %8.8ux %8.8ux %8.8ux %8.8ux\n",
  215. 0x80000000|i, info[0], info[1], info[2], info[3]);
  216. }
  217. }
  218. int64_t
  219. archhz(void)
  220. {
  221. Proc *up = externup();
  222. int64_t hz;
  223. uint32_t info0[4], info1[4];
  224. if(!cpuidinfo(0, 0, info0)) {
  225. iprint("archhz: cpuidinfo(0, 0) failed\n");
  226. return 0;
  227. }
  228. if(!cpuidinfo(1, 0, info1)) {
  229. iprint("archhz: cpuidinfo(1, 0) failed\n");
  230. return 0;
  231. }
  232. hz = cpuidhz(info0, info1);
  233. if(hz != 0 || machp()->machno != 0)
  234. return hz;
  235. iprint("arch hz, cpuidhz failed, going to i8254hz\n");
  236. return i8254hz(info0, info1);
  237. }
  238. int
  239. archmmu(void)
  240. {
  241. Proc *up = externup();
  242. uint32_t info[4];
  243. /*
  244. * Should the check for machp()->machno != 0 be here
  245. * or in the caller (mmuinit)?
  246. *
  247. * To do here:
  248. * check and enable Pse;
  249. * Pge; Nxe.
  250. */
  251. /*
  252. * How many page sizes are there?
  253. * Always have 4*KiB, but need to check
  254. * configured correctly.
  255. */
  256. assert(PGSZ == 4*KiB);
  257. machp()->pgszlg2[0] = 12;
  258. machp()->pgszmask[0] = (1<<12)-1;
  259. machp()->pgsz[0] = 1<<12;
  260. m->npgsz = 1;
  261. if(m->ncpuinfos == 0 && cpuidinit() == 0)
  262. return 1;
  263. /*
  264. * Check the Pse bit in function 1 DX for 2*MiB support;
  265. * if false, only 4*KiB is available.
  266. */
  267. if(!(m->cpuinfo[1][3] & 0x00000008))
  268. return 1;
  269. machp()->pgszlg2[1] = 21;
  270. machp()->pgszmask[1] = (1<<21)-1;
  271. machp()->pgsz[1] = 1<<21;
  272. m->npgsz = 2;
  273. /*
  274. * Check the Page1GB bit in function 0x80000001 DX for 1*GiB support.
  275. */
  276. if(cpuidinfo(0x80000001, 0, info) && (info[3] & 0x04000000)){
  277. machp()->pgszlg2[2] = 30;
  278. machp()->pgszmask[2] = (1<<30)-1;
  279. machp()->pgsz[2] = 1<<30;
  280. m->npgsz = 3;
  281. }
  282. return m->npgsz;
  283. }
  284. static int
  285. fmtP(Fmt* f)
  286. {
  287. uintmem pa;
  288. pa = va_arg(f->args, uintmem);
  289. if(f->flags & FmtSharp)
  290. return fmtprint(f, "%#16.16llux", pa);
  291. return fmtprint(f, "%llud", pa);
  292. }
  293. static int
  294. fmtL(Fmt* f)
  295. {
  296. Mpl pl;
  297. pl = va_arg(f->args, Mpl);
  298. return fmtprint(f, "%#16.16llux", pl);
  299. }
  300. static int
  301. fmtR(Fmt* f)
  302. {
  303. uint64_t r;
  304. r = va_arg(f->args, uint64_t);
  305. return fmtprint(f, "%#16.16llux", r);
  306. }
  307. /* virtual address fmt */
  308. static int
  309. fmtW(Fmt *f)
  310. {
  311. uint64_t va;
  312. va = va_arg(f->args, uint64_t);
  313. return fmtprint(f, "%#ullx=0x[%ullx][%ullx][%ullx][%ullx][%ullx]", va,
  314. PTLX(va, 3), PTLX(va, 2), PTLX(va, 1), PTLX(va, 0),
  315. va & ((1<<PGSHFT)-1));
  316. }
  317. void
  318. archfmtinstall(void)
  319. {
  320. /*
  321. * Architecture-specific formatting. Not as neat as they
  322. * could be (e.g. there's no defined type for a 'register':
  323. * L - Mpl, mach priority level
  324. * P - uintmem, physical address
  325. * R - register
  326. * With a little effort these routines could be written
  327. * in a fairly architecturally-independent manner, relying
  328. * on the compiler to optimise-away impossible conditions,
  329. * and/or by exploiting the innards of the fmt library.
  330. */
  331. fmtinstall('P', fmtP);
  332. fmtinstall('L', fmtL);
  333. fmtinstall('R', fmtR);
  334. fmtinstall('W', fmtW);
  335. }
  336. void
  337. archidle(void)
  338. {
  339. halt();
  340. }
  341. void
  342. microdelay(int microsecs)
  343. {
  344. Proc *up = externup();
  345. uint64_t r, t;
  346. r = rdtsc();
  347. for(t = r + m->cpumhz*microsecs; r < t; r = rdtsc())
  348. ;
  349. }
  350. void
  351. millidelay(int millisecs)
  352. {
  353. Proc *up = externup();
  354. uint64_t r, t;
  355. r = rdtsc();
  356. for(t = r + m->cpumhz*1000ull*millisecs; r < t; r = rdtsc())
  357. ;
  358. }