PageRenderTime 27ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 0ms

/x86info-1.30/Intel/cachesize.c

#
C | 336 lines | 264 code | 45 blank | 27 comment | 52 complexity | fe7e3cb67f0cbe08d7a0c712c7655258 MD5 | raw file
Possible License(s): GPL-2.0
  1. /*
  2. * (C) 2001-2011 Dave Jones.
  3. *
  4. * Licensed under the terms of the GNU GPL License version 2.
  5. *
  6. * Intel specific parts
  7. *
  8. * References:
  9. * http://www.intel.com/Assets/PDF/appnote/241618.pdf
  10. */
  11. #include <stdio.h>
  12. #include <string.h>
  13. #include "../x86info.h"
  14. #include "Intel.h"
  15. #define MB(x) ((x) * 1024)
  16. struct _cache_table
  17. {
  18. unsigned char descriptor;
  19. int size;
  20. char *string;
  21. };
  22. static struct _cache_table TRACE_cache_table[] =
  23. {
  24. { 0x70, 12, "Instruction trace cache: 12K uOps, 8-way associative." },
  25. { 0x71, 16, "Instruction trace cache: 16K uOps, 8-way associative." },
  26. { 0x72, 32, "Instruction trace cache: 32K uOps, 8-way associative." },
  27. { 0x73, 64, "Instruction trace cache: 64K uOps, 8-way associative." },
  28. { 0, 0, NULL }
  29. };
  30. static struct _cache_table L1I_cache_table[] =
  31. {
  32. { 0x6, 8, "L1 Instruction cache: 8KB, 4-way associative. 32 byte line size." },
  33. { 0x8, 16, "L1 Instruction cache: 16KB, 4-way associative. 32 byte line size." },
  34. { 0x9, 32, "L1 Instruction cache: 32KB, 4-way associative. 64 byte line size." },
  35. { 0x30, 32, "L1 Instruction cache: 32KB, 8-way associative. 64 byte line size." },
  36. { 0, 0, NULL }
  37. };
  38. static struct _cache_table L1D_cache_table[] =
  39. {
  40. { 0xa, 8, "L1 Data cache: 8KB, 2-way associative. 32 byte line size." },
  41. { 0xc, 16, "L1 Data cache: 16KB, 4-way associative. 32 byte line size." },
  42. { 0xd, 16, "L1 Data cache: 16KB, 4-way associative. 64 byte line size. ECC." },
  43. { 0xe, 24, "L1 Data cache: 24KB, 6-way associative. 64 byte line size. ECC." },
  44. { 0x2c, 32, "L1 Data cache: 32KB, 8-way associative. 64 byte line size." },
  45. { 0x60, 16, "L1 Data cache: 16KB, sectored, 8-way associative. 64 byte line size." },
  46. { 0x66 , 8, "L1 Data cache: 8KB, sectored, 4-way associative. 64 byte line size." },
  47. { 0x67, 16, "L1 Data cache: 16KB, sectored, 4-way associative. 64 byte line size." },
  48. { 0x68, 32, "L1 Data cache: 32KB, sectored, 4-way associative. 64 byte line size." },
  49. { 0, 0, NULL }
  50. };
  51. static struct _cache_table L2_cache_table[] =
  52. {
  53. { 0x21, 256, "L2 (MLC): 256KB, 8-way associative. 64 byte line size." },
  54. { 0x39, 128, "L2 cache: 128KB, 4-way associative. Sectored. 64 byte line size." },
  55. /* { 0x3a, 192, "L2 cache: 192KB, 6-way associative. Sectored. 64 byte line size." },
  56. { 0x3b, 128, "L2 cache: 128KB, 2-way associative. Sectored. 64 byte line size." },
  57. { 0x3c, 256, "L2 cache: 256KB, 4-way associative. Sectored. 64 byte line size." },
  58. { 0x3d, 384, "L2 cache: 384KB, 6-way associative. Sectored. 64 byte line size." },
  59. { 0x3e, 512, "L2 cache: 512KB, 4-way associative. Sectored. 64 byte line size." },
  60. { 0x3f, 256, "L2 cache: 256KB, 2-way associative. Sectored. 64 byte line size." }, */
  61. /* 3a->3f are no longer listed. */
  62. { 0x41, 128, "L2 cache: 128KB, 4-way associative. 32 byte line size." },
  63. { 0x42, 256, "L2 cache: 256KB, 4-way associative. 32 byte line size." },
  64. { 0x43, 512, "L2 cache: 512KB, 4-way associative. 32 byte line size." },
  65. { 0x44, MB(1), "L2 cache: 1MB, 4-way associative. 32 byte line size." },
  66. { 0x45, MB(2), "L2 cache: 2MB, 4-way associative. 32 byte line size." },
  67. { 0x48, MB(3), "L2 cache: 3MB, 12-way associative. 64 byte line size. Unified on-die." },
  68. { 0x4e, MB(6), "L2 cache: 6MB, 24-way set associative, 64-byte line size." },
  69. { 0x79, 128, "L2 cache: 128KB, sectored, 8-way associative. 64 byte line size." },
  70. { 0x7a, 256, "L2 cache: 256KB, sectored, 8-way associative. 64 byte line size." },
  71. { 0x7b, 512, "L2 cache: 512KB, sectored, 8-way associative. 64 byte line size." },
  72. { 0x7c, MB(1), "L2 cache: 1MB, sectored, 8-way associative. 64 byte line size." },
  73. { 0x7d, MB(2), "L2 cache: 2MB, 8-way associative. 64 byte line size." },
  74. { 0x7f, 512, "L2 cache: 512KB, 2-way associative. 64 byte line size." },
  75. { 0x80, 512, "L2 cache: 512KB, 8-way associative. 64 byte line size." },
  76. { 0x82, 256, "L2 cache: 256KB, 8-way associative. 32 byte line size." },
  77. { 0x83, 512, "L2 cache: 512KB, 8-way associative. 32 byte line size." },
  78. { 0x84, MB(1), "L2 cache: 1MB, 8-way associative. 32 byte line size." },
  79. { 0x85, MB(2), "L2 cache: 2MB, 8-way associative. 32 byte line size." },
  80. { 0x86, 512, "L2 cache: 512KB, 4-way associative. 64 byte line size." },
  81. { 0x87, MB(1), "L2 cache: 1MB, 8-way associative. 64 byte line size." },
  82. { 0, 0, NULL }
  83. };
  84. static struct _cache_table L2L3_cache_table[] =
  85. {
  86. { 0x46, MB(4), "L2 cache: 4MB, 4-way associative. 64 byte line size." },
  87. { 0x47, MB(8), "L2 cache: 8MB, 8-way associative. 64 byte line size." },
  88. { 0x48, MB(3), "L2 cache: 3MB, 12-way associative. 64 byte line size." },
  89. { 0x49, MB(4), "L2 cache: 4MB, 16-way associative. 64 byte line size." },
  90. { 0x4a, MB(6), "L2 cache: 6MB, 12-way associative. 64 byte line size." },
  91. { 0x4b, MB(8), "L2 cache: 8MB, 16-way associative. 64 byte line size." },
  92. { 0x4c, MB(12), "L2 cache: 12MB, 12-way associative. 64 byte line size." },
  93. { 0x4d, MB(16), "L2 cache: 16MB, 16-way associative. 64 byte line size." },
  94. { 0x78, MB(1), "L2 cache: 1MB, sectored, 8-way associative. 64 byte line size." },
  95. { 0, 0, NULL }
  96. };
  97. static struct _cache_table L3L2_cache_table[] =
  98. {
  99. { 0x46, MB(4), "L3 cache: 4MB, 4-way associative. 64 byte line size." },
  100. { 0x47, MB(8), "L3 cache: 8MB, 8-way associative. 64 byte line size." },
  101. { 0x49, MB(4), "L3 cache: 4MB, 16-way associative. 64 byte line size." },
  102. { 0x4a, MB(6), "L3 cache: 6MB, 12-way associative. 64 byte line size." },
  103. { 0x4b, MB(8), "L3 cache: 8MB, 16-way associative. 64 byte line size." },
  104. { 0x4c, MB(12), "L3 cache: 12MB, 12-way associative. 64 byte line size." },
  105. { 0x4d, MB(16), "L3 cache: 16MB, 16-way associative. 64 byte line size." },
  106. { 0x78, MB(1), "L3 cache: 1MB, sectored, 8-way associative. 64 byte line size." },
  107. { 0xd0, 512, "L3 cache: 512KB, 4-way associative. 64 byte line size." },
  108. { 0xd1, MB(1), "L3 cache: 1MB, 4-way associative. 64 byte line size." },
  109. { 0xd2, MB(2), "L3 cache: 2MB, 4-way associative. 64 byte line size." },
  110. { 0xd6, MB(1), "L3 cache: 1MB, 8-way associative. 64 byte line size." },
  111. { 0xd7, MB(2), "L3 cache: 2MB, 8-way associative. 64 byte line size." },
  112. { 0xd8, MB(4), "L3 cache: 4MB, 8-way associative. 64 byte line size." },
  113. { 0xdc, MB(2), "L3 cache: 2MB, 12-way associative. 64 byte line size." },
  114. { 0xdd, MB(4), "L3 cache: 4MB, 12-way associative. 64 byte line size." },
  115. { 0xe2, MB(2), "L3 cache: 2MB, 16-way associative. 64 byte line size." },
  116. { 0xe3, MB(4), "L3 cache: 4MB, 16-way associative. 64 byte line size." },
  117. { 0xe4, MB(8), "L3 cache: 8MB, 16-way associative. 64 byte line size." },
  118. { 0xea, MB(12), "L3 cache: 12MB, 24-way associative. 64 byte line size." },
  119. { 0xeb, MB(18), "L3 cache: 18MB, 24-way associative. 64 byte line size." },
  120. { 0xec, MB(24), "L3 cache: 24MB, 24-way associative. 64 byte line size." },
  121. { 0xde, MB(8), "L3 cache: 8MB, 12-way associative. 64 byte line size." },
  122. { 0, 0, NULL }
  123. };
  124. static struct _cache_table L3_cache_table[] =
  125. {
  126. { 0x22, 512, "L3 cache: 512KB, 4-way associative. 64 byte line size." },
  127. { 0x23, MB(1), "L3 cache: 1MB, 8-way associative. 64 byte line size." },
  128. { 0x25, MB(2), "L3 cache: 2MB, 8-way associative. 64 byte line size." },
  129. { 0x29, MB(4), "L3 cache: 4MB, 8-way associative. 64 byte line size." },
  130. { 0, 0, NULL }
  131. };
  132. static struct _cache_table ITLB_cache_table[] =
  133. {
  134. { 0x1, 32, "Instruction TLB: 4KB pages, 4-way associative, 32 entries" },
  135. { 0x2, 2, "Instruction TLB: 4MB pages, fully associative, 2 entries" },
  136. { 0x50, 64, "Instruction TLB: 4K, 2MB or 4MB pages, fully associative, 64 entries." },
  137. { 0x51, 128, "Instruction TLB: 4K, 2MB or 4MB pages, fully associative, 128 entries." },
  138. { 0x52, 256, "Instruction TLB: 4K, 2MB or 4MB pages, fully associative, 256 entries." },
  139. { 0x55, 7, "Instruction TLB: 2MB or 4MB pages, fully associative, 7 entries" },
  140. { 0xb0, 128, "Instruction TLB: 4K pages, 4-way associative, 128 entries." },
  141. { 0xb1, 4, "Instruction TLB: 4x 4MB page entries, or 8x 2MB pages entries, 4-way associative" },
  142. { 0xb2, 64, "Instruction TLB: 4K pages, 4-way associative, 64 entries." },
  143. { 0, 0, NULL }
  144. };
  145. static struct _cache_table DTLB_cache_table[] =
  146. {
  147. { 0x3, 64, "Data TLB: 4KB pages, 4-way associative, 64 entries" },
  148. { 0x4, 8, "Data TLB: 4MB pages, 4-way associative, 8 entries" },
  149. { 0x5, 32, "Data TLB: 4MB pages, 4-way associative, 32 entries" },
  150. { 0x56, 16, "L1 Data TLB: 4MB pages, 4-way set associative, 16 entries" },
  151. { 0x57, 16, "L1 Data TLB: 4KB pages, 4-way set associative, 16 entries" },
  152. { 0x5a, 32, "Data TLB: 4KB or 4MB pages, fully associative, 32 entries." },
  153. { 0x5b, 64, "Data TLB: 4KB or 4MB pages, fully associative, 64 entries." },
  154. { 0x5c, 128, "Data TLB: 4KB or 4MB pages, fully associative, 128 entries." },
  155. { 0x5d, 256, "Data TLB: 4KB or 4MB pages, fully associative, 256 entries." },
  156. { 0xb3, 128, "Data TLB: 4K pages, 4-way associative, 128 entries." },
  157. { 0xb4, 256, "Data TLB: 4K pages, 4-way associative, 256 entries." },
  158. { 0xca, 512, "Data TLB: 4K pages, 4-way associative, 512 entries." },
  159. { 0, 0, NULL }
  160. };
  161. static struct _cache_table prefetch_table[] =
  162. {
  163. {0xf0, 64, "64 byte prefetching."},
  164. {0xf1, 64, "128 byte prefetching."},
  165. };
  166. static unsigned char found_unknown=0;
  167. static unsigned char unknown_array[256];
  168. /* Decode Intel TLB and cache info descriptors */
  169. //TODO : Errata workaround. http://www.sandpile.org/post/msgs/20002736.htm
  170. static void decode_Intel_cache(int des, struct cpudata *cpu, int output,
  171. struct _cache_table *table)
  172. {
  173. int k = 0;
  174. int found = 0;
  175. /* "No 2nd-level cache or, if processor contains a valid 2nd-level
  176. cache, no 3rd-level cache". Skip this pointless entry.*/
  177. if (des == 0x40)
  178. return;
  179. //TODO: Add description to link-list in cpu->
  180. while ((table[k].descriptor != 0) && (found == 0)) {
  181. if (table[k].descriptor == des) {
  182. if (table == TRACE_cache_table)
  183. cpu->cachesize_trace += table[k].size;
  184. if (table == L1I_cache_table)
  185. cpu->cachesize_L1_I += table[k].size;
  186. if (table == L1D_cache_table)
  187. cpu->cachesize_L1_D += table[k].size;
  188. if (table == L2_cache_table)
  189. cpu->cachesize_L2 += table[k].size;
  190. if (table == L2L3_cache_table)
  191. cpu->cachesize_L2 += table[k].size;
  192. if (table == L3_cache_table)
  193. cpu->cachesize_L3 += table[k].size;
  194. if (table == L3L2_cache_table)
  195. cpu->cachesize_L3 += table[k].size;
  196. if (output)
  197. printf(" %s\n", table[k].string);
  198. found = 1;
  199. }
  200. k++;
  201. }
  202. if ((found == 0) && (unknown_array[des] == 0)) {
  203. unknown_array[des] = 1;
  204. found_unknown++;
  205. }
  206. }
  207. static void decode_cache(struct cpudata *cpu, struct _cache_table *table, int output)
  208. {
  209. unsigned int i, j, n;
  210. unsigned int regs[4];
  211. /* Decode TLB and cache info */
  212. cpuid(cpu->number, 2, &regs[0], &regs[1], &regs[2], &regs[3]);
  213. /* Number of times to iterate */
  214. n = regs[0] & 0xff;
  215. for (i=0; i<n; i++) {
  216. cpuid(cpu->number, 2, &regs[0], &regs[1], &regs[2], &regs[3]);
  217. /* If bit 31 is set, this is an unknown format */
  218. for (j=0; j<3; j++)
  219. if (regs[j] & 0x80000000)
  220. regs[j] = 0;
  221. /* Byte 0 is level count, not a descriptor */
  222. for (j=1; j<16; j++) {
  223. unsigned char val = regs[j / 4] >> (unsigned int)(8 * (j % 4));
  224. if (val)
  225. decode_Intel_cache(val, cpu, output, table);
  226. }
  227. }
  228. }
  229. static void clean_unknowns(struct _cache_table *table)
  230. {
  231. int j=0;
  232. int des;
  233. while (table[j].descriptor != 0) {
  234. des = table[j++].descriptor;
  235. if (unknown_array[des] == 1) {
  236. unknown_array[des] = 0;
  237. found_unknown--;
  238. }
  239. }
  240. }
  241. void decode_Intel_caches(struct cpudata *cpu, int output)
  242. {
  243. unsigned int i = 0;
  244. unsigned char oldknown;
  245. if (cpu->cpuid_level < 2)
  246. return;
  247. memset(&unknown_array, 0, sizeof(unknown_array));
  248. if (output)
  249. printf("Cache info\n");
  250. decode_cache(cpu, TRACE_cache_table, output);
  251. decode_cache(cpu, L1I_cache_table, output);
  252. decode_cache(cpu, L1D_cache_table, output);
  253. oldknown = found_unknown;
  254. decode_cache(cpu, L2_cache_table, output);
  255. if (found_unknown > 0) {
  256. if (oldknown == found_unknown)
  257. decode_cache(cpu, L2L3_cache_table, output);
  258. else
  259. decode_cache(cpu, L3L2_cache_table, output);
  260. }
  261. decode_cache(cpu, L3_cache_table, output);
  262. if (output)
  263. printf("TLB info\n");
  264. decode_cache(cpu, ITLB_cache_table, output);
  265. decode_cache(cpu, DTLB_cache_table, output);
  266. decode_cache(cpu, prefetch_table, output);
  267. if (found_unknown == 0)
  268. return;
  269. /* Remove any known entries */
  270. clean_unknowns(TRACE_cache_table);
  271. clean_unknowns(L1I_cache_table);
  272. clean_unknowns(L1D_cache_table);
  273. clean_unknowns(L2_cache_table);
  274. clean_unknowns(L3_cache_table);
  275. clean_unknowns(L2L3_cache_table);
  276. clean_unknowns(ITLB_cache_table);
  277. clean_unknowns(DTLB_cache_table);
  278. clean_unknowns(prefetch_table);
  279. if (found_unknown == 0)
  280. return;
  281. if (output)
  282. printf("Found unknown cache descriptors: ");
  283. for (i=0; i<256; i++) {
  284. if (unknown_array[i] == 1)
  285. if (output)
  286. printf("%02x ", i);
  287. }
  288. if (output)
  289. printf("\n");
  290. found_unknown = 0;
  291. }