ia64/xen-unstable

view linux-2.6.11-xen-sparse/arch/xen/kernel/gnttab.c @ 5272:cefe173ea09b

bitkeeper revision 1.1638 (429f0702i8Aq9b8ywQxXo9xS63DS0A)

missing braces for the for body (this is not python)

Signed-off-by: Vincent Hanquez <vincent@xensource.com>
author vh249@arcadians.cl.cam.ac.uk
date Thu Jun 02 13:17:54 2005 +0000 (2005-06-02)
parents 39bfbd5ae9b8
children 11dce3390a66
line source
1 /******************************************************************************
2 * gnttab.c
3 *
4 * Two sets of functionality:
5 * 1. Granting foreign access to our memory reservation.
6 * 2. Accessing others' memory reservations via grant references.
7 * (i.e., mechanisms for both sender and recipient of grant references)
8 *
9 * Copyright (c) 2005, Christopher Clark
10 * Copyright (c) 2004, K A Fraser
11 */
13 #include <linux/config.h>
14 #include <linux/module.h>
15 #include <linux/sched.h>
16 #include <asm/pgtable.h>
17 #include <asm/fixmap.h>
18 #include <asm/uaccess.h>
19 #include <asm-xen/xen_proc.h>
20 #include <asm-xen/linux-public/privcmd.h>
21 #include <asm-xen/gnttab.h>
23 #if 1
24 #define ASSERT(_p) \
25 if ( !(_p) ) { printk(KERN_ALERT"Assertion '%s': line %d, file %s\n", \
26 #_p , __LINE__, __FILE__); *(int*)0=0; }
27 #else
28 #define ASSERT(_p) ((void)0)
29 #endif
31 #define WPRINTK(fmt, args...) \
32 printk(KERN_WARNING "xen_grant: " fmt, ##args)
35 EXPORT_SYMBOL(gnttab_grant_foreign_access);
36 EXPORT_SYMBOL(gnttab_end_foreign_access);
37 EXPORT_SYMBOL(gnttab_query_foreign_access);
38 EXPORT_SYMBOL(gnttab_grant_foreign_transfer);
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_claim_grant_reference);
43 EXPORT_SYMBOL(gnttab_release_grant_reference);
44 EXPORT_SYMBOL(gnttab_grant_foreign_access_ref);
45 EXPORT_SYMBOL(gnttab_grant_foreign_transfer_ref);
47 static grant_ref_t gnttab_free_list[NR_GRANT_ENTRIES];
48 static grant_ref_t gnttab_free_head;
50 static grant_entry_t *shared;
52 /*
53 * Lock-free grant-entry allocator
54 */
56 static inline int
57 get_free_entry(
58 void)
59 {
60 grant_ref_t fh, nfh = gnttab_free_head;
61 do { if ( unlikely((fh = nfh) == NR_GRANT_ENTRIES) ) return -1; }
62 while ( unlikely((nfh = cmpxchg(&gnttab_free_head, fh,
63 gnttab_free_list[fh])) != fh) );
64 return fh;
65 }
67 static inline void
68 put_free_entry(
69 grant_ref_t ref)
70 {
71 grant_ref_t fh, nfh = gnttab_free_head;
72 do { gnttab_free_list[ref] = fh = nfh; wmb(); }
73 while ( unlikely((nfh = cmpxchg(&gnttab_free_head, fh, ref)) != fh) );
74 }
76 /*
77 * Public grant-issuing interface functions
78 */
80 int
81 gnttab_grant_foreign_access(
82 domid_t domid, unsigned long frame, int readonly)
83 {
84 int ref;
86 if ( unlikely((ref = get_free_entry()) == -1) )
87 return -ENOSPC;
89 shared[ref].frame = frame;
90 shared[ref].domid = domid;
91 wmb();
92 shared[ref].flags = GTF_permit_access | (readonly ? GTF_readonly : 0);
94 return ref;
95 }
97 void
98 gnttab_grant_foreign_access_ref(
99 grant_ref_t ref, domid_t domid, unsigned long frame, int readonly)
100 {
101 shared[ref].frame = frame;
102 shared[ref].domid = domid;
103 wmb();
104 shared[ref].flags = GTF_permit_access | (readonly ? GTF_readonly : 0);
105 }
108 int
109 gnttab_query_foreign_access( grant_ref_t ref )
110 {
111 u16 nflags;
113 nflags = shared[ref].flags;
115 return ( nflags & (GTF_reading|GTF_writing) );
116 }
118 void
119 gnttab_end_foreign_access( grant_ref_t ref, int readonly )
120 {
121 u16 flags, nflags;
123 nflags = shared[ref].flags;
124 do {
125 if ( (flags = nflags) & (GTF_reading|GTF_writing) )
126 printk(KERN_ALERT "WARNING: g.e. still in use!\n");
127 }
128 while ( (nflags = cmpxchg(&shared[ref].flags, flags, 0)) != flags );
130 put_free_entry(ref);
131 }
133 int
134 gnttab_grant_foreign_transfer(
135 domid_t domid, unsigned long pfn )
136 {
137 int ref;
139 if ( unlikely((ref = get_free_entry()) == -1) )
140 return -ENOSPC;
142 shared[ref].frame = pfn;
143 shared[ref].domid = domid;
144 wmb();
145 shared[ref].flags = GTF_accept_transfer;
147 return ref;
148 }
150 void
151 gnttab_grant_foreign_transfer_ref(
152 grant_ref_t ref, domid_t domid, unsigned long pfn )
153 {
154 shared[ref].frame = pfn;
155 shared[ref].domid = domid;
156 wmb();
157 shared[ref].flags = GTF_accept_transfer;
158 }
160 unsigned long
161 gnttab_end_foreign_transfer(
162 grant_ref_t ref)
163 {
164 unsigned long frame = 0;
165 u16 flags;
167 flags = shared[ref].flags;
168 ASSERT(flags == (GTF_accept_transfer | GTF_transfer_committed));
170 /*
171 * If a transfer is committed then wait for the frame address to appear.
172 * Otherwise invalidate the grant entry against future use.
173 */
174 if ( likely(flags != GTF_accept_transfer) ||
175 (cmpxchg(&shared[ref].flags, flags, 0) != GTF_accept_transfer) )
176 while ( unlikely((frame = shared[ref].frame) == 0) )
177 cpu_relax();
179 put_free_entry(ref);
181 return frame;
182 }
184 void
185 gnttab_free_grant_references( u16 count, grant_ref_t head )
186 {
187 /* TODO: O(N)...? */
188 grant_ref_t to_die = 0, next = head;
189 int i;
191 for ( i = 0; i < count; i++ )
192 {
193 to_die = next;
194 next = gnttab_free_list[next];
195 put_free_entry( to_die );
196 }
197 }
199 int
200 gnttab_alloc_grant_references( u16 count,
201 grant_ref_t *head,
202 grant_ref_t *terminal )
203 {
204 int i;
205 grant_ref_t h = gnttab_free_head;
207 for ( i = 0; i < count; i++ )
208 if ( unlikely(get_free_entry() == -1) )
209 goto not_enough_refs;
211 *head = h;
212 *terminal = gnttab_free_head;
214 return 0;
216 not_enough_refs:
217 gnttab_free_head = h;
218 return -ENOSPC;
219 }
221 int
222 gnttab_claim_grant_reference( grant_ref_t *private_head,
223 grant_ref_t terminal )
224 {
225 grant_ref_t g;
226 if ( unlikely((g = *private_head) == terminal) )
227 return -ENOSPC;
228 *private_head = gnttab_free_list[g];
229 return g;
230 }
232 void
233 gnttab_release_grant_reference( grant_ref_t *private_head,
234 grant_ref_t release )
235 {
236 gnttab_free_list[release] = *private_head;
237 *private_head = release;
238 }
240 /*
241 * ProcFS operations
242 */
244 #ifdef CONFIG_PROC_FS
246 static struct proc_dir_entry *grant_pde;
248 static int grant_ioctl(struct inode *inode, struct file *file,
249 unsigned int cmd, unsigned long data)
250 {
251 int ret;
252 privcmd_hypercall_t hypercall;
254 /* XXX Need safety checks here if using for anything other
255 * than debugging */
256 return -ENOSYS;
258 if ( cmd != IOCTL_PRIVCMD_HYPERCALL )
259 return -ENOSYS;
261 if ( copy_from_user(&hypercall, (void *)data, sizeof(hypercall)) )
262 return -EFAULT;
264 if ( hypercall.op != __HYPERVISOR_grant_table_op )
265 return -ENOSYS;
267 /* hypercall-invoking asm taken from privcmd.c */
268 __asm__ __volatile__ (
269 "pushl %%ebx; pushl %%ecx; pushl %%edx; pushl %%esi; pushl %%edi; "
270 "movl 4(%%eax),%%ebx ;"
271 "movl 8(%%eax),%%ecx ;"
272 "movl 12(%%eax),%%edx ;"
273 "movl 16(%%eax),%%esi ;"
274 "movl 20(%%eax),%%edi ;"
275 "movl (%%eax),%%eax ;"
276 TRAP_INSTR "; "
277 "popl %%edi; popl %%esi; popl %%edx; popl %%ecx; popl %%ebx"
278 : "=a" (ret) : "0" (&hypercall) : "memory" );
280 return ret;
281 }
283 static struct file_operations grant_file_ops = {
284 ioctl: grant_ioctl,
285 };
287 static int grant_read(char *page, char **start, off_t off,
288 int count, int *eof, void *data)
289 {
290 int len;
291 unsigned int i;
292 grant_entry_t *gt;
294 gt = (grant_entry_t *)shared;
295 len = 0;
297 for ( i = 0; i < NR_GRANT_ENTRIES; i++ )
298 /* TODO: safety catch here until this can handle >PAGE_SIZE output */
299 if (len > (PAGE_SIZE - 200))
300 {
301 len += sprintf( page + len, "Truncated.\n");
302 break;
303 }
305 if ( gt[i].flags )
306 len += sprintf( page + len,
307 "Grant: ref (0x%x) flags (0x%hx) dom (0x%hx) frame (0x%x)\n",
308 i,
309 gt[i].flags,
310 gt[i].domid,
311 gt[i].frame );
313 *eof = 1;
314 return len;
315 }
317 static int grant_write(struct file *file, const char __user *buffer,
318 unsigned long count, void *data)
319 {
320 /* TODO: implement this */
321 return -ENOSYS;
322 }
324 #endif /* CONFIG_PROC_FS */
326 int gnttab_resume(void)
327 {
328 gnttab_setup_table_t setup;
329 unsigned long frames[NR_GRANT_FRAMES];
330 int i;
332 setup.dom = DOMID_SELF;
333 setup.nr_frames = NR_GRANT_FRAMES;
334 setup.frame_list = frames;
336 BUG_ON(HYPERVISOR_grant_table_op(GNTTABOP_setup_table, &setup, 1) != 0);
337 BUG_ON(setup.status != 0);
339 for ( i = 0; i < NR_GRANT_FRAMES; i++ )
340 set_fixmap(FIX_GNTTAB_END - i, frames[i] << PAGE_SHIFT);
342 return 0;
343 }
345 int gnttab_suspend(void)
346 {
347 int i;
349 for ( i = 0; i < NR_GRANT_FRAMES; i++ )
350 clear_fixmap(FIX_GNTTAB_END - i);
352 return 0;
353 }
355 static int __init gnttab_init(void)
356 {
357 int i;
359 BUG_ON(gnttab_resume());
361 shared = (grant_entry_t *)fix_to_virt(FIX_GNTTAB_END);
363 for ( i = 0; i < NR_GRANT_ENTRIES; i++ )
364 gnttab_free_list[i] = i + 1;
366 #ifdef CONFIG_PROC_FS
367 /*
368 * /proc/xen/grant : used by libxc to access grant tables
369 */
370 if ( (grant_pde = create_xen_proc_entry("grant", 0600)) == NULL )
371 {
372 WPRINTK("Unable to create grant xen proc entry\n");
373 return -1;
374 }
376 grant_file_ops.read = grant_pde->proc_fops->read;
377 grant_file_ops.write = grant_pde->proc_fops->write;
379 grant_pde->proc_fops = &grant_file_ops;
381 grant_pde->read_proc = &grant_read;
382 grant_pde->write_proc = &grant_write;
383 #endif
385 printk("Grant table initialized\n");
386 return 0;
387 }
389 __initcall(gnttab_init);