direct-io.hg

view linux-2.6-xen-sparse/arch/xen/kernel/gnttab.c @ 8670:d8232e9f7988

Remove unneeded /proc/xen/grant and its libxc wrapper.

Signed-off-by: Keir Fraser <keir@xensource.com>
author kaf24@firebug.cl.cam.ac.uk
date Thu Jan 26 00:17:06 2006 +0100 (2006-01-26)
parents 4dbca1428acd
children 990c009015e8
line source
1 /******************************************************************************
2 * gnttab.c
3 *
4 * Granting foreign access to our memory reservation.
5 *
6 * Copyright (c) 2005, Christopher Clark
7 * Copyright (c) 2004-2005, K A Fraser
8 */
10 #include <linux/config.h>
11 #include <linux/module.h>
12 #include <linux/sched.h>
13 #include <asm/pgtable.h>
14 #include <asm-xen/xen-public/xen.h>
15 #include <asm/fixmap.h>
16 #include <asm/uaccess.h>
17 #include <asm-xen/linux-public/privcmd.h>
18 #include <asm-xen/gnttab.h>
19 #include <asm/synch_bitops.h>
21 #if 1
22 #define ASSERT(_p) \
23 if ( !(_p) ) { printk(KERN_ALERT"Assertion '%s': line %d, file %s\n", \
24 #_p , __LINE__, __FILE__); *(int*)0=0; }
25 #else
26 #define ASSERT(_p) ((void)0)
27 #endif
29 #define WPRINTK(fmt, args...) \
30 printk(KERN_WARNING "xen_grant: " fmt, ##args)
33 EXPORT_SYMBOL(gnttab_grant_foreign_access);
34 EXPORT_SYMBOL(gnttab_end_foreign_access_ref);
35 EXPORT_SYMBOL(gnttab_end_foreign_access);
36 EXPORT_SYMBOL(gnttab_query_foreign_access);
37 EXPORT_SYMBOL(gnttab_grant_foreign_transfer);
38 EXPORT_SYMBOL(gnttab_end_foreign_transfer_ref);
39 EXPORT_SYMBOL(gnttab_end_foreign_transfer);
40 EXPORT_SYMBOL(gnttab_alloc_grant_references);
41 EXPORT_SYMBOL(gnttab_free_grant_references);
42 EXPORT_SYMBOL(gnttab_free_grant_reference);
43 EXPORT_SYMBOL(gnttab_claim_grant_reference);
44 EXPORT_SYMBOL(gnttab_release_grant_reference);
45 EXPORT_SYMBOL(gnttab_request_free_callback);
46 EXPORT_SYMBOL(gnttab_grant_foreign_access_ref);
47 EXPORT_SYMBOL(gnttab_grant_foreign_transfer_ref);
49 /* External tools reserve first few grant table entries. */
50 #define NR_RESERVED_ENTRIES 8
52 #define NR_GRANT_ENTRIES (NR_GRANT_FRAMES * PAGE_SIZE / sizeof(grant_entry_t))
53 #define GNTTAB_LIST_END (NR_GRANT_ENTRIES + 1)
55 static grant_ref_t gnttab_list[NR_GRANT_ENTRIES];
56 static int gnttab_free_count;
57 static grant_ref_t gnttab_free_head;
58 static spinlock_t gnttab_list_lock = SPIN_LOCK_UNLOCKED;
60 static grant_entry_t *shared;
62 static struct gnttab_free_callback *gnttab_free_callback_list = NULL;
64 static int
65 get_free_entries(int count)
66 {
67 unsigned long flags;
68 int ref;
69 grant_ref_t head;
70 spin_lock_irqsave(&gnttab_list_lock, flags);
71 if (gnttab_free_count < count) {
72 spin_unlock_irqrestore(&gnttab_list_lock, flags);
73 return -1;
74 }
75 ref = head = gnttab_free_head;
76 gnttab_free_count -= count;
77 while (count-- > 1)
78 head = gnttab_list[head];
79 gnttab_free_head = gnttab_list[head];
80 gnttab_list[head] = GNTTAB_LIST_END;
81 spin_unlock_irqrestore(&gnttab_list_lock, flags);
82 return ref;
83 }
85 #define get_free_entry() get_free_entries(1)
87 static void
88 do_free_callbacks(void)
89 {
90 struct gnttab_free_callback *callback, *next;
92 callback = gnttab_free_callback_list;
93 gnttab_free_callback_list = NULL;
95 while (callback != NULL) {
96 next = callback->next;
97 if (gnttab_free_count >= callback->count) {
98 callback->next = NULL;
99 callback->fn(callback->arg);
100 } else {
101 callback->next = gnttab_free_callback_list;
102 gnttab_free_callback_list = callback;
103 }
104 callback = next;
105 }
106 }
108 static inline void
109 check_free_callbacks(void)
110 {
111 if (unlikely(gnttab_free_callback_list))
112 do_free_callbacks();
113 }
115 static void
116 put_free_entry(grant_ref_t ref)
117 {
118 unsigned long flags;
119 spin_lock_irqsave(&gnttab_list_lock, flags);
120 gnttab_list[ref] = gnttab_free_head;
121 gnttab_free_head = ref;
122 gnttab_free_count++;
123 check_free_callbacks();
124 spin_unlock_irqrestore(&gnttab_list_lock, flags);
125 }
127 /*
128 * Public grant-issuing interface functions
129 */
131 int
132 gnttab_grant_foreign_access(domid_t domid, unsigned long frame, int readonly)
133 {
134 int ref;
136 if (unlikely((ref = get_free_entry()) == -1))
137 return -ENOSPC;
139 shared[ref].frame = frame;
140 shared[ref].domid = domid;
141 wmb();
142 shared[ref].flags = GTF_permit_access | (readonly ? GTF_readonly : 0);
144 return ref;
145 }
147 void
148 gnttab_grant_foreign_access_ref(grant_ref_t ref, domid_t domid,
149 unsigned long frame, int readonly)
150 {
151 shared[ref].frame = frame;
152 shared[ref].domid = domid;
153 wmb();
154 shared[ref].flags = GTF_permit_access | (readonly ? GTF_readonly : 0);
155 }
158 int
159 gnttab_query_foreign_access(grant_ref_t ref)
160 {
161 u16 nflags;
163 nflags = shared[ref].flags;
165 return (nflags & (GTF_reading|GTF_writing));
166 }
168 int
169 gnttab_end_foreign_access_ref(grant_ref_t ref, int readonly)
170 {
171 u16 flags, nflags;
173 nflags = shared[ref].flags;
174 do {
175 if ( (flags = nflags) & (GTF_reading|GTF_writing) ) {
176 printk(KERN_ALERT "WARNING: g.e. still in use!\n");
177 return 0;
178 }
179 }
180 while ((nflags = synch_cmpxchg(&shared[ref].flags, flags, 0)) !=
181 flags);
183 return 1;
184 }
186 void
187 gnttab_end_foreign_access(grant_ref_t ref, int readonly, unsigned long page)
188 {
189 if (gnttab_end_foreign_access_ref(ref, readonly)) {
190 put_free_entry(ref);
191 if (page != 0) {
192 free_page(page);
193 }
194 }
195 else {
196 /* XXX This needs to be fixed so that the ref and page are
197 placed on a list to be freed up later. */
198 printk(KERN_WARNING
199 "WARNING: leaking g.e. and page still in use!\n");
200 }
201 }
203 int
204 gnttab_grant_foreign_transfer(domid_t domid)
205 {
206 int ref;
208 if (unlikely((ref = get_free_entry()) == -1))
209 return -ENOSPC;
211 shared[ref].frame = 0;
212 shared[ref].domid = domid;
213 wmb();
214 shared[ref].flags = GTF_accept_transfer;
216 return ref;
217 }
219 void
220 gnttab_grant_foreign_transfer_ref(grant_ref_t ref, domid_t domid)
221 {
222 shared[ref].frame = 0;
223 shared[ref].domid = domid;
224 wmb();
225 shared[ref].flags = GTF_accept_transfer;
226 }
228 unsigned long
229 gnttab_end_foreign_transfer_ref(grant_ref_t ref)
230 {
231 unsigned long frame;
232 u16 flags;
234 /*
235 * If a transfer is not even yet started, try to reclaim the grant
236 * reference and return failure (== 0).
237 */
238 while (!((flags = shared[ref].flags) & GTF_transfer_committed)) {
239 if ( synch_cmpxchg(&shared[ref].flags, flags, 0) == flags )
240 return 0;
241 cpu_relax();
242 }
244 /* If a transfer is in progress then wait until it is completed. */
245 while (!(flags & GTF_transfer_completed)) {
246 flags = shared[ref].flags;
247 cpu_relax();
248 }
250 /* Read the frame number /after/ reading completion status. */
251 rmb();
252 frame = shared[ref].frame;
253 BUG_ON(frame == 0);
255 return frame;
256 }
258 unsigned long
259 gnttab_end_foreign_transfer(grant_ref_t ref)
260 {
261 unsigned long frame = gnttab_end_foreign_transfer_ref(ref);
262 put_free_entry(ref);
263 return frame;
264 }
266 void
267 gnttab_free_grant_reference(grant_ref_t ref)
268 {
270 put_free_entry(ref);
271 }
273 void
274 gnttab_free_grant_references(grant_ref_t head)
275 {
276 grant_ref_t ref;
277 unsigned long flags;
278 int count = 1;
279 if (head == GNTTAB_LIST_END)
280 return;
281 spin_lock_irqsave(&gnttab_list_lock, flags);
282 ref = head;
283 while (gnttab_list[ref] != GNTTAB_LIST_END) {
284 ref = gnttab_list[ref];
285 count++;
286 }
287 gnttab_list[ref] = gnttab_free_head;
288 gnttab_free_head = head;
289 gnttab_free_count += count;
290 check_free_callbacks();
291 spin_unlock_irqrestore(&gnttab_list_lock, flags);
292 }
294 int
295 gnttab_alloc_grant_references(u16 count, grant_ref_t *head)
296 {
297 int h = get_free_entries(count);
299 if (h == -1)
300 return -ENOSPC;
302 *head = h;
304 return 0;
305 }
307 int
308 gnttab_claim_grant_reference(grant_ref_t *private_head)
309 {
310 grant_ref_t g = *private_head;
311 if (unlikely(g == GNTTAB_LIST_END))
312 return -ENOSPC;
313 *private_head = gnttab_list[g];
314 return g;
315 }
317 void
318 gnttab_release_grant_reference(grant_ref_t *private_head, grant_ref_t release)
319 {
320 gnttab_list[release] = *private_head;
321 *private_head = release;
322 }
324 void
325 gnttab_request_free_callback(struct gnttab_free_callback *callback,
326 void (*fn)(void *), void *arg, u16 count)
327 {
328 unsigned long flags;
329 spin_lock_irqsave(&gnttab_list_lock, flags);
330 if (callback->next)
331 goto out;
332 callback->fn = fn;
333 callback->arg = arg;
334 callback->count = count;
335 callback->next = gnttab_free_callback_list;
336 gnttab_free_callback_list = callback;
337 check_free_callbacks();
338 out:
339 spin_unlock_irqrestore(&gnttab_list_lock, flags);
340 }
342 int
343 gnttab_resume(void)
344 {
345 gnttab_setup_table_t setup;
346 unsigned long frames[NR_GRANT_FRAMES];
347 int i;
349 setup.dom = DOMID_SELF;
350 setup.nr_frames = NR_GRANT_FRAMES;
351 setup.frame_list = frames;
353 BUG_ON(HYPERVISOR_grant_table_op(GNTTABOP_setup_table, &setup, 1));
354 BUG_ON(setup.status != 0);
356 #ifdef __ia64__
357 shared = __va(frames[0] << PAGE_SHIFT);
358 printk("grant table at %p\n", shared);
359 #else
360 for (i = 0; i < NR_GRANT_FRAMES; i++)
361 set_fixmap(FIX_GNTTAB_END - i, frames[i] << PAGE_SHIFT);
362 #endif
364 return 0;
365 }
367 int
368 gnttab_suspend(void)
369 {
370 int i;
372 for (i = 0; i < NR_GRANT_FRAMES; i++)
373 clear_fixmap(FIX_GNTTAB_END - i);
375 return 0;
376 }
378 static int __init
379 gnttab_init(void)
380 {
381 int i;
383 if (xen_init() < 0)
384 return -ENODEV;
386 BUG_ON(gnttab_resume());
388 #ifndef __ia64__
389 shared = (grant_entry_t *)fix_to_virt(FIX_GNTTAB_END);
390 #endif
392 for (i = NR_RESERVED_ENTRIES; i < NR_GRANT_ENTRIES; i++)
393 gnttab_list[i] = i + 1;
394 gnttab_free_count = NR_GRANT_ENTRIES - NR_RESERVED_ENTRIES;
395 gnttab_free_head = NR_RESERVED_ENTRIES;
397 printk("Grant table initialized\n");
398 return 0;
399 }
401 core_initcall(gnttab_init);
403 /*
404 * Local variables:
405 * c-file-style: "linux"
406 * indent-tabs-mode: t
407 * c-indent-level: 8
408 * c-basic-offset: 8
409 * tab-width: 8
410 * End:
411 */