ia64/xen-unstable

view extras/mini-os/gnttab.c @ 18811:390ef36eb596

Remove Xen-private definitions from kexec public header.

Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Wed Nov 19 13:13:39 2008 +0000 (2008-11-19)
parents a1c98534418b
children
line source
1 /*
2 ****************************************************************************
3 * (C) 2006 - Cambridge University
4 ****************************************************************************
5 *
6 * File: gnttab.c
7 * Author: Steven Smith (sos22@cam.ac.uk)
8 * Changes: Grzegorz Milos (gm281@cam.ac.uk)
9 *
10 * Date: July 2006
11 *
12 * Environment: Xen Minimal OS
13 * Description: Simple grant tables implementation. About as stupid as it's
14 * possible to be and still work.
15 *
16 ****************************************************************************
17 */
18 #include <os.h>
19 #include <mm.h>
20 #include <gnttab.h>
21 #include <semaphore.h>
23 #define NR_RESERVED_ENTRIES 8
25 /* NR_GRANT_FRAMES must be less than or equal to that configured in Xen */
26 #ifdef __ia64__
27 #define NR_GRANT_FRAMES 1
28 #else
29 #define NR_GRANT_FRAMES 4
30 #endif
31 #define NR_GRANT_ENTRIES (NR_GRANT_FRAMES * PAGE_SIZE / sizeof(grant_entry_t))
33 static grant_entry_t *gnttab_table;
34 static grant_ref_t gnttab_list[NR_GRANT_ENTRIES];
35 #ifdef GNT_DEBUG
36 static char inuse[NR_GRANT_ENTRIES];
37 #endif
38 static __DECLARE_SEMAPHORE_GENERIC(gnttab_sem, 0);
40 static void
41 put_free_entry(grant_ref_t ref)
42 {
43 unsigned long flags;
44 local_irq_save(flags);
45 #ifdef GNT_DEBUG
46 BUG_ON(!inuse[ref]);
47 inuse[ref] = 0;
48 #endif
49 gnttab_list[ref] = gnttab_list[0];
50 gnttab_list[0] = ref;
51 local_irq_restore(flags);
52 up(&gnttab_sem);
53 }
55 static grant_ref_t
56 get_free_entry(void)
57 {
58 unsigned int ref;
59 unsigned long flags;
60 down(&gnttab_sem);
61 local_irq_save(flags);
62 ref = gnttab_list[0];
63 BUG_ON(ref < NR_RESERVED_ENTRIES || ref >= NR_GRANT_ENTRIES);
64 gnttab_list[0] = gnttab_list[ref];
65 #ifdef GNT_DEBUG
66 BUG_ON(inuse[ref]);
67 inuse[ref] = 1;
68 #endif
69 local_irq_restore(flags);
70 return ref;
71 }
73 grant_ref_t
74 gnttab_grant_access(domid_t domid, unsigned long frame, int readonly)
75 {
76 grant_ref_t ref;
78 ref = get_free_entry();
79 gnttab_table[ref].frame = frame;
80 gnttab_table[ref].domid = domid;
81 wmb();
82 readonly *= GTF_readonly;
83 gnttab_table[ref].flags = GTF_permit_access | readonly;
85 return ref;
86 }
88 grant_ref_t
89 gnttab_grant_transfer(domid_t domid, unsigned long pfn)
90 {
91 grant_ref_t ref;
93 ref = get_free_entry();
94 gnttab_table[ref].frame = pfn;
95 gnttab_table[ref].domid = domid;
96 wmb();
97 gnttab_table[ref].flags = GTF_accept_transfer;
99 return ref;
100 }
102 int
103 gnttab_end_access(grant_ref_t ref)
104 {
105 u16 flags, nflags;
107 BUG_ON(ref >= NR_GRANT_ENTRIES || ref < NR_RESERVED_ENTRIES);
109 nflags = gnttab_table[ref].flags;
110 do {
111 if ((flags = nflags) & (GTF_reading|GTF_writing)) {
112 printk("WARNING: g.e. still in use! (%x)\n", flags);
113 return 0;
114 }
115 } while ((nflags = synch_cmpxchg(&gnttab_table[ref].flags, flags, 0)) !=
116 flags);
118 put_free_entry(ref);
119 return 1;
120 }
122 unsigned long
123 gnttab_end_transfer(grant_ref_t ref)
124 {
125 unsigned long frame;
126 u16 flags;
128 BUG_ON(ref >= NR_GRANT_ENTRIES || ref < NR_RESERVED_ENTRIES);
130 while (!((flags = gnttab_table[ref].flags) & GTF_transfer_committed)) {
131 if (synch_cmpxchg(&gnttab_table[ref].flags, flags, 0) == flags) {
132 printk("Release unused transfer grant.\n");
133 put_free_entry(ref);
134 return 0;
135 }
136 }
138 /* If a transfer is in progress then wait until it is completed. */
139 while (!(flags & GTF_transfer_completed)) {
140 flags = gnttab_table[ref].flags;
141 }
143 /* Read the frame number /after/ reading completion status. */
144 rmb();
145 frame = gnttab_table[ref].frame;
147 put_free_entry(ref);
149 return frame;
150 }
152 grant_ref_t
153 gnttab_alloc_and_grant(void **map)
154 {
155 unsigned long mfn;
156 grant_ref_t gref;
158 *map = (void *)alloc_page();
159 mfn = virt_to_mfn(*map);
160 gref = gnttab_grant_access(0, mfn, 0);
161 return gref;
162 }
164 static const char * const gnttabop_error_msgs[] = GNTTABOP_error_msgs;
166 const char *
167 gnttabop_error(int16_t status)
168 {
169 status = -status;
170 if (status < 0 || status >= ARRAY_SIZE(gnttabop_error_msgs))
171 return "bad status";
172 else
173 return gnttabop_error_msgs[status];
174 }
176 void
177 init_gnttab(void)
178 {
179 struct gnttab_setup_table setup;
180 unsigned long frames[NR_GRANT_FRAMES];
181 int i;
183 #ifdef GNT_DEBUG
184 memset(inuse, 1, sizeof(inuse));
185 #endif
186 for (i = NR_RESERVED_ENTRIES; i < NR_GRANT_ENTRIES; i++)
187 put_free_entry(i);
189 setup.dom = DOMID_SELF;
190 setup.nr_frames = NR_GRANT_FRAMES;
191 set_xen_guest_handle(setup.frame_list, frames);
193 HYPERVISOR_grant_table_op(GNTTABOP_setup_table, &setup, 1);
194 gnttab_table = map_frames(frames, NR_GRANT_FRAMES);
195 printk("gnttab_table mapped at %p.\n", gnttab_table);
196 }
198 void
199 fini_gnttab(void)
200 {
201 struct gnttab_setup_table setup;
203 setup.dom = DOMID_SELF;
204 setup.nr_frames = 0;
206 HYPERVISOR_grant_table_op(GNTTABOP_setup_table, &setup, 1);
207 }