| 1 | |
| 2 | |
| 3 | |
| 4 | |
| 5 | |
| 6 | |
| 7 | |
| 8 | |
| 9 | |
| 10 | |
| 11 | |
| 12 | |
| 13 | |
| 14 | |
| 15 | |
| 16 | |
| 17 | |
| 18 | |
| 19 | #include <sys/types.h> |
| 20 | #include <mach/vm_param.h> |
| 21 | #include <machine/spl.h> |
| 22 | #include <vm/pmap.h> |
| 23 | #include <vm/vm_map.h> |
| 24 | #include <vm/vm_kern.h> |
| 25 | #include "grant.h" |
| 26 | |
| 27 | #define NR_RESERVED_ENTRIES8 8 |
| 28 | #define NR_GRANT_PAGES4 4 |
| 29 | |
| 30 | decl_simple_lock_data(static,lock)static struct simple_lock_data_empty lock;; |
| 31 | static struct grant_entry *grants; |
| 32 | static vm_map_entry_t grants_map_entry; |
| 33 | static int last_grant = NR_RESERVED_ENTRIES8; |
| 34 | |
| 35 | static grant_ref_t free_grants = -1; |
| 36 | |
| 37 | static grant_ref_t grant_alloc(void) { |
| 38 | grant_ref_t grant; |
| 39 | if (free_grants != -1) { |
| 40 | grant = free_grants; |
| 41 | free_grants = grants[grant].frame; |
| 42 | } else { |
| 43 | grant = last_grant++; |
| 44 | if (grant == (NR_GRANT_PAGES4 * PAGE_SIZE(1 << 12))/sizeof(*grants)) |
| 45 | panic("not enough grant entries, increase NR_GRANT_PAGES"); |
| 46 | } |
| 47 | return grant; |
| 48 | } |
| 49 | |
| 50 | static void grant_free(grant_ref_t grant) { |
| 51 | grants[grant].frame = free_grants; |
| 52 | free_grants = grant; |
| 53 | } |
| 54 | |
| 55 | static grant_ref_t grant_set(domid_t domid, unsigned long mfn, uint16_t flags) { |
| 56 | spl_t spl = splhigh(); |
| 57 | simple_lock(&lock); |
| 58 | |
| 59 | grant_ref_t grant = grant_alloc(); |
| 60 | grants[grant].domid = domid; |
| 61 | grants[grant].frame = mfn; |
| 62 | wmb()__asm__ __volatile__("lock; addl $0,0(%esp)"); |
| 63 | grants[grant].flags = flags; |
| 64 | |
| 65 | simple_unlock(&lock)((void)(&lock)); |
| 66 | splx(spl); |
| 67 | return grant; |
| 68 | } |
| 69 | |
| 70 | grant_ref_t hyp_grant_give(domid_t domid, unsigned long frame, int readonly) { |
| 71 | return grant_set(domid, pfn_to_mfn(frame)(mfn_list[frame]), |
| 72 | GTF_permit_access(1U<<0) | (readonly ? GTF_readonly(1U<<(2)) : 0)); |
| 73 | } |
| 74 | |
| 75 | grant_ref_t hyp_grant_accept_transfer(domid_t domid, unsigned long frame) { |
| 76 | return grant_set(domid, frame, GTF_accept_transfer(2U<<0)); |
| 77 | } |
| 78 | |
| 79 | unsigned long hyp_grant_finish_transfer(grant_ref_t grant) { |
| 80 | unsigned long frame; |
| 81 | spl_t spl = splhigh(); |
| 82 | simple_lock(&lock); |
| 83 | |
| 84 | if (!(grants[grant].flags & GTF_transfer_committed(1U<<(2)))) |
| 85 | panic("grant transfer %x not committed\n", grant); |
| 86 | while (!(grants[grant].flags & GTF_transfer_completed(1U<<(3)))) |
| 87 | machine_relax(); |
| 88 | rmb()__asm__ __volatile__("lock; addl $0,0(%esp)"); |
| 89 | frame = grants[grant].frame; |
| 90 | grant_free(grant); |
| 91 | |
| 92 | simple_unlock(&lock)((void)(&lock)); |
| 93 | splx(spl); |
| 94 | return frame; |
| 95 | } |
| 96 | |
| 97 | void hyp_grant_takeback(grant_ref_t grant) { |
| 98 | spl_t spl = splhigh(); |
| 99 | simple_lock(&lock); |
| 100 | |
| 101 | if (grants[grant].flags & (GTF_reading(1U<<(3))|GTF_writing(1U<<(4)))) |
| 102 | panic("grant %d still in use (%lx)\n", grant, grants[grant].flags); |
| 103 | |
| 104 | |
| 105 | grants[grant].flags = 0; |
| 106 | wmb()__asm__ __volatile__("lock; addl $0,0(%esp)"); |
| 107 | |
| 108 | grant_free(grant); |
| 109 | |
| 110 | simple_unlock(&lock)((void)(&lock)); |
| 111 | splx(spl); |
| 112 | } |
| 113 | |
| 114 | void *hyp_grant_address(grant_ref_t grant) { |
| 115 | return &grants[grant]; |
| 116 | } |
| 117 | |
| 118 | void hyp_grant_init(void) { |
| 119 | struct gnttab_setup_table setup; |
| 120 | unsigned long frame[NR_GRANT_PAGES4]; |
| 121 | long ret; |
| 122 | int i; |
| 123 | vm_offset_t addr; |
| 124 | |
| 125 | setup.dom = DOMID_SELF(0x7FF0U); |
| 126 | setup.nr_frames = NR_GRANT_PAGES4; |
| 127 | setup.frame_list = (void*) kvtolin(frame)((vm_offset_t)(frame) - 0xC0000000UL + ((0xc0000000UL))); |
| 128 | |
| 129 | ret = hyp_grant_table_op(GNTTABOP_setup_table2, kvtolin(&setup)((vm_offset_t)(&setup) - 0xC0000000UL + ((0xc0000000UL))), 1); |
| 130 | if (ret) |
| |
| |
| 131 | panic("setup grant table error %d", ret); |
| 132 | if (setup.status) |
| 3 | | Branch condition evaluates to a garbage value |
|
| 133 | panic("setup grant table: %d\n", setup.status); |
| 134 | |
| 135 | simple_lock_init(&lock); |
| 136 | vm_map_find_entry(kernel_map, &addr, NR_GRANT_PAGES4 * PAGE_SIZE(1 << 12), |
| 137 | (vm_offset_t) 0, kernel_object, &grants_map_entry); |
| 138 | grants = (void*) addr; |
| 139 | |
| 140 | for (i = 0; i < NR_GRANT_PAGES4; i++) |
| 141 | pmap_map_mfn((void *)grants + i * PAGE_SIZE(1 << 12), frame[i]); |
| 142 | } |