grant.c 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. /*
  2. * Copyright (C) 2006-2009 Free Software Foundation
  3. *
  4. * This program is free software ; you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation ; either version 2 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY ; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with the program ; if not, write to the Free Software
  16. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17. */
  18. #include <sys/types.h>
  19. #include <mach/vm_param.h>
  20. #include <machine/spl.h>
  21. #include <vm/pmap.h>
  22. #include <vm/vm_map.h>
  23. #include <vm/vm_kern.h>
  24. #include "grant.h"
  25. #define NR_RESERVED_ENTRIES 8
  26. #define NR_GRANT_PAGES 8
  27. decl_simple_lock_data(static,lock);
  28. static struct grant_entry *grants;
  29. static vm_map_entry_t grants_map_entry;
  30. static int last_grant = NR_RESERVED_ENTRIES;
  31. static grant_ref_t free_grants = -1;
  32. static grant_ref_t grant_alloc(void) {
  33. grant_ref_t grant;
  34. if (free_grants != -1) {
  35. grant = free_grants;
  36. free_grants = grants[grant].frame;
  37. } else {
  38. grant = last_grant++;
  39. if (grant == (NR_GRANT_PAGES * PAGE_SIZE)/sizeof(*grants))
  40. panic("not enough grant entries, increase NR_GRANT_PAGES");
  41. }
  42. return grant;
  43. }
  44. static void grant_free(grant_ref_t grant) {
  45. grants[grant].frame = free_grants;
  46. free_grants = grant;
  47. }
  48. static grant_ref_t grant_set(domid_t domid, unsigned long mfn, uint16_t flags) {
  49. spl_t spl = splhigh();
  50. simple_lock(&lock);
  51. grant_ref_t grant = grant_alloc();
  52. grants[grant].domid = domid;
  53. grants[grant].frame = mfn;
  54. wmb();
  55. grants[grant].flags = flags;
  56. simple_unlock(&lock);
  57. splx(spl);
  58. return grant;
  59. }
  60. grant_ref_t hyp_grant_give(domid_t domid, unsigned long frame, int readonly) {
  61. return grant_set(domid, pfn_to_mfn(frame),
  62. GTF_permit_access | (readonly ? GTF_readonly : 0));
  63. }
  64. grant_ref_t hyp_grant_accept_transfer(domid_t domid, unsigned long frame) {
  65. return grant_set(domid, frame, GTF_accept_transfer);
  66. }
  67. unsigned long hyp_grant_finish_transfer(grant_ref_t grant) {
  68. unsigned long frame;
  69. spl_t spl = splhigh();
  70. simple_lock(&lock);
  71. if (!(grants[grant].flags & GTF_transfer_committed))
  72. panic("grant transfer %x not committed\n", grant);
  73. while (!(grants[grant].flags & GTF_transfer_completed))
  74. machine_relax();
  75. rmb();
  76. frame = grants[grant].frame;
  77. grant_free(grant);
  78. simple_unlock(&lock);
  79. splx(spl);
  80. return frame;
  81. }
  82. void hyp_grant_takeback(grant_ref_t grant) {
  83. spl_t spl = splhigh();
  84. simple_lock(&lock);
  85. if (grants[grant].flags & (GTF_reading|GTF_writing))
  86. panic("grant %d still in use (%lx)\n", grant, grants[grant].flags);
  87. /* Note: this is not safe, a cmpxchg is needed, see grant_table.h */
  88. grants[grant].flags = 0;
  89. wmb();
  90. grant_free(grant);
  91. simple_unlock(&lock);
  92. splx(spl);
  93. }
  94. void *hyp_grant_address(grant_ref_t grant) {
  95. return &grants[grant];
  96. }
  97. void hyp_grant_init(void) {
  98. struct gnttab_setup_table setup;
  99. unsigned long frame[NR_GRANT_PAGES];
  100. long ret;
  101. int i;
  102. vm_offset_t addr;
  103. setup.dom = DOMID_SELF;
  104. setup.nr_frames = NR_GRANT_PAGES;
  105. setup.frame_list = (void*) kvtolin(frame);
  106. ret = hyp_grant_table_op(GNTTABOP_setup_table, kvtolin(&setup), 1);
  107. if (ret)
  108. panic("setup grant table error %d", ret);
  109. if (setup.status)
  110. panic("setup grant table: %d\n", setup.status);
  111. simple_lock_init(&lock);
  112. vm_map_find_entry(kernel_map, &addr, NR_GRANT_PAGES * PAGE_SIZE,
  113. (vm_offset_t) 0, kernel_object, &grants_map_entry);
  114. grants = (void*) addr;
  115. for (i = 0; i < NR_GRANT_PAGES; i++)
  116. pmap_map_mfn((void *)grants + i * PAGE_SIZE, frame[i]);
  117. }