debuggers.hg

view xen/common/compat/grant_table.c @ 19969:09dbdf12c33d

Eliminate grant_table_op restriction

Eliminate the hard-coded, arbitrarily chosen limit of 512 grant table
ops a domain may submit at a time, and instead check for necessary
preemption after each individual element got processed, invoking the
hypercall continuation logic when necessary.

Signed-off-by: Jan Beulich <jbeulich@novell.com>
author Keir Fraser <keir.fraser@citrix.com>
date Mon Jul 13 12:18:04 2009 +0100 (2009-07-13)
parents bcee82a0e9d6
children 7d4f05a65d5a
line source
1 /******************************************************************************
2 * common/compat/grant_table.c
3 *
4 */
6 #include <compat/grant_table.h>
8 #define xen_grant_entry grant_entry
9 CHECK_grant_entry;
10 #undef xen_grant_entry
12 #define xen_gnttab_map_grant_ref gnttab_map_grant_ref
13 CHECK_gnttab_map_grant_ref;
14 #undef xen_gnttab_map_grant_ref
16 #define xen_gnttab_unmap_grant_ref gnttab_unmap_grant_ref
17 CHECK_gnttab_unmap_grant_ref;
18 #undef xen_gnttab_unmap_grant_ref
20 #define xen_gnttab_unmap_and_replace gnttab_unmap_and_replace
21 CHECK_gnttab_unmap_and_replace;
22 #undef xen_gnttab_unmap_and_replace
24 DEFINE_XEN_GUEST_HANDLE(gnttab_setup_table_compat_t);
25 DEFINE_XEN_GUEST_HANDLE(gnttab_transfer_compat_t);
26 DEFINE_XEN_GUEST_HANDLE(gnttab_copy_compat_t);
28 #define xen_gnttab_dump_table gnttab_dump_table
29 CHECK_gnttab_dump_table;
30 #undef xen_gnttab_dump_table
32 int compat_grant_table_op(unsigned int cmd,
33 XEN_GUEST_HANDLE(void) cmp_uop,
34 unsigned int count)
35 {
36 int rc = 0;
37 unsigned int i;
38 XEN_GUEST_HANDLE(void) cnt_uop;
40 set_xen_guest_handle(cnt_uop, NULL);
41 switch ( cmd )
42 {
43 #define CASE(name) \
44 case GNTTABOP_##name: \
45 if ( unlikely(!guest_handle_okay(guest_handle_cast(cmp_uop, \
46 gnttab_##name##_compat_t), \
47 count)) ) \
48 rc = -EFAULT; \
49 break
51 #ifndef CHECK_gnttab_map_grant_ref
52 CASE(map_grant_ref);
53 #endif
55 #ifndef CHECK_gnttab_unmap_grant_ref
56 CASE(unmap_grant_ref);
57 #endif
59 #ifndef CHECK_gnttab_unmap_and_replace
60 CASE(unmap_and_replace);
61 #endif
63 #ifndef CHECK_gnttab_setup_table
64 CASE(setup_table);
65 #endif
67 #ifndef CHECK_gnttab_transfer
68 CASE(transfer);
69 #endif
71 #ifndef CHECK_gnttab_copy
72 CASE(copy);
73 #endif
75 #ifndef CHECK_gnttab_dump_table
76 CASE(dump_table);
77 #endif
79 #undef CASE
80 default:
81 return do_grant_table_op(cmd, cmp_uop, count);
82 }
84 if ( (int)count < 0 )
85 rc = -EINVAL;
87 for ( i = 0; i < count && rc == 0; )
88 {
89 unsigned int n;
90 union {
91 XEN_GUEST_HANDLE(void) uop;
92 struct gnttab_setup_table *setup;
93 struct gnttab_transfer *xfer;
94 struct gnttab_copy *copy;
95 } nat;
96 union {
97 struct compat_gnttab_setup_table setup;
98 struct compat_gnttab_transfer xfer;
99 struct compat_gnttab_copy copy;
100 } cmp;
102 set_xen_guest_handle(nat.uop, COMPAT_ARG_XLAT_VIRT_BASE);
103 switch ( cmd )
104 {
105 case GNTTABOP_setup_table:
106 if ( unlikely(count > 1) )
107 rc = -EINVAL;
108 else if ( unlikely(__copy_from_guest(&cmp.setup, cmp_uop, 1)) )
109 rc = -EFAULT;
110 else if ( unlikely(!compat_handle_okay(cmp.setup.frame_list, cmp.setup.nr_frames)) )
111 rc = -EFAULT;
112 else
113 {
114 unsigned int max_frame_list_size_in_page =
115 (COMPAT_ARG_XLAT_SIZE - sizeof(*nat.setup)) /
116 sizeof(*nat.setup->frame_list.p);
117 if ( max_frame_list_size_in_page < max_nr_grant_frames )
118 {
119 gdprintk(XENLOG_WARNING,
120 "max_nr_grant_frames is too large (%u,%u)\n",
121 max_nr_grant_frames, max_frame_list_size_in_page);
122 rc = -EINVAL;
123 }
124 else
125 {
126 #define XLAT_gnttab_setup_table_HNDL_frame_list(_d_, _s_) \
127 set_xen_guest_handle((_d_)->frame_list, (unsigned long *)(nat.setup + 1))
128 XLAT_gnttab_setup_table(nat.setup, &cmp.setup);
129 #undef XLAT_gnttab_setup_table_HNDL_frame_list
130 rc = gnttab_setup_table(guest_handle_cast(nat.uop, gnttab_setup_table_t), 1);
131 }
132 }
133 ASSERT(rc <= 0);
134 if ( rc == 0 )
135 {
136 #define XLAT_gnttab_setup_table_HNDL_frame_list(_d_, _s_) \
137 do \
138 { \
139 if ( (_s_)->status == GNTST_okay ) \
140 { \
141 for ( i = 0; i < (_s_)->nr_frames; ++i ) \
142 { \
143 unsigned int frame = (_s_)->frame_list.p[i]; \
144 (void)__copy_to_compat_offset((_d_)->frame_list, i, &frame, 1); \
145 } \
146 } \
147 } while (0)
148 XLAT_gnttab_setup_table(&cmp.setup, nat.setup);
149 #undef XLAT_gnttab_setup_table_HNDL_frame_list
150 if ( unlikely(__copy_to_guest(cmp_uop, &cmp.setup, 1)) )
151 rc = -EFAULT;
152 else
153 i = 1;
154 }
155 break;
157 case GNTTABOP_transfer:
158 for ( n = 0; n < COMPAT_ARG_XLAT_SIZE / sizeof(*nat.xfer) && i < count && rc == 0; ++i, ++n )
159 {
160 if ( unlikely(__copy_from_guest_offset(&cmp.xfer, cmp_uop, i, 1)) )
161 rc = -EFAULT;
162 else
163 {
164 XLAT_gnttab_transfer(nat.xfer + n, &cmp.xfer);
165 }
166 }
167 if ( rc == 0 )
168 rc = gnttab_transfer(guest_handle_cast(nat.uop, gnttab_transfer_t), n);
169 if ( rc > 0 )
170 {
171 ASSERT(rc < n);
172 i -= n - rc;
173 n = rc;
174 }
175 if ( rc >= 0 )
176 {
177 XEN_GUEST_HANDLE(gnttab_transfer_compat_t) xfer;
179 xfer = guest_handle_cast(cmp_uop, gnttab_transfer_compat_t);
180 guest_handle_add_offset(xfer, i);
181 cnt_uop = guest_handle_cast(xfer, void);
182 while ( n-- )
183 {
184 guest_handle_add_offset(xfer, -1);
185 if ( __copy_field_to_guest(xfer, nat.xfer + n, status) )
186 rc = -EFAULT;
187 }
188 }
189 break;
191 case GNTTABOP_copy:
192 for ( n = 0; n < COMPAT_ARG_XLAT_SIZE / sizeof(*nat.copy) && i < count && rc == 0; ++i, ++n )
193 {
194 if ( unlikely(__copy_from_guest_offset(&cmp.copy, cmp_uop, i, 1)) )
195 rc = -EFAULT;
196 else
197 {
198 enum XLAT_gnttab_copy_source_u source_u;
199 enum XLAT_gnttab_copy_dest_u dest_u;
201 if ( cmp.copy.flags & GNTCOPY_source_gref )
202 source_u = XLAT_gnttab_copy_source_u_ref;
203 else
204 source_u = XLAT_gnttab_copy_source_u_gmfn;
205 if ( cmp.copy.flags & GNTCOPY_dest_gref )
206 dest_u = XLAT_gnttab_copy_dest_u_ref;
207 else
208 dest_u = XLAT_gnttab_copy_dest_u_gmfn;
209 XLAT_gnttab_copy(nat.copy + n, &cmp.copy);
210 }
211 }
212 if ( rc == 0 )
213 rc = gnttab_copy(guest_handle_cast(nat.uop, gnttab_copy_t), n);
214 if ( rc > 0 )
215 {
216 ASSERT(rc < n);
217 i -= n - rc;
218 n = rc;
219 }
220 if ( rc >= 0 )
221 {
222 XEN_GUEST_HANDLE(gnttab_copy_compat_t) copy;
224 copy = guest_handle_cast(cmp_uop, gnttab_copy_compat_t);
225 guest_handle_add_offset(copy, i);
226 cnt_uop = guest_handle_cast(copy, void);
227 while ( n-- )
228 {
229 guest_handle_add_offset(copy, -1);
230 if ( __copy_field_to_guest(copy, nat.copy + n, status) )
231 rc = -EFAULT;
232 }
233 }
234 break;
236 default:
237 domain_crash(current->domain);
238 break;
239 }
240 }
242 if ( rc > 0 )
243 {
244 ASSERT(i < count);
245 ASSERT(!guest_handle_is_null(cnt_uop));
246 rc = hypercall_create_continuation(__HYPERVISOR_grant_table_op,
247 "ihi", cmd, cnt_uop, count - i);
248 }
250 return rc;
251 }
253 /*
254 * Local variables:
255 * mode: C
256 * c-set-style: "BSD"
257 * c-basic-offset: 4
258 * tab-width: 4
259 * indent-tabs-mode: nil
260 * End:
261 */