hab_qvm.c 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright (c) 2016-2021, The Linux Foundation. All rights reserved.
  4. * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
  5. */
  6. #include "hab.h"
  7. #include "hab_qvm.h"
  8. /*
  9. * 1. The entry values are only for platform without probe features. For those
  10. * platforms with probe feature, correct address and irq will be updated in it.
  11. * 2. Length of the array decides the maximum number of successful probe attempts.
  12. * Excessive probe attempts will fail and return -ENODEV.
  13. * 3. The number of vdev-shmem devices for hab in linux-lv/la.config should be
  14. * the same as the entry number of the below array to successfully probe and only
  15. * probe those vdev-shmem devices for HAB if other vdev-shmem users exist.
  16. */
  17. static struct shmem_irq_config pchan_factory_settings[] = {
  18. {0x1b000000, 7},
  19. {0x1b001000, 8},
  20. {0x1b002000, 9},
  21. {0x1b003000, 10},
  22. {0x1b004000, 11},
  23. {0x1b005000, 12},
  24. {0x1b006000, 13},
  25. {0x1b007000, 14},
  26. {0x1b008000, 15},
  27. {0x1b009000, 16},
  28. {0x1b00a000, 17},
  29. {0x1b00b000, 18},
  30. {0x1b00c000, 19},
  31. {0x1b00d000, 20},
  32. {0x1b00e000, 21},
  33. {0x1b00f000, 22},
  34. {0x1b010000, 23},
  35. {0x1b011000, 24},
  36. {0x1b012000, 25},
  37. {0x1b013000, 26},
  38. {0x1b014000, 27},
  39. {0x1b015000, 28},
  40. {0x1b016000, 29},
  41. {0x1b017000, 30},
  42. {0x1b018000, 31},
  43. {0x1b019000, 32},
  44. };
  45. struct qvm_plugin_info qvm_priv_info = {
  46. pchan_factory_settings,
  47. ARRAY_SIZE(pchan_factory_settings),
  48. 0,
  49. ARRAY_SIZE(pchan_factory_settings)
  50. };
  51. /*
  52. * this is common but only for guest
  53. */
  54. uint64_t get_guest_ctrl_paddr(struct qvm_channel *dev,
  55. unsigned long factory_addr, int irq, const char *name, uint32_t pages)
  56. {
  57. int i;
  58. unsigned long factory_va;
  59. pr_debug("name = %s, factory paddr = 0x%lx, irq %d, pages %d\n",
  60. name, factory_addr, irq, pages);
  61. /* get guest factory's va */
  62. factory_va = hab_shmem_factory_va(factory_addr);
  63. dev->guest_factory = (struct guest_shm_factory *)factory_va;
  64. if (dev->guest_factory->signature != GUEST_SHM_SIGNATURE) {
  65. pr_err("signature error: %ld != %llu, factory addr %lx\n",
  66. GUEST_SHM_SIGNATURE, dev->guest_factory->signature,
  67. factory_addr);
  68. iounmap(dev->guest_factory);
  69. return 0;
  70. }
  71. dev->guest_intr = dev->guest_factory->vector;
  72. /*
  73. * Set the name field on the factory page to identify the shared memory
  74. * region
  75. */
  76. for (i = 0; i < strlen(name) && i < GUEST_SHM_MAX_NAME - 1; i++)
  77. dev->guest_factory->name[i] = name[i];
  78. dev->guest_factory->name[i] = (char) 0;
  79. guest_shm_create(dev->guest_factory, pages);
  80. /* See if we successfully created/attached to the region. */
  81. if (dev->guest_factory->status != GSS_OK) {
  82. pr_err("create failed: %d\n", dev->guest_factory->status);
  83. iounmap(dev->guest_factory);
  84. return 0;
  85. }
  86. pr_debug("shm creation size %x, paddr=%llx, vector %d, dev %pK\n",
  87. dev->guest_factory->size,
  88. dev->guest_factory->shmem,
  89. dev->guest_intr,
  90. dev);
  91. dev->factory_addr = factory_addr;
  92. dev->irq = irq;
  93. return dev->guest_factory->shmem;
  94. }
  95. void hab_pipe_reset(struct physical_channel *pchan)
  96. {
  97. struct hab_pipe_endpoint *pipe_ep;
  98. struct qvm_channel *dev = (struct qvm_channel *)pchan->hyp_data;
  99. pipe_ep = hab_pipe_init(dev->pipe, &dev->tx_buf,
  100. &dev->rx_buf, &dev->dbg_itms, PIPE_SHMEM_SIZE,
  101. pchan->is_be ? 0 : 1);
  102. if (dev->pipe_ep != pipe_ep)
  103. pr_warn("The pipe endpoint must not change\n");
  104. }
  105. /*
  106. * allocate hypervisor plug-in specific resource for pchan, and call hab pchan
  107. * alloc common function. hab driver struct is directly accessed.
  108. * commdev: pointer to store the pchan address
  109. * id: index to hab_device (mmids)
  110. * is_be: pchan local endpoint role
  111. * name: pchan name
  112. * return: status 0: success, otherwise: failures
  113. */
  114. int habhyp_commdev_alloc(void **commdev, int is_be, char *name,
  115. int vmid_remote, struct hab_device *mmid_device)
  116. {
  117. struct qvm_channel *dev = NULL;
  118. struct qvm_channel_os *dev_os = NULL;
  119. struct physical_channel **pchan = (struct physical_channel **)commdev;
  120. int ret = 0;
  121. char *shmdata;
  122. uint32_t pipe_alloc_size =
  123. hab_pipe_calc_required_bytes(PIPE_SHMEM_SIZE);
  124. uint32_t pipe_alloc_pages =
  125. (pipe_alloc_size + PAGE_SIZE - 1) / PAGE_SIZE;
  126. pr_debug("%s: pipe_alloc_size is %d\n", __func__, pipe_alloc_size);
  127. /* allocate common part for the commdev */
  128. dev = kzalloc(sizeof(*dev), GFP_KERNEL);
  129. if (!dev) {
  130. ret = -ENOMEM;
  131. goto err;
  132. }
  133. /* allocate the os-specific data for the commdev */
  134. dev_os = kzalloc(sizeof(*dev_os), GFP_KERNEL);
  135. if (!dev_os) {
  136. ret = -ENOMEM;
  137. goto err;
  138. }
  139. dev->os_data = dev_os;
  140. spin_lock_init(&dev->io_lock);
  141. /*
  142. * create/attach to the shmem region, and get back the
  143. * shmem data vaddr
  144. */
  145. shmdata = hab_shmem_attach(dev, name, pipe_alloc_pages);
  146. if (IS_ERR(shmdata)) {
  147. ret = PTR_ERR(shmdata);
  148. goto err;
  149. }
  150. dev->pipe = (struct hab_pipe *)shmdata;
  151. pr_debug("\"%s\": pipesize %d, addr 0x%pK, be %d\n", name,
  152. pipe_alloc_size, dev->pipe, is_be);
  153. dev->pipe_ep = hab_pipe_init(dev->pipe, &dev->tx_buf, &dev->rx_buf,
  154. &dev->dbg_itms, PIPE_SHMEM_SIZE, is_be ? 0 : 1);
  155. /* newly created pchan is added to mmid device list */
  156. *pchan = hab_pchan_alloc(mmid_device, vmid_remote);
  157. if (!(*pchan)) {
  158. ret = -ENOMEM;
  159. goto err;
  160. }
  161. (*pchan)->closed = 0;
  162. (*pchan)->hyp_data = (void *)dev;
  163. strscpy((*pchan)->name, name, MAX_VMID_NAME_SIZE);
  164. (*pchan)->is_be = is_be;
  165. ret = habhyp_commdev_create_dispatcher(*pchan);
  166. if (ret < 0)
  167. goto err;
  168. return ret;
  169. err:
  170. pr_err("%s failed\n", __func__);
  171. if (*commdev)
  172. habhyp_commdev_dealloc(*commdev);
  173. return ret;
  174. }
  175. int habhyp_commdev_dealloc(void *commdev)
  176. {
  177. struct physical_channel *pchan = (struct physical_channel *)commdev;
  178. struct qvm_channel *dev = pchan->hyp_data;
  179. /* os specific deallocation for this commdev */
  180. habhyp_commdev_dealloc_os(commdev);
  181. if (get_refcnt(pchan->refcount) > 1) {
  182. pr_warn("potential leak pchan %s vchans %d refcnt %d\n",
  183. pchan->name, pchan->vcnt,
  184. get_refcnt(pchan->refcount));
  185. }
  186. kfree(dev->os_data);
  187. kfree(dev);
  188. hab_pchan_put(pchan);
  189. return 0;
  190. }
  191. int hab_hypervisor_register(void)
  192. {
  193. int ret = 0;
  194. /* os-specific registration work */
  195. ret = hab_hypervisor_register_os();
  196. if (ret)
  197. goto done;
  198. pr_info("initializing for %s VM\n", hab_driver.b_server_dom ?
  199. "host" : "guest");
  200. hab_driver.hyp_priv = &qvm_priv_info;
  201. done:
  202. return ret;
  203. }
  204. void hab_hypervisor_unregister(void)
  205. {
  206. hab_hypervisor_unregister_os();
  207. }
  208. int hab_hypervisor_register_post(void) { return 0; }