vof.c 28 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060
  1. /*
  2. * QEMU PowerPC Virtual Open Firmware.
  3. *
  4. * This implements client interface from OpenFirmware IEEE1275 on the QEMU
  5. * side to leave only a very basic firmware in the VM.
  6. *
  7. * Copyright (c) 2021 IBM Corporation.
  8. *
  9. * SPDX-License-Identifier: GPL-2.0-or-later
  10. */
  11. #include "qemu/osdep.h"
  12. #include "qemu/timer.h"
  13. #include "qemu/range.h"
  14. #include "qemu/units.h"
  15. #include "qemu/log.h"
  16. #include "qapi/error.h"
  17. #include "exec/address-spaces.h"
  18. #include "hw/ppc/vof.h"
  19. #include "hw/ppc/fdt.h"
  20. #include "sysemu/runstate.h"
  21. #include "qom/qom-qobject.h"
  22. #include "trace.h"
  23. #include <libfdt.h>
  24. /*
  25. * OF 1275 "nextprop" description suggests is it 32 bytes max but
  26. * LoPAPR defines "ibm,query-interrupt-source-number" which is 33 chars long.
  27. */
  28. #define OF_PROPNAME_LEN_MAX 64
  29. #define VOF_MAX_PATH 256
  30. #define VOF_MAX_SETPROPLEN 2048
  31. #define VOF_MAX_METHODLEN 256
  32. #define VOF_MAX_FORTHCODE 256
  33. #define VOF_VTY_BUF_SIZE 256
  34. typedef struct {
  35. uint64_t start;
  36. uint64_t size;
  37. } OfClaimed;
  38. typedef struct {
  39. char *path; /* the path used to open the instance */
  40. uint32_t phandle;
  41. } OfInstance;
  42. static int readstr(hwaddr pa, char *buf, int size)
  43. {
  44. if (VOF_MEM_READ(pa, buf, size) != MEMTX_OK) {
  45. return -1;
  46. }
  47. if (strnlen(buf, size) == size) {
  48. buf[size - 1] = '\0';
  49. trace_vof_error_str_truncated(buf, size);
  50. return -1;
  51. }
  52. return 0;
  53. }
  54. static bool cmpservice(const char *s, unsigned nargs, unsigned nret,
  55. const char *s1, unsigned nargscheck, unsigned nretcheck)
  56. {
  57. if (strcmp(s, s1)) {
  58. return false;
  59. }
  60. if ((nargscheck && (nargs != nargscheck)) ||
  61. (nretcheck && (nret != nretcheck))) {
  62. trace_vof_error_param(s, nargscheck, nretcheck, nargs, nret);
  63. return false;
  64. }
  65. return true;
  66. }
  67. static void prop_format(char *tval, int tlen, const void *prop, int len)
  68. {
  69. int i;
  70. const unsigned char *c;
  71. char *t;
  72. const char bin[] = "...";
  73. for (i = 0, c = prop; i < len; ++i, ++c) {
  74. if (*c == '\0' && i == len - 1) {
  75. strncpy(tval, prop, tlen - 1);
  76. return;
  77. }
  78. if (*c < 0x20 || *c >= 0x80) {
  79. break;
  80. }
  81. }
  82. for (i = 0, c = prop, t = tval; i < len; ++i, ++c) {
  83. if (t >= tval + tlen - sizeof(bin) - 1 - 2 - 1) {
  84. strcpy(t, bin);
  85. return;
  86. }
  87. if (i && i % 4 == 0 && i != len - 1) {
  88. strcat(t, " ");
  89. ++t;
  90. }
  91. t += sprintf(t, "%02X", *c & 0xFF);
  92. }
  93. }
  94. static int get_path(const void *fdt, int offset, char *buf, int len)
  95. {
  96. int ret;
  97. ret = fdt_get_path(fdt, offset, buf, len - 1);
  98. if (ret < 0) {
  99. return ret;
  100. }
  101. buf[len - 1] = '\0';
  102. return strlen(buf) + 1;
  103. }
  104. static int phandle_to_path(const void *fdt, uint32_t ph, char *buf, int len)
  105. {
  106. int ret;
  107. ret = fdt_node_offset_by_phandle(fdt, ph);
  108. if (ret < 0) {
  109. return ret;
  110. }
  111. return get_path(fdt, ret, buf, len);
  112. }
  113. static int path_offset(const void *fdt, const char *path)
  114. {
  115. g_autofree char *p = NULL;
  116. char *at;
  117. /*
  118. * https://www.devicetree.org/open-firmware/bindings/ppc/release/ppc-2_1.html#HDR16
  119. *
  120. * "Conversion from numeric representation to text representation shall use
  121. * the lower case forms of the hexadecimal digits in the range a..f,
  122. * suppressing leading zeros".
  123. */
  124. p = g_strdup(path);
  125. for (at = strchr(p, '@'); at && *at; ) {
  126. if (*at == '/') {
  127. at = strchr(at, '@');
  128. } else {
  129. *at = tolower(*at);
  130. ++at;
  131. }
  132. }
  133. return fdt_path_offset(fdt, p);
  134. }
  135. static uint32_t vof_finddevice(const void *fdt, uint32_t nodeaddr)
  136. {
  137. char fullnode[VOF_MAX_PATH];
  138. uint32_t ret = PROM_ERROR;
  139. int offset;
  140. if (readstr(nodeaddr, fullnode, sizeof(fullnode))) {
  141. return (uint32_t) ret;
  142. }
  143. offset = path_offset(fdt, fullnode);
  144. if (offset >= 0) {
  145. ret = fdt_get_phandle(fdt, offset);
  146. }
  147. trace_vof_finddevice(fullnode, ret);
  148. return ret;
  149. }
  150. static const void *getprop(const void *fdt, int nodeoff, const char *propname,
  151. int *proplen, bool *write0)
  152. {
  153. const char *unit, *prop;
  154. const void *ret = fdt_getprop(fdt, nodeoff, propname, proplen);
  155. if (ret) {
  156. if (write0) {
  157. *write0 = false;
  158. }
  159. return ret;
  160. }
  161. if (strcmp(propname, "name")) {
  162. return NULL;
  163. }
  164. /*
  165. * We return a value for "name" from path if queried but property does not
  166. * exist. @proplen does not include the unit part in this case.
  167. */
  168. prop = fdt_get_name(fdt, nodeoff, proplen);
  169. if (!prop) {
  170. *proplen = 0;
  171. return NULL;
  172. }
  173. unit = memchr(prop, '@', *proplen);
  174. if (unit) {
  175. *proplen = unit - prop;
  176. }
  177. *proplen += 1;
  178. /*
  179. * Since it might be cut at "@" and there will be no trailing zero
  180. * in the prop buffer, tell the caller to write zero at the end.
  181. */
  182. if (write0) {
  183. *write0 = true;
  184. }
  185. return prop;
  186. }
  187. static uint32_t vof_getprop(const void *fdt, uint32_t nodeph, uint32_t pname,
  188. uint32_t valaddr, uint32_t vallen)
  189. {
  190. char propname[OF_PROPNAME_LEN_MAX + 1];
  191. uint32_t ret = 0;
  192. int proplen = 0;
  193. const void *prop;
  194. char trval[64] = "";
  195. int nodeoff = fdt_node_offset_by_phandle(fdt, nodeph);
  196. bool write0;
  197. if (nodeoff < 0) {
  198. return PROM_ERROR;
  199. }
  200. if (readstr(pname, propname, sizeof(propname))) {
  201. return PROM_ERROR;
  202. }
  203. prop = getprop(fdt, nodeoff, propname, &proplen, &write0);
  204. if (prop) {
  205. const char zero = 0;
  206. int cb = MIN(proplen, vallen);
  207. if (VOF_MEM_WRITE(valaddr, prop, cb) != MEMTX_OK ||
  208. /* if that was "name" with a unit address, overwrite '@' with '0' */
  209. (write0 &&
  210. cb == proplen &&
  211. VOF_MEM_WRITE(valaddr + cb - 1, &zero, 1) != MEMTX_OK)) {
  212. ret = PROM_ERROR;
  213. } else {
  214. /*
  215. * OF1275 says:
  216. * "Size is either the actual size of the property, or -1 if name
  217. * does not exist", hence returning proplen instead of cb.
  218. */
  219. ret = proplen;
  220. /* Do not format a value if tracepoint is silent, for performance */
  221. if (trace_event_get_state(TRACE_VOF_GETPROP) &&
  222. qemu_loglevel_mask(LOG_TRACE)) {
  223. prop_format(trval, sizeof(trval), prop, ret);
  224. }
  225. }
  226. } else {
  227. ret = PROM_ERROR;
  228. }
  229. trace_vof_getprop(nodeph, propname, ret, trval);
  230. return ret;
  231. }
  232. static uint32_t vof_getproplen(const void *fdt, uint32_t nodeph, uint32_t pname)
  233. {
  234. char propname[OF_PROPNAME_LEN_MAX + 1];
  235. uint32_t ret = 0;
  236. int proplen = 0;
  237. const void *prop;
  238. int nodeoff = fdt_node_offset_by_phandle(fdt, nodeph);
  239. if (nodeoff < 0) {
  240. return PROM_ERROR;
  241. }
  242. if (readstr(pname, propname, sizeof(propname))) {
  243. return PROM_ERROR;
  244. }
  245. prop = getprop(fdt, nodeoff, propname, &proplen, NULL);
  246. if (prop) {
  247. ret = proplen;
  248. } else {
  249. ret = PROM_ERROR;
  250. }
  251. trace_vof_getproplen(nodeph, propname, ret);
  252. return ret;
  253. }
  254. static uint32_t vof_setprop(MachineState *ms, void *fdt, Vof *vof,
  255. uint32_t nodeph, uint32_t pname,
  256. uint32_t valaddr, uint32_t vallen)
  257. {
  258. char propname[OF_PROPNAME_LEN_MAX + 1];
  259. uint32_t ret = PROM_ERROR;
  260. int offset, rc;
  261. char trval[64] = "";
  262. char nodepath[VOF_MAX_PATH] = "";
  263. Object *vmo = object_dynamic_cast(OBJECT(ms), TYPE_VOF_MACHINE_IF);
  264. VofMachineIfClass *vmc;
  265. g_autofree char *val = NULL;
  266. if (vallen > VOF_MAX_SETPROPLEN) {
  267. goto trace_exit;
  268. }
  269. if (readstr(pname, propname, sizeof(propname))) {
  270. goto trace_exit;
  271. }
  272. offset = fdt_node_offset_by_phandle(fdt, nodeph);
  273. if (offset < 0) {
  274. goto trace_exit;
  275. }
  276. rc = get_path(fdt, offset, nodepath, sizeof(nodepath));
  277. if (rc <= 0) {
  278. goto trace_exit;
  279. }
  280. val = g_malloc0(vallen);
  281. if (VOF_MEM_READ(valaddr, val, vallen) != MEMTX_OK) {
  282. goto trace_exit;
  283. }
  284. if (!vmo) {
  285. goto trace_exit;
  286. }
  287. vmc = VOF_MACHINE_GET_CLASS(vmo);
  288. if (!vmc->setprop || !vmc->setprop(ms, nodepath, propname, val, vallen)) {
  289. goto trace_exit;
  290. }
  291. rc = fdt_setprop(fdt, offset, propname, val, vallen);
  292. if (rc) {
  293. goto trace_exit;
  294. }
  295. if (trace_event_get_state(TRACE_VOF_SETPROP) &&
  296. qemu_loglevel_mask(LOG_TRACE)) {
  297. prop_format(trval, sizeof(trval), val, vallen);
  298. }
  299. ret = vallen;
  300. trace_exit:
  301. trace_vof_setprop(nodeph, propname, trval, vallen, ret);
  302. return ret;
  303. }
  304. static uint32_t vof_nextprop(const void *fdt, uint32_t phandle,
  305. uint32_t prevaddr, uint32_t nameaddr)
  306. {
  307. int offset, nodeoff = fdt_node_offset_by_phandle(fdt, phandle);
  308. char prev[OF_PROPNAME_LEN_MAX + 1];
  309. const char *tmp;
  310. if (readstr(prevaddr, prev, sizeof(prev))) {
  311. return PROM_ERROR;
  312. }
  313. fdt_for_each_property_offset(offset, fdt, nodeoff) {
  314. if (!fdt_getprop_by_offset(fdt, offset, &tmp, NULL)) {
  315. return 0;
  316. }
  317. if (prev[0] == '\0' || strcmp(prev, tmp) == 0) {
  318. if (prev[0] != '\0') {
  319. offset = fdt_next_property_offset(fdt, offset);
  320. if (offset < 0) {
  321. return 0;
  322. }
  323. }
  324. if (!fdt_getprop_by_offset(fdt, offset, &tmp, NULL)) {
  325. return 0;
  326. }
  327. if (VOF_MEM_WRITE(nameaddr, tmp, strlen(tmp) + 1) != MEMTX_OK) {
  328. return PROM_ERROR;
  329. }
  330. return 1;
  331. }
  332. }
  333. return 0;
  334. }
  335. static uint32_t vof_peer(const void *fdt, uint32_t phandle)
  336. {
  337. uint32_t ret = 0;
  338. int rc;
  339. if (phandle == 0) {
  340. rc = fdt_path_offset(fdt, "/");
  341. } else {
  342. rc = fdt_next_subnode(fdt, fdt_node_offset_by_phandle(fdt, phandle));
  343. }
  344. if (rc >= 0) {
  345. ret = fdt_get_phandle(fdt, rc);
  346. }
  347. return ret;
  348. }
  349. static uint32_t vof_child(const void *fdt, uint32_t phandle)
  350. {
  351. uint32_t ret = 0;
  352. int rc = fdt_first_subnode(fdt, fdt_node_offset_by_phandle(fdt, phandle));
  353. if (rc >= 0) {
  354. ret = fdt_get_phandle(fdt, rc);
  355. }
  356. return ret;
  357. }
  358. static uint32_t vof_parent(const void *fdt, uint32_t phandle)
  359. {
  360. uint32_t ret = 0;
  361. int rc = fdt_parent_offset(fdt, fdt_node_offset_by_phandle(fdt, phandle));
  362. if (rc >= 0) {
  363. ret = fdt_get_phandle(fdt, rc);
  364. }
  365. return ret;
  366. }
  367. static uint32_t vof_do_open(void *fdt, Vof *vof, int offset, const char *path)
  368. {
  369. uint32_t ret = PROM_ERROR;
  370. OfInstance *inst = NULL;
  371. if (vof->of_instance_last == 0xFFFFFFFF) {
  372. /* We do not recycle ihandles yet */
  373. goto trace_exit;
  374. }
  375. inst = g_new0(OfInstance, 1);
  376. inst->phandle = fdt_get_phandle(fdt, offset);
  377. g_assert(inst->phandle);
  378. ++vof->of_instance_last;
  379. inst->path = g_strdup(path);
  380. g_hash_table_insert(vof->of_instances,
  381. GINT_TO_POINTER(vof->of_instance_last),
  382. inst);
  383. ret = vof->of_instance_last;
  384. trace_exit:
  385. trace_vof_open(path, inst ? inst->phandle : 0, ret);
  386. return ret;
  387. }
  388. uint32_t vof_client_open_store(void *fdt, Vof *vof, const char *nodename,
  389. const char *prop, const char *path)
  390. {
  391. int offset, node = fdt_path_offset(fdt, nodename);
  392. uint32_t inst;
  393. offset = fdt_path_offset(fdt, path);
  394. if (offset < 0) {
  395. trace_vof_error_unknown_path(path);
  396. return PROM_ERROR;
  397. }
  398. inst = vof_do_open(fdt, vof, offset, path);
  399. return fdt_setprop_cell(fdt, node, prop, inst) >= 0 ? 0 : PROM_ERROR;
  400. }
  401. static uint32_t vof_open(void *fdt, Vof *vof, uint32_t pathaddr)
  402. {
  403. char path[VOF_MAX_PATH];
  404. int offset;
  405. if (readstr(pathaddr, path, sizeof(path))) {
  406. return PROM_ERROR;
  407. }
  408. offset = path_offset(fdt, path);
  409. if (offset < 0) {
  410. trace_vof_error_unknown_path(path);
  411. return PROM_ERROR;
  412. }
  413. return vof_do_open(fdt, vof, offset, path);
  414. }
  415. static void vof_close(Vof *vof, uint32_t ihandle)
  416. {
  417. if (!g_hash_table_remove(vof->of_instances, GINT_TO_POINTER(ihandle))) {
  418. trace_vof_error_unknown_ihandle_close(ihandle);
  419. }
  420. }
  421. static uint32_t vof_instance_to_package(Vof *vof, uint32_t ihandle)
  422. {
  423. gpointer instp = g_hash_table_lookup(vof->of_instances,
  424. GINT_TO_POINTER(ihandle));
  425. uint32_t ret = PROM_ERROR;
  426. if (instp) {
  427. ret = ((OfInstance *)instp)->phandle;
  428. }
  429. trace_vof_instance_to_package(ihandle, ret);
  430. return ret;
  431. }
  432. static uint32_t vof_package_to_path(const void *fdt, uint32_t phandle,
  433. uint32_t buf, uint32_t len)
  434. {
  435. int rc;
  436. char tmp[VOF_MAX_PATH] = "";
  437. rc = phandle_to_path(fdt, phandle, tmp, sizeof(tmp));
  438. if (rc > 0) {
  439. if (VOF_MEM_WRITE(buf, tmp, rc) != MEMTX_OK) {
  440. rc = -1;
  441. }
  442. }
  443. trace_vof_package_to_path(phandle, tmp, rc);
  444. return rc > 0 ? (uint32_t)rc : PROM_ERROR;
  445. }
  446. static uint32_t vof_instance_to_path(void *fdt, Vof *vof, uint32_t ihandle,
  447. uint32_t buf, uint32_t len)
  448. {
  449. int rc = -1;
  450. uint32_t phandle = vof_instance_to_package(vof, ihandle);
  451. char tmp[VOF_MAX_PATH] = "";
  452. if (phandle != -1) {
  453. rc = phandle_to_path(fdt, phandle, tmp, sizeof(tmp));
  454. if (rc > 0) {
  455. if (VOF_MEM_WRITE(buf, tmp, rc) != MEMTX_OK) {
  456. rc = -1;
  457. }
  458. }
  459. }
  460. trace_vof_instance_to_path(ihandle, phandle, tmp, rc);
  461. return rc > 0 ? (uint32_t)rc : PROM_ERROR;
  462. }
  463. static uint32_t vof_write(Vof *vof, uint32_t ihandle, uint32_t buf,
  464. uint32_t len)
  465. {
  466. char tmp[VOF_VTY_BUF_SIZE];
  467. unsigned cb;
  468. OfInstance *inst = (OfInstance *)
  469. g_hash_table_lookup(vof->of_instances, GINT_TO_POINTER(ihandle));
  470. if (!inst) {
  471. trace_vof_error_write(ihandle);
  472. return PROM_ERROR;
  473. }
  474. for ( ; len > 0; len -= cb) {
  475. cb = MIN(len, sizeof(tmp) - 1);
  476. if (VOF_MEM_READ(buf, tmp, cb) != MEMTX_OK) {
  477. return PROM_ERROR;
  478. }
  479. /* FIXME: there is no backend(s) yet so just call a trace */
  480. if (trace_event_get_state(TRACE_VOF_WRITE) &&
  481. qemu_loglevel_mask(LOG_TRACE)) {
  482. tmp[cb] = '\0';
  483. trace_vof_write(ihandle, cb, tmp);
  484. }
  485. }
  486. return len;
  487. }
  488. static void vof_claimed_dump(GArray *claimed)
  489. {
  490. int i;
  491. OfClaimed c;
  492. if (trace_event_get_state(TRACE_VOF_CLAIMED) &&
  493. qemu_loglevel_mask(LOG_TRACE)) {
  494. for (i = 0; i < claimed->len; ++i) {
  495. c = g_array_index(claimed, OfClaimed, i);
  496. trace_vof_claimed(c.start, c.start + c.size, c.size);
  497. }
  498. }
  499. }
  500. static bool vof_claim_avail(GArray *claimed, uint64_t virt, uint64_t size)
  501. {
  502. int i;
  503. OfClaimed c;
  504. for (i = 0; i < claimed->len; ++i) {
  505. c = g_array_index(claimed, OfClaimed, i);
  506. if (ranges_overlap(c.start, c.size, virt, size)) {
  507. return false;
  508. }
  509. }
  510. return true;
  511. }
  512. static void vof_claim_add(GArray *claimed, uint64_t virt, uint64_t size)
  513. {
  514. OfClaimed newclaim;
  515. newclaim.start = virt;
  516. newclaim.size = size;
  517. g_array_append_val(claimed, newclaim);
  518. }
  519. static gint of_claimed_compare_func(gconstpointer a, gconstpointer b)
  520. {
  521. return ((OfClaimed *)a)->start - ((OfClaimed *)b)->start;
  522. }
  523. static void vof_dt_memory_available(void *fdt, GArray *claimed, uint64_t base)
  524. {
  525. int i, n, offset, proplen = 0, sc, ac;
  526. target_ulong mem0_end;
  527. const uint8_t *mem0_reg;
  528. g_autofree uint8_t *avail = NULL;
  529. uint8_t *availcur;
  530. if (!fdt || !claimed) {
  531. return;
  532. }
  533. offset = fdt_path_offset(fdt, "/");
  534. _FDT(offset);
  535. ac = fdt_address_cells(fdt, offset);
  536. g_assert(ac == 1 || ac == 2);
  537. sc = fdt_size_cells(fdt, offset);
  538. g_assert(sc == 1 || sc == 2);
  539. offset = fdt_path_offset(fdt, "/memory@0");
  540. _FDT(offset);
  541. mem0_reg = fdt_getprop(fdt, offset, "reg", &proplen);
  542. g_assert(mem0_reg && proplen == sizeof(uint32_t) * (ac + sc));
  543. if (sc == 2) {
  544. mem0_end = be64_to_cpu(*(uint64_t *)(mem0_reg + sizeof(uint32_t) * ac));
  545. } else {
  546. mem0_end = be32_to_cpu(*(uint32_t *)(mem0_reg + sizeof(uint32_t) * ac));
  547. }
  548. g_array_sort(claimed, of_claimed_compare_func);
  549. vof_claimed_dump(claimed);
  550. /*
  551. * VOF resides in the first page so we do not need to check if there is
  552. * available memory before the first claimed block
  553. */
  554. g_assert(claimed->len && (g_array_index(claimed, OfClaimed, 0).start == 0));
  555. avail = g_malloc0(sizeof(uint32_t) * (ac + sc) * claimed->len);
  556. for (i = 0, n = 0, availcur = avail; i < claimed->len; ++i) {
  557. OfClaimed c = g_array_index(claimed, OfClaimed, i);
  558. uint64_t start, size;
  559. start = c.start + c.size;
  560. if (i < claimed->len - 1) {
  561. OfClaimed cn = g_array_index(claimed, OfClaimed, i + 1);
  562. size = cn.start - start;
  563. } else {
  564. size = mem0_end - start;
  565. }
  566. if (ac == 2) {
  567. *(uint64_t *) availcur = cpu_to_be64(start);
  568. } else {
  569. *(uint32_t *) availcur = cpu_to_be32(start);
  570. }
  571. availcur += sizeof(uint32_t) * ac;
  572. if (sc == 2) {
  573. *(uint64_t *) availcur = cpu_to_be64(size);
  574. } else {
  575. *(uint32_t *) availcur = cpu_to_be32(size);
  576. }
  577. availcur += sizeof(uint32_t) * sc;
  578. if (size) {
  579. trace_vof_avail(c.start + c.size, c.start + c.size + size, size);
  580. ++n;
  581. }
  582. }
  583. _FDT((fdt_setprop(fdt, offset, "available", avail, availcur - avail)));
  584. }
  585. /*
  586. * OF1275:
  587. * "Allocates size bytes of memory. If align is zero, the allocated range
  588. * begins at the virtual address virt. Otherwise, an aligned address is
  589. * automatically chosen and the input argument virt is ignored".
  590. *
  591. * In other words, exactly one of @virt and @align is non-zero.
  592. */
  593. uint64_t vof_claim(Vof *vof, uint64_t virt, uint64_t size,
  594. uint64_t align)
  595. {
  596. uint64_t ret;
  597. if (size == 0) {
  598. ret = -1;
  599. } else if (align == 0) {
  600. if (!vof_claim_avail(vof->claimed, virt, size)) {
  601. ret = -1;
  602. } else {
  603. ret = virt;
  604. }
  605. } else {
  606. vof->claimed_base = QEMU_ALIGN_UP(vof->claimed_base, align);
  607. while (1) {
  608. if (vof->claimed_base >= vof->top_addr) {
  609. error_report("Out of RMA memory for the OF client");
  610. return -1;
  611. }
  612. if (vof_claim_avail(vof->claimed, vof->claimed_base, size)) {
  613. break;
  614. }
  615. vof->claimed_base += size;
  616. }
  617. ret = vof->claimed_base;
  618. }
  619. if (ret != -1) {
  620. vof->claimed_base = MAX(vof->claimed_base, ret + size);
  621. vof_claim_add(vof->claimed, ret, size);
  622. }
  623. trace_vof_claim(virt, size, align, ret);
  624. return ret;
  625. }
  626. static uint32_t vof_release(Vof *vof, uint64_t virt, uint64_t size)
  627. {
  628. uint32_t ret = PROM_ERROR;
  629. int i;
  630. GArray *claimed = vof->claimed;
  631. OfClaimed c;
  632. for (i = 0; i < claimed->len; ++i) {
  633. c = g_array_index(claimed, OfClaimed, i);
  634. if (c.start == virt && c.size == size) {
  635. g_array_remove_index(claimed, i);
  636. ret = 0;
  637. break;
  638. }
  639. }
  640. trace_vof_release(virt, size, ret);
  641. return ret;
  642. }
  643. static void vof_instantiate_rtas(Error **errp)
  644. {
  645. error_setg(errp, "The firmware should have instantiated RTAS");
  646. }
  647. static uint32_t vof_call_method(MachineState *ms, Vof *vof, uint32_t methodaddr,
  648. uint32_t ihandle, uint32_t param1,
  649. uint32_t param2, uint32_t param3,
  650. uint32_t param4, uint32_t *ret2)
  651. {
  652. uint32_t ret = PROM_ERROR;
  653. char method[VOF_MAX_METHODLEN] = "";
  654. OfInstance *inst;
  655. if (!ihandle) {
  656. goto trace_exit;
  657. }
  658. inst = (OfInstance *)g_hash_table_lookup(vof->of_instances,
  659. GINT_TO_POINTER(ihandle));
  660. if (!inst) {
  661. goto trace_exit;
  662. }
  663. if (readstr(methodaddr, method, sizeof(method))) {
  664. goto trace_exit;
  665. }
  666. if (strcmp(inst->path, "/") == 0) {
  667. if (strcmp(method, "ibm,client-architecture-support") == 0) {
  668. Object *vmo = object_dynamic_cast(OBJECT(ms), TYPE_VOF_MACHINE_IF);
  669. if (vmo) {
  670. VofMachineIfClass *vmc = VOF_MACHINE_GET_CLASS(vmo);
  671. g_assert(vmc->client_architecture_support);
  672. ret = (uint32_t)vmc->client_architecture_support(ms, first_cpu,
  673. param1);
  674. }
  675. *ret2 = 0;
  676. }
  677. } else if (strcmp(inst->path, "/rtas") == 0) {
  678. if (strcmp(method, "instantiate-rtas") == 0) {
  679. vof_instantiate_rtas(&error_fatal);
  680. ret = 0;
  681. *ret2 = param1; /* rtas-base */
  682. }
  683. } else {
  684. trace_vof_error_unknown_method(method);
  685. }
  686. trace_exit:
  687. trace_vof_method(ihandle, method, param1, ret, *ret2);
  688. return ret;
  689. }
  690. static uint32_t vof_call_interpret(uint32_t cmdaddr, uint32_t param1,
  691. uint32_t param2, uint32_t *ret2)
  692. {
  693. uint32_t ret = PROM_ERROR;
  694. char cmd[VOF_MAX_FORTHCODE] = "";
  695. /* No interpret implemented so just call a trace */
  696. readstr(cmdaddr, cmd, sizeof(cmd));
  697. trace_vof_interpret(cmd, param1, param2, ret, *ret2);
  698. return ret;
  699. }
  700. static void vof_quiesce(MachineState *ms, void *fdt, Vof *vof)
  701. {
  702. Object *vmo = object_dynamic_cast(OBJECT(ms), TYPE_VOF_MACHINE_IF);
  703. /* After "quiesce", no change is expected to the FDT, pack FDT to ensure */
  704. int rc = fdt_pack(fdt);
  705. assert(rc == 0);
  706. if (vmo) {
  707. VofMachineIfClass *vmc = VOF_MACHINE_GET_CLASS(vmo);
  708. if (vmc->quiesce) {
  709. vmc->quiesce(ms);
  710. }
  711. }
  712. vof_claimed_dump(vof->claimed);
  713. }
  714. static uint32_t vof_client_handle(MachineState *ms, void *fdt, Vof *vof,
  715. const char *service,
  716. uint32_t *args, unsigned nargs,
  717. uint32_t *rets, unsigned nrets)
  718. {
  719. uint32_t ret = 0;
  720. /* @nrets includes the value which this function returns */
  721. #define cmpserv(s, a, r) \
  722. cmpservice(service, nargs, nrets, (s), (a), (r))
  723. if (cmpserv("finddevice", 1, 1)) {
  724. ret = vof_finddevice(fdt, args[0]);
  725. } else if (cmpserv("getprop", 4, 1)) {
  726. ret = vof_getprop(fdt, args[0], args[1], args[2], args[3]);
  727. } else if (cmpserv("getproplen", 2, 1)) {
  728. ret = vof_getproplen(fdt, args[0], args[1]);
  729. } else if (cmpserv("setprop", 4, 1)) {
  730. ret = vof_setprop(ms, fdt, vof, args[0], args[1], args[2], args[3]);
  731. } else if (cmpserv("nextprop", 3, 1)) {
  732. ret = vof_nextprop(fdt, args[0], args[1], args[2]);
  733. } else if (cmpserv("peer", 1, 1)) {
  734. ret = vof_peer(fdt, args[0]);
  735. } else if (cmpserv("child", 1, 1)) {
  736. ret = vof_child(fdt, args[0]);
  737. } else if (cmpserv("parent", 1, 1)) {
  738. ret = vof_parent(fdt, args[0]);
  739. } else if (cmpserv("open", 1, 1)) {
  740. ret = vof_open(fdt, vof, args[0]);
  741. } else if (cmpserv("close", 1, 0)) {
  742. vof_close(vof, args[0]);
  743. } else if (cmpserv("instance-to-package", 1, 1)) {
  744. ret = vof_instance_to_package(vof, args[0]);
  745. } else if (cmpserv("package-to-path", 3, 1)) {
  746. ret = vof_package_to_path(fdt, args[0], args[1], args[2]);
  747. } else if (cmpserv("instance-to-path", 3, 1)) {
  748. ret = vof_instance_to_path(fdt, vof, args[0], args[1], args[2]);
  749. } else if (cmpserv("write", 3, 1)) {
  750. ret = vof_write(vof, args[0], args[1], args[2]);
  751. } else if (cmpserv("claim", 3, 1)) {
  752. uint64_t ret64 = vof_claim(vof, args[0], args[1], args[2]);
  753. if (ret64 < 0x100000000UL) {
  754. vof_dt_memory_available(fdt, vof->claimed, vof->claimed_base);
  755. ret = (uint32_t)ret64;
  756. } else {
  757. if (ret64 != -1) {
  758. vof_release(vof, ret, args[1]);
  759. }
  760. ret = PROM_ERROR;
  761. }
  762. } else if (cmpserv("release", 2, 0)) {
  763. ret = vof_release(vof, args[0], args[1]);
  764. if (ret != PROM_ERROR) {
  765. vof_dt_memory_available(fdt, vof->claimed, vof->claimed_base);
  766. }
  767. } else if (cmpserv("call-method", 0, 0)) {
  768. ret = vof_call_method(ms, vof, args[0], args[1], args[2], args[3],
  769. args[4], args[5], rets);
  770. } else if (cmpserv("interpret", 0, 0)) {
  771. ret = vof_call_interpret(args[0], args[1], args[2], rets);
  772. } else if (cmpserv("milliseconds", 0, 1)) {
  773. ret = qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL);
  774. } else if (cmpserv("quiesce", 0, 0)) {
  775. vof_quiesce(ms, fdt, vof);
  776. } else if (cmpserv("exit", 0, 0)) {
  777. error_report("Stopped as the VM requested \"exit\"");
  778. vm_stop(RUN_STATE_PAUSED);
  779. } else {
  780. trace_vof_error_unknown_service(service, nargs, nrets);
  781. ret = -1;
  782. }
  783. #undef cmpserv
  784. return ret;
  785. }
  786. /* Defined as Big Endian */
  787. struct prom_args {
  788. uint32_t service;
  789. uint32_t nargs;
  790. uint32_t nret;
  791. uint32_t args[10];
  792. } QEMU_PACKED;
  793. int vof_client_call(MachineState *ms, Vof *vof, void *fdt,
  794. target_ulong args_real)
  795. {
  796. struct prom_args args_be;
  797. uint32_t args[ARRAY_SIZE(args_be.args)];
  798. uint32_t rets[ARRAY_SIZE(args_be.args)] = { 0 }, ret;
  799. char service[64];
  800. unsigned nargs, nret, i;
  801. if (VOF_MEM_READ(args_real, &args_be, sizeof(args_be)) != MEMTX_OK) {
  802. return -EINVAL;
  803. }
  804. nargs = be32_to_cpu(args_be.nargs);
  805. if (nargs >= ARRAY_SIZE(args_be.args)) {
  806. return -EINVAL;
  807. }
  808. if (VOF_MEM_READ(be32_to_cpu(args_be.service), service, sizeof(service)) !=
  809. MEMTX_OK) {
  810. return -EINVAL;
  811. }
  812. if (strnlen(service, sizeof(service)) == sizeof(service)) {
  813. /* Too long service name */
  814. return -EINVAL;
  815. }
  816. for (i = 0; i < nargs; ++i) {
  817. args[i] = be32_to_cpu(args_be.args[i]);
  818. }
  819. nret = be32_to_cpu(args_be.nret);
  820. if (nret > ARRAY_SIZE(args_be.args) - nargs) {
  821. return -EINVAL;
  822. }
  823. ret = vof_client_handle(ms, fdt, vof, service, args, nargs, rets, nret);
  824. if (!nret) {
  825. return 0;
  826. }
  827. /* @nrets includes the value which this function returns */
  828. args_be.args[nargs] = cpu_to_be32(ret);
  829. for (i = 1; i < nret; ++i) {
  830. args_be.args[nargs + i] = cpu_to_be32(rets[i - 1]);
  831. }
  832. if (VOF_MEM_WRITE(args_real + offsetof(struct prom_args, args[nargs]),
  833. args_be.args + nargs, sizeof(args_be.args[0]) * nret) !=
  834. MEMTX_OK) {
  835. return -EINVAL;
  836. }
  837. return 0;
  838. }
  839. static void vof_instance_free(gpointer data)
  840. {
  841. OfInstance *inst = (OfInstance *)data;
  842. g_free(inst->path);
  843. g_free(inst);
  844. }
  845. void vof_init(Vof *vof, uint64_t top_addr, Error **errp)
  846. {
  847. vof_cleanup(vof);
  848. vof->of_instances = g_hash_table_new_full(g_direct_hash, g_direct_equal,
  849. NULL, vof_instance_free);
  850. vof->claimed = g_array_new(false, false, sizeof(OfClaimed));
  851. /* Keep allocations in 32bit as CLI ABI can only return cells==32bit */
  852. vof->top_addr = MIN(top_addr, 4 * GiB);
  853. if (vof_claim(vof, 0, vof->fw_size, 0) == -1) {
  854. error_setg(errp, "Memory for firmware is in use");
  855. }
  856. }
  857. void vof_cleanup(Vof *vof)
  858. {
  859. if (vof->claimed) {
  860. g_array_unref(vof->claimed);
  861. }
  862. if (vof->of_instances) {
  863. g_hash_table_unref(vof->of_instances);
  864. }
  865. vof->claimed = NULL;
  866. vof->of_instances = NULL;
  867. }
  868. void vof_build_dt(void *fdt, Vof *vof)
  869. {
  870. uint32_t phandle = fdt_get_max_phandle(fdt);
  871. int offset, proplen = 0;
  872. const void *prop;
  873. /* Assign phandles to nodes without predefined phandles (like XICS/XIVE) */
  874. for (offset = fdt_next_node(fdt, -1, NULL);
  875. offset >= 0;
  876. offset = fdt_next_node(fdt, offset, NULL)) {
  877. prop = fdt_getprop(fdt, offset, "phandle", &proplen);
  878. if (prop) {
  879. continue;
  880. }
  881. ++phandle;
  882. _FDT(fdt_setprop_cell(fdt, offset, "phandle", phandle));
  883. }
  884. vof_dt_memory_available(fdt, vof->claimed, vof->claimed_base);
  885. }
  886. static const TypeInfo vof_machine_if_info = {
  887. .name = TYPE_VOF_MACHINE_IF,
  888. .parent = TYPE_INTERFACE,
  889. .class_size = sizeof(VofMachineIfClass),
  890. };
  891. static void vof_machine_if_register_types(void)
  892. {
  893. type_register_static(&vof_machine_if_info);
  894. }
  895. type_init(vof_machine_if_register_types)