1 /******************************************************************************
2  *
3  * xc_monitor.c
4  *
5  * Interface to VM event monitor
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 
xc_monitor_enable(xc_interface * xch,uint32_t domain_id,uint32_t * port)25 void *xc_monitor_enable(xc_interface *xch, uint32_t domain_id, uint32_t *port)
26 {
27     return xc_vm_event_enable(xch, domain_id, HVM_PARAM_MONITOR_RING_PFN,
28                               port);
29 }
30 
xc_monitor_disable(xc_interface * xch,uint32_t domain_id)31 int xc_monitor_disable(xc_interface *xch, uint32_t domain_id)
32 {
33     return xc_vm_event_control(xch, domain_id,
34                                XEN_VM_EVENT_DISABLE,
35                                XEN_DOMCTL_VM_EVENT_OP_MONITOR,
36                                NULL);
37 }
38 
xc_monitor_resume(xc_interface * xch,uint32_t domain_id)39 int xc_monitor_resume(xc_interface *xch, uint32_t domain_id)
40 {
41     return xc_vm_event_control(xch, domain_id,
42                                XEN_VM_EVENT_RESUME,
43                                XEN_DOMCTL_VM_EVENT_OP_MONITOR,
44                                NULL);
45 }
46 
xc_monitor_get_capabilities(xc_interface * xch,uint32_t domain_id,uint32_t * capabilities)47 int xc_monitor_get_capabilities(xc_interface *xch, uint32_t domain_id,
48                                 uint32_t *capabilities)
49 {
50     int rc;
51     DECLARE_DOMCTL;
52 
53     if ( !capabilities )
54     {
55         errno = EINVAL;
56         return -1;
57     }
58 
59     domctl.cmd = XEN_DOMCTL_monitor_op;
60     domctl.domain = domain_id;
61     domctl.u.monitor_op.op = XEN_DOMCTL_MONITOR_OP_GET_CAPABILITIES;
62 
63     rc = do_domctl(xch, &domctl);
64     if ( rc )
65         return rc;
66 
67     *capabilities = domctl.u.monitor_op.event;
68     return 0;
69 }
70 
xc_monitor_write_ctrlreg(xc_interface * xch,uint32_t domain_id,uint16_t index,bool enable,bool sync,uint64_t bitmask,bool onchangeonly)71 int xc_monitor_write_ctrlreg(xc_interface *xch, uint32_t domain_id,
72                              uint16_t index, bool enable, bool sync,
73                              uint64_t bitmask, bool onchangeonly)
74 {
75     DECLARE_DOMCTL;
76 
77     domctl.cmd = XEN_DOMCTL_monitor_op;
78     domctl.domain = domain_id;
79     domctl.u.monitor_op.op = enable ? XEN_DOMCTL_MONITOR_OP_ENABLE
80                                     : XEN_DOMCTL_MONITOR_OP_DISABLE;
81     domctl.u.monitor_op.event = XEN_DOMCTL_MONITOR_EVENT_WRITE_CTRLREG;
82     domctl.u.monitor_op.u.mov_to_cr.index = index;
83     domctl.u.monitor_op.u.mov_to_cr.sync = sync;
84     domctl.u.monitor_op.u.mov_to_cr.onchangeonly = onchangeonly;
85     domctl.u.monitor_op.u.mov_to_cr.bitmask = bitmask;
86     domctl.u.monitor_op.u.mov_to_cr.pad1 = 0;
87     domctl.u.monitor_op.u.mov_to_cr.pad2 = 0;
88 
89     return do_domctl(xch, &domctl);
90 }
91 
xc_monitor_mov_to_msr(xc_interface * xch,uint32_t domain_id,uint32_t msr,bool enable,bool onchangeonly)92 int xc_monitor_mov_to_msr(xc_interface *xch, uint32_t domain_id, uint32_t msr,
93                           bool enable, bool onchangeonly)
94 {
95     DECLARE_DOMCTL;
96 
97     domctl.cmd = XEN_DOMCTL_monitor_op;
98     domctl.domain = domain_id;
99     domctl.u.monitor_op.op = enable ? XEN_DOMCTL_MONITOR_OP_ENABLE
100                                     : XEN_DOMCTL_MONITOR_OP_DISABLE;
101     domctl.u.monitor_op.event = XEN_DOMCTL_MONITOR_EVENT_MOV_TO_MSR;
102     domctl.u.monitor_op.u.mov_to_msr.msr = msr;
103     domctl.u.monitor_op.u.mov_to_msr.onchangeonly = onchangeonly;
104 
105     return do_domctl(xch, &domctl);
106 }
107 
xc_monitor_software_breakpoint(xc_interface * xch,uint32_t domain_id,bool enable)108 int xc_monitor_software_breakpoint(xc_interface *xch, uint32_t domain_id,
109                                    bool enable)
110 {
111     DECLARE_DOMCTL;
112 
113     domctl.cmd = XEN_DOMCTL_monitor_op;
114     domctl.domain = domain_id;
115     domctl.u.monitor_op.op = enable ? XEN_DOMCTL_MONITOR_OP_ENABLE
116                                     : XEN_DOMCTL_MONITOR_OP_DISABLE;
117     domctl.u.monitor_op.event = XEN_DOMCTL_MONITOR_EVENT_SOFTWARE_BREAKPOINT;
118 
119     return do_domctl(xch, &domctl);
120 }
121 
xc_monitor_singlestep(xc_interface * xch,uint32_t domain_id,bool enable)122 int xc_monitor_singlestep(xc_interface *xch, uint32_t domain_id,
123                           bool enable)
124 {
125     DECLARE_DOMCTL;
126 
127     domctl.cmd = XEN_DOMCTL_monitor_op;
128     domctl.domain = domain_id;
129     domctl.u.monitor_op.op = enable ? XEN_DOMCTL_MONITOR_OP_ENABLE
130                                     : XEN_DOMCTL_MONITOR_OP_DISABLE;
131     domctl.u.monitor_op.event = XEN_DOMCTL_MONITOR_EVENT_SINGLESTEP;
132 
133     return do_domctl(xch, &domctl);
134 }
135 
xc_monitor_descriptor_access(xc_interface * xch,uint32_t domain_id,bool enable)136 int xc_monitor_descriptor_access(xc_interface *xch, uint32_t domain_id,
137                                  bool enable)
138 {
139     DECLARE_DOMCTL;
140 
141     domctl.cmd = XEN_DOMCTL_monitor_op;
142     domctl.domain = domain_id;
143     domctl.u.monitor_op.op = enable ? XEN_DOMCTL_MONITOR_OP_ENABLE
144                                     : XEN_DOMCTL_MONITOR_OP_DISABLE;
145     domctl.u.monitor_op.event = XEN_DOMCTL_MONITOR_EVENT_DESC_ACCESS;
146 
147     return do_domctl(xch, &domctl);
148 }
149 
xc_monitor_guest_request(xc_interface * xch,uint32_t domain_id,bool enable,bool sync,bool allow_userspace)150 int xc_monitor_guest_request(xc_interface *xch, uint32_t domain_id, bool enable,
151                              bool sync, bool allow_userspace)
152 {
153     DECLARE_DOMCTL;
154 
155     domctl.cmd = XEN_DOMCTL_monitor_op;
156     domctl.domain = domain_id;
157     domctl.u.monitor_op.op = enable ? XEN_DOMCTL_MONITOR_OP_ENABLE
158                                     : XEN_DOMCTL_MONITOR_OP_DISABLE;
159     domctl.u.monitor_op.event = XEN_DOMCTL_MONITOR_EVENT_GUEST_REQUEST;
160     domctl.u.monitor_op.u.guest_request.sync = sync;
161     domctl.u.monitor_op.u.guest_request.allow_userspace = enable ? allow_userspace : false;
162 
163     return do_domctl(xch, &domctl);
164 }
165 
xc_monitor_inguest_pagefault(xc_interface * xch,uint32_t domain_id,bool disable)166 int xc_monitor_inguest_pagefault(xc_interface *xch, uint32_t domain_id,
167                                 bool disable)
168 {
169     DECLARE_DOMCTL;
170 
171     domctl.cmd = XEN_DOMCTL_monitor_op;
172     domctl.domain = domain_id;
173     domctl.u.monitor_op.op = disable ? XEN_DOMCTL_MONITOR_OP_ENABLE
174                                     : XEN_DOMCTL_MONITOR_OP_DISABLE;
175     domctl.u.monitor_op.event = XEN_DOMCTL_MONITOR_EVENT_INGUEST_PAGEFAULT;
176 
177     return do_domctl(xch, &domctl);
178 }
179 
xc_monitor_emulate_each_rep(xc_interface * xch,uint32_t domain_id,bool enable)180 int xc_monitor_emulate_each_rep(xc_interface *xch, uint32_t domain_id,
181                                 bool enable)
182 {
183     DECLARE_DOMCTL;
184 
185     domctl.cmd = XEN_DOMCTL_monitor_op;
186     domctl.domain = domain_id;
187     domctl.u.monitor_op.op = XEN_DOMCTL_MONITOR_OP_EMULATE_EACH_REP;
188     domctl.u.monitor_op.event = enable;
189 
190     return do_domctl(xch, &domctl);
191 }
192 
xc_monitor_debug_exceptions(xc_interface * xch,uint32_t domain_id,bool enable,bool sync)193 int xc_monitor_debug_exceptions(xc_interface *xch, uint32_t domain_id,
194                                 bool enable, bool sync)
195 {
196     DECLARE_DOMCTL;
197 
198     domctl.cmd = XEN_DOMCTL_monitor_op;
199     domctl.domain = domain_id;
200     domctl.u.monitor_op.op = enable ? XEN_DOMCTL_MONITOR_OP_ENABLE
201                                     : XEN_DOMCTL_MONITOR_OP_DISABLE;
202     domctl.u.monitor_op.event = XEN_DOMCTL_MONITOR_EVENT_DEBUG_EXCEPTION;
203     domctl.u.monitor_op.u.debug_exception.sync = sync;
204 
205     return do_domctl(xch, &domctl);
206 }
207 
xc_monitor_cpuid(xc_interface * xch,uint32_t domain_id,bool enable)208 int xc_monitor_cpuid(xc_interface *xch, uint32_t domain_id, bool enable)
209 {
210     DECLARE_DOMCTL;
211 
212     domctl.cmd = XEN_DOMCTL_monitor_op;
213     domctl.domain = domain_id;
214     domctl.u.monitor_op.op = enable ? XEN_DOMCTL_MONITOR_OP_ENABLE
215                                     : XEN_DOMCTL_MONITOR_OP_DISABLE;
216     domctl.u.monitor_op.event = XEN_DOMCTL_MONITOR_EVENT_CPUID;
217 
218     return do_domctl(xch, &domctl);
219 }
220 
xc_monitor_privileged_call(xc_interface * xch,uint32_t domain_id,bool enable)221 int xc_monitor_privileged_call(xc_interface *xch, uint32_t domain_id,
222                                bool enable)
223 {
224     DECLARE_DOMCTL;
225 
226     domctl.cmd = XEN_DOMCTL_monitor_op;
227     domctl.domain = domain_id;
228     domctl.u.monitor_op.op = enable ? XEN_DOMCTL_MONITOR_OP_ENABLE
229                                     : XEN_DOMCTL_MONITOR_OP_DISABLE;
230     domctl.u.monitor_op.event = XEN_DOMCTL_MONITOR_EVENT_PRIVILEGED_CALL;
231 
232     return do_domctl(xch, &domctl);
233 }
234 
xc_monitor_emul_unimplemented(xc_interface * xch,uint32_t domain_id,bool enable)235 int xc_monitor_emul_unimplemented(xc_interface *xch, uint32_t domain_id,
236                                   bool enable)
237 {
238     DECLARE_DOMCTL;
239 
240     domctl.cmd = XEN_DOMCTL_monitor_op;
241     domctl.domain = domain_id;
242     domctl.u.monitor_op.op = enable ? XEN_DOMCTL_MONITOR_OP_ENABLE
243                                     : XEN_DOMCTL_MONITOR_OP_DISABLE;
244     domctl.u.monitor_op.event = XEN_DOMCTL_MONITOR_EVENT_EMUL_UNIMPLEMENTED;
245 
246     return do_domctl(xch, &domctl);
247 }
248 
249 /*
250  * Local variables:
251  * mode: C
252  * c-file-style: "BSD"
253  * c-basic-offset: 4
254  * tab-width: 4
255  * indent-tabs-mode: nil
256  * End:
257  */
258