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