archamd64.c 8.7 KB

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