gnttab.c 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * (C) 2006 - Cambridge University
  4. * (C) 2020 - EPAM Systems Inc.
  5. *
  6. * File: gnttab.c [1]
  7. * Author: Steven Smith (sos22@cam.ac.uk)
  8. * Changes: Grzegorz Milos (gm281@cam.ac.uk)
  9. *
  10. * Date: July 2006
  11. *
  12. * Description: Simple grant tables implementation. About as stupid as it's
  13. * possible to be and still work.
  14. *
  15. * [1] - http://xenbits.xen.org/gitweb/?p=mini-os.git;a=summary
  16. */
  17. #include <common.h>
  18. #include <asm/global_data.h>
  19. #include <linux/compiler.h>
  20. #include <log.h>
  21. #include <malloc.h>
  22. #include <asm/armv8/mmu.h>
  23. #include <asm/io.h>
  24. #include <asm/xen/system.h>
  25. #include <linux/bug.h>
  26. #include <xen/gnttab.h>
  27. #include <xen/hvm.h>
  28. #include <xen/interface/memory.h>
  29. DECLARE_GLOBAL_DATA_PTR;
  30. #define NR_RESERVED_ENTRIES 8
  31. /* NR_GRANT_FRAMES must be less than or equal to that configured in Xen */
  32. #define NR_GRANT_FRAMES 1
  33. #define NR_GRANT_ENTRIES (NR_GRANT_FRAMES * PAGE_SIZE / sizeof(struct grant_entry_v1))
  34. static struct grant_entry_v1 *gnttab_table;
  35. static grant_ref_t gnttab_list[NR_GRANT_ENTRIES];
  36. static void put_free_entry(grant_ref_t ref)
  37. {
  38. unsigned long flags;
  39. local_irq_save(flags);
  40. gnttab_list[ref] = gnttab_list[0];
  41. gnttab_list[0] = ref;
  42. local_irq_restore(flags);
  43. }
  44. static grant_ref_t get_free_entry(void)
  45. {
  46. unsigned int ref;
  47. unsigned long flags;
  48. local_irq_save(flags);
  49. ref = gnttab_list[0];
  50. BUG_ON(ref < NR_RESERVED_ENTRIES || ref >= NR_GRANT_ENTRIES);
  51. gnttab_list[0] = gnttab_list[ref];
  52. local_irq_restore(flags);
  53. return ref;
  54. }
  55. /**
  56. * gnttab_grant_access() - Allow access to the given frame.
  57. * The function creates an entry in the grant table according
  58. * to the specified parameters.
  59. * @domid: the id of the domain for which access is allowed
  60. * @frame: the number of the shared frame
  61. * @readonly: determines whether the frame is shared read-only or read-write
  62. *
  63. * Return: relevant grant reference
  64. */
  65. grant_ref_t gnttab_grant_access(domid_t domid, unsigned long frame, int readonly)
  66. {
  67. grant_ref_t ref;
  68. ref = get_free_entry();
  69. gnttab_table[ref].frame = frame;
  70. gnttab_table[ref].domid = domid;
  71. wmb();
  72. readonly *= GTF_readonly;
  73. gnttab_table[ref].flags = GTF_permit_access | readonly;
  74. return ref;
  75. }
  76. /**
  77. * gnttab_end_access() - End of memory sharing. The function invalidates
  78. * the entry in the grant table.
  79. */
  80. int gnttab_end_access(grant_ref_t ref)
  81. {
  82. u16 flags, nflags;
  83. BUG_ON(ref >= NR_GRANT_ENTRIES || ref < NR_RESERVED_ENTRIES);
  84. nflags = gnttab_table[ref].flags;
  85. do {
  86. flags = nflags;
  87. if ((flags) & (GTF_reading | GTF_writing)) {
  88. printf("WARNING: g.e. still in use! (%x)\n", flags);
  89. return 0;
  90. }
  91. } while ((nflags = synch_cmpxchg(&gnttab_table[ref].flags, flags, 0)) !=
  92. flags);
  93. put_free_entry(ref);
  94. return 1;
  95. }
  96. grant_ref_t gnttab_alloc_and_grant(void **map)
  97. {
  98. unsigned long mfn;
  99. grant_ref_t gref;
  100. *map = (void *)memalign(PAGE_SIZE, PAGE_SIZE);
  101. mfn = virt_to_mfn(*map);
  102. gref = gnttab_grant_access(0, mfn, 0);
  103. return gref;
  104. }
  105. static const char * const gnttabop_error_msgs[] = GNTTABOP_error_msgs;
  106. const char *gnttabop_error(int16_t status)
  107. {
  108. status = -status;
  109. if (status < 0 || status >= ARRAY_SIZE(gnttabop_error_msgs))
  110. return "bad status";
  111. else
  112. return gnttabop_error_msgs[status];
  113. }
  114. /* Get Xen's suggested physical page assignments for the grant table. */
  115. void get_gnttab_base(phys_addr_t *gnttab_base, phys_size_t *gnttab_sz)
  116. {
  117. const void *blob = gd->fdt_blob;
  118. struct fdt_resource res;
  119. int mem;
  120. mem = fdt_node_offset_by_compatible(blob, -1, "xen,xen");
  121. if (mem < 0) {
  122. printf("No xen,xen compatible found\n");
  123. BUG();
  124. }
  125. mem = fdt_get_resource(blob, mem, "reg", 0, &res);
  126. if (mem == -FDT_ERR_NOTFOUND) {
  127. printf("No grant table base in the device tree\n");
  128. BUG();
  129. }
  130. *gnttab_base = (phys_addr_t)res.start;
  131. if (gnttab_sz)
  132. *gnttab_sz = (phys_size_t)(res.end - res.start + 1);
  133. debug("FDT suggests grant table base at %llx\n",
  134. *gnttab_base);
  135. }
  136. void init_gnttab(void)
  137. {
  138. struct xen_add_to_physmap xatp;
  139. struct gnttab_setup_table setup;
  140. xen_pfn_t frames[NR_GRANT_FRAMES];
  141. int i, rc;
  142. debug("%s\n", __func__);
  143. for (i = NR_RESERVED_ENTRIES; i < NR_GRANT_ENTRIES; i++)
  144. put_free_entry(i);
  145. get_gnttab_base((phys_addr_t *)&gnttab_table, NULL);
  146. for (i = 0; i < NR_GRANT_FRAMES; i++) {
  147. xatp.domid = DOMID_SELF;
  148. xatp.size = 0;
  149. xatp.space = XENMAPSPACE_grant_table;
  150. xatp.idx = i;
  151. xatp.gpfn = PFN_DOWN((unsigned long)gnttab_table) + i;
  152. rc = HYPERVISOR_memory_op(XENMEM_add_to_physmap, &xatp);
  153. if (rc)
  154. printf("XENMEM_add_to_physmap failed; status = %d\n",
  155. rc);
  156. BUG_ON(rc != 0);
  157. }
  158. setup.dom = DOMID_SELF;
  159. setup.nr_frames = NR_GRANT_FRAMES;
  160. set_xen_guest_handle(setup.frame_list, frames);
  161. }
  162. void fini_gnttab(void)
  163. {
  164. struct xen_remove_from_physmap xrtp;
  165. struct gnttab_setup_table setup;
  166. int i, rc;
  167. debug("%s\n", __func__);
  168. for (i = 0; i < NR_GRANT_FRAMES; i++) {
  169. xrtp.domid = DOMID_SELF;
  170. xrtp.gpfn = PFN_DOWN((unsigned long)gnttab_table) + i;
  171. rc = HYPERVISOR_memory_op(XENMEM_remove_from_physmap, &xrtp);
  172. if (rc)
  173. printf("XENMEM_remove_from_physmap failed; status = %d\n",
  174. rc);
  175. BUG_ON(rc != 0);
  176. }
  177. setup.dom = DOMID_SELF;
  178. setup.nr_frames = 0;
  179. }