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