1 /******************************************************************************
2 *
3 * xc_altp2m.c
4 *
5 * Interface to altp2m related HVMOPs
6 *
7 * Copyright (c) 2015 Tamas K Lengyel (tamas@tklengyel.com)
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 <stdbool.h>
25 #include <xen/hvm/hvm_op.h>
26
xc_altp2m_get_domain_state(xc_interface * handle,uint32_t dom,bool * state)27 int xc_altp2m_get_domain_state(xc_interface *handle, uint32_t dom, bool *state)
28 {
29 int rc;
30 DECLARE_HYPERCALL_BUFFER(xen_hvm_altp2m_op_t, arg);
31
32 arg = xc_hypercall_buffer_alloc(handle, arg, sizeof(*arg));
33 if ( arg == NULL )
34 return -1;
35
36 arg->version = HVMOP_ALTP2M_INTERFACE_VERSION;
37 arg->cmd = HVMOP_altp2m_get_domain_state;
38 arg->domain = dom;
39
40 rc = xencall2(handle->xcall, __HYPERVISOR_hvm_op, HVMOP_altp2m,
41 HYPERCALL_BUFFER_AS_ARG(arg));
42
43 if ( !rc )
44 *state = arg->u.domain_state.state;
45
46 xc_hypercall_buffer_free(handle, arg);
47 return rc;
48 }
49
xc_altp2m_set_domain_state(xc_interface * handle,uint32_t dom,bool state)50 int xc_altp2m_set_domain_state(xc_interface *handle, uint32_t dom, bool state)
51 {
52 int rc;
53 DECLARE_HYPERCALL_BUFFER(xen_hvm_altp2m_op_t, arg);
54
55 arg = xc_hypercall_buffer_alloc(handle, arg, sizeof(*arg));
56 if ( arg == NULL )
57 return -1;
58
59 arg->version = HVMOP_ALTP2M_INTERFACE_VERSION;
60 arg->cmd = HVMOP_altp2m_set_domain_state;
61 arg->domain = dom;
62 arg->u.domain_state.state = state;
63
64 rc = xencall2(handle->xcall, __HYPERVISOR_hvm_op, HVMOP_altp2m,
65 HYPERCALL_BUFFER_AS_ARG(arg));
66
67 xc_hypercall_buffer_free(handle, arg);
68 return rc;
69 }
70
71 /* This is a bit odd to me that it acts on current.. */
xc_altp2m_set_vcpu_enable_notify(xc_interface * handle,uint32_t domid,uint32_t vcpuid,xen_pfn_t gfn)72 int xc_altp2m_set_vcpu_enable_notify(xc_interface *handle, uint32_t domid,
73 uint32_t vcpuid, xen_pfn_t gfn)
74 {
75 int rc;
76 DECLARE_HYPERCALL_BUFFER(xen_hvm_altp2m_op_t, arg);
77
78 arg = xc_hypercall_buffer_alloc(handle, arg, sizeof(*arg));
79 if ( arg == NULL )
80 return -1;
81
82 arg->version = HVMOP_ALTP2M_INTERFACE_VERSION;
83 arg->cmd = HVMOP_altp2m_vcpu_enable_notify;
84 arg->domain = domid;
85 arg->u.enable_notify.vcpu_id = vcpuid;
86 arg->u.enable_notify.gfn = gfn;
87
88 rc = xencall2(handle->xcall, __HYPERVISOR_hvm_op, HVMOP_altp2m,
89 HYPERCALL_BUFFER_AS_ARG(arg));
90
91 xc_hypercall_buffer_free(handle, arg);
92 return rc;
93 }
94
xc_altp2m_create_view(xc_interface * handle,uint32_t domid,xenmem_access_t default_access,uint16_t * view_id)95 int xc_altp2m_create_view(xc_interface *handle, uint32_t domid,
96 xenmem_access_t default_access, uint16_t *view_id)
97 {
98 int rc;
99 DECLARE_HYPERCALL_BUFFER(xen_hvm_altp2m_op_t, arg);
100
101 arg = xc_hypercall_buffer_alloc(handle, arg, sizeof(*arg));
102 if ( arg == NULL )
103 return -1;
104
105 arg->version = HVMOP_ALTP2M_INTERFACE_VERSION;
106 arg->cmd = HVMOP_altp2m_create_p2m;
107 arg->domain = domid;
108 arg->u.view.view = -1;
109 arg->u.view.hvmmem_default_access = default_access;
110
111 rc = xencall2(handle->xcall, __HYPERVISOR_hvm_op, HVMOP_altp2m,
112 HYPERCALL_BUFFER_AS_ARG(arg));
113
114 if ( !rc )
115 *view_id = arg->u.view.view;
116
117 xc_hypercall_buffer_free(handle, arg);
118 return rc;
119 }
120
xc_altp2m_destroy_view(xc_interface * handle,uint32_t domid,uint16_t view_id)121 int xc_altp2m_destroy_view(xc_interface *handle, uint32_t domid,
122 uint16_t view_id)
123 {
124 int rc;
125 DECLARE_HYPERCALL_BUFFER(xen_hvm_altp2m_op_t, arg);
126
127 arg = xc_hypercall_buffer_alloc(handle, arg, sizeof(*arg));
128 if ( arg == NULL )
129 return -1;
130
131 arg->version = HVMOP_ALTP2M_INTERFACE_VERSION;
132 arg->cmd = HVMOP_altp2m_destroy_p2m;
133 arg->domain = domid;
134 arg->u.view.view = view_id;
135
136 rc = xencall2(handle->xcall, __HYPERVISOR_hvm_op, HVMOP_altp2m,
137 HYPERCALL_BUFFER_AS_ARG(arg));
138
139 xc_hypercall_buffer_free(handle, arg);
140 return rc;
141 }
142
143 /* Switch all vCPUs of the domain to the specified altp2m view */
xc_altp2m_switch_to_view(xc_interface * handle,uint32_t domid,uint16_t view_id)144 int xc_altp2m_switch_to_view(xc_interface *handle, uint32_t domid,
145 uint16_t view_id)
146 {
147 int rc;
148 DECLARE_HYPERCALL_BUFFER(xen_hvm_altp2m_op_t, arg);
149
150 arg = xc_hypercall_buffer_alloc(handle, arg, sizeof(*arg));
151 if ( arg == NULL )
152 return -1;
153
154 arg->version = HVMOP_ALTP2M_INTERFACE_VERSION;
155 arg->cmd = HVMOP_altp2m_switch_p2m;
156 arg->domain = domid;
157 arg->u.view.view = view_id;
158
159 rc = xencall2(handle->xcall, __HYPERVISOR_hvm_op, HVMOP_altp2m,
160 HYPERCALL_BUFFER_AS_ARG(arg));
161
162 xc_hypercall_buffer_free(handle, arg);
163 return rc;
164 }
165
xc_altp2m_set_mem_access(xc_interface * handle,uint32_t domid,uint16_t view_id,xen_pfn_t gfn,xenmem_access_t access)166 int xc_altp2m_set_mem_access(xc_interface *handle, uint32_t domid,
167 uint16_t view_id, xen_pfn_t gfn,
168 xenmem_access_t access)
169 {
170 int rc;
171 DECLARE_HYPERCALL_BUFFER(xen_hvm_altp2m_op_t, arg);
172
173 arg = xc_hypercall_buffer_alloc(handle, arg, sizeof(*arg));
174 if ( arg == NULL )
175 return -1;
176
177 arg->version = HVMOP_ALTP2M_INTERFACE_VERSION;
178 arg->cmd = HVMOP_altp2m_set_mem_access;
179 arg->domain = domid;
180 arg->u.set_mem_access.view = view_id;
181 arg->u.set_mem_access.hvmmem_access = access;
182 arg->u.set_mem_access.gfn = gfn;
183
184 rc = xencall2(handle->xcall, __HYPERVISOR_hvm_op, HVMOP_altp2m,
185 HYPERCALL_BUFFER_AS_ARG(arg));
186
187 xc_hypercall_buffer_free(handle, arg);
188 return rc;
189 }
190
xc_altp2m_change_gfn(xc_interface * handle,uint32_t domid,uint16_t view_id,xen_pfn_t old_gfn,xen_pfn_t new_gfn)191 int xc_altp2m_change_gfn(xc_interface *handle, uint32_t domid,
192 uint16_t view_id, xen_pfn_t old_gfn,
193 xen_pfn_t new_gfn)
194 {
195 int rc;
196 DECLARE_HYPERCALL_BUFFER(xen_hvm_altp2m_op_t, arg);
197
198 arg = xc_hypercall_buffer_alloc(handle, arg, sizeof(*arg));
199 if ( arg == NULL )
200 return -1;
201
202 arg->version = HVMOP_ALTP2M_INTERFACE_VERSION;
203 arg->cmd = HVMOP_altp2m_change_gfn;
204 arg->domain = domid;
205 arg->u.change_gfn.view = view_id;
206 arg->u.change_gfn.old_gfn = old_gfn;
207 arg->u.change_gfn.new_gfn = new_gfn;
208
209 rc = xencall2(handle->xcall, __HYPERVISOR_hvm_op, HVMOP_altp2m,
210 HYPERCALL_BUFFER_AS_ARG(arg));
211
212 xc_hypercall_buffer_free(handle, arg);
213 return rc;
214 }
215
216