archamd64.c 9.0 KB

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