grant-table.c 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. /******************************************************************************
  2. * grant_table.c
  3. * x86 specific part
  4. *
  5. * Granting foreign access to our memory reservation.
  6. *
  7. * Copyright (c) 2005-2006, Christopher Clark
  8. * Copyright (c) 2004-2005, K A Fraser
  9. * Copyright (c) 2008 Isaku Yamahata <yamahata at valinux co jp>
  10. * VA Linux Systems Japan. Split out x86 specific part.
  11. *
  12. * This program is free software; you can redistribute it and/or
  13. * modify it under the terms of the GNU General Public License version 2
  14. * as published by the Free Software Foundation; or, when distributed
  15. * separately from the Linux kernel or incorporated into other
  16. * software packages, subject to the following license:
  17. *
  18. * Permission is hereby granted, free of charge, to any person obtaining a copy
  19. * of this source file (the "Software"), to deal in the Software without
  20. * restriction, including without limitation the rights to use, copy, modify,
  21. * merge, publish, distribute, sublicense, and/or sell copies of the Software,
  22. * and to permit persons to whom the Software is furnished to do so, subject to
  23. * the following conditions:
  24. *
  25. * The above copyright notice and this permission notice shall be included in
  26. * all copies or substantial portions of the Software.
  27. *
  28. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  29. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  30. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  31. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  32. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  33. * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  34. * IN THE SOFTWARE.
  35. */
  36. #include <linux/sched.h>
  37. #include <linux/mm.h>
  38. #include <linux/vmalloc.h>
  39. #include <xen/interface/xen.h>
  40. #include <xen/page.h>
  41. #include <xen/grant_table.h>
  42. #include <asm/pgtable.h>
  43. static int map_pte_fn(pte_t *pte, struct page *pmd_page,
  44. unsigned long addr, void *data)
  45. {
  46. unsigned long **frames = (unsigned long **)data;
  47. set_pte_at(&init_mm, addr, pte, mfn_pte((*frames)[0], PAGE_KERNEL));
  48. (*frames)++;
  49. return 0;
  50. }
  51. /*
  52. * This function is used to map shared frames to store grant status. It is
  53. * different from map_pte_fn above, the frames type here is uint64_t.
  54. */
  55. static int map_pte_fn_status(pte_t *pte, struct page *pmd_page,
  56. unsigned long addr, void *data)
  57. {
  58. uint64_t **frames = (uint64_t **)data;
  59. set_pte_at(&init_mm, addr, pte, mfn_pte((*frames)[0], PAGE_KERNEL));
  60. (*frames)++;
  61. return 0;
  62. }
  63. static int unmap_pte_fn(pte_t *pte, struct page *pmd_page,
  64. unsigned long addr, void *data)
  65. {
  66. set_pte_at(&init_mm, addr, pte, __pte(0));
  67. return 0;
  68. }
  69. int arch_gnttab_map_shared(unsigned long *frames, unsigned long nr_gframes,
  70. unsigned long max_nr_gframes,
  71. void **__shared)
  72. {
  73. int rc;
  74. void *shared = *__shared;
  75. if (shared == NULL) {
  76. struct vm_struct *area =
  77. alloc_vm_area(PAGE_SIZE * max_nr_gframes, NULL);
  78. BUG_ON(area == NULL);
  79. shared = area->addr;
  80. *__shared = shared;
  81. }
  82. rc = apply_to_page_range(&init_mm, (unsigned long)shared,
  83. PAGE_SIZE * nr_gframes,
  84. map_pte_fn, &frames);
  85. return rc;
  86. }
  87. int arch_gnttab_map_status(uint64_t *frames, unsigned long nr_gframes,
  88. unsigned long max_nr_gframes,
  89. grant_status_t **__shared)
  90. {
  91. int rc;
  92. grant_status_t *shared = *__shared;
  93. if (shared == NULL) {
  94. /* No need to pass in PTE as we are going to do it
  95. * in apply_to_page_range anyhow. */
  96. struct vm_struct *area =
  97. alloc_vm_area(PAGE_SIZE * max_nr_gframes, NULL);
  98. BUG_ON(area == NULL);
  99. shared = area->addr;
  100. *__shared = shared;
  101. }
  102. rc = apply_to_page_range(&init_mm, (unsigned long)shared,
  103. PAGE_SIZE * nr_gframes,
  104. map_pte_fn_status, &frames);
  105. return rc;
  106. }
  107. void arch_gnttab_unmap(void *shared, unsigned long nr_gframes)
  108. {
  109. apply_to_page_range(&init_mm, (unsigned long)shared,
  110. PAGE_SIZE * nr_gframes, unmap_pte_fn, NULL);
  111. }
  112. #ifdef CONFIG_XEN_PVH
  113. #include <xen/balloon.h>
  114. #include <xen/events.h>
  115. #include <xen/xen.h>
  116. #include <linux/slab.h>
  117. static int __init xlated_setup_gnttab_pages(void)
  118. {
  119. struct page **pages;
  120. xen_pfn_t *pfns;
  121. int rc;
  122. unsigned int i;
  123. unsigned long nr_grant_frames = gnttab_max_grant_frames();
  124. BUG_ON(nr_grant_frames == 0);
  125. pages = kcalloc(nr_grant_frames, sizeof(pages[0]), GFP_KERNEL);
  126. if (!pages)
  127. return -ENOMEM;
  128. pfns = kcalloc(nr_grant_frames, sizeof(pfns[0]), GFP_KERNEL);
  129. if (!pfns) {
  130. kfree(pages);
  131. return -ENOMEM;
  132. }
  133. rc = alloc_xenballooned_pages(nr_grant_frames, pages, 0 /* lowmem */);
  134. if (rc) {
  135. pr_warn("%s Couldn't balloon alloc %ld pfns rc:%d\n", __func__,
  136. nr_grant_frames, rc);
  137. kfree(pages);
  138. kfree(pfns);
  139. return rc;
  140. }
  141. for (i = 0; i < nr_grant_frames; i++)
  142. pfns[i] = page_to_pfn(pages[i]);
  143. rc = arch_gnttab_map_shared(pfns, nr_grant_frames, nr_grant_frames,
  144. &xen_auto_xlat_grant_frames.vaddr);
  145. if (rc) {
  146. pr_warn("%s Couldn't map %ld pfns rc:%d\n", __func__,
  147. nr_grant_frames, rc);
  148. free_xenballooned_pages(nr_grant_frames, pages);
  149. kfree(pages);
  150. kfree(pfns);
  151. return rc;
  152. }
  153. kfree(pages);
  154. xen_auto_xlat_grant_frames.pfn = pfns;
  155. xen_auto_xlat_grant_frames.count = nr_grant_frames;
  156. return 0;
  157. }
  158. static int __init xen_pvh_gnttab_setup(void)
  159. {
  160. if (!xen_pvh_domain())
  161. return -ENODEV;
  162. return xlated_setup_gnttab_pages();
  163. }
  164. /* Call it _before_ __gnttab_init as we need to initialize the
  165. * xen_auto_xlat_grant_frames first. */
  166. core_initcall(xen_pvh_gnttab_setup);
  167. #endif