source: trunk/packages/xen-common/xen-common/xen/common/compat/grant_table.c @ 34

Last change on this file since 34 was 34, checked in by hartmans, 17 years ago

Add xen and xen-common

File size: 6.8 KB
Line 
1/******************************************************************************
2 * common/compat/grant_table.c
3 *
4 */
5
6#include <compat/grant_table.h>
7
8#define xen_grant_entry grant_entry
9CHECK_grant_entry;
10#undef xen_grant_entry
11
12#define xen_gnttab_map_grant_ref gnttab_map_grant_ref
13CHECK_gnttab_map_grant_ref;
14#undef xen_gnttab_map_grant_ref
15
16#define xen_gnttab_unmap_grant_ref gnttab_unmap_grant_ref
17CHECK_gnttab_unmap_grant_ref;
18#undef xen_gnttab_unmap_grant_ref
19
20DEFINE_XEN_GUEST_HANDLE(gnttab_setup_table_compat_t);
21DEFINE_XEN_GUEST_HANDLE(gnttab_transfer_compat_t);
22DEFINE_XEN_GUEST_HANDLE(gnttab_copy_compat_t);
23
24#define xen_gnttab_dump_table gnttab_dump_table
25CHECK_gnttab_dump_table;
26#undef xen_gnttab_dump_table
27
28int compat_grant_table_op(unsigned int cmd,
29                          XEN_GUEST_HANDLE(void) cmp_uop,
30                          unsigned int count)
31{
32    int rc = 0;
33    unsigned int i;
34
35    switch ( cmd )
36    {
37#define CASE(name) \
38    case GNTTABOP_##name: \
39        if ( unlikely(!guest_handle_okay(guest_handle_cast(cmp_uop, \
40                                                           gnttab_##name##_compat_t), \
41                                         count)) ) \
42            rc = -EFAULT; \
43        break
44
45#ifndef CHECK_gnttab_map_grant_ref
46    CASE(map_grant_ref);
47#endif
48
49#ifndef CHECK_gnttab_unmap_grant_ref
50    CASE(unmap_grant_ref);
51#endif
52
53#ifndef CHECK_gnttab_setup_table
54    CASE(setup_table);
55#endif
56
57#ifndef CHECK_gnttab_transfer
58    CASE(transfer);
59#endif
60
61#ifndef CHECK_gnttab_copy
62    CASE(copy);
63#endif
64
65#ifndef CHECK_gnttab_dump_table
66    CASE(dump_table);
67#endif
68
69#undef CASE
70    default:
71        return do_grant_table_op(cmd, cmp_uop, count);
72    }
73
74    if ( count > 512 )
75        rc = -EINVAL;
76
77    for ( i = 0; i < count && rc == 0; )
78    {
79        unsigned int n;
80        union {
81            XEN_GUEST_HANDLE(void) uop;
82            struct gnttab_setup_table *setup;
83            struct gnttab_transfer *xfer;
84            struct gnttab_copy *copy;
85        } nat;
86        union {
87            struct compat_gnttab_setup_table setup;
88            struct compat_gnttab_transfer xfer;
89            struct compat_gnttab_copy copy;
90        } cmp;
91
92        set_xen_guest_handle(nat.uop, (void *)COMPAT_ARG_XLAT_VIRT_START(current->vcpu_id));
93        switch ( cmd )
94        {
95        case GNTTABOP_setup_table:
96            if ( unlikely(count > 1) )
97                rc = -EINVAL;
98            else if ( unlikely(__copy_from_guest(&cmp.setup, cmp_uop, 1)) )
99                rc = -EFAULT;
100            else if ( unlikely(!compat_handle_okay(cmp.setup.frame_list, cmp.setup.nr_frames)) )
101                rc = -EFAULT;
102            else
103            {
104                BUG_ON((COMPAT_ARG_XLAT_SIZE - sizeof(*nat.setup)) / sizeof(*nat.setup->frame_list.p) < max_nr_grant_frames);
105#define XLAT_gnttab_setup_table_HNDL_frame_list(_d_, _s_) \
106                set_xen_guest_handle((_d_)->frame_list, (unsigned long *)(nat.setup + 1))
107                XLAT_gnttab_setup_table(nat.setup, &cmp.setup);
108#undef XLAT_gnttab_setup_table_HNDL_frame_list
109                rc = gnttab_setup_table(guest_handle_cast(nat.uop, gnttab_setup_table_t), 1);
110            }
111            if ( rc == 0 )
112            {
113#define XLAT_gnttab_setup_table_HNDL_frame_list(_d_, _s_) \
114                do \
115                { \
116                    if ( (_s_)->status == GNTST_okay ) \
117                    { \
118                        for ( i = 0; i < (_s_)->nr_frames; ++i ) \
119                        { \
120                            unsigned int frame = (_s_)->frame_list.p[i]; \
121                            BUG_ON(frame != (_s_)->frame_list.p[i]); \
122                            (void)__copy_to_compat_offset((_d_)->frame_list, i, &frame, 1); \
123                        } \
124                    } \
125                } while (0)
126                XLAT_gnttab_setup_table(&cmp.setup, nat.setup);
127#undef XLAT_gnttab_setup_table_HNDL_frame_list
128                if ( unlikely(__copy_to_guest(cmp_uop, &cmp.setup, 1)) )
129                    rc = -EFAULT;
130                else
131                    i = 1;
132            }
133            break;
134
135        case GNTTABOP_transfer:
136            for ( n = 0; n < COMPAT_ARG_XLAT_SIZE / sizeof(*nat.xfer) && i < count && rc == 0; ++i, ++n )
137            {
138                if ( unlikely(__copy_from_guest_offset(&cmp.xfer, cmp_uop, i, 1)) )
139                    rc = -EFAULT;
140                else
141                {
142                    XLAT_gnttab_transfer(nat.xfer + n, &cmp.xfer);
143                }
144            }
145            if ( rc == 0 )
146                rc = gnttab_transfer(guest_handle_cast(nat.uop, gnttab_transfer_t), n);
147            if ( rc == 0 )
148            {
149                XEN_GUEST_HANDLE(gnttab_transfer_compat_t) xfer;
150
151                xfer = guest_handle_cast(cmp_uop, gnttab_transfer_compat_t);
152                guest_handle_add_offset(xfer, i);
153                while ( n-- )
154                {
155                    guest_handle_add_offset(xfer, -1);
156                    if ( __copy_field_to_guest(xfer, nat.xfer, status) )
157                        rc = -EFAULT;
158                }
159            }
160            break;
161
162        case GNTTABOP_copy:
163            for ( n = 0; n < COMPAT_ARG_XLAT_SIZE / sizeof(*nat.copy) && i < count && rc == 0; ++i, ++n )
164            {
165                if ( unlikely(__copy_from_guest_offset(&cmp.copy, cmp_uop, i, 1)) )
166                    rc = -EFAULT;
167                else
168                {
169                    enum XLAT_gnttab_copy_source_u source_u;
170                    enum XLAT_gnttab_copy_dest_u dest_u;
171
172                    if ( cmp.copy.flags & GNTCOPY_source_gref )
173                        source_u = XLAT_gnttab_copy_source_u_ref;
174                    else
175                        source_u = XLAT_gnttab_copy_source_u_gmfn;
176                    if ( cmp.copy.flags & GNTCOPY_dest_gref )
177                        dest_u = XLAT_gnttab_copy_dest_u_ref;
178                    else
179                        dest_u = XLAT_gnttab_copy_dest_u_gmfn;
180                    XLAT_gnttab_copy(nat.copy + n, &cmp.copy);
181                }
182            }
183            if ( rc == 0 )
184                rc = gnttab_copy(guest_handle_cast(nat.uop, gnttab_copy_t), n);
185            if ( rc == 0 )
186            {
187                XEN_GUEST_HANDLE(gnttab_copy_compat_t) copy;
188
189                copy = guest_handle_cast(cmp_uop, gnttab_copy_compat_t);
190                guest_handle_add_offset(copy, i);
191                while ( n-- )
192                {
193                    guest_handle_add_offset(copy, -1);
194                    if ( __copy_field_to_guest(copy, nat.copy, status) )
195                        rc = -EFAULT;
196                }
197            }
198            break;
199
200        default:
201            domain_crash(current->domain);
202            break;
203        }
204    }
205
206    return rc;
207}
208
209/*
210 * Local variables:
211 * mode: C
212 * c-set-style: "BSD"
213 * c-basic-offset: 4
214 * tab-width: 4
215 * indent-tabs-mode: nil
216 * End:
217 */
Note: See TracBrowser for help on using the repository browser.