cpuinfo.c 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784
  1. #include "cpuinfo.h"
  2. #include "cpuinfo_cfg.h"
  3. #include <string.h>
  4. #define BIT(ofs) (0x1U << (ofs))
  5. #define EXTENSION_NUM (26)
  6. #define POW2(n) (1U << (n))
  7. #define LINESZ(n) ((n) > 0U ? POW2((n) - 1) : 0)
  8. /* Check register field with default field name print */
  9. #define CHECK_FIELD_DFT(reg, field) \
  10. if (reg.b.field) { \
  11. CIF_PRINTF(" %s", #field); \
  12. }
  13. /* Check register field with string specified */
  14. #define CHECK_FIELD(reg, field, str) \
  15. if (reg.b.field) { \
  16. CIF_PRINTF(" %s", str); \
  17. }
  18. /* Show register value */
  19. #define SHOW_VALUE(reg, field) \
  20. CIF_PRINTF(" %s=%u\r\n", #field, reg.b.field);
  21. #define STRCAT_BUF(buf, fmt, ...) \
  22. snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), fmt, ##__VA_ARGS__)
  23. #define CHECK_STRCAT_BUF(reg, field, buf, fmt, ...) \
  24. do { \
  25. if (reg.b.field) { \
  26. STRCAT_BUF(buf, fmt, ##__VA_ARGS__); \
  27. } \
  28. } while (0)
  29. #define BASIC_CPUINFO_FMT "Nuclei CPU Detected: mhartid-0x%x marchid-0x%04x v%d.%d.%d, ISA: RV%d%s"
  30. /** `BUF_SIZE` is the size of string buffer in `get_basic_cpuinfo`
  31. */
  32. #ifndef BUF_SIZE
  33. #define BUF_SIZE (1024)
  34. #endif
  35. static void show_isa(uint32_t xlen, U32_CSR_MISA_Type misa,
  36. U32_CSR_MCFG_INFO_Type mcfg);
  37. static void show_mcfg(const CPU_INFO_Group *cpuinfo);
  38. static void show_micfg_mdcfg(U32_CSR_MCFG_INFO_Type mcfg,
  39. U32_CSR_MICFG_INFO_Type micfg,
  40. U32_CSR_MDCFG_INFO_Type mdcfg);
  41. static void show_mtlbcfg(U32_CSR_MCFG_INFO_Type mcfg,
  42. U32_CSR_MTLBCFG_INFO_Type mtlbcfg);
  43. static void show_iregion(const CPU_INFO_Group *cpuinfo);
  44. static void show_mfiocfg(U32_CSR_MCFG_INFO_Type mcfg,
  45. U64_CSR_MFIOCFG_INFO_Type mfiocfg);
  46. static void show_mppicfg(U32_CSR_MCFG_INFO_Type mcfg,
  47. U64_CSR_MPPICFG_INFO_Type mppicfg);
  48. static void show_prefetch_cfg(IINFO_Type *iinfo);
  49. static void show_isa_support(IINFO_Type *iinfo);
  50. static void show_mvlm_cfg(IINFO_Type *iinfo);
  51. static void show_flash_bus(IINFO_Type *iinfo);
  52. static void show_mem_region_cfg(IINFO_Type *iinfo);
  53. static void show_mcppi_cfg(IINFO_Type *iinfo);
  54. static void show_cmo(IINFO_Type *iinfo);
  55. static void show_performance_cfg(IINFO_Type *iinfo);
  56. static void show_misc_cfg(IINFO_Type *iinfo);
  57. /**
  58. * Convert to human readable size with option
  59. * \param size: size in bytes
  60. * \param lite: !=0 for lite version
  61. */
  62. static char *cvt_size_opt(uint32_t size, int lite);
  63. #define cvt_size(size) cvt_size_opt(size, 0)
  64. static void show_cache_info(uint32_t set, uint32_t way, uint32_t lsize,
  65. uint32_t ecc);
  66. void show_cpuinfo(const CPU_INFO_Group *cpuinfo)
  67. {
  68. if (cpuinfo == NULL) {
  69. return;
  70. }
  71. if (cpuinfo->misa.d == 0) {
  72. CIF_PRINTF("\r\n-----Invalid RISC-V MISA CSR found, no CPU Information could be dumped-----\r\n");
  73. return;
  74. }
  75. CIF_PRINTF("\r\n-----Nuclei RISC-V CPU Configuration Information-----\r\n");
  76. /* ID and version */
  77. CIF_PRINTF(" MARCHID: 0x%04x\r\n", cpuinfo->marchid.d);
  78. CIF_PRINTF(" MHARTID: 0x%x\r\n", cpuinfo->mhartid);
  79. CIF_PRINTF(" MIMPID: 0x%06x\r\n", cpuinfo->mimpid.d);
  80. /* ISA */
  81. show_isa(cpuinfo->xlen, cpuinfo->misa, cpuinfo->mcfginfo);
  82. /* Support */
  83. show_mcfg(cpuinfo);
  84. /* ILM, DLM, I/D Cache */
  85. show_micfg_mdcfg(cpuinfo->mcfginfo, cpuinfo->micfginfo, cpuinfo->mdcfginfo);
  86. /* TLB */
  87. show_mtlbcfg(cpuinfo->mcfginfo, cpuinfo->mtlbcfginfo);
  88. /* FIO */
  89. show_mfiocfg(cpuinfo->mcfginfo, cpuinfo->mfiocfginfo);
  90. /* PPI */
  91. show_mppicfg(cpuinfo->mcfginfo, cpuinfo->mppicfginfo);
  92. /* IREGION */
  93. show_iregion(cpuinfo);
  94. CIF_PRINTF("-----End of Nuclei CPU INFO-----\r\n");
  95. }
  96. int get_basic_cpuinfo(const CPU_INFO_Group *cpuinfo, char *str, unsigned long len)
  97. {
  98. if (str == NULL || cpuinfo == NULL) {
  99. return -1;
  100. }
  101. if (cpuinfo->misa.d == 0) {
  102. return -1;
  103. }
  104. static char buf[BUF_SIZE] = {0}; // features string buffer
  105. buf[0] = '\0'; // clear the buffer each time call this function
  106. char isa[EXTENSION_NUM + 1];
  107. /* construct ISA string */
  108. int pos = 0;
  109. for (int i = 0; i < EXTENSION_NUM; ++i) {
  110. if (cpuinfo->misa.d & BIT(i)) {
  111. isa[pos++] = 'A' + i;
  112. }
  113. }
  114. isa[pos] = '\0';
  115. if (!cpuinfo->mcfg_exist) {
  116. goto simple;
  117. }
  118. /* construct features string */
  119. U32_CSR_MCFG_INFO_Type mcfg = cpuinfo->mcfginfo;
  120. CHECK_STRCAT_BUF(mcfg, plic, buf, "MMU, PLIC, ");
  121. CHECK_STRCAT_BUF(mcfg, eclic, buf, "ECLIC, ");
  122. CHECK_STRCAT_BUF(mcfg, fio, buf, "FIO, ");
  123. CHECK_STRCAT_BUF(mcfg, ppi, buf, "PPI, ");
  124. CHECK_STRCAT_BUF(mcfg, nice, buf, "NICE, ");
  125. CHECK_STRCAT_BUF(mcfg, vnice, buf, "VNICE, ");
  126. CHECK_STRCAT_BUF(mcfg, etrace, buf, "ETRACE, ");
  127. CHECK_STRCAT_BUF(mcfg, ecc, buf, "ECC, ");
  128. CHECK_STRCAT_BUF(mcfg, tee, buf, "TEE, ");
  129. CHECK_STRCAT_BUF(mcfg, sec_mode, buf, "SMWG, ");
  130. IINFO_ISA_SUPPORT0_Type isa_support0;
  131. isa_support0.d = cpuinfo->iinfo->isa_support0;
  132. CHECK_STRCAT_BUF(isa_support0, svpbmt, buf, "Svpbmt, ");
  133. IINFO_MCMO_INFO_Type cmo;
  134. cmo.d = cpuinfo->iinfo->cmo_info;
  135. CHECK_STRCAT_BUF(cmo, cmo_cfg, buf, "CMO, ");
  136. if (mcfg.b.smp) {
  137. STRCAT_BUF(buf, "SMPx%d, ", cpuinfo->smpcfg.b.smp_core_num + 1);
  138. }
  139. /* show local memory and cache info */
  140. U32_CSR_MICFG_INFO_Type micfg = cpuinfo->micfginfo;
  141. U32_CSR_MDCFG_INFO_Type mdcfg = cpuinfo->mdcfginfo;
  142. CHECK_STRCAT_BUF(mcfg, ilm, buf, "ILM-%s, ",
  143. cvt_size_opt(POW2(micfg.b.lm_size + 7), 1));
  144. CHECK_STRCAT_BUF(mcfg, dlm, buf, "DLM-%s, ",
  145. cvt_size_opt(POW2(mdcfg.b.lm_size + 7), 1));
  146. CHECK_STRCAT_BUF(
  147. mcfg, icache, buf, "IC-%s, ",
  148. cvt_size_opt(POW2(micfg.b.set + 3) * POW2(micfg.b.lsize + 2) *
  149. (micfg.b.way + 1),
  150. 1));
  151. CHECK_STRCAT_BUF(
  152. mcfg, dcache, buf, "DC-%s, ",
  153. cvt_size_opt(POW2(mdcfg.b.set + 3) * POW2(mdcfg.b.lsize + 2) *
  154. (mdcfg.b.way + 1),
  155. 1));
  156. /* remove the comma at the end */
  157. if (strlen(buf) > 0 && buf[strlen(buf) - 2] == ',') {
  158. buf[strlen(buf) - 2] = '\0';
  159. }
  160. /* Feature name must have at least 2 chars */
  161. if (strlen(buf) < 2) {
  162. goto simple;
  163. }
  164. return snprintf(str, len, BASIC_CPUINFO_FMT ", Feature: %s", cpuinfo->mhartid,
  165. cpuinfo->marchid.d, cpuinfo->mimpid.b.first_vernum,
  166. cpuinfo->mimpid.b.mid_vernum, cpuinfo->mimpid.b.last_vernum,
  167. cpuinfo->xlen, isa, buf);
  168. simple:
  169. return snprintf(str, len, BASIC_CPUINFO_FMT, cpuinfo->mhartid, cpuinfo->marchid.d,
  170. cpuinfo->mimpid.b.first_vernum, cpuinfo->mimpid.b.mid_vernum,
  171. cpuinfo->mimpid.b.last_vernum, cpuinfo->xlen, isa);
  172. }
  173. static void show_isa(uint32_t xlen, U32_CSR_MISA_Type misa,
  174. U32_CSR_MCFG_INFO_Type mcfg)
  175. {
  176. CIF_PRINTF(" ISA:");
  177. CIF_PRINTF(" RV%d", xlen);
  178. for (int i = 0; i < EXTENSION_NUM; i++) {
  179. if (misa.d & BIT(i)) {
  180. if ('X' == ('A' + i)) {
  181. CIF_PRINTF(" NICE");
  182. } else {
  183. CIF_PRINTF(" %c", 'A' + i);
  184. }
  185. }
  186. }
  187. CHECK_FIELD(mcfg, dsp_n1, "Xxldspn1x");
  188. CHECK_FIELD(mcfg, dsp_n2, "Xxldspn2x");
  189. CHECK_FIELD(mcfg, dsp_n3, "Xxldspn3x");
  190. if (mcfg.b.zc_xlcz) {
  191. if (mcfg.b.xlcz == 0) {
  192. CIF_PRINTF(" Zc Xxlcz");
  193. } else {
  194. CIF_PRINTF(" Zc");
  195. }
  196. }
  197. CHECK_FIELD(mcfg, zilsd, "Zilsd");
  198. CIF_PRINTF("\r\n");
  199. }
  200. static void show_mcfg(const CPU_INFO_Group *cpuinfo)
  201. {
  202. if (!cpuinfo->mcfg_exist) {
  203. return;
  204. }
  205. U32_CSR_MCFG_INFO_Type mcfg = cpuinfo->mcfginfo;
  206. CIF_PRINTF(" MCFG:");
  207. CHECK_FIELD(mcfg, tee, "TEE")
  208. CHECK_FIELD(mcfg, ecc, "ECC")
  209. CHECK_FIELD(mcfg, eclic, "ECLIC")
  210. CHECK_FIELD(mcfg, plic, "PLIC")
  211. CHECK_FIELD(mcfg, fio, "FIO")
  212. CHECK_FIELD(mcfg, ppi, "PPI")
  213. CHECK_FIELD(mcfg, nice, "NICE")
  214. CHECK_FIELD(mcfg, ilm, "ILM")
  215. CHECK_FIELD(mcfg, dlm, "DLM")
  216. CHECK_FIELD(mcfg, icache, "ICACHE")
  217. CHECK_FIELD(mcfg, dcache, "DCACHE")
  218. CHECK_FIELD(mcfg, smp, "SMP")
  219. CHECK_FIELD(mcfg, iregion, "IREGION")
  220. CHECK_FIELD(mcfg, sec_mode, "SMWG")
  221. CHECK_FIELD(mcfg, etrace, "ETRACE")
  222. CHECK_FIELD(mcfg, vnice, "VNICE")
  223. CHECK_FIELD(mcfg, sstc, "SSTC")
  224. switch (mcfg.b.safety_mecha) {
  225. case 0b00:
  226. CIF_PRINTF(" No-Safety-Mechanism");
  227. break;
  228. case 0b01:
  229. CIF_PRINTF(" Lockstep");
  230. break;
  231. case 0b10:
  232. CIF_PRINTF(" Lockstep+SplitMode");
  233. break;
  234. case 0b11:
  235. CIF_PRINTF(" ASIL-B");
  236. break;
  237. default:
  238. break;
  239. }
  240. if (cpuinfo->vlenb >0) {
  241. switch (mcfg.b.vpu_degree) {
  242. case 0b00:
  243. CIF_PRINTF(" DLEN=VLEN/2");
  244. break;
  245. case 0b01:
  246. CIF_PRINTF(" DLEN=VLEN");
  247. break;
  248. default:
  249. break;
  250. }
  251. CIF_PRINTF(" VLEN=%u", cpuinfo->vlenb * 8);
  252. }
  253. CIF_PRINTF("\r\n");
  254. }
  255. static void show_micfg_mdcfg(U32_CSR_MCFG_INFO_Type mcfg,
  256. U32_CSR_MICFG_INFO_Type micfg,
  257. U32_CSR_MDCFG_INFO_Type mdcfg)
  258. {
  259. /* ILM */
  260. if (mcfg.b.ilm) {
  261. CIF_PRINTF(" ILM:");
  262. CIF_PRINTF(" %s", cvt_size(POW2(micfg.b.lm_size + 7)));
  263. CHECK_FIELD(micfg, lm_xonly, "execute-only");
  264. CHECK_FIELD(micfg, lm_ecc, "has-ecc");
  265. CIF_PRINTF("\r\n");
  266. }
  267. /* DLM */
  268. if (mcfg.b.dlm) {
  269. CIF_PRINTF(" DLM:");
  270. CIF_PRINTF(" %s", cvt_size(POW2(mdcfg.b.lm_size + 7)));
  271. CHECK_FIELD(mdcfg, lm_ecc, "has-ecc");
  272. CIF_PRINTF("\r\n");
  273. }
  274. /* ICACHE */
  275. if (mcfg.b.icache) {
  276. CIF_PRINTF(" ICACHE:");
  277. show_cache_info(POW2(micfg.b.set + 3), micfg.b.way + 1,
  278. POW2(micfg.b.lsize + 2), mcfg.b.ecc);
  279. }
  280. /* DCACHE */
  281. if (mcfg.b.dcache) {
  282. CIF_PRINTF(" DCACHE:");
  283. show_cache_info(POW2(mdcfg.b.set + 3), mdcfg.b.way + 1,
  284. POW2(mdcfg.b.lsize + 2), mcfg.b.ecc);
  285. }
  286. }
  287. static void show_mtlbcfg(U32_CSR_MCFG_INFO_Type mcfg,
  288. U32_CSR_MTLBCFG_INFO_Type mtlbcfg)
  289. {
  290. /* TLB only present with MMU, when PLIC present MMU will present */
  291. if (mcfg.b.plic) {
  292. if (mtlbcfg.nb.mapping == 1) {
  293. CIF_PRINTF(" TLB:");
  294. CIF_PRINTF(" MainTLB(entry=%u,way=%u,ecc=%u)",
  295. POW2(mtlbcfg.nb.set + 3), mtlbcfg.nb.way + 1,
  296. mtlbcfg.nb.ecc);
  297. CIF_PRINTF(" ITLB(entry=%u) DTLB(entry=%u)\r\n",
  298. mtlbcfg.nb.i_size + 1, mtlbcfg.nb.d_size + 1);
  299. } else {
  300. CIF_PRINTF(" TLB:");
  301. CIF_PRINTF(" MainTLB(entry=%u,way=%u,ecc=%u)",
  302. POW2(mtlbcfg.b.set + 3), mtlbcfg.b.way + 1,
  303. mtlbcfg.b.ecc);
  304. CIF_PRINTF(" ITLB(entry=%u) DTLB(entry=%u)\r\n",
  305. LINESZ(mtlbcfg.b.i_size), LINESZ(mtlbcfg.b.d_size));
  306. }
  307. }
  308. }
  309. static void show_iregion(const CPU_INFO_Group *cpuinfo)
  310. {
  311. U32_CSR_MCFG_INFO_Type mcfg = cpuinfo->mcfginfo;
  312. if (!mcfg.b.iregion) {
  313. return;
  314. }
  315. CIF_PRINTF(" IREGION:");
  316. U64_CSR_MIRGB_INFO_Type mirgb = cpuinfo->mirgbinfo;
  317. uint64_t iregion_base = cpuinfo->iregion_base;
  318. CIF_PRINTF(" %#" CIF_PRIxADDR "", (addr_t)iregion_base);
  319. CIF_PRINTF(" %s\r\n", cvt_size(POW2(mirgb.b.iregion_size + 9)));
  320. CIF_PRINTF(" Unit Size Address\r\n");
  321. CIF_PRINTF(" IINFO 64KB 0x%" CIF_PRIxADDR "\r\n",
  322. (addr_t)iregion_base + CPUINFO_IRG_IINFO_OFS);
  323. CIF_PRINTF(" DEBUG 64KB %#" CIF_PRIxADDR "\r\n",
  324. (addr_t)iregion_base + CPUINFO_IRG_DEBUG_OFS);
  325. if (mcfg.b.eclic) {
  326. CIF_PRINTF(" ECLIC 64KB %#" CIF_PRIxADDR "\r\n",
  327. (addr_t)iregion_base + CPUINFO_IRG_ECLIC_OFS);
  328. }
  329. CIF_PRINTF(" TIMER 64KB %#" CIF_PRIxADDR "\r\n",
  330. (addr_t)iregion_base + CPUINFO_IRG_TIMER_OFS);
  331. if (mcfg.b.smp) {
  332. CIF_PRINTF(" SMP 64KB %#" CIF_PRIxADDR "\r\n",
  333. (addr_t)iregion_base + CPUINFO_IRG_SMP_OFS);
  334. }
  335. U32_SMP_CFG_Type smp_cfg = cpuinfo->smpcfg;
  336. /* If has eclic and has equal or more than 1 core, CIDU will present
  337. * The actual core number is `smp_core_num + 1` */
  338. if (mcfg.b.eclic && (smp_cfg.b.smp_core_num >= 1)) {
  339. CIF_PRINTF(" CIDU 64KB %#" CIF_PRIxADDR "\r\n",
  340. (addr_t)iregion_base + CPUINFO_IRG_IDU_OFS);
  341. }
  342. if (mcfg.b.plic) {
  343. CIF_PRINTF(" PLIC 64MB %#" CIF_PRIxADDR "\r\n",
  344. (addr_t)iregion_base + CPUINFO_IRG_PLIC_OFS);
  345. }
  346. /* SMP */
  347. if (mcfg.b.smp) {
  348. CIF_PRINTF(" SMP_CFG:");
  349. CIF_PRINTF(" CC_PRESENT=%d", smp_cfg.b.cc);
  350. CIF_PRINTF(" SMP_NUM=%d", smp_cfg.b.smp_core_num + 1);
  351. CIF_PRINTF(" IOCP_NUM=%d", smp_cfg.b.iocp_num);
  352. CIF_PRINTF(" PMON_NUM=%d", smp_cfg.b.pmon_num);
  353. CIF_PRINTF("\r\n");
  354. }
  355. /* ECLIC */
  356. if (mcfg.b.eclic) {
  357. ECLIC_Type *eclic = cpuinfo->eclic;
  358. U32_ECLIC_INFO_Type eclic_info = eclic->info;
  359. CIF_PRINTF(" ECLIC:");
  360. CIF_PRINTF(" VERSION=0x%x", eclic_info.b.version);
  361. CIF_PRINTF(" NUM_INTERRUPT=%u", eclic_info.b.num_interrupt);
  362. CIF_PRINTF(" CLICINTCTLBITS=%u", eclic_info.b.clicintctlbits);
  363. CIF_PRINTF(" MTH=%u", eclic->mth);
  364. CIF_PRINTF(" NLBITS=%u", (eclic->cfg & 0x1E) >> 1);
  365. CIF_PRINTF("\r\n");
  366. }
  367. /* L2CACHE */
  368. if (smp_cfg.b.cc) {
  369. U32_CC_CFG_Type cc_cfg = cpuinfo->cccfg;
  370. CIF_PRINTF(" L2CACHE:");
  371. show_cache_info(POW2(cc_cfg.b.set), cc_cfg.b.way + 1,
  372. POW2(cc_cfg.b.lsize + 2), cc_cfg.b.ecc);
  373. }
  374. // NOTE: mpasize always have, and is PA_SIZE of RTL configuration
  375. // if it is 0, it means it dont have IINFO region
  376. if (cpuinfo->iinfo->mpasize == 0) {
  377. return;
  378. }
  379. /* IREGION INFO */
  380. CIF_PRINTF(" INFO-Detail:\r\n");
  381. /* MPASIZE */
  382. uint32_t mpasize = cpuinfo->iinfo->mpasize;
  383. CIF_PRINTF(" mpasize : %u\r\n", mpasize);
  384. /* prefetch related registers */
  385. show_prefetch_cfg(cpuinfo->iinfo);
  386. /* ISA_SUPPORT VPU_CFG_INFO */
  387. show_isa_support(cpuinfo->iinfo);
  388. /* MVLM_CFG */
  389. show_mvlm_cfg(cpuinfo->iinfo);
  390. /* FLASH_BASE_ADDR */
  391. show_flash_bus(cpuinfo->iinfo);
  392. /* MEM_REGION_CFG */
  393. show_mem_region_cfg(cpuinfo->iinfo);
  394. /* MCPPI_CFG */
  395. show_mcppi_cfg(cpuinfo->iinfo);
  396. /* CMO_INFO */
  397. show_cmo(cpuinfo->iinfo);
  398. /* PERFORMANCE_CFG */
  399. show_performance_cfg(cpuinfo->iinfo);
  400. /* MERGEL1DCTRL and ACCESS_CTRL */
  401. show_misc_cfg(cpuinfo->iinfo);
  402. }
  403. static void show_mfiocfg(U32_CSR_MCFG_INFO_Type mcfg,
  404. U64_CSR_MFIOCFG_INFO_Type mfiocfg)
  405. {
  406. if (mcfg.b.fio) {
  407. CIF_PRINTF(" FIO:");
  408. CIF_PRINTF(" %#" CIF_PRIxADDR "", (addr_t)((uint64_t)mfiocfg.d & (~0x3FFULL)));
  409. CIF_PRINTF(" %s\r\n", cvt_size(POW2(mfiocfg.b.fio_size + 9)));
  410. }
  411. }
  412. static void show_mppicfg(U32_CSR_MCFG_INFO_Type mcfg,
  413. U64_CSR_MPPICFG_INFO_Type mppicfg)
  414. {
  415. if (mcfg.b.ppi) {
  416. CIF_PRINTF(" PPI:");
  417. CIF_PRINTF(" %#" CIF_PRIxADDR "", (addr_t)((uint64_t)mppicfg.d & (~0x3FFULL)));
  418. CIF_PRINTF(" %s\r\n", cvt_size(POW2(mppicfg.b.ppi_size + 9)));
  419. }
  420. }
  421. static void show_prefetch_cfg(IINFO_Type *iinfo)
  422. {
  423. IINFO_PFL1INFO_Type pfl1info;
  424. pfl1info.d = iinfo->pfl1info;
  425. if (pfl1info.b.pf_cfg) {
  426. CIF_PRINTF(" prefetch: present\r\n");
  427. const char *pf_cfg[] = {"none", "normal", "high performance"};
  428. if (pfl1info.b.pf_cfg < 3) {
  429. CIF_PRINTF(" prefetch_mode: %s\r\n",
  430. pf_cfg[pfl1info.b.pf_cfg]);
  431. }
  432. if (iinfo->pfl1dctrl4 & BIT(0)) {
  433. CIF_PRINTF(" status: enable\r\n");
  434. } else {
  435. CIF_PRINTF(" status: disable\r\n");
  436. }
  437. if (pfl1info.b.pf_ver) {
  438. CIF_PRINTF(" version=%u\r\n",
  439. pfl1info.b.pf_ver);
  440. }
  441. /* prefetch config */
  442. IINFO_PFL1DCTRL1_Type pfl1dctrl1;
  443. IINFO_PFL1DCTRL2_Type pfl1dctrl2;
  444. IINFO_PFL1DCTRL3_Type pfl1dctrl3;
  445. pfl1dctrl1.d = iinfo->pfl1dctrl1;
  446. pfl1dctrl2.d = iinfo->pfl1dctrl2;
  447. pfl1dctrl3.d = iinfo->pfl1dctrl3;
  448. SHOW_VALUE(pfl1info, l2_pf_lbuf_num);
  449. SHOW_VALUE(pfl1info, l2_pf_dbuf_num);
  450. SHOW_VALUE(pfl1dctrl1, l1d_ena);
  451. SHOW_VALUE(pfl1dctrl1, cc_ena);
  452. SHOW_VALUE(pfl1dctrl1, scalar_ena);
  453. SHOW_VALUE(pfl1dctrl1, vector_ena);
  454. SHOW_VALUE(pfl1dctrl1, write_pref_ena);
  455. SHOW_VALUE(pfl1dctrl1, cross_page_pref_ena);
  456. SHOW_VALUE(pfl1dctrl1, pref_conflict_stop_th);
  457. SHOW_VALUE(pfl1dctrl1, pref_conflict_decr_sel);
  458. SHOW_VALUE(pfl1dctrl2, degree_incr_th);
  459. SHOW_VALUE(pfl1dctrl2, degree_decr_th);
  460. SHOW_VALUE(pfl1dctrl2, next_line_ena_th);
  461. SHOW_VALUE(pfl1dctrl2, write_noalloc_l1_th);
  462. SHOW_VALUE(pfl1dctrl2, write_noalloc_l2_th);
  463. SHOW_VALUE(pfl1dctrl3, max_stream_l1_degree);
  464. SHOW_VALUE(pfl1dctrl3, max_stream_l2_degree);
  465. SHOW_VALUE(pfl1dctrl3, max_stride_cplx_l1_degree);
  466. SHOW_VALUE(pfl1dctrl3, max_stride_cplx_l2_degree);
  467. } else {
  468. CIF_PRINTF(" prefetch: absent\r\n");
  469. }
  470. }
  471. static void show_isa_support(IINFO_Type *iinfo)
  472. {
  473. IINFO_ISA_SUPPORT0_Type isa_support0;
  474. IINFO_ISA_SUPPORT1_Type isa_support1;
  475. isa_support0.d = iinfo->isa_support0;
  476. isa_support1.d = iinfo->isa_support1;
  477. if (isa_support0.b.exist || isa_support1.b.exist) {
  478. CIF_PRINTF(" isa supported: present\r\n");
  479. CIF_PRINTF(" extension_list:");
  480. if (isa_support0.b.exist) {
  481. CHECK_FIELD_DFT(isa_support0, vector);
  482. CHECK_FIELD_DFT(isa_support0, smepmp);
  483. CHECK_FIELD_DFT(isa_support0, sscofpmf);
  484. CHECK_FIELD_DFT(isa_support0, zfh);
  485. CHECK_FIELD_DFT(isa_support0, zfhmin);
  486. CHECK_FIELD_DFT(isa_support0, zfa);
  487. CHECK_FIELD_DFT(isa_support0, svnapot);
  488. CHECK_FIELD_DFT(isa_support0, svpbmt);
  489. CHECK_FIELD_DFT(isa_support0, svinval);
  490. CHECK_FIELD_DFT(isa_support0, bf16);
  491. CHECK_FIELD_DFT(isa_support0, zimop);
  492. CHECK_FIELD_DFT(isa_support0, zcmop);
  493. CHECK_FIELD_DFT(isa_support0, zicond);
  494. CHECK_FIELD_DFT(isa_support0, zihintntl);
  495. CHECK_FIELD_DFT(isa_support0, zihintpause);
  496. CHECK_FIELD_DFT(isa_support0, smrnmi);
  497. CHECK_FIELD_DFT(isa_support0, zihpm);
  498. CHECK_FIELD_DFT(isa_support0, smcntrpmf);
  499. CHECK_FIELD_DFT(isa_support0, zicntr);
  500. CHECK_FIELD_DFT(isa_support0, zawrs);
  501. }
  502. if (isa_support1.b.exist) {
  503. CHECK_FIELD_DFT(isa_support1, ssqosid);
  504. CHECK_FIELD_DFT(isa_support1, zicflip);
  505. CHECK_FIELD_DFT(isa_support1, zicfiss);
  506. CHECK_FIELD_DFT(isa_support1, smctr);
  507. CHECK_FIELD_DFT(isa_support1, zacas);
  508. CHECK_FIELD_DFT(isa_support1, zabha);
  509. CHECK_FIELD_DFT(isa_support1, smdbltrp);
  510. CHECK_FIELD_DFT(isa_support1, ssdbltrp);
  511. CHECK_FIELD_DFT(isa_support1, smcdeleg);
  512. CHECK_FIELD_DFT(isa_support1, smmpm);
  513. CHECK_FIELD_DFT(isa_support1, smnpm);
  514. CHECK_FIELD_DFT(isa_support1, ssnpm);
  515. CHECK_FIELD_DFT(isa_support1, smstateen);
  516. CHECK_FIELD_DFT(isa_support1, sstateen);
  517. CHECK_FIELD_DFT(isa_support1, smcsrind);
  518. CHECK_FIELD_DFT(isa_support1, sscsrind);
  519. CHECK_FIELD_DFT(isa_support1, svadu);
  520. }
  521. CIF_PRINTF("\r\n");
  522. } else {
  523. CIF_PRINTF(" isa supported: absent\r\n");
  524. }
  525. /* VPU related extensions */
  526. if (isa_support0.b.exist && isa_support0.b.vector) {
  527. CIF_PRINTF(" vpu: present\r\n");
  528. CIF_PRINTF(" vpu_extension_list:");
  529. CHECK_FIELD_DFT(isa_support0, vector_b);
  530. CHECK_FIELD_DFT(isa_support0, vector_k);
  531. CHECK_FIELD_DFT(isa_support0, zve32x);
  532. CHECK_FIELD_DFT(isa_support0, zve32f);
  533. CHECK_FIELD_DFT(isa_support0, zve64x);
  534. CHECK_FIELD_DFT(isa_support0, zve64f);
  535. CHECK_FIELD_DFT(isa_support0, zve64d);
  536. CHECK_FIELD_DFT(isa_support0, zvfh);
  537. CHECK_FIELD_DFT(isa_support0, zvfhmin);
  538. CIF_PRINTF("\r\n");
  539. uint32_t vpu_cfg_info = iinfo->vpu_cfg_info;
  540. CIF_PRINTF(" noseg_noshuf=%u\r\n",
  541. (unsigned int)(vpu_cfg_info & BIT(0)));
  542. CIF_PRINTF(" elen64=%u\r\n",
  543. (unsigned int)(vpu_cfg_info & BIT(1)) >> 1);
  544. } else {
  545. CIF_PRINTF(" vpu: absent\r\n");
  546. }
  547. }
  548. static void show_mvlm_cfg(IINFO_Type *iinfo)
  549. {
  550. IINFO_MVLM_CFG_LO_Type mvlm_cfg_lo;
  551. mvlm_cfg_lo.d = iinfo->mvlm_cfg_lo;
  552. if (mvlm_cfg_lo.b.vlm) {
  553. CIF_PRINTF(" vlm: present\r\n");
  554. IINFO_MVLM_CFG_HI_Type mvlm_cfg_hi = iinfo->mvlm_cfg_hi;
  555. uint64_t vlm_base =
  556. (uint64_t)mvlm_cfg_hi << 32 | (mvlm_cfg_lo.d & (~0x3FFULL));
  557. CIF_PRINTF(" base=0x%" CIF_PRIxADDR "\r\n", (addr_t)vlm_base);
  558. CIF_PRINTF(" size=%s\r\n",
  559. cvt_size(POW2(mvlm_cfg_lo.b.vlm_size + 9)));
  560. } else {
  561. CIF_PRINTF(" vlm: absent\r\n");
  562. }
  563. }
  564. static void show_flash_bus(IINFO_Type *iinfo)
  565. {
  566. IINFO_FLASH_BASE_ADDR_LO_Type addr_lo;
  567. addr_lo.d = iinfo->flash_base_addr_lo;
  568. if (addr_lo.b.flash) {
  569. CIF_PRINTF(" flash bus: present\r\n");
  570. IINFO_FLASH_BASE_ADDR_HI_Type addr_hi = iinfo->flash_base_addr_hi;
  571. uint64_t flash_base =
  572. (uint64_t)addr_hi << 32 | (addr_lo.d & (~0x3FFULL));
  573. CIF_PRINTF(" base=0x%" CIF_PRIxADDR "\r\n", (addr_t)flash_base);
  574. CIF_PRINTF(" size=%s\r\n",
  575. cvt_size(addr_lo.b.flash_size + 9));
  576. } else {
  577. CIF_PRINTF(" flash bus: absent\r\n");
  578. }
  579. }
  580. static void show_mem_region_cfg(IINFO_Type *iinfo)
  581. {
  582. IINFO_MEM_REGION_CFG_LO_Type region_lo;
  583. uint64_t region_base;
  584. region_lo.d = iinfo->mem_region0_cfg_lo;
  585. if (region_lo.b.exist) {
  586. CIF_PRINTF(" mem_region0: present\r\n");
  587. IINFO_MEM_REGION_CFG_HI_Type region_hi = iinfo->mem_region0_cfg_hi;
  588. region_base = (uint64_t)region_hi << 32 | (region_lo.d & (~0x3FFULL));
  589. if (region_lo.b.mem_region_ena) {
  590. CIF_PRINTF(" status: enable\r\n");
  591. } else {
  592. CIF_PRINTF(" status: disable\r\n");
  593. }
  594. CIF_PRINTF(" base=0x%" CIF_PRIxADDR "\r\n", (addr_t)region_base);
  595. CIF_PRINTF(" size=%s\r\n",
  596. cvt_size(region_lo.b.mem_region_size + 9));
  597. } else {
  598. CIF_PRINTF(" mem_region0: absent\r\n");
  599. }
  600. region_lo.d = iinfo->mem_region1_cfg_lo;
  601. if (region_lo.b.exist) {
  602. CIF_PRINTF(" mem_region1: present\r\n");
  603. IINFO_MEM_REGION_CFG_HI_Type region_hi = iinfo->mem_region1_cfg_hi;
  604. region_base = (uint64_t)region_hi << 32 | (region_lo.d & (~0x3FFULL));
  605. if (region_lo.b.mem_region_ena) {
  606. CIF_PRINTF(" status: enable\r\n");
  607. } else {
  608. CIF_PRINTF(" status: disable\r\n");
  609. }
  610. CIF_PRINTF(" base=0x%" CIF_PRIxADDR "\r\n", (addr_t)region_base);
  611. CIF_PRINTF(" size=%s\r\n",
  612. cvt_size(region_lo.b.mem_region_size + 9));
  613. } else {
  614. CIF_PRINTF(" mem_region1: absent\r\n");
  615. }
  616. }
  617. static void show_mcppi_cfg(IINFO_Type *iinfo)
  618. {
  619. IINFO_MCPPI_CFG_LO_Type mcppi_lo;
  620. mcppi_lo.d = iinfo->mcppi_cfg_lo;
  621. if (mcppi_lo.b.exist) {
  622. CIF_PRINTF(" cppi: present\r\n");
  623. IINFO_MCPPI_CFG_HI_Type mcppi_hi = iinfo->mcppi_cfg_hi;
  624. uint64_t mcppi_base =
  625. (uint64_t)mcppi_hi << 32 | (mcppi_lo.d & (~0x3FFULL));
  626. if (mcppi_lo.b.cppi_ena) {
  627. CIF_PRINTF(" status: enable\r\n");
  628. } else {
  629. CIF_PRINTF(" status: disable\r\n");
  630. }
  631. CIF_PRINTF(" base=0x%" CIF_PRIxADDR "\r\n", (addr_t)mcppi_base);
  632. CIF_PRINTF(" size=%s\r\n",
  633. cvt_size(mcppi_lo.b.cppi_size + 9));
  634. } else {
  635. CIF_PRINTF(" cppi: absent\r\n");
  636. }
  637. }
  638. static void show_cmo(IINFO_Type *iinfo)
  639. {
  640. IINFO_MCMO_INFO_Type cmo_info;
  641. cmo_info.d = iinfo->cmo_info;
  642. if (cmo_info.b.cmo_cfg) {
  643. CIF_PRINTF(" cmo: present\r\n");
  644. CIF_PRINTF(" cbozero_size: %u Bytes\r\n",
  645. POW2(cmo_info.b.cbozero_size + 2));
  646. CIF_PRINTF(" cmo_size: %u Bytes\r\n",
  647. POW2(cmo_info.b.cmo_size + 2));
  648. CIF_PRINTF(" cmo_prefetch=%u\r\n",
  649. cmo_info.b.cmo_pft);
  650. } else {
  651. CIF_PRINTF(" cmo: absent\r\n");
  652. }
  653. }
  654. static void show_performance_cfg(IINFO_Type *iinfo)
  655. {
  656. IINFO_PERFORMANCE_CFG0_Type performance_cfg0;
  657. IINFO_PERFORMANCE_CFG1_Type performance_cfg1;
  658. performance_cfg0.d = iinfo->performance_cfg0;
  659. performance_cfg1.d = iinfo->performance_cfg1;
  660. if (performance_cfg0.b.exist || performance_cfg1.b.exist) {
  661. CIF_PRINTF(" hw performance: present\r\n");
  662. if (performance_cfg0.b.exist) {
  663. const char *bus[] = {"ICB", "AXI", "AHBL"};
  664. if (performance_cfg0.b.bus_type < 3) {
  665. CIF_PRINTF(" bus: %s\r\n",
  666. bus[performance_cfg0.b.bus_type]);
  667. }
  668. SHOW_VALUE(performance_cfg0, fpu_cycle);
  669. SHOW_VALUE(performance_cfg0, high_div);
  670. SHOW_VALUE(performance_cfg0, dcache_2stage);
  671. SHOW_VALUE(performance_cfg0, delay_branch_flush);
  672. SHOW_VALUE(performance_cfg0, dual_issue);
  673. SHOW_VALUE(performance_cfg0, cross_4k);
  674. SHOW_VALUE(performance_cfg0, dlm_2stage);
  675. SHOW_VALUE(performance_cfg0, lsu_cut_fwd);
  676. SHOW_VALUE(performance_cfg0, dsp_cycle);
  677. SHOW_VALUE(performance_cfg0, ifu_cut_timing);
  678. SHOW_VALUE(performance_cfg0, mem_cut_timing);
  679. SHOW_VALUE(performance_cfg0, dcache_prefetch);
  680. SHOW_VALUE(performance_cfg0, dcache_lbuf_num);
  681. SHOW_VALUE(performance_cfg0, mul_cyc);
  682. }
  683. if (performance_cfg1.b.exist) {
  684. SHOW_VALUE(performance_cfg1, vfpu_cyc);
  685. SHOW_VALUE(performance_cfg1, bht_entry_width);
  686. SHOW_VALUE(performance_cfg1, high_performance);
  687. SHOW_VALUE(performance_cfg1, agu_quick_forward);
  688. SHOW_VALUE(performance_cfg1, cau_fwd);
  689. SHOW_VALUE(performance_cfg1, hpm_ver);
  690. }
  691. } else {
  692. CIF_PRINTF(" hw performance: absent\r\n");
  693. }
  694. }
  695. static void show_misc_cfg(IINFO_Type *iinfo)
  696. {
  697. IINFO_MERGEL1DCTRL_Type mergel1dctrl;
  698. IINFO_ACCESS_CTRL_Type access_ctrl;
  699. mergel1dctrl.d = iinfo->mergel1dctrl;
  700. access_ctrl.d = iinfo->access_ctrl;
  701. CIF_PRINTF(" misc: \r\n");
  702. SHOW_VALUE(mergel1dctrl, ws_tmout_max);
  703. SHOW_VALUE(mergel1dctrl, nc_tmout_max);
  704. SHOW_VALUE(mergel1dctrl, dev_store_early_ret);
  705. SHOW_VALUE(access_ctrl, pf_access);
  706. SHOW_VALUE(access_ctrl, cache_csr_access);
  707. SHOW_VALUE(access_ctrl, pma_csr_access);
  708. }
  709. static char *cvt_size_opt(uint32_t size, int lite)
  710. {
  711. static char buf[32];
  712. char units[] = {'B', 'K', 'M', 'G'};
  713. int i = 0;
  714. while (size >= 1024 && i < 3) {
  715. size >>= 10;
  716. i++;
  717. }
  718. if (lite) {
  719. sprintf(buf, "%u%c", size, units[i]);
  720. } else {
  721. sprintf(buf, "%u %c%s", size, units[i], i > 0 ? "B" : "");
  722. }
  723. return buf;
  724. }
  725. static void show_cache_info(uint32_t set, uint32_t way, uint32_t lsize,
  726. uint32_t ecc)
  727. {
  728. CIF_PRINTF(" %s", cvt_size(set * way * lsize));
  729. CIF_PRINTF("(set=%d,", set);
  730. CIF_PRINTF("way=%d,", way);
  731. CIF_PRINTF("lsize=%d,", lsize);
  732. CIF_PRINTF("ecc=%d)\r\n", !!ecc);
  733. }