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 | } |