archamd64.c 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457
  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 monitor 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. 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. 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 4xx */
  133. case 0x000006a0: /* i7 paurea... */
  134. case 0x000106a0: /* i7,5,3 9xx */
  135. case 0x000106c0: /* Atom (45nm, 32nm) */
  136. case 0x000106e0: /* i7,5,3 8xx */
  137. case 0x000206a0: /* i7,5,3 2xxx */
  138. case 0x000206c0: /* i7,5,3 4xxx */
  139. case 0x000306a0: /* i7,5,3 3xxx */
  140. case 0x000306f0: /* i7,5,3 5xxx */
  141. case 0x000506e0: /* i7,5,3 6xxx */
  142. case 0x00050650: /* i9 7900X */
  143. case 0x000806e0: /* i7,5,3 85xx */
  144. case 0x000906e0: /* i7,5,3 77xx 8xxx */
  145. /*
  146. * Get the FSB frequemcy.
  147. * If processor has Enhanced Intel Speedstep Technology
  148. * then non-integer bus frequency ratios are possible.
  149. */
  150. //print("CPUID EIST: %d\n", (info1[2] & 0x00000080));
  151. if(info1[2] & 0x00000080){
  152. msr = rdmsr(0x198);
  153. r = (msr>>40) & 0x1f;
  154. }
  155. else{
  156. msr = 0;
  157. r = rdmsr(0x2a) & 0x1f;
  158. }
  159. f = rdmsr(0xcd) & 0x07;
  160. //iprint("rdmsr Intel: %d\n", rdmsr(0x2a));
  161. //iprint("Intel msr.lo %d\n", r);
  162. //iprint("Intel msr.hi %d\n", f);
  163. switch(f){
  164. default:
  165. return 0;
  166. case 7:
  167. hz = 83000000000ll;
  168. break;
  169. case 5:
  170. hz = 100000000000ll;
  171. break;
  172. case 1:
  173. hz = 133333333333ll;
  174. break;
  175. case 3:
  176. hz = 166666666666ll;
  177. break;
  178. case 2:
  179. hz = 200000000000ll;
  180. break;
  181. case 0:
  182. hz = 266666666666ll;
  183. break;
  184. case 4:
  185. hz = 333333333333ll;
  186. break;
  187. case 6:
  188. hz = 400000000000ll;
  189. break;
  190. }
  191. //iprint("hz %d r %d\n", hz, r);
  192. /*
  193. * Hz is *1000 at this point.
  194. * Do the scaling then round it.
  195. */
  196. if(msr & 0x0000400000000000ll)
  197. hz = hz*(r+10) + hz/2;
  198. else
  199. hz = hz*(r+10);
  200. hz = ((hz/100)+5)/10;
  201. break;
  202. }
  203. DBG("cpuidhz: 0x2a: %#llx hz %lld\n", rdmsr(0x2a), hz);
  204. }
  205. else if(strcmp("AuthenticAMD",vendorid) == 0){
  206. switch(info1[0] & 0x0fff0ff0){
  207. default:
  208. return 0;
  209. case 0x00050ff0: /* K8 Athlon Venice 64 / Qemu64 */
  210. case 0x00020fc0: /* K8 Athlon Lima 64 */
  211. case 0x00000f50: /* K8 Opteron 2xxx */
  212. case 0x00100f60: /* K8 Athlon II X2 */
  213. msr = rdmsr(0xc0010042);
  214. r = (msr>>16) & 0x3f;
  215. hz = 200000000ULL*(4 * 2 + r)/2;
  216. break;
  217. case 0x00100f40: /* Phenom II X2 && Athlon II X4 559 Processor */
  218. case 0x00100f20: /* Phenom II X4 */
  219. case 0x00100fa0: /* Phenom II X6 */
  220. case 0x00100f90: /* K10 Opteron 61xx */
  221. case 0x00600f00: /* K10 Opteron 62xx */
  222. case 0x00600f10: /* K10 Opteron 6272, FX 6xxx/4xxx */
  223. case 0x00600f20: /* K10 Opteron 63xx, FX 3xxx/8xxx/9xxx */
  224. case 0x00700f00: /* Athlon II X4 5xxx */
  225. case 0x00800f10: /* Ryzen 5 and 7 */
  226. case 0x00810f10: /* Ryzen 3 */
  227. msr = rdmsr(0xc0010064);
  228. r = msr & 0x1f;
  229. hz = ((r+0x10)*100000000ll)/(1<<(msr>>6 & 0x07));
  230. break;
  231. case 0x00000620: /* QEMU64 / Athlon MP/XP */
  232. msr = rdmsr(0xc0010064);
  233. r = (msr>>6) & 0x07;
  234. hz = (((msr & 0x3f)+0x10)*100000000ll)/(1<<r);
  235. break;
  236. }
  237. DBG("cpuidhz: %#llx hz %lld\n", msr, hz);
  238. }
  239. else {
  240. return 0;
  241. }
  242. return hz;
  243. }
  244. void
  245. cpuiddump(void)
  246. {
  247. int i;
  248. uint32_t info[4];
  249. if(!DBGFLG)
  250. return;
  251. if(machp()->CPU.ncpuinfos == 0 && cpuidinit() == 0)
  252. return;
  253. for(i = 0; i < machp()->CPU.ncpuinfos; i++){
  254. cpuid(i, 0, info);
  255. DBG("eax = %#8.8x: %8.8x %8.8x %8.8x %8.8x\n",
  256. i, info[0], info[1], info[2], info[3]);
  257. }
  258. for(i = 0; i < machp()->CPU.ncpuinfoe; i++){
  259. cpuid(0x80000000|i, 0, info);
  260. DBG("eax = %#8.8x: %8.8x %8.8x %8.8x %8.8x\n",
  261. 0x80000000|i, info[0], info[1], info[2], info[3]);
  262. }
  263. }
  264. int64_t
  265. archhz(void)
  266. {
  267. int64_t hz;
  268. uint32_t info0[4], info1[4];
  269. if(!cpuidinfo(0, 0, info0)) {
  270. iprint("archhz: cpuidinfo(0, 0) failed\n");
  271. return 0;
  272. }
  273. if(!cpuidinfo(1, 0, info1)) {
  274. iprint("archhz: cpuidinfo(1, 0) failed\n");
  275. return 0;
  276. }
  277. hz = cpuidhz(info0, info1);
  278. if(hz > 0 || machp()->machno != 0)
  279. return hz;
  280. iprint("archhz, cpuidhz failed, going to i8254hz\n");
  281. return i8254hz(info0, info1);
  282. }
  283. int
  284. archmmu(void)
  285. {
  286. uint32_t info[4];
  287. /*
  288. * Should the check for machp()->machno != 0 be here
  289. * or in the caller (mmuinit)?
  290. *
  291. * To do here:
  292. * check and enable Pse;
  293. * Pge; Nxe.
  294. */
  295. /*
  296. * How many page sizes are there?
  297. * Always have 4*KiB, but need to check
  298. * configured correctly.
  299. */
  300. assert(PGSZ == 4*KiB);
  301. sys->pgszlg2[0] = 12;
  302. sys->pgszmask[0] = (1<<12)-1;
  303. sys->pgsz[0] = 1<<12;
  304. sys->npgsz = 1;
  305. if(machp()->CPU.ncpuinfos == 0 && cpuidinit() == 0)
  306. return 1;
  307. /*
  308. * Check the Pse bit in function 1 DX for 2*MiB support;
  309. * if false, only 4*KiB is available.
  310. */
  311. if(!(machp()->CPU.cpuinfo[1][3] & 0x00000008))
  312. return 1;
  313. sys->pgszlg2[1] = 21;
  314. sys->pgszmask[1] = (1<<21)-1;
  315. sys->pgsz[1] = 1<<21;
  316. sys->npgsz = 2;
  317. /*
  318. * Check the Page1GB bit in function 0x80000001 DX for 1*GiB support.
  319. */
  320. if(cpuidinfo(0x80000001, 0, info) && (info[3] & 0x04000000)){
  321. sys->pgszlg2[2] = 30;
  322. sys->pgszmask[2] = (1<<30)-1;
  323. sys->pgsz[2] = 1<<30;
  324. sys->npgsz = 3;
  325. }
  326. return sys->npgsz;
  327. }
  328. static int
  329. fmtP(Fmt* f)
  330. {
  331. uintmem pa;
  332. pa = va_arg(f->args, uintmem);
  333. if(f->flags & FmtSharp)
  334. return fmtprint(f, "%#16.16llx", pa);
  335. return fmtprint(f, "%llu", pa);
  336. }
  337. static int
  338. fmtL(Fmt* f)
  339. {
  340. Mpl pl;
  341. pl = va_arg(f->args, Mpl);
  342. return fmtprint(f, "%#16.16llx", pl);
  343. }
  344. static int
  345. fmtR(Fmt* f)
  346. {
  347. uint64_t r;
  348. r = va_arg(f->args, uint64_t);
  349. return fmtprint(f, "%#16.16llx", r);
  350. }
  351. /* virtual address fmt */
  352. static int
  353. fmtW(Fmt *f)
  354. {
  355. uint64_t va;
  356. va = va_arg(f->args, uint64_t);
  357. return fmtprint(f, "%#llx=0x[%llx][%llx][%llx][%llx][%llx]", va,
  358. PTLX(va, 3), PTLX(va, 2), PTLX(va, 1), PTLX(va, 0),
  359. va & ((1<<PGSHFT)-1));
  360. }
  361. void
  362. archfmtinstall(void)
  363. {
  364. /*
  365. * Architecture-specific formatting. Not as neat as they
  366. * could be (e.g. there's no defined type for a 'register':
  367. * L - Mpl, mach priority level
  368. * P - uintmem, physical address
  369. * R - register
  370. * With a little effort these routines could be written
  371. * in a fairly architecturally-independent manner, relying
  372. * on the compiler to optimise-away impossible conditions,
  373. * and/or by exploiting the innards of the fmt library.
  374. */
  375. fmtinstall('P', fmtP);
  376. fmtinstall('L', fmtL);
  377. fmtinstall('R', fmtR);
  378. fmtinstall('W', fmtW);
  379. }
  380. void
  381. archidle(void)
  382. {
  383. halt();
  384. }
  385. void
  386. microdelay(int microsecs)
  387. {
  388. uint64_t r, t;
  389. r = rdtsc();
  390. for(t = r + (sys->cyclefreq*microsecs)/1000000ull; r < t; r = rdtsc())
  391. ;
  392. }
  393. void
  394. millidelay(int millisecs)
  395. {
  396. uint64_t r, t;
  397. r = rdtsc();
  398. for(t = r + (sys->cyclefreq*millisecs)/1000ull; r < t; r = rdtsc())
  399. ;
  400. }