debuggers.hg

view xen/common/compat/grant_table.c @ 22848:6341fe0f4e5a

Added tag 4.1.0-rc2 for changeset 9dca60d88c63
author Keir Fraser <keir@xen.org>
date Tue Jan 25 14:06:55 2011 +0000 (2011-01-25)
parents 95ea2052b41b
children
line source
1 /******************************************************************************
2 * common/compat/grant_table.c
3 *
4 */
6 #include <compat/grant_table.h>
8 #define xen_grant_entry_v1 grant_entry_v1
9 CHECK_grant_entry_v1;
10 #undef xen_grant_entry_v1
12 #define xen_grant_entry_header grant_entry_header
13 CHECK_grant_entry_header;
14 #undef xen_grant_entry_header
16 #define xen_grant_entry_v2 grant_entry_v2
17 CHECK_grant_entry_v2;
18 #undef xen_grant_entry_v2
20 #define xen_gnttab_map_grant_ref gnttab_map_grant_ref
21 CHECK_gnttab_map_grant_ref;
22 #undef xen_gnttab_map_grant_ref
24 #define xen_gnttab_unmap_grant_ref gnttab_unmap_grant_ref
25 CHECK_gnttab_unmap_grant_ref;
26 #undef xen_gnttab_unmap_grant_ref
28 #define xen_gnttab_unmap_and_replace gnttab_unmap_and_replace
29 CHECK_gnttab_unmap_and_replace;
30 #undef xen_gnttab_unmap_and_replace
32 DEFINE_XEN_GUEST_HANDLE(gnttab_setup_table_compat_t);
33 DEFINE_XEN_GUEST_HANDLE(gnttab_transfer_compat_t);
34 DEFINE_XEN_GUEST_HANDLE(gnttab_copy_compat_t);
36 #define xen_gnttab_dump_table gnttab_dump_table
37 CHECK_gnttab_dump_table;
38 #undef xen_gnttab_dump_table
40 #define xen_gnttab_set_version gnttab_set_version
41 CHECK_gnttab_set_version;
42 #undef xen_gnttab_set_version
44 DEFINE_XEN_GUEST_HANDLE(gnttab_get_status_frames_compat_t);
46 #define xen_gnttab_get_version gnttab_get_version
47 CHECK_gnttab_get_version;
48 #undef xen_gnttab_get_version
50 int compat_grant_table_op(unsigned int cmd,
51 XEN_GUEST_HANDLE(void) cmp_uop,
52 unsigned int count)
53 {
54 int rc = 0;
55 unsigned int i;
56 XEN_GUEST_HANDLE(void) cnt_uop;
58 set_xen_guest_handle(cnt_uop, NULL);
59 switch ( cmd )
60 {
61 #define CASE(name) \
62 case GNTTABOP_##name: \
63 if ( unlikely(!guest_handle_okay(guest_handle_cast(cmp_uop, \
64 gnttab_##name##_compat_t), \
65 count)) ) \
66 rc = -EFAULT; \
67 break
69 #ifndef CHECK_gnttab_map_grant_ref
70 CASE(map_grant_ref);
71 #endif
73 #ifndef CHECK_gnttab_unmap_grant_ref
74 CASE(unmap_grant_ref);
75 #endif
77 #ifndef CHECK_gnttab_unmap_and_replace
78 CASE(unmap_and_replace);
79 #endif
81 #ifndef CHECK_gnttab_setup_table
82 CASE(setup_table);
83 #endif
85 #ifndef CHECK_gnttab_transfer
86 CASE(transfer);
87 #endif
89 #ifndef CHECK_gnttab_copy
90 CASE(copy);
91 #endif
93 #ifndef CHECK_gnttab_dump_table
94 CASE(dump_table);
95 #endif
97 #ifndef CHECK_gnttab_get_status_frames
98 CASE(get_status_frames);
99 #endif
101 #undef CASE
102 default:
103 return do_grant_table_op(cmd, cmp_uop, count);
104 }
106 if ( (int)count < 0 )
107 rc = -EINVAL;
109 for ( i = 0; i < count && rc == 0; )
110 {
111 unsigned int n;
112 union {
113 XEN_GUEST_HANDLE(void) uop;
114 struct gnttab_setup_table *setup;
115 struct gnttab_transfer *xfer;
116 struct gnttab_copy *copy;
117 struct gnttab_get_status_frames *get_status;
118 } nat;
119 union {
120 struct compat_gnttab_setup_table setup;
121 struct compat_gnttab_transfer xfer;
122 struct compat_gnttab_copy copy;
123 struct compat_gnttab_get_status_frames get_status;
124 } cmp;
126 set_xen_guest_handle(nat.uop, COMPAT_ARG_XLAT_VIRT_BASE);
127 switch ( cmd )
128 {
129 case GNTTABOP_setup_table:
130 if ( unlikely(count > 1) )
131 rc = -EINVAL;
132 else if ( unlikely(__copy_from_guest(&cmp.setup, cmp_uop, 1)) )
133 rc = -EFAULT;
134 else if ( unlikely(!compat_handle_okay(cmp.setup.frame_list, cmp.setup.nr_frames)) )
135 rc = -EFAULT;
136 else
137 {
138 unsigned int max_frame_list_size_in_page =
139 (COMPAT_ARG_XLAT_SIZE - sizeof(*nat.setup)) /
140 sizeof(*nat.setup->frame_list.p);
141 if ( max_frame_list_size_in_page < max_nr_grant_frames )
142 {
143 gdprintk(XENLOG_WARNING,
144 "max_nr_grant_frames is too large (%u,%u)\n",
145 max_nr_grant_frames, max_frame_list_size_in_page);
146 rc = -EINVAL;
147 }
148 else
149 {
150 #define XLAT_gnttab_setup_table_HNDL_frame_list(_d_, _s_) \
151 set_xen_guest_handle((_d_)->frame_list, (unsigned long *)(nat.setup + 1))
152 XLAT_gnttab_setup_table(nat.setup, &cmp.setup);
153 #undef XLAT_gnttab_setup_table_HNDL_frame_list
154 rc = gnttab_setup_table(guest_handle_cast(nat.uop, gnttab_setup_table_t), 1);
155 }
156 }
157 ASSERT(rc <= 0);
158 if ( rc == 0 )
159 {
160 #define XLAT_gnttab_setup_table_HNDL_frame_list(_d_, _s_) \
161 do \
162 { \
163 if ( (_s_)->status == GNTST_okay ) \
164 { \
165 for ( i = 0; i < (_s_)->nr_frames; ++i ) \
166 { \
167 unsigned int frame = (_s_)->frame_list.p[i]; \
168 (void)__copy_to_compat_offset((_d_)->frame_list, i, &frame, 1); \
169 } \
170 } \
171 } while (0)
172 XLAT_gnttab_setup_table(&cmp.setup, nat.setup);
173 #undef XLAT_gnttab_setup_table_HNDL_frame_list
174 if ( unlikely(__copy_to_guest(cmp_uop, &cmp.setup, 1)) )
175 rc = -EFAULT;
176 else
177 i = 1;
178 }
179 break;
181 case GNTTABOP_transfer:
182 for ( n = 0; n < COMPAT_ARG_XLAT_SIZE / sizeof(*nat.xfer) && i < count && rc == 0; ++i, ++n )
183 {
184 if ( unlikely(__copy_from_guest_offset(&cmp.xfer, cmp_uop, i, 1)) )
185 rc = -EFAULT;
186 else
187 {
188 XLAT_gnttab_transfer(nat.xfer + n, &cmp.xfer);
189 }
190 }
191 if ( rc == 0 )
192 rc = gnttab_transfer(guest_handle_cast(nat.uop, gnttab_transfer_t), n);
193 if ( rc > 0 )
194 {
195 ASSERT(rc < n);
196 i -= n - rc;
197 n = rc;
198 }
199 if ( rc >= 0 )
200 {
201 XEN_GUEST_HANDLE(gnttab_transfer_compat_t) xfer;
203 xfer = guest_handle_cast(cmp_uop, gnttab_transfer_compat_t);
204 guest_handle_add_offset(xfer, i);
205 cnt_uop = guest_handle_cast(xfer, void);
206 while ( n-- )
207 {
208 guest_handle_add_offset(xfer, -1);
209 if ( __copy_field_to_guest(xfer, nat.xfer + n, status) )
210 rc = -EFAULT;
211 }
212 }
213 break;
215 case GNTTABOP_copy:
216 for ( n = 0; n < COMPAT_ARG_XLAT_SIZE / sizeof(*nat.copy) && i < count && rc == 0; ++i, ++n )
217 {
218 if ( unlikely(__copy_from_guest_offset(&cmp.copy, cmp_uop, i, 1)) )
219 rc = -EFAULT;
220 else
221 {
222 enum XLAT_gnttab_copy_source_u source_u;
223 enum XLAT_gnttab_copy_dest_u dest_u;
225 if ( cmp.copy.flags & GNTCOPY_source_gref )
226 source_u = XLAT_gnttab_copy_source_u_ref;
227 else
228 source_u = XLAT_gnttab_copy_source_u_gmfn;
229 if ( cmp.copy.flags & GNTCOPY_dest_gref )
230 dest_u = XLAT_gnttab_copy_dest_u_ref;
231 else
232 dest_u = XLAT_gnttab_copy_dest_u_gmfn;
233 XLAT_gnttab_copy(nat.copy + n, &cmp.copy);
234 }
235 }
236 if ( rc == 0 )
237 rc = gnttab_copy(guest_handle_cast(nat.uop, gnttab_copy_t), n);
238 if ( rc > 0 )
239 {
240 ASSERT(rc < n);
241 i -= n - rc;
242 n = rc;
243 }
244 if ( rc >= 0 )
245 {
246 XEN_GUEST_HANDLE(gnttab_copy_compat_t) copy;
248 copy = guest_handle_cast(cmp_uop, gnttab_copy_compat_t);
249 guest_handle_add_offset(copy, i);
250 cnt_uop = guest_handle_cast(copy, void);
251 while ( n-- )
252 {
253 guest_handle_add_offset(copy, -1);
254 if ( __copy_field_to_guest(copy, nat.copy + n, status) )
255 rc = -EFAULT;
256 }
257 }
258 break;
260 case GNTTABOP_get_status_frames: {
261 unsigned int max_frame_list_size_in_pages =
262 (COMPAT_ARG_XLAT_SIZE - sizeof(*nat.get_status)) /
263 sizeof(*nat.get_status->frame_list.p);
264 if ( count != 1)
265 {
266 rc = -EINVAL;
267 break;
268 }
269 if ( unlikely(__copy_from_guest(&cmp.get_status, cmp_uop, 1) ||
270 !compat_handle_okay(cmp.get_status.frame_list,
271 cmp.get_status.nr_frames)) )
272 {
273 rc = -EFAULT;
274 break;
275 }
276 if ( max_frame_list_size_in_pages <
277 grant_to_status_frames(max_nr_grant_frames) )
278 {
279 gdprintk(XENLOG_WARNING,
280 "grant_to_status_frames(max_nr_grant_frames) is too large (%u,%u)\n",
281 grant_to_status_frames(max_nr_grant_frames),
282 max_frame_list_size_in_pages);
283 rc = -EINVAL;
284 break;
285 }
287 #define XLAT_gnttab_get_status_frames_HNDL_frame_list(_d_, _s_) \
288 set_xen_guest_handle((_d_)->frame_list, (uint64_t *)(nat.get_status + 1))
289 XLAT_gnttab_get_status_frames(nat.get_status, &cmp.get_status);
290 #undef XLAT_gnttab_get_status_frames_HNDL_frame_list
292 rc = gnttab_get_status_frames(
293 guest_handle_cast(nat.uop, gnttab_get_status_frames_t),
294 count);
295 if ( rc >= 0 )
296 {
297 #define XLAT_gnttab_get_status_frames_HNDL_frame_list(_d_, _s_) \
298 do \
299 { \
300 if ( (_s_)->status == GNTST_okay ) \
301 { \
302 for ( i = 0; i < (_s_)->nr_frames; ++i ) \
303 { \
304 uint64_t frame = (_s_)->frame_list.p[i]; \
305 (void)__copy_to_compat_offset((_d_)->frame_list, i, &frame, 1); \
306 } \
307 } \
308 } while (0)
309 XLAT_gnttab_get_status_frames(&cmp.get_status, nat.get_status);
310 #undef XLAT_gnttab_get_status_frames_HNDL_frame_list
311 if ( unlikely(__copy_to_guest(cmp_uop, &cmp.get_status, 1)) )
312 rc = -EFAULT;
313 }
314 break;
315 }
317 default:
318 domain_crash(current->domain);
319 break;
320 }
321 }
323 if ( rc > 0 )
324 {
325 ASSERT(i < count);
326 ASSERT(!guest_handle_is_null(cnt_uop));
327 rc = hypercall_create_continuation(__HYPERVISOR_grant_table_op,
328 "ihi", cmd, cnt_uop, count - i);
329 }
331 return rc;
332 }
334 /*
335 * Local variables:
336 * mode: C
337 * c-set-style: "BSD"
338 * c-basic-offset: 4
339 * tab-width: 4
340 * indent-tabs-mode: nil
341 * End:
342 */