rev |
line source |
cl349@4693
|
1 /******************************************************************************
|
cl349@4693
|
2 * gnttab.c
|
cl349@4693
|
3 *
|
cl349@4693
|
4 * Two sets of functionality:
|
cl349@4693
|
5 * 1. Granting foreign access to our memory reservation.
|
cl349@4693
|
6 * 2. Accessing others' memory reservations via grant references.
|
cl349@4693
|
7 * (i.e., mechanisms for both sender and recipient of grant references)
|
cl349@4693
|
8 *
|
cl349@4693
|
9 * Copyright (c) 2005, Christopher Clark
|
cl349@4693
|
10 * Copyright (c) 2004, K A Fraser
|
cl349@4693
|
11 */
|
cl349@4693
|
12
|
cl349@4693
|
13 #include <linux/config.h>
|
cl349@4693
|
14 #include <linux/module.h>
|
cl349@4693
|
15 #include <linux/sched.h>
|
cl349@4693
|
16 #include <asm/pgtable.h>
|
cl349@4693
|
17 #include <asm/fixmap.h>
|
cl349@4693
|
18 #include <asm/uaccess.h>
|
cl349@4693
|
19 #include <asm-xen/xen_proc.h>
|
cl349@4693
|
20 #include <asm-xen/linux-public/privcmd.h>
|
cl349@4693
|
21 #include <asm-xen/gnttab.h>
|
kaf24@6760
|
22 #include <asm/synch_bitops.h>
|
cl349@4693
|
23
|
cl349@4693
|
24 #if 1
|
cl349@4693
|
25 #define ASSERT(_p) \
|
cl349@4693
|
26 if ( !(_p) ) { printk(KERN_ALERT"Assertion '%s': line %d, file %s\n", \
|
cl349@4693
|
27 #_p , __LINE__, __FILE__); *(int*)0=0; }
|
cl349@4693
|
28 #else
|
cl349@4693
|
29 #define ASSERT(_p) ((void)0)
|
cl349@4693
|
30 #endif
|
cl349@4693
|
31
|
cl349@4693
|
32 #define WPRINTK(fmt, args...) \
|
cl349@4693
|
33 printk(KERN_WARNING "xen_grant: " fmt, ##args)
|
cl349@4693
|
34
|
cl349@4693
|
35
|
cl349@4693
|
36 EXPORT_SYMBOL(gnttab_grant_foreign_access);
|
kaf24@6396
|
37 EXPORT_SYMBOL(gnttab_end_foreign_access_ref);
|
cl349@4693
|
38 EXPORT_SYMBOL(gnttab_end_foreign_access);
|
cl349@4693
|
39 EXPORT_SYMBOL(gnttab_query_foreign_access);
|
cl349@4693
|
40 EXPORT_SYMBOL(gnttab_grant_foreign_transfer);
|
kaf24@6396
|
41 EXPORT_SYMBOL(gnttab_end_foreign_transfer_ref);
|
cl349@4693
|
42 EXPORT_SYMBOL(gnttab_end_foreign_transfer);
|
cl349@4693
|
43 EXPORT_SYMBOL(gnttab_alloc_grant_references);
|
cl349@4693
|
44 EXPORT_SYMBOL(gnttab_free_grant_references);
|
cl349@6347
|
45 EXPORT_SYMBOL(gnttab_free_grant_reference);
|
cl349@4693
|
46 EXPORT_SYMBOL(gnttab_claim_grant_reference);
|
cl349@4693
|
47 EXPORT_SYMBOL(gnttab_release_grant_reference);
|
cl349@4693
|
48 EXPORT_SYMBOL(gnttab_grant_foreign_access_ref);
|
cl349@4693
|
49 EXPORT_SYMBOL(gnttab_grant_foreign_transfer_ref);
|
cl349@4693
|
50
|
cl349@6349
|
51 #define NR_GRANT_ENTRIES (NR_GRANT_FRAMES * PAGE_SIZE / sizeof(grant_entry_t))
|
cl349@6349
|
52 #define GNTTAB_LIST_END (NR_GRANT_ENTRIES + 1)
|
cl349@6349
|
53
|
cl349@6349
|
54 static grant_ref_t gnttab_list[NR_GRANT_ENTRIES];
|
cl349@6349
|
55 static int gnttab_free_count = NR_GRANT_ENTRIES;
|
cl349@4693
|
56 static grant_ref_t gnttab_free_head;
|
cl349@6349
|
57 static spinlock_t gnttab_list_lock = SPIN_LOCK_UNLOCKED;
|
cl349@4693
|
58
|
cl349@4693
|
59 static grant_entry_t *shared;
|
cl349@4693
|
60
|
cl349@6339
|
61 static struct gnttab_free_callback *gnttab_free_callback_list = NULL;
|
cl349@4693
|
62
|
cl349@6349
|
63 static int
|
cl349@6349
|
64 get_free_entries(int count)
|
cl349@4693
|
65 {
|
cl349@6349
|
66 unsigned long flags;
|
cl349@6349
|
67 int ref;
|
cl349@6349
|
68 grant_ref_t head;
|
cl349@6349
|
69 spin_lock_irqsave(&gnttab_list_lock, flags);
|
cl349@6349
|
70 if (gnttab_free_count < count) {
|
cl349@6349
|
71 spin_unlock_irqrestore(&gnttab_list_lock, flags);
|
cl349@6349
|
72 return -1;
|
cl349@6349
|
73 }
|
cl349@6349
|
74 ref = head = gnttab_free_head;
|
cl349@6349
|
75 gnttab_free_count -= count;
|
cl349@6349
|
76 while (count-- > 1)
|
cl349@6349
|
77 head = gnttab_list[head];
|
cl349@6349
|
78 gnttab_free_head = gnttab_list[head];
|
cl349@6349
|
79 gnttab_list[head] = GNTTAB_LIST_END;
|
cl349@6349
|
80 spin_unlock_irqrestore(&gnttab_list_lock, flags);
|
cl349@6349
|
81 return ref;
|
cl349@4693
|
82 }
|
cl349@4693
|
83
|
cl349@6349
|
84 #define get_free_entry() get_free_entries(1)
|
cl349@6349
|
85
|
cl349@6349
|
86 static void
|
cl349@6349
|
87 do_free_callbacks(void)
|
cl349@6339
|
88 {
|
cl349@6346
|
89 struct gnttab_free_callback *callback = gnttab_free_callback_list, *next;
|
cl349@6339
|
90 gnttab_free_callback_list = NULL;
|
cl349@6339
|
91 while (callback) {
|
cl349@6342
|
92 next = callback->next;
|
cl349@6349
|
93 if (gnttab_free_count >= callback->count) {
|
cl349@6349
|
94 callback->next = NULL;
|
cl349@6349
|
95 callback->fn(callback->arg);
|
cl349@6349
|
96 } else {
|
cl349@6349
|
97 callback->next = gnttab_free_callback_list;
|
cl349@6349
|
98 gnttab_free_callback_list = callback;
|
cl349@6349
|
99 }
|
cl349@6342
|
100 callback = next;
|
cl349@6339
|
101 }
|
cl349@4693
|
102 }
|
cl349@4693
|
103
|
cl349@4693
|
104 static inline void
|
cl349@6349
|
105 check_free_callbacks(void)
|
cl349@4693
|
106 {
|
cl349@6349
|
107 if (unlikely(gnttab_free_callback_list))
|
cl349@6349
|
108 do_free_callbacks();
|
cl349@6349
|
109 }
|
cl349@6349
|
110
|
cl349@6349
|
111 static void
|
cl349@6349
|
112 put_free_entry(grant_ref_t ref)
|
cl349@6349
|
113 {
|
cl349@6346
|
114 unsigned long flags;
|
cl349@6349
|
115 spin_lock_irqsave(&gnttab_list_lock, flags);
|
cl349@6349
|
116 gnttab_list[ref] = gnttab_free_head;
|
cl349@6349
|
117 gnttab_free_head = ref;
|
cl349@6349
|
118 gnttab_free_count++;
|
cl349@6349
|
119 check_free_callbacks();
|
cl349@6349
|
120 spin_unlock_irqrestore(&gnttab_list_lock, flags);
|
cl349@4693
|
121 }
|
cl349@4693
|
122
|
cl349@4693
|
123 /*
|
cl349@4693
|
124 * Public grant-issuing interface functions
|
cl349@4693
|
125 */
|
cl349@4693
|
126
|
cl349@4693
|
127 int
|
cl349@6349
|
128 gnttab_grant_foreign_access(domid_t domid, unsigned long frame, int readonly)
|
cl349@4693
|
129 {
|
cl349@4693
|
130 int ref;
|
cl349@4693
|
131
|
cl349@4693
|
132 if ( unlikely((ref = get_free_entry()) == -1) )
|
cl349@4693
|
133 return -ENOSPC;
|
cl349@4693
|
134
|
cl349@4693
|
135 shared[ref].frame = frame;
|
cl349@4693
|
136 shared[ref].domid = domid;
|
cl349@4693
|
137 wmb();
|
cl349@4693
|
138 shared[ref].flags = GTF_permit_access | (readonly ? GTF_readonly : 0);
|
cl349@4693
|
139
|
cl349@4693
|
140 return ref;
|
cl349@4693
|
141 }
|
cl349@4693
|
142
|
cl349@4693
|
143 void
|
cl349@6349
|
144 gnttab_grant_foreign_access_ref(grant_ref_t ref, domid_t domid,
|
cl349@6349
|
145 unsigned long frame, int readonly)
|
cl349@4693
|
146 {
|
cl349@4693
|
147 shared[ref].frame = frame;
|
cl349@4693
|
148 shared[ref].domid = domid;
|
cl349@4693
|
149 wmb();
|
cl349@4693
|
150 shared[ref].flags = GTF_permit_access | (readonly ? GTF_readonly : 0);
|
cl349@4693
|
151 }
|
cl349@4693
|
152
|
cl349@4693
|
153
|
cl349@4693
|
154 int
|
cl349@6349
|
155 gnttab_query_foreign_access(grant_ref_t ref)
|
cl349@4693
|
156 {
|
cl349@4693
|
157 u16 nflags;
|
cl349@4693
|
158
|
cl349@4693
|
159 nflags = shared[ref].flags;
|
cl349@4693
|
160
|
cl349@4693
|
161 return ( nflags & (GTF_reading|GTF_writing) );
|
cl349@4693
|
162 }
|
cl349@4693
|
163
|
cl349@4693
|
164 void
|
kaf24@6396
|
165 gnttab_end_foreign_access_ref(grant_ref_t ref, int readonly)
|
cl349@4693
|
166 {
|
cl349@4693
|
167 u16 flags, nflags;
|
cl349@4693
|
168
|
cl349@4693
|
169 nflags = shared[ref].flags;
|
cl349@4693
|
170 do {
|
cl349@4693
|
171 if ( (flags = nflags) & (GTF_reading|GTF_writing) )
|
cl349@4693
|
172 printk(KERN_ALERT "WARNING: g.e. still in use!\n");
|
cl349@4693
|
173 }
|
sos22@5391
|
174 while ( (nflags = synch_cmpxchg(&shared[ref].flags, flags, 0)) != flags );
|
kaf24@6396
|
175 }
|
cl349@4693
|
176
|
kaf24@6396
|
177 void
|
kaf24@6396
|
178 gnttab_end_foreign_access(grant_ref_t ref, int readonly)
|
kaf24@6396
|
179 {
|
kaf24@6396
|
180 gnttab_end_foreign_access_ref(ref, readonly);
|
cl349@4693
|
181 put_free_entry(ref);
|
cl349@4693
|
182 }
|
cl349@4693
|
183
|
cl349@4693
|
184 int
|
cl349@6349
|
185 gnttab_grant_foreign_transfer(domid_t domid, unsigned long pfn)
|
cl349@4693
|
186 {
|
cl349@4693
|
187 int ref;
|
cl349@4693
|
188
|
cl349@4693
|
189 if ( unlikely((ref = get_free_entry()) == -1) )
|
cl349@4693
|
190 return -ENOSPC;
|
cl349@4693
|
191
|
cl349@4693
|
192 shared[ref].frame = pfn;
|
cl349@4693
|
193 shared[ref].domid = domid;
|
cl349@4693
|
194 wmb();
|
cl349@4693
|
195 shared[ref].flags = GTF_accept_transfer;
|
cl349@4693
|
196
|
cl349@4693
|
197 return ref;
|
cl349@4693
|
198 }
|
cl349@4693
|
199
|
cl349@4693
|
200 void
|
cl349@6349
|
201 gnttab_grant_foreign_transfer_ref(grant_ref_t ref, domid_t domid,
|
cl349@6349
|
202 unsigned long pfn)
|
cl349@4693
|
203 {
|
cl349@4693
|
204 shared[ref].frame = pfn;
|
cl349@4693
|
205 shared[ref].domid = domid;
|
cl349@4693
|
206 wmb();
|
cl349@4693
|
207 shared[ref].flags = GTF_accept_transfer;
|
cl349@4693
|
208 }
|
cl349@4693
|
209
|
cl349@4693
|
210 unsigned long
|
kaf24@6396
|
211 gnttab_end_foreign_transfer_ref(grant_ref_t ref)
|
cl349@4693
|
212 {
|
cl349@4693
|
213 unsigned long frame = 0;
|
cl349@4693
|
214 u16 flags;
|
cl349@4693
|
215
|
cl349@4693
|
216 flags = shared[ref].flags;
|
kaf24@6396
|
217
|
cl349@4693
|
218 /*
|
cl349@4693
|
219 * If a transfer is committed then wait for the frame address to appear.
|
cl349@4693
|
220 * Otherwise invalidate the grant entry against future use.
|
cl349@4693
|
221 */
|
cl349@4693
|
222 if ( likely(flags != GTF_accept_transfer) ||
|
sos22@5391
|
223 (synch_cmpxchg(&shared[ref].flags, flags, 0) != GTF_accept_transfer) )
|
cl349@4693
|
224 while ( unlikely((frame = shared[ref].frame) == 0) )
|
cl349@4693
|
225 cpu_relax();
|
cl349@4693
|
226
|
kaf24@6396
|
227 return frame;
|
kaf24@6396
|
228 }
|
kaf24@6396
|
229
|
kaf24@6396
|
230 unsigned long
|
kaf24@6396
|
231 gnttab_end_foreign_transfer(grant_ref_t ref)
|
kaf24@6396
|
232 {
|
kaf24@6396
|
233 unsigned long frame = gnttab_end_foreign_transfer_ref(ref);
|
cl349@4693
|
234 put_free_entry(ref);
|
cl349@4693
|
235 return frame;
|
cl349@4693
|
236 }
|
cl349@4693
|
237
|
cl349@4693
|
238 void
|
cl349@6349
|
239 gnttab_free_grant_reference(grant_ref_t ref)
|
cl349@4693
|
240 {
|
cl349@6339
|
241
|
cl349@6339
|
242 put_free_entry(ref);
|
cl349@6339
|
243 }
|
cl349@4693
|
244
|
cl349@6339
|
245 void
|
cl349@6349
|
246 gnttab_free_grant_references(grant_ref_t head)
|
cl349@4693
|
247 {
|
cl349@6339
|
248 grant_ref_t ref;
|
cl349@6349
|
249 unsigned long flags;
|
cl349@6349
|
250 int count = 1;
|
cl349@6349
|
251 if (head == GNTTAB_LIST_END)
|
cl349@6349
|
252 return;
|
cl349@6349
|
253 spin_lock_irqsave(&gnttab_list_lock, flags);
|
cl349@6349
|
254 ref = head;
|
cl349@6349
|
255 while (gnttab_list[ref] != GNTTAB_LIST_END) {
|
cl349@6349
|
256 ref = gnttab_list[ref];
|
cl349@6349
|
257 count++;
|
vh249@5272
|
258 }
|
cl349@6349
|
259 gnttab_list[ref] = gnttab_free_head;
|
cl349@6349
|
260 gnttab_free_head = head;
|
cl349@6349
|
261 gnttab_free_count += count;
|
cl349@6349
|
262 check_free_callbacks();
|
cl349@6349
|
263 spin_unlock_irqrestore(&gnttab_list_lock, flags);
|
cl349@4693
|
264 }
|
cl349@4693
|
265
|
cl349@4693
|
266 int
|
cl349@6349
|
267 gnttab_alloc_grant_references(u16 count, grant_ref_t *head)
|
cl349@4693
|
268 {
|
cl349@6349
|
269 int h = get_free_entries(count);
|
cl349@4693
|
270
|
cl349@6349
|
271 if (h == -1)
|
cl349@6349
|
272 return -ENOSPC;
|
cl349@4693
|
273
|
cl349@4693
|
274 *head = h;
|
cl349@4693
|
275
|
cl349@4693
|
276 return 0;
|
cl349@4693
|
277 }
|
cl349@4693
|
278
|
cl349@4693
|
279 int
|
cl349@6349
|
280 gnttab_claim_grant_reference(grant_ref_t *private_head)
|
cl349@4693
|
281 {
|
cl349@6349
|
282 grant_ref_t g = *private_head;
|
cl349@6349
|
283 if (unlikely(g == GNTTAB_LIST_END))
|
cl349@4693
|
284 return -ENOSPC;
|
cl349@6349
|
285 *private_head = gnttab_list[g];
|
cl349@4693
|
286 return g;
|
cl349@4693
|
287 }
|
cl349@4693
|
288
|
cl349@4693
|
289 void
|
cl349@6349
|
290 gnttab_release_grant_reference(grant_ref_t *private_head, grant_ref_t release)
|
cl349@4693
|
291 {
|
cl349@6349
|
292 gnttab_list[release] = *private_head;
|
cl349@4693
|
293 *private_head = release;
|
cl349@4693
|
294 }
|
cl349@4693
|
295
|
cl349@6339
|
296 void
|
cl349@6339
|
297 gnttab_request_free_callback(struct gnttab_free_callback *callback,
|
cl349@6349
|
298 void (*fn)(void *), void *arg, u16 count)
|
cl349@4693
|
299 {
|
cl349@6346
|
300 unsigned long flags;
|
cl349@6349
|
301 spin_lock_irqsave(&gnttab_list_lock, flags);
|
cl349@6342
|
302 if (callback->next)
|
cl349@6349
|
303 goto out;
|
cl349@6342
|
304 callback->fn = fn;
|
cl349@6342
|
305 callback->arg = arg;
|
cl349@6349
|
306 callback->count = count;
|
cl349@6339
|
307 callback->next = gnttab_free_callback_list;
|
cl349@6339
|
308 gnttab_free_callback_list = callback;
|
cl349@6349
|
309 check_free_callbacks();
|
cl349@6349
|
310 out:
|
cl349@6349
|
311 spin_unlock_irqrestore(&gnttab_list_lock, flags);
|
cl349@4693
|
312 }
|
cl349@4693
|
313
|
cl349@4693
|
314 /*
|
cl349@4693
|
315 * ProcFS operations
|
cl349@4693
|
316 */
|
cl349@4693
|
317
|
cl349@4693
|
318 #ifdef CONFIG_PROC_FS
|
cl349@4693
|
319
|
cl349@4693
|
320 static struct proc_dir_entry *grant_pde;
|
cl349@4693
|
321
|
cl349@6349
|
322 static int
|
cl349@6349
|
323 grant_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
|
cl349@6349
|
324 unsigned long data)
|
cl349@4693
|
325 {
|
cl349@4693
|
326 int ret;
|
cl349@4693
|
327 privcmd_hypercall_t hypercall;
|
cl349@4693
|
328
|
cl349@4693
|
329 /* XXX Need safety checks here if using for anything other
|
cl349@4693
|
330 * than debugging */
|
cl349@4693
|
331 return -ENOSYS;
|
cl349@4693
|
332
|
cl349@4693
|
333 if ( cmd != IOCTL_PRIVCMD_HYPERCALL )
|
cl349@4693
|
334 return -ENOSYS;
|
cl349@4693
|
335
|
cl349@4693
|
336 if ( copy_from_user(&hypercall, (void *)data, sizeof(hypercall)) )
|
cl349@4693
|
337 return -EFAULT;
|
cl349@4693
|
338
|
cl349@4693
|
339 if ( hypercall.op != __HYPERVISOR_grant_table_op )
|
cl349@4693
|
340 return -ENOSYS;
|
cl349@4693
|
341
|
cl349@4693
|
342 /* hypercall-invoking asm taken from privcmd.c */
|
cl349@4693
|
343 __asm__ __volatile__ (
|
cl349@4693
|
344 "pushl %%ebx; pushl %%ecx; pushl %%edx; pushl %%esi; pushl %%edi; "
|
cl349@4693
|
345 "movl 4(%%eax),%%ebx ;"
|
cl349@4693
|
346 "movl 8(%%eax),%%ecx ;"
|
cl349@4693
|
347 "movl 12(%%eax),%%edx ;"
|
cl349@4693
|
348 "movl 16(%%eax),%%esi ;"
|
cl349@4693
|
349 "movl 20(%%eax),%%edi ;"
|
cl349@4693
|
350 "movl (%%eax),%%eax ;"
|
cl349@4693
|
351 TRAP_INSTR "; "
|
cl349@4693
|
352 "popl %%edi; popl %%esi; popl %%edx; popl %%ecx; popl %%ebx"
|
cl349@4693
|
353 : "=a" (ret) : "0" (&hypercall) : "memory" );
|
cl349@4693
|
354
|
cl349@4693
|
355 return ret;
|
cl349@4693
|
356 }
|
cl349@4693
|
357
|
cl349@4693
|
358 static struct file_operations grant_file_ops = {
|
cl349@4693
|
359 ioctl: grant_ioctl,
|
cl349@4693
|
360 };
|
cl349@4693
|
361
|
cl349@6349
|
362 static int
|
cl349@6349
|
363 grant_read(char *page, char **start, off_t off, int count, int *eof,
|
cl349@6349
|
364 void *data)
|
cl349@4693
|
365 {
|
cl349@4693
|
366 int len;
|
cl349@4693
|
367 unsigned int i;
|
cl349@4693
|
368 grant_entry_t *gt;
|
cl349@4693
|
369
|
cl349@4693
|
370 gt = (grant_entry_t *)shared;
|
cl349@4693
|
371 len = 0;
|
cl349@4693
|
372
|
cl349@4693
|
373 for ( i = 0; i < NR_GRANT_ENTRIES; i++ )
|
cl349@4693
|
374 /* TODO: safety catch here until this can handle >PAGE_SIZE output */
|
cl349@4693
|
375 if (len > (PAGE_SIZE - 200))
|
cl349@4693
|
376 {
|
cl349@4693
|
377 len += sprintf( page + len, "Truncated.\n");
|
cl349@4693
|
378 break;
|
cl349@4693
|
379 }
|
cl349@4693
|
380
|
cl349@4693
|
381 if ( gt[i].flags )
|
cl349@4693
|
382 len += sprintf( page + len,
|
cl349@4693
|
383 "Grant: ref (0x%x) flags (0x%hx) dom (0x%hx) frame (0x%x)\n",
|
cl349@4693
|
384 i,
|
cl349@4693
|
385 gt[i].flags,
|
cl349@4693
|
386 gt[i].domid,
|
cl349@4693
|
387 gt[i].frame );
|
cl349@4693
|
388
|
cl349@4693
|
389 *eof = 1;
|
cl349@4693
|
390 return len;
|
cl349@4693
|
391 }
|
cl349@4693
|
392
|
cl349@6349
|
393 static int
|
cl349@6349
|
394 grant_write(struct file *file, const char __user *buffer, unsigned long count,
|
cl349@6349
|
395 void *data)
|
cl349@4693
|
396 {
|
cl349@4693
|
397 /* TODO: implement this */
|
cl349@4693
|
398 return -ENOSYS;
|
cl349@4693
|
399 }
|
cl349@4693
|
400
|
cl349@4693
|
401 #endif /* CONFIG_PROC_FS */
|
cl349@4693
|
402
|
cl349@6349
|
403 int
|
cl349@6349
|
404 gnttab_resume(void)
|
cl349@4693
|
405 {
|
cl349@4693
|
406 gnttab_setup_table_t setup;
|
cl349@4693
|
407 unsigned long frames[NR_GRANT_FRAMES];
|
cl349@4693
|
408 int i;
|
cl349@4693
|
409
|
cl349@4693
|
410 setup.dom = DOMID_SELF;
|
cl349@4693
|
411 setup.nr_frames = NR_GRANT_FRAMES;
|
cl349@4693
|
412 setup.frame_list = frames;
|
cl349@4693
|
413
|
cl349@4693
|
414 BUG_ON(HYPERVISOR_grant_table_op(GNTTABOP_setup_table, &setup, 1) != 0);
|
cl349@4693
|
415 BUG_ON(setup.status != 0);
|
cl349@4693
|
416
|
cl349@4693
|
417 for ( i = 0; i < NR_GRANT_FRAMES; i++ )
|
cl349@4777
|
418 set_fixmap(FIX_GNTTAB_END - i, frames[i] << PAGE_SHIFT);
|
cl349@4693
|
419
|
cl349@4693
|
420 return 0;
|
cl349@4693
|
421 }
|
cl349@4693
|
422
|
cl349@6349
|
423 int
|
cl349@6349
|
424 gnttab_suspend(void)
|
cl349@4693
|
425 {
|
cl349@4693
|
426 int i;
|
cl349@4693
|
427
|
cl349@4693
|
428 for ( i = 0; i < NR_GRANT_FRAMES; i++ )
|
cl349@4693
|
429 clear_fixmap(FIX_GNTTAB_END - i);
|
cl349@4693
|
430
|
cl349@4693
|
431 return 0;
|
cl349@4693
|
432 }
|
cl349@4693
|
433
|
cl349@6349
|
434 static int __init
|
cl349@6349
|
435 gnttab_init(void)
|
cl349@4693
|
436 {
|
cl349@4693
|
437 int i;
|
cl349@4693
|
438
|
cl349@4693
|
439 BUG_ON(gnttab_resume());
|
cl349@4693
|
440
|
cl349@4693
|
441 shared = (grant_entry_t *)fix_to_virt(FIX_GNTTAB_END);
|
cl349@4693
|
442
|
cl349@4693
|
443 for ( i = 0; i < NR_GRANT_ENTRIES; i++ )
|
cl349@6349
|
444 gnttab_list[i] = i + 1;
|
cl349@4693
|
445
|
cl349@4693
|
446 #ifdef CONFIG_PROC_FS
|
cl349@4693
|
447 /*
|
cl349@4693
|
448 * /proc/xen/grant : used by libxc to access grant tables
|
cl349@4693
|
449 */
|
cl349@4693
|
450 if ( (grant_pde = create_xen_proc_entry("grant", 0600)) == NULL )
|
cl349@4693
|
451 {
|
cl349@4693
|
452 WPRINTK("Unable to create grant xen proc entry\n");
|
cl349@4693
|
453 return -1;
|
cl349@4693
|
454 }
|
cl349@4693
|
455
|
cl349@4693
|
456 grant_file_ops.read = grant_pde->proc_fops->read;
|
cl349@4693
|
457 grant_file_ops.write = grant_pde->proc_fops->write;
|
cl349@4693
|
458
|
cl349@4693
|
459 grant_pde->proc_fops = &grant_file_ops;
|
cl349@4693
|
460
|
cl349@4693
|
461 grant_pde->read_proc = &grant_read;
|
cl349@4693
|
462 grant_pde->write_proc = &grant_write;
|
cl349@4693
|
463 #endif
|
cl349@4693
|
464
|
cl349@4693
|
465 printk("Grant table initialized\n");
|
cl349@4693
|
466 return 0;
|
cl349@4693
|
467 }
|
cl349@4693
|
468
|
cl349@4693
|
469 __initcall(gnttab_init);
|