PageRenderTime 36ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/Intel/cachesize.c

https://github.com/jamesd/x86info
C | 308 lines | 243 code | 44 blank | 21 comment | 52 complexity | c46198f02cd283895fc12d3d8006ca4c MD5 | raw file
Possible License(s): GPL-2.0
  1. /*
  2. * (C) 2001 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://developer.intel.com/
  10. * http://microcodes.sourceforge.net/CPUID.htm
  11. */
  12. #include <stdio.h>
  13. #include <string.h>
  14. #include "../x86info.h"
  15. #include "Intel.h"
  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. { 0x30, 32, "L1 Instruction cache: 32KB, 8-way associative. 64 byte line size." },
  35. { 0, 0, NULL }
  36. };
  37. static struct _cache_table L1D_cache_table[] =
  38. {
  39. { 0xa, 8, "L1 Data cache: 8KB, 2-way associative. 32 byte line size." },
  40. { 0xc, 16, "L1 Data cache: 16KB, 4-way associative. 32 byte line size." },
  41. { 0x2c, 32, "L1 Data cache: 32KB, 8-way associative. 64 byte line size." },
  42. { 0x60, 16, "L1 Data cache: 16KB, sectored, 8-way associative. 64 byte line size." },
  43. { 0x66, 8, "L1 Data cache: 8KB, sectored, 4-way associative. 64 byte line size." },
  44. { 0x67, 16, "L1 Data cache: 16KB, sectored, 4-way associative. 64 byte line size." },
  45. { 0x68, 32, "L1 Data cache: 32KB, sectored, 4-way associative. 64 byte line size." },
  46. { 0, 0, NULL }
  47. };
  48. static struct _cache_table L2_cache_table[] =
  49. {
  50. { 0x39, 128, "L2 unified cache: 128KB, 4-way associative. 64 byte line size." },
  51. { 0x3a, 192, "L2 unified cache: 192KB, 6-way associative. 64 byte line size." },
  52. { 0x3b, 128, "L2 unified cache: 128KB, 2-way associative. 64 byte line size." },
  53. { 0x3c, 256, "L2 unified cache: 256KB, 4-way associative. 64 byte line size." },
  54. { 0x3d, 384, "L2 unified cache: 384KB, 6-way associative. 64 byte line size." },
  55. { 0x3e, 512, "L2 unified cache: 512KB, 4-way associative. 64 byte line size." },
  56. { 0x3f, 256, "L2 unified cache: 256KB, 2-way associative. 64 byte line size." },
  57. { 0x41, 128, "L2 unified cache: 128KB, 4-way associative. 32 byte line size." },
  58. { 0x42, 256, "L2 unified cache: 256KB, 4-way associative. 32 byte line size." },
  59. { 0x43, 512, "L2 unified cache: 512KB, 4-way associative. 32 byte line size." },
  60. { 0x44, 1024, "L2 unified cache: 1MB, 4-way associative. 32 byte line size." },
  61. { 0x45, 2048, "L2 unified cache: 2MB, 4-way associative. 32 byte line size." },
  62. { 0x4e, 6144, "L2 unified cache: 6MB, 24-way set associative, 64-byte line size." },
  63. { 0x79, 128, "L2 unified cache: 128KB, sectored, 8-way associative. 64 byte line size." },
  64. { 0x7a, 256, "L2 unified cache: 256KB, sectored, 8-way associative. 64 byte line size." },
  65. { 0x7b, 512, "L2 unified cache: 512KB, sectored, 8-way associative. 64 byte line size." },
  66. { 0x7c, 1024, "L2 unified cache: 1MB, sectored, 8-way associative. 64 byte line size." },
  67. { 0x7d, 2048, "L2 unified cache: 2MB, sectored, 8-way associative. 64 byte line size." },
  68. { 0x7f, 512, "L2 unified cache: 512KB, 2-way associative. 64 byte line size." },
  69. { 0x82, 256, "L2 unified cache: 256KB, 8-way associative. 32 byte line size." },
  70. { 0x83, 512, "L2 unified cache: 512KB, 8-way associative. 32 byte line size." },
  71. { 0x84, 1024, "L2 unified cache: 1MB, 8-way associative. 32 byte line size." },
  72. { 0x85, 2048, "L2 unified cache: 2MB, 8-way associative. 32 byte line size." },
  73. { 0x86, 512, "L2 unified cache: 512KB, 4-way associative. 64 byte line size." },
  74. { 0x87, 1024, "L2 unified cache: 1MB, 8-way associative. 64 byte line size." },
  75. { 0, 0, NULL }
  76. };
  77. static struct _cache_table L2L3_cache_table[] =
  78. {
  79. { 0x46, 4096, "L2 unified cache: 4MB, 4-way associative. 64 byte line size." },
  80. { 0x47, 8192, "L2 unified cache: 8MB, 8-way associative. 64 byte line size." },
  81. { 0x49, 4096, "L2 unified cache: 4MB, 16-way associative. 64 byte line size." },
  82. { 0x4a, 6144, "L2 unified cache: 6MB, 12-way associative. 64 byte line size." },
  83. { 0x4b, 8192, "L2 unified cache: 8MB, 16-way associative. 64 byte line size." },
  84. { 0x4c, 12288, "L2 unified cache: 12MB, 12-way associative. 64 byte line size." },
  85. { 0x4d, 16384, "L2 unified cache: 16MB, 16-way associative. 64 byte line size." },
  86. { 0x78, 1024, "L2 unified cache: 1MB, sectored, 8-way associative. 64 byte line size." },
  87. { 0, 0, NULL }
  88. };
  89. static struct _cache_table L3L2_cache_table[] =
  90. {
  91. { 0x46, 4096, "L3 unified cache: 4MB, 4-way associative. 64 byte line size." },
  92. { 0x47, 8192, "L3 unified cache: 8MB, 8-way associative. 64 byte line size." },
  93. { 0x49, 4096, "L3 unified cache: 4MB, 16-way associative. 64 byte line size." },
  94. { 0x4a, 6144, "L3 unified cache: 6MB, 12-way associative. 64 byte line size." },
  95. { 0x4b, 8192, "L3 unified cache: 8MB, 16-way associative. 64 byte line size." },
  96. { 0x4c, 12288, "L3 unified cache: 12MB, 12-way associative. 64 byte line size." },
  97. { 0x4d, 16384, "L3 unified cache: 16MB, 16-way associative. 64 byte line size." },
  98. { 0x78, 1024, "L3 unified cache: 1MB, sectored, 8-way associative. 64 byte line size." },
  99. { 0, 0, NULL }
  100. };
  101. static struct _cache_table L3_cache_table[] =
  102. {
  103. { 0x22, 512, "L3 unified cache: 512KB, 4-way associative. 64 byte line size." },
  104. { 0x23, 1024, "L3 unified cache: 1MB, 8-way associative. 64 byte line size." },
  105. { 0x25, 2048, "L3 unified cache: 2MB, 8-way associative. 64 byte line size." },
  106. { 0x29, 4096, "L3 unified cache: 4MB, 8-way associative. 64 byte line size." },
  107. { 0, 0, NULL }
  108. };
  109. static struct _cache_table ITLB_cache_table[] =
  110. {
  111. { 0x1, 32, "Instruction TLB: 4KB pages, 4-way associative, 32 entries" },
  112. { 0x2, 2, "Instruction TLB: 4MB pages, fully associative, 2 entries" },
  113. { 0x50, 64, "Instruction TLB: 4K, 2MB or 4MB pages, fully associative, 64 entries." },
  114. { 0x51, 128, "Instruction TLB: 4K, 2MB or 4MB pages, fully associative, 128 entries." },
  115. { 0x52, 256, "Instruction TLB: 4K, 2MB or 4MB pages, fully associative, 256 entries." },
  116. { 0xb0, 128, "Instruction TLB: 4K pages, 4-way associative, 128 entries." },
  117. { 0xb1, 4, "Instruction TLB: 4x 4MB page entries, or 8x 2MB pages entries, 4-way associative" },
  118. { 0, 0, NULL }
  119. };
  120. static struct _cache_table DTLB_cache_table[] =
  121. {
  122. { 0x3, 64, "Data TLB: 4KB pages, 4-way associative, 64 entries" },
  123. { 0x4, 8, "Data TLB: 4MB pages, 4-way associative, 8 entries" },
  124. { 0x5, 32, "Data TLB: 4MB pages, 4-way associative, 32 entries" },
  125. { 0x56, 16, "L1 Data TLB: 4MB pages, 4-way set associative, 16 entries" },
  126. { 0x57, 16, "L1 Data TLB: 4KB pages, 4-way set associative, 16 entries" },
  127. { 0x5b, 64, "Data TLB: 4KB or 4MB pages, fully associative, 64 entries." },
  128. { 0x5c, 128, "Data TLB: 4KB or 4MB pages, fully associative, 128 entries." },
  129. { 0x5d, 256, "Data TLB: 4KB or 4MB pages, fully associative, 256 entries." },
  130. { 0xb3, 128, "Data TLB: 4K pages, 4-way associative, 128 entries." },
  131. { 0xb4, 256, "Data TLB: 4K pages, 4-way associative, 256 entries." },
  132. { 0, 0, NULL }
  133. };
  134. static struct _cache_table prefetch_table[] =
  135. {
  136. {0xf0, 64, "64 byte prefetching."},
  137. {0xf1, 64, "128 byte prefetching."},
  138. };
  139. static unsigned char found_unknown=0;
  140. static unsigned char unknown_array[256];
  141. /* Decode Intel TLB and cache info descriptors */
  142. //TODO : Errata workaround. http://www.sandpile.org/post/msgs/20002736.htm
  143. static void decode_Intel_cache(int des, struct cpudata *cpu, int output,
  144. struct _cache_table *table)
  145. {
  146. int k = 0;
  147. int found = 0;
  148. /* "No 2nd-level cache or, if processor contains a valid 2nd-level
  149. cache, no 3rd-level cache". Skip this pointless entry.*/
  150. if (des == 0x40)
  151. return;
  152. //TODO: Add description to link-list in cpu->
  153. while ((table[k].descriptor != 0) && (found == 0)) {
  154. if (table[k].descriptor == des) {
  155. if (table == TRACE_cache_table)
  156. cpu->cachesize_trace += table[k].size;
  157. if (table == L1I_cache_table)
  158. cpu->cachesize_L1_I += table[k].size;
  159. if (table == L1D_cache_table)
  160. cpu->cachesize_L1_D += table[k].size;
  161. if (table == L2_cache_table)
  162. cpu->cachesize_L2 += table[k].size;
  163. if (table == L2L3_cache_table)
  164. cpu->cachesize_L2 += table[k].size;
  165. if (table == L3_cache_table)
  166. cpu->cachesize_L3 += table[k].size;
  167. if (table == L3L2_cache_table)
  168. cpu->cachesize_L3 += table[k].size;
  169. if (output)
  170. printf(" %s\n", table[k].string);
  171. found = 1;
  172. }
  173. k++;
  174. }
  175. if ((found == 0) && (unknown_array[des] == 0)) {
  176. unknown_array[des] = 1;
  177. found_unknown++;
  178. }
  179. }
  180. static void decode_cache(struct cpudata *cpu, struct _cache_table *table, int output)
  181. {
  182. unsigned int i, j, n;
  183. unsigned int regs[4];
  184. /* Decode TLB and cache info */
  185. cpuid(cpu->number, 2, &regs[0], &regs[1], &regs[2], &regs[3]);
  186. /* Number of times to iterate */
  187. n = regs[0] & 0xff;
  188. for (i=0; i<n; i++) {
  189. cpuid(cpu->number, 2, &regs[0], &regs[1], &regs[2], &regs[3]);
  190. /* If bit 31 is set, this is an unknown format */
  191. for (j=0; j<3; j++)
  192. if (regs[j] & 0x80000000)
  193. regs[j] = 0;
  194. /* Byte 0 is level count, not a descriptor */
  195. for (j=1; j<16; j++) {
  196. unsigned char val = regs[j / 4] >> (unsigned int)(8 * (j % 4));
  197. if (val)
  198. decode_Intel_cache(val, cpu, output, table);
  199. }
  200. }
  201. }
  202. static void clean_unknowns(struct _cache_table *table)
  203. {
  204. int j=0;
  205. int des;
  206. while (table[j].descriptor != 0) {
  207. des = table[j++].descriptor;
  208. if (unknown_array[des] == 1) {
  209. unknown_array[des] = 0;
  210. found_unknown--;
  211. }
  212. }
  213. }
  214. void decode_Intel_caches(struct cpudata *cpu, int output)
  215. {
  216. unsigned int i = 0;
  217. unsigned char oldknown;
  218. if (cpu->maxi < 2)
  219. return;
  220. memset(&unknown_array, 0, sizeof(unknown_array));
  221. if (output)
  222. printf("Cache info\n");
  223. decode_cache(cpu, TRACE_cache_table, output);
  224. decode_cache(cpu, L1I_cache_table, output);
  225. decode_cache(cpu, L1D_cache_table, output);
  226. oldknown = found_unknown;
  227. decode_cache(cpu, L2_cache_table, output);
  228. if (found_unknown > 0) {
  229. if (oldknown == found_unknown)
  230. decode_cache(cpu, L2L3_cache_table, output);
  231. else
  232. decode_cache(cpu, L3L2_cache_table, output);
  233. }
  234. decode_cache(cpu, L3_cache_table, output);
  235. if (output)
  236. printf("TLB info\n");
  237. decode_cache(cpu, ITLB_cache_table, output);
  238. decode_cache(cpu, DTLB_cache_table, output);
  239. decode_cache(cpu, prefetch_table, output);
  240. if (found_unknown == 0)
  241. return;
  242. /* Remove any known entries */
  243. clean_unknowns(TRACE_cache_table);
  244. clean_unknowns(L1I_cache_table);
  245. clean_unknowns(L1D_cache_table);
  246. clean_unknowns(L2_cache_table);
  247. clean_unknowns(L3_cache_table);
  248. clean_unknowns(L2L3_cache_table);
  249. clean_unknowns(ITLB_cache_table);
  250. clean_unknowns(DTLB_cache_table);
  251. clean_unknowns(prefetch_table);
  252. if (found_unknown == 0)
  253. return;
  254. if (output)
  255. printf("Found unknown cache descriptors: ");
  256. for (i=0; i<256; i++) {
  257. if (unknown_array[i] == 1)
  258. if (output)
  259. printf("%02x ", i);
  260. }
  261. if (output)
  262. printf("\n");
  263. found_unknown = 0;
  264. }