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) *handle = mso.u.nominate.handle;
93 
94     return rc;
95 }
96 
xc_memshr_nominate_gref(xc_interface * xch,uint32_t domid,grant_ref_t gref,uint64_t * handle)97 int xc_memshr_nominate_gref(xc_interface *xch,
98                             uint32_t domid,
99                             grant_ref_t gref,
100                             uint64_t *handle)
101 {
102     int rc;
103     xen_mem_sharing_op_t mso;
104 
105     memset(&mso, 0, sizeof(mso));
106 
107     mso.op = XENMEM_sharing_op_nominate_gref;
108     mso.u.nominate.u.grant_ref = gref;
109 
110     rc = xc_memshr_memop(xch, domid, &mso);
111 
112     if (!rc) *handle = mso.u.nominate.handle;
113 
114     return rc;
115 }
116 
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)117 int xc_memshr_share_gfns(xc_interface *xch,
118                          uint32_t source_domain,
119                          unsigned long source_gfn,
120                          uint64_t source_handle,
121                          uint32_t client_domain,
122                          unsigned long client_gfn,
123                          uint64_t client_handle)
124 {
125     xen_mem_sharing_op_t mso;
126 
127     memset(&mso, 0, sizeof(mso));
128 
129     mso.op = XENMEM_sharing_op_share;
130 
131     mso.u.share.source_handle = source_handle;
132     mso.u.share.source_gfn    = source_gfn;
133     mso.u.share.client_domain = client_domain;
134     mso.u.share.client_gfn    = client_gfn;
135     mso.u.share.client_handle = client_handle;
136 
137     return xc_memshr_memop(xch, source_domain, &mso);
138 }
139 
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)140 int xc_memshr_share_grefs(xc_interface *xch,
141                           uint32_t source_domain,
142                           grant_ref_t source_gref,
143                           uint64_t source_handle,
144                           uint32_t client_domain,
145                           grant_ref_t client_gref,
146                           uint64_t client_handle)
147 {
148     xen_mem_sharing_op_t mso;
149 
150     memset(&mso, 0, sizeof(mso));
151 
152     mso.op = XENMEM_sharing_op_share;
153 
154     mso.u.share.source_handle = source_handle;
155     XENMEM_SHARING_OP_FIELD_MAKE_GREF(mso.u.share.source_gfn, source_gref);
156     mso.u.share.client_domain = client_domain;
157     XENMEM_SHARING_OP_FIELD_MAKE_GREF(mso.u.share.client_gfn, client_gref);
158     mso.u.share.client_handle = client_handle;
159 
160     return xc_memshr_memop(xch, source_domain, &mso);
161 }
162 
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)163 int xc_memshr_add_to_physmap(xc_interface *xch,
164                     uint32_t source_domain,
165                     unsigned long source_gfn,
166                     uint64_t source_handle,
167                     uint32_t client_domain,
168                     unsigned long client_gfn)
169 {
170     xen_mem_sharing_op_t mso;
171 
172     memset(&mso, 0, sizeof(mso));
173 
174     mso.op = XENMEM_sharing_op_add_physmap;
175 
176     mso.u.share.source_handle = source_handle;
177     mso.u.share.source_gfn    = source_gfn;
178     mso.u.share.client_domain = client_domain;
179     mso.u.share.client_gfn    = client_gfn;
180 
181     return xc_memshr_memop(xch, source_domain, &mso);
182 }
183 
xc_memshr_range_share(xc_interface * xch,uint32_t source_domain,uint32_t client_domain,uint64_t first_gfn,uint64_t last_gfn)184 int xc_memshr_range_share(xc_interface *xch,
185                           uint32_t source_domain,
186                           uint32_t client_domain,
187                           uint64_t first_gfn,
188                           uint64_t last_gfn)
189 {
190     xen_mem_sharing_op_t mso;
191 
192     memset(&mso, 0, sizeof(mso));
193 
194     mso.op = XENMEM_sharing_op_range_share;
195 
196     mso.u.range.client_domain = client_domain;
197     mso.u.range.first_gfn = first_gfn;
198     mso.u.range.last_gfn = last_gfn;
199 
200     return xc_memshr_memop(xch, source_domain, &mso);
201 }
202 
xc_memshr_domain_resume(xc_interface * xch,uint32_t domid)203 int xc_memshr_domain_resume(xc_interface *xch,
204                             uint32_t domid)
205 {
206     return xc_vm_event_control(xch, domid,
207                                XEN_VM_EVENT_RESUME,
208                                XEN_DOMCTL_VM_EVENT_OP_SHARING,
209                                NULL);
210 }
211 
xc_memshr_debug_gfn(xc_interface * xch,uint32_t domid,unsigned long gfn)212 int xc_memshr_debug_gfn(xc_interface *xch,
213                         uint32_t domid,
214                         unsigned long gfn)
215 {
216     xen_mem_sharing_op_t mso;
217 
218     memset(&mso, 0, sizeof(mso));
219 
220     mso.op = XENMEM_sharing_op_debug_gfn;
221     mso.u.debug.u.gfn = gfn;
222 
223     return xc_memshr_memop(xch, domid, &mso);
224 }
225 
xc_memshr_debug_gref(xc_interface * xch,uint32_t domid,grant_ref_t gref)226 int xc_memshr_debug_gref(xc_interface *xch,
227                          uint32_t domid,
228                          grant_ref_t gref)
229 {
230     xen_mem_sharing_op_t mso;
231 
232     memset(&mso, 0, sizeof(mso));
233 
234     mso.op = XENMEM_sharing_op_debug_gref;
235     mso.u.debug.u.gref = gref;
236 
237     return xc_memshr_memop(xch, domid, &mso);
238 }
239 
xc_memshr_audit(xc_interface * xch)240 int xc_memshr_audit(xc_interface *xch)
241 {
242     xen_mem_sharing_op_t mso;
243 
244     memset(&mso, 0, sizeof(mso));
245 
246     mso.op = XENMEM_sharing_op_audit;
247 
248     return do_memory_op(xch, XENMEM_sharing_op, &mso, sizeof(mso));
249 }
250 
xc_sharing_freed_pages(xc_interface * xch)251 long xc_sharing_freed_pages(xc_interface *xch)
252 {
253     return do_memory_op(xch, XENMEM_get_sharing_freed_pages, NULL, 0);
254 }
255 
xc_sharing_used_frames(xc_interface * xch)256 long xc_sharing_used_frames(xc_interface *xch)
257 {
258     return do_memory_op(xch, XENMEM_get_sharing_shared_pages, NULL, 0);
259 }
260 
261