1 /******************************************************************************
2 *
3 * xc_memshr.c
4 *
5 * Interface to low-level memory sharing functionality.
6 *
7 * Copyright (c) 2009 Citrix Systems, Inc. (Grzegorz Milos)
8 *
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; If not, see <http://www.gnu.org/licenses/>.
21 */
22
23 #include "xc_private.h"
24 #include <xen/memory.h>
25 #include <xen/grant_table.h>
26
xc_memshr_control(xc_interface * xch,uint32_t domid,int enable)27 int xc_memshr_control(xc_interface *xch,
28 uint32_t domid,
29 int enable)
30 {
31 DECLARE_DOMCTL;
32 struct xen_domctl_mem_sharing_op *op;
33
34 domctl.cmd = XEN_DOMCTL_mem_sharing_op;
35 domctl.interface_version = XEN_DOMCTL_INTERFACE_VERSION;
36 domctl.domain = domid;
37 op = &(domctl.u.mem_sharing_op);
38 op->op = XEN_DOMCTL_MEM_SHARING_CONTROL;
39 op->u.enable = enable;
40
41 return do_domctl(xch, &domctl);
42 }
43
xc_memshr_ring_enable(xc_interface * xch,uint32_t domid,uint32_t * port)44 int xc_memshr_ring_enable(xc_interface *xch,
45 uint32_t domid,
46 uint32_t *port)
47 {
48 if ( !port )
49 {
50 errno = EINVAL;
51 return -1;
52 }
53
54 return xc_vm_event_control(xch, domid,
55 XEN_VM_EVENT_ENABLE,
56 XEN_DOMCTL_VM_EVENT_OP_SHARING,
57 port);
58 }
59
xc_memshr_ring_disable(xc_interface * xch,uint32_t domid)60 int xc_memshr_ring_disable(xc_interface *xch,
61 uint32_t domid)
62 {
63 return xc_vm_event_control(xch, domid,
64 XEN_VM_EVENT_DISABLE,
65 XEN_DOMCTL_VM_EVENT_OP_SHARING,
66 NULL);
67 }
68
xc_memshr_memop(xc_interface * xch,uint32_t domid,xen_mem_sharing_op_t * mso)69 static int xc_memshr_memop(xc_interface *xch, uint32_t domid,
70 xen_mem_sharing_op_t *mso)
71 {
72 mso->domain = domid;
73
74 return do_memory_op(xch, XENMEM_sharing_op, mso, sizeof(*mso));
75 }
76
xc_memshr_nominate_gfn(xc_interface * xch,uint32_t domid,unsigned long gfn,uint64_t * handle)77 int xc_memshr_nominate_gfn(xc_interface *xch,
78 uint32_t domid,
79 unsigned long gfn,
80 uint64_t *handle)
81 {
82 int rc;
83 xen_mem_sharing_op_t mso;
84
85 memset(&mso, 0, sizeof(mso));
86
87 mso.op = XENMEM_sharing_op_nominate_gfn;
88 mso.u.nominate.u.gfn = gfn;
89
90 rc = xc_memshr_memop(xch, domid, &mso);
91
92 if ( !rc )
93 *handle = mso.u.nominate.handle;
94
95 return rc;
96 }
97
xc_memshr_nominate_gref(xc_interface * xch,uint32_t domid,grant_ref_t gref,uint64_t * handle)98 int xc_memshr_nominate_gref(xc_interface *xch,
99 uint32_t domid,
100 grant_ref_t gref,
101 uint64_t *handle)
102 {
103 int rc;
104 xen_mem_sharing_op_t mso;
105
106 memset(&mso, 0, sizeof(mso));
107
108 mso.op = XENMEM_sharing_op_nominate_gref;
109 mso.u.nominate.u.grant_ref = gref;
110
111 rc = xc_memshr_memop(xch, domid, &mso);
112
113 if ( !rc )
114 *handle = mso.u.nominate.handle;
115
116 return rc;
117 }
118
xc_memshr_share_gfns(xc_interface * xch,uint32_t source_domain,unsigned long source_gfn,uint64_t source_handle,uint32_t client_domain,unsigned long client_gfn,uint64_t client_handle)119 int xc_memshr_share_gfns(xc_interface *xch,
120 uint32_t source_domain,
121 unsigned long source_gfn,
122 uint64_t source_handle,
123 uint32_t client_domain,
124 unsigned long client_gfn,
125 uint64_t client_handle)
126 {
127 xen_mem_sharing_op_t mso;
128
129 memset(&mso, 0, sizeof(mso));
130
131 mso.op = XENMEM_sharing_op_share;
132
133 mso.u.share.source_handle = source_handle;
134 mso.u.share.source_gfn = source_gfn;
135 mso.u.share.client_domain = client_domain;
136 mso.u.share.client_gfn = client_gfn;
137 mso.u.share.client_handle = client_handle;
138
139 return xc_memshr_memop(xch, source_domain, &mso);
140 }
141
xc_memshr_share_grefs(xc_interface * xch,uint32_t source_domain,grant_ref_t source_gref,uint64_t source_handle,uint32_t client_domain,grant_ref_t client_gref,uint64_t client_handle)142 int xc_memshr_share_grefs(xc_interface *xch,
143 uint32_t source_domain,
144 grant_ref_t source_gref,
145 uint64_t source_handle,
146 uint32_t client_domain,
147 grant_ref_t client_gref,
148 uint64_t client_handle)
149 {
150 xen_mem_sharing_op_t mso;
151
152 memset(&mso, 0, sizeof(mso));
153
154 mso.op = XENMEM_sharing_op_share;
155
156 mso.u.share.source_handle = source_handle;
157 XENMEM_SHARING_OP_FIELD_MAKE_GREF(mso.u.share.source_gfn, source_gref);
158 mso.u.share.client_domain = client_domain;
159 XENMEM_SHARING_OP_FIELD_MAKE_GREF(mso.u.share.client_gfn, client_gref);
160 mso.u.share.client_handle = client_handle;
161
162 return xc_memshr_memop(xch, source_domain, &mso);
163 }
164
xc_memshr_add_to_physmap(xc_interface * xch,uint32_t source_domain,unsigned long source_gfn,uint64_t source_handle,uint32_t client_domain,unsigned long client_gfn)165 int xc_memshr_add_to_physmap(xc_interface *xch,
166 uint32_t source_domain,
167 unsigned long source_gfn,
168 uint64_t source_handle,
169 uint32_t client_domain,
170 unsigned long client_gfn)
171 {
172 xen_mem_sharing_op_t mso;
173
174 memset(&mso, 0, sizeof(mso));
175
176 mso.op = XENMEM_sharing_op_add_physmap;
177
178 mso.u.share.source_handle = source_handle;
179 mso.u.share.source_gfn = source_gfn;
180 mso.u.share.client_domain = client_domain;
181 mso.u.share.client_gfn = client_gfn;
182
183 return xc_memshr_memop(xch, source_domain, &mso);
184 }
185
xc_memshr_range_share(xc_interface * xch,uint32_t source_domain,uint32_t client_domain,uint64_t first_gfn,uint64_t last_gfn)186 int xc_memshr_range_share(xc_interface *xch,
187 uint32_t source_domain,
188 uint32_t client_domain,
189 uint64_t first_gfn,
190 uint64_t last_gfn)
191 {
192 xen_mem_sharing_op_t mso;
193
194 memset(&mso, 0, sizeof(mso));
195
196 mso.op = XENMEM_sharing_op_range_share;
197
198 mso.u.range.client_domain = client_domain;
199 mso.u.range.first_gfn = first_gfn;
200 mso.u.range.last_gfn = last_gfn;
201
202 return xc_memshr_memop(xch, source_domain, &mso);
203 }
204
xc_memshr_domain_resume(xc_interface * xch,uint32_t domid)205 int xc_memshr_domain_resume(xc_interface *xch,
206 uint32_t domid)
207 {
208 return xc_vm_event_control(xch, domid,
209 XEN_VM_EVENT_RESUME,
210 XEN_DOMCTL_VM_EVENT_OP_SHARING,
211 NULL);
212 }
213
xc_memshr_debug_gfn(xc_interface * xch,uint32_t domid,unsigned long gfn)214 int xc_memshr_debug_gfn(xc_interface *xch,
215 uint32_t domid,
216 unsigned long gfn)
217 {
218 xen_mem_sharing_op_t mso;
219
220 memset(&mso, 0, sizeof(mso));
221
222 mso.op = XENMEM_sharing_op_debug_gfn;
223 mso.u.debug.u.gfn = gfn;
224
225 return xc_memshr_memop(xch, domid, &mso);
226 }
227
xc_memshr_debug_gref(xc_interface * xch,uint32_t domid,grant_ref_t gref)228 int xc_memshr_debug_gref(xc_interface *xch,
229 uint32_t domid,
230 grant_ref_t gref)
231 {
232 xen_mem_sharing_op_t mso;
233
234 memset(&mso, 0, sizeof(mso));
235
236 mso.op = XENMEM_sharing_op_debug_gref;
237 mso.u.debug.u.gref = gref;
238
239 return xc_memshr_memop(xch, domid, &mso);
240 }
241
xc_memshr_fork(xc_interface * xch,uint32_t pdomid,uint32_t domid,bool allow_with_iommu,bool block_interrupts)242 int xc_memshr_fork(xc_interface *xch, uint32_t pdomid, uint32_t domid,
243 bool allow_with_iommu, bool block_interrupts)
244 {
245 xen_mem_sharing_op_t mso;
246
247 memset(&mso, 0, sizeof(mso));
248
249 mso.op = XENMEM_sharing_op_fork;
250 mso.u.fork.parent_domain = pdomid;
251
252 if ( allow_with_iommu )
253 mso.u.fork.flags |= XENMEM_FORK_WITH_IOMMU_ALLOWED;
254 if ( block_interrupts )
255 mso.u.fork.flags |= XENMEM_FORK_BLOCK_INTERRUPTS;
256
257 return xc_memshr_memop(xch, domid, &mso);
258 }
259
xc_memshr_fork_reset(xc_interface * xch,uint32_t domid)260 int xc_memshr_fork_reset(xc_interface *xch, uint32_t domid)
261 {
262 xen_mem_sharing_op_t mso;
263
264 memset(&mso, 0, sizeof(mso));
265 mso.op = XENMEM_sharing_op_fork_reset;
266
267 return xc_memshr_memop(xch, domid, &mso);
268 }
269
xc_memshr_audit(xc_interface * xch)270 int xc_memshr_audit(xc_interface *xch)
271 {
272 xen_mem_sharing_op_t mso;
273
274 memset(&mso, 0, sizeof(mso));
275
276 mso.op = XENMEM_sharing_op_audit;
277
278 return do_memory_op(xch, XENMEM_sharing_op, &mso, sizeof(mso));
279 }
280
xc_sharing_freed_pages(xc_interface * xch)281 long xc_sharing_freed_pages(xc_interface *xch)
282 {
283 return do_memory_op(xch, XENMEM_get_sharing_freed_pages, NULL, 0);
284 }
285
xc_sharing_used_frames(xc_interface * xch)286 long xc_sharing_used_frames(xc_interface *xch)
287 {
288 return do_memory_op(xch, XENMEM_get_sharing_shared_pages, NULL, 0);
289 }
290