cas.c 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264
  1. /*-
  2. * Copyright (c) 2019 Leandro Lupori
  3. *
  4. * Redistribution and use in source and binary forms, with or without
  5. * modification, are permitted provided that the following conditions
  6. * are met:
  7. * 1. Redistributions of source code must retain the above copyright
  8. * notice, this list of conditions and the following disclaimer.
  9. * 2. Redistributions in binary form must reproduce the above copyright
  10. * notice, this list of conditions and the following disclaimer in the
  11. * documentation and/or other materials provided with the distribution.
  12. *
  13. * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
  14. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  15. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  16. * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  17. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  18. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  19. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  20. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  21. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  22. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  23. * SUCH DAMAGE.
  24. */
  25. #include <openfirm.h>
  26. #include <stand.h>
  27. #include <sys/endian.h>
  28. /* #define CAS_DEBUG */
  29. #ifdef CAS_DEBUG
  30. #define DPRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__)
  31. #else
  32. #define DPRINTF(fmt, ...) do { ; } while (0)
  33. #endif
  34. /* PVR */
  35. #define PVR_CPU_P8E 0x004b0000
  36. #define PVR_CPU_P8NVL 0x004c0000
  37. #define PVR_CPU_P8 0x004d0000
  38. #define PVR_CPU_P9 0x004e0000
  39. #define PVR_CPU_MASK 0xffff0000
  40. #define PVR_ISA_207 0x0f000004
  41. #define PVR_ISA_300 0x0f000005
  42. #define PVR_ISA_MASK 0xffffffff
  43. /* loader version of kernel's CPU_MAXSIZE */
  44. #define MAX_CPUS ((uint32_t)256u)
  45. /* Option Vectors' settings */
  46. /* length of ignored OV */
  47. #define OV_IGN_LEN 0
  48. /* byte 1 (of any OV) */
  49. #define OV_IGN 0x80
  50. /* Option Vector 5 */
  51. /* byte 2 */
  52. #define OV5_LPAR 0x80
  53. #define OV5_SPLPAR 0x40
  54. #define OV5_DRMEM 0x20
  55. #define OV5_LP 0x10
  56. #define OV5_ALPHA_PART 0x08
  57. #define OV5_DMA_DELAY 0x04
  58. #define OV5_DONATE_CPU 0x02
  59. #define OV5_MSI 0x01
  60. /* 9-12: max cpus */
  61. #define OV5_MAX_CPUS(n) ((MAX_CPUS >> (3*8 - (n)*8)) & 0xff)
  62. /* 13-14: LoPAPR Level */
  63. #define LOPAPR_LEVEL 0x0101 /* 1.1 */
  64. #define OV5_LOPAPR_LEVEL(n) ((LOPAPR_LEVEL >> (8 - (n)*8)) & 0xff)
  65. /* byte 17: Platform Facilities */
  66. #define OV5_RNG 0x80
  67. #define OV5_COMP_ENG 0x40
  68. #define OV5_ENC_ENG 0x20
  69. /* byte 21: Sub-Processors */
  70. #define OV5_NO_SUBPROCS 0
  71. #define OV5_SUBPROCS 1
  72. /* byte 23: interrupt controller */
  73. #define OV5_INTC_XICS 0
  74. /* byte 24: MMU */
  75. #define OV5_MMU_INDEX 24
  76. #define OV5_MMU_HPT 0
  77. #define OV5_MMU_RADIX 0x40
  78. #define OV5_MMU_EITHER 0x80
  79. #define OV5_MMU_DYNAMIC 0xc0
  80. /* byte 25: HPT MMU Extensions */
  81. #define OV5_HPT_EXT_INDEX 25
  82. #define OV5_HPT_GTSE 0x40
  83. /* byte 26: Radix MMU Extensions */
  84. #define OV5_RADIX_EXT_INDEX 26
  85. #define OV5_RADIX_GTSE 0x40
  86. struct pvr {
  87. uint32_t mask;
  88. uint32_t val;
  89. };
  90. struct opt_vec_ignore {
  91. char data[2];
  92. } __packed;
  93. struct opt_vec4 {
  94. char data[3];
  95. } __packed;
  96. struct opt_vec5 {
  97. char data[27];
  98. } __packed;
  99. static struct ibm_arch_vec {
  100. struct pvr pvr_list[7];
  101. uint8_t num_opts;
  102. struct opt_vec_ignore vec1;
  103. struct opt_vec_ignore vec2;
  104. struct opt_vec_ignore vec3;
  105. struct opt_vec4 vec4;
  106. struct opt_vec5 vec5;
  107. } __packed ibm_arch_vec = {
  108. /* pvr_list */ {
  109. { htobe32(PVR_CPU_MASK), htobe32(PVR_CPU_P8) },
  110. { htobe32(PVR_CPU_MASK), htobe32(PVR_CPU_P8E) },
  111. { htobe32(PVR_CPU_MASK), htobe32(PVR_CPU_P8NVL) },
  112. { htobe32(PVR_CPU_MASK), htobe32(PVR_CPU_P9) },
  113. { htobe32(PVR_ISA_MASK), htobe32(PVR_ISA_207) },
  114. { htobe32(PVR_ISA_MASK), htobe32(PVR_ISA_300) },
  115. { 0, 0xffffffffu } /* terminator */
  116. },
  117. 4, /* num_opts (4 actually means 5 option vectors) */
  118. { OV_IGN_LEN, OV_IGN }, /* OV1 */
  119. { OV_IGN_LEN, OV_IGN }, /* OV2 */
  120. { OV_IGN_LEN, OV_IGN }, /* OV3 */
  121. /* OV4 (can't be ignored) */ {
  122. sizeof(struct opt_vec4) - 2, /* length (n-2) */
  123. 0,
  124. 10 /* Minimum VP entitled capacity percentage * 100
  125. * (if absent assume 10%) */
  126. },
  127. /* OV5 */ {
  128. sizeof(struct opt_vec5) - 2, /* length (n-2) */
  129. 0, /* don't ignore */
  130. OV5_LPAR | OV5_SPLPAR | OV5_LP | OV5_MSI,
  131. 0,
  132. 0, /* Cooperative Memory Over-commitment */
  133. 0, /* Associativity Information Option */
  134. 0, /* Binary Option Controls */
  135. 0, /* Reserved */
  136. 0, /* Reserved */
  137. OV5_MAX_CPUS(0),
  138. OV5_MAX_CPUS(1), /* 10 */
  139. OV5_MAX_CPUS(2),
  140. OV5_MAX_CPUS(3),
  141. OV5_LOPAPR_LEVEL(0),
  142. OV5_LOPAPR_LEVEL(1),
  143. 0, /* Reserved */
  144. 0, /* Reserved */
  145. 0, /* Platform Facilities */
  146. 0, /* Reserved */
  147. 0, /* Reserved */
  148. 0, /* Reserved */ /* 20 */
  149. OV5_NO_SUBPROCS,
  150. 0, /* DRMEM_V2 */
  151. OV5_INTC_XICS,
  152. OV5_MMU_HPT,
  153. 0,
  154. 0
  155. }
  156. };
  157. int
  158. ppc64_cas(void)
  159. {
  160. phandle_t pkg;
  161. ihandle_t inst;
  162. cell_t err;
  163. uint8_t buf[16], idx, val;
  164. int i, len, rc, radix_mmu;
  165. const char *var;
  166. char *ov5;
  167. pkg = OF_finddevice("/chosen");
  168. if (pkg == -1) {
  169. printf("cas: couldn't find /chosen\n");
  170. return (-1);
  171. }
  172. len = OF_getprop(pkg, "ibm,arch-vec-5-platform-support", buf,
  173. sizeof(buf));
  174. if (len == -1)
  175. /* CAS not supported */
  176. return (0);
  177. radix_mmu = 0;
  178. ov5 = ibm_arch_vec.vec5.data;
  179. for (i = 0; i < len; i += 2) {
  180. idx = buf[i];
  181. val = buf[i + 1];
  182. DPRINTF("idx 0x%02x val 0x%02x\n", idx, val);
  183. switch (idx) {
  184. case OV5_MMU_INDEX:
  185. /*
  186. * Note that testing for OV5_MMU_RADIX/OV5_MMU_EITHER
  187. * also covers OV5_MMU_DYNAMIC.
  188. */
  189. if ((val & OV5_MMU_RADIX) || (val & OV5_MMU_EITHER))
  190. radix_mmu = 1;
  191. break;
  192. case OV5_RADIX_EXT_INDEX:
  193. if (val & OV5_RADIX_GTSE)
  194. ov5[idx] = OV5_RADIX_GTSE;
  195. break;
  196. case OV5_HPT_EXT_INDEX:
  197. default:
  198. break;
  199. }
  200. }
  201. if (!radix_mmu)
  202. /*
  203. * If radix is not supported, set radix_mmu to 0 to avoid
  204. * the kernel trying to use it and panic.
  205. */
  206. setenv("radix_mmu", "0", 1);
  207. else if ((var = getenv("radix_mmu")) != NULL && var[0] == '0')
  208. radix_mmu = 0;
  209. else
  210. ov5[OV5_MMU_INDEX] = OV5_MMU_RADIX;
  211. inst = OF_open("/");
  212. if (inst == -1) {
  213. printf("cas: failed to open / node\n");
  214. return (-1);
  215. }
  216. DPRINTF("MMU 0x%02x RADIX_EXT 0x%02x\n",
  217. ov5[OV5_MMU_INDEX], ov5[OV5_RADIX_EXT_INDEX]);
  218. rc = OF_call_method("ibm,client-architecture-support",
  219. inst, 1, 1, &ibm_arch_vec, &err);
  220. if (rc != 0 || err) {
  221. printf("cas: CAS method returned an error: rc %d err %jd\n",
  222. rc, (intmax_t)err);
  223. rc = -1;
  224. }
  225. OF_close(inst);
  226. printf("cas: selected %s MMU\n", radix_mmu ? "radix" : "hash");
  227. return (rc);
  228. }