hab_parser.c 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright (c) 2017-2018, 2021, The Linux Foundation. All rights reserved.
  4. * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
  5. */
  6. #include "hab.h"
  7. #include <linux/of.h>
  8. /*
  9. * set valid mmid value in tbl to show this is valid entry. All inputs here are
  10. * normalized to 1 based integer
  11. */
  12. static int fill_vmid_mmid_tbl(struct vmid_mmid_desc *tbl, int32_t vm_start,
  13. int32_t vm_range, int32_t mmid_start,
  14. int32_t mmid_range, int32_t be, int kernel_only)
  15. {
  16. int i, j;
  17. for (i = vm_start; i < vm_start+vm_range; i++) {
  18. tbl[i].vmid = i; /* set valid vmid value to make it usable */
  19. for (j = mmid_start; j < mmid_start + mmid_range; j++) {
  20. /* sanity check */
  21. if (tbl[i].mmid[j] != HABCFG_VMID_INVALID) {
  22. pr_err("overwrite previous setting vmid %d, mmid %d, be %d, kernel only %d\n",
  23. i, j, tbl[i].is_listener[j], tbl[i].kernel_only[j]);
  24. }
  25. tbl[i].mmid[j] = j;
  26. tbl[i].is_listener[j] = be; /* BE IS listen */
  27. tbl[i].kernel_only[j] = kernel_only;
  28. }
  29. }
  30. return 0;
  31. }
  32. void dump_settings(struct local_vmid *settings)
  33. {
  34. pr_debug("self vmid is %d\n", settings->self);
  35. }
  36. #ifdef CONFIG_MSM_VHOST_HAB
  37. int fill_default_gvm_settings(struct local_vmid *settings, int vmid_default,
  38. int mmid_start, int mmid_end)
  39. {
  40. int32_t be = HABCFG_BE_TRUE;
  41. int32_t range = 1;
  42. int32_t vmremote = vmid_default;
  43. /* pchan is not kernel only by default */
  44. int32_t kernel_only = 0;
  45. /* default gvm always talks to host as vm0 */
  46. settings->self = 0;
  47. return fill_vmid_mmid_tbl(settings->vmid_mmid_list, vmremote, range,
  48. mmid_start/100, (mmid_end-mmid_start)/100+1, be, kernel_only);
  49. }
  50. #else
  51. int fill_default_gvm_settings(struct local_vmid *settings, int vmid_local,
  52. int mmid_start, int mmid_end)
  53. {
  54. int32_t be = HABCFG_BE_FALSE;
  55. int32_t range = 1;
  56. int32_t vmremote = 0; /* default to host[0] as local is guest[2] */
  57. /* pchan is not kernel only by default */
  58. int32_t kernel_only = 0;
  59. settings->self = vmid_local;
  60. /* default gvm always talks to host as vm0 */
  61. return fill_vmid_mmid_tbl(settings->vmid_mmid_list, vmremote, range,
  62. mmid_start/100, (mmid_end-mmid_start)/100+1, be, kernel_only);
  63. }
  64. #endif
  65. /* device tree based parser */
  66. static int hab_parse_dt(struct local_vmid *settings)
  67. {
  68. int result, i;
  69. struct device_node *hab_node = NULL;
  70. struct device_node *mmid_grp_node = NULL;
  71. const char *role = NULL;
  72. int tmp = -1, vmids_num;
  73. u32 vmids[16];
  74. int32_t grp_start_id, be;
  75. int kernel_only;
  76. /* parse device tree*/
  77. pr_debug("parsing hab node in device tree...\n");
  78. hab_node = of_find_compatible_node(NULL, NULL, "qcom,hab");
  79. if (!hab_node) {
  80. pr_err("no hab device tree node\n");
  81. return -ENODEV;
  82. }
  83. /* read the local vmid of this VM, like 0 for host, 1 for AGL GVM */
  84. result = of_property_read_u32(hab_node, "vmid", &tmp);
  85. if (result) {
  86. pr_err("failed to read local vmid, result = %d\n", result);
  87. return result;
  88. }
  89. pr_debug("local vmid = %d\n", tmp);
  90. settings->self = tmp;
  91. for_each_child_of_node(hab_node, mmid_grp_node) {
  92. /* read the group starting id */
  93. result = of_property_read_u32(mmid_grp_node,
  94. "grp-start-id", &tmp);
  95. if (result) {
  96. pr_err("failed to read grp-start-id, result = %d\n",
  97. result);
  98. return result;
  99. }
  100. pr_debug("grp-start-id = %d\n", tmp);
  101. grp_start_id = tmp;
  102. /* read the role(fe/be) of these pchans in this mmid group */
  103. result = of_property_read_string(mmid_grp_node, "role", &role);
  104. if (result) {
  105. pr_err("failed to get role, result = %d\n", result);
  106. return result;
  107. }
  108. pr_debug("local role of this mmid group is %s\n", role);
  109. if (!strcmp(role, "be"))
  110. be = 1;
  111. else
  112. be = 0;
  113. /* read the remote vmids for these pchans in this mmid group */
  114. vmids_num = of_property_count_elems_of_size(mmid_grp_node,
  115. "remote-vmids", sizeof(u32));
  116. result = of_property_read_u32_array(mmid_grp_node,
  117. "remote-vmids", vmids, vmids_num);
  118. if (result) {
  119. pr_err("failed to read remote-vmids, result = %d\n",
  120. result);
  121. return result;
  122. }
  123. /* check the kernel_only flag for these pchans in this mmid group */
  124. result = of_property_read_bool(mmid_grp_node, "kernel_only");
  125. if (result) {
  126. kernel_only = 1;
  127. pr_debug("kernel_only flag is set for this mmid group\n");
  128. } else {
  129. kernel_only = 0;
  130. pr_debug("kernel_only flag is not set for this mmid group\n");
  131. }
  132. for (i = 0; i < vmids_num; i++) {
  133. pr_debug("vmids_num = %d, vmids[%d] = %d\n",
  134. vmids_num, i, vmids[i]);
  135. result = fill_vmid_mmid_tbl(
  136. settings->vmid_mmid_list,
  137. vmids[i], 1,
  138. grp_start_id/100, 1, be, kernel_only);
  139. if (result) {
  140. pr_err("fill_vmid_mmid_tbl failed\n");
  141. return result;
  142. }
  143. }
  144. }
  145. dump_settings(settings);
  146. return 0;
  147. }
  148. /*
  149. * 0: successful
  150. * negative: various failure core
  151. */
  152. int hab_parse(struct local_vmid *settings)
  153. {
  154. int ret;
  155. ret = hab_parse_dt(settings);
  156. return ret;
  157. }