1 /******************************************************************************
2 *
3 * Copyright (c) 2007-2008, D G Murray <Derek.Murray@cl.cam.ac.uk>
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation;
8 * version 2.1 of the License.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 #include "xc_private.h"
20
xc_gnttab_op(xc_interface * xch,int cmd,void * op,int op_size,int count)21 int xc_gnttab_op(xc_interface *xch, int cmd, void * op, int op_size, int count)
22 {
23 int ret = 0;
24 DECLARE_HYPERCALL_BOUNCE(op, count * op_size, XC_HYPERCALL_BUFFER_BOUNCE_BOTH);
25
26 if ( xc_hypercall_bounce_pre(xch, op) )
27 {
28 PERROR("Could not bounce buffer for grant table op hypercall");
29 goto out1;
30 }
31
32 ret = xencall3(xch->xcall, __HYPERVISOR_grant_table_op,
33 cmd, HYPERCALL_BUFFER_AS_ARG(op), count);
34
35 xc_hypercall_bounce_post(xch, op);
36
37 out1:
38 return ret;
39 }
40
xc_gnttab_query_size(xc_interface * xch,struct gnttab_query_size * query)41 int xc_gnttab_query_size(xc_interface *xch, struct gnttab_query_size *query)
42 {
43 int rc;
44
45 rc = xc_gnttab_op(xch, GNTTABOP_query_size, query, sizeof(*query), 1);
46
47 if ( rc || (query->status != GNTST_okay) )
48 ERROR("Could not query dom %u's grant size\n", query->dom);
49
50 return rc;
51 }
52
xc_gnttab_get_version(xc_interface * xch,uint32_t domid)53 int xc_gnttab_get_version(xc_interface *xch, uint32_t domid)
54 {
55 struct gnttab_get_version query;
56 int rc;
57
58 query.dom = domid;
59 rc = xc_gnttab_op(xch, GNTTABOP_get_version, &query, sizeof(query),
60 1);
61 if ( rc < 0 )
62 return rc;
63 else
64 return query.version;
65 }
66
_gnttab_map_table(xc_interface * xch,uint32_t domid,int * gnt_num)67 static void *_gnttab_map_table(xc_interface *xch, uint32_t domid, int *gnt_num)
68 {
69 int rc, i;
70 struct gnttab_query_size query;
71 struct gnttab_setup_table setup;
72 DECLARE_HYPERCALL_BUFFER(unsigned long, frame_list);
73 xen_pfn_t *pfn_list = NULL;
74 grant_entry_v1_t *gnt = NULL;
75
76 if ( !gnt_num )
77 return NULL;
78
79 query.dom = domid;
80 rc = xc_gnttab_op(xch, GNTTABOP_query_size, &query, sizeof(query), 1);
81
82 if ( rc || (query.status != GNTST_okay) )
83 {
84 ERROR("Could not query dom%d's grant size\n", domid);
85 return NULL;
86 }
87
88 *gnt_num = query.nr_frames * (PAGE_SIZE / sizeof(grant_entry_v1_t) );
89
90 frame_list = xc_hypercall_buffer_alloc(xch, frame_list, query.nr_frames * sizeof(unsigned long));
91 if ( !frame_list )
92 {
93 ERROR("Could not allocate frame_list in xc_gnttab_map_table\n");
94 return NULL;
95 }
96
97 pfn_list = malloc(query.nr_frames * sizeof(xen_pfn_t));
98 if ( !pfn_list )
99 {
100 ERROR("Could not allocate pfn_list in xc_gnttab_map_table\n");
101 goto err;
102 }
103
104 setup.dom = domid;
105 setup.nr_frames = query.nr_frames;
106 set_xen_guest_handle(setup.frame_list, frame_list);
107
108 /* XXX Any race with other setup_table hypercall? */
109 rc = xc_gnttab_op(xch, GNTTABOP_setup_table, &setup, sizeof(setup),
110 1);
111
112 if ( rc || (setup.status != GNTST_okay) )
113 {
114 ERROR("Could not get grant table frame list\n");
115 goto err;
116 }
117
118 for ( i = 0; i < setup.nr_frames; i++ )
119 pfn_list[i] = frame_list[i];
120
121 gnt = xc_map_foreign_pages(xch, domid, PROT_READ, pfn_list,
122 setup.nr_frames);
123 if ( !gnt )
124 {
125 ERROR("Could not map grant table\n");
126 goto err;
127 }
128
129 err:
130 if ( frame_list )
131 xc_hypercall_buffer_free(xch, frame_list);
132 free(pfn_list);
133
134 return gnt;
135 }
136
xc_gnttab_map_table_v1(xc_interface * xch,uint32_t domid,int * gnt_num)137 grant_entry_v1_t *xc_gnttab_map_table_v1(xc_interface *xch, uint32_t domid,
138 int *gnt_num)
139 {
140 if (xc_gnttab_get_version(xch, domid) == 2)
141 return NULL;
142 return _gnttab_map_table(xch, domid, gnt_num);
143 }
144
xc_gnttab_map_table_v2(xc_interface * xch,uint32_t domid,int * gnt_num)145 grant_entry_v2_t *xc_gnttab_map_table_v2(xc_interface *xch, uint32_t domid,
146 int *gnt_num)
147 {
148 if (xc_gnttab_get_version(xch, domid) != 2)
149 return NULL;
150 return _gnttab_map_table(xch, domid, gnt_num);
151 }
152
153 /*
154 * Local variables:
155 * mode: C
156 * c-file-style: "BSD"
157 * c-basic-offset: 4
158 * tab-width: 4
159 * indent-tabs-mode: nil
160 * End:
161 */
162