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)92 int xc_monitor_mov_to_msr(xc_interface *xch, uint32_t domain_id, uint32_t msr,
93                           bool enable)
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 
104     return do_domctl(xch, &domctl);
105 }
106 
xc_monitor_software_breakpoint(xc_interface * xch,uint32_t domain_id,bool enable)107 int xc_monitor_software_breakpoint(xc_interface *xch, uint32_t domain_id,
108                                    bool enable)
109 {
110     DECLARE_DOMCTL;
111 
112     domctl.cmd = XEN_DOMCTL_monitor_op;
113     domctl.domain = domain_id;
114     domctl.u.monitor_op.op = enable ? XEN_DOMCTL_MONITOR_OP_ENABLE
115                                     : XEN_DOMCTL_MONITOR_OP_DISABLE;
116     domctl.u.monitor_op.event = XEN_DOMCTL_MONITOR_EVENT_SOFTWARE_BREAKPOINT;
117 
118     return do_domctl(xch, &domctl);
119 }
120 
xc_monitor_singlestep(xc_interface * xch,uint32_t domain_id,bool enable)121 int xc_monitor_singlestep(xc_interface *xch, uint32_t domain_id,
122                           bool enable)
123 {
124     DECLARE_DOMCTL;
125 
126     domctl.cmd = XEN_DOMCTL_monitor_op;
127     domctl.domain = domain_id;
128     domctl.u.monitor_op.op = enable ? XEN_DOMCTL_MONITOR_OP_ENABLE
129                                     : XEN_DOMCTL_MONITOR_OP_DISABLE;
130     domctl.u.monitor_op.event = XEN_DOMCTL_MONITOR_EVENT_SINGLESTEP;
131 
132     return do_domctl(xch, &domctl);
133 }
134 
xc_monitor_descriptor_access(xc_interface * xch,uint32_t domain_id,bool enable)135 int xc_monitor_descriptor_access(xc_interface *xch, uint32_t domain_id,
136                                  bool enable)
137 {
138     DECLARE_DOMCTL;
139 
140     domctl.cmd = XEN_DOMCTL_monitor_op;
141     domctl.domain = domain_id;
142     domctl.u.monitor_op.op = enable ? XEN_DOMCTL_MONITOR_OP_ENABLE
143                                     : XEN_DOMCTL_MONITOR_OP_DISABLE;
144     domctl.u.monitor_op.event = XEN_DOMCTL_MONITOR_EVENT_DESC_ACCESS;
145 
146     return do_domctl(xch, &domctl);
147 }
148 
xc_monitor_guest_request(xc_interface * xch,uint32_t domain_id,bool enable,bool sync,bool allow_userspace)149 int xc_monitor_guest_request(xc_interface *xch, uint32_t domain_id, bool enable,
150                              bool sync, bool allow_userspace)
151 {
152     DECLARE_DOMCTL;
153 
154     domctl.cmd = XEN_DOMCTL_monitor_op;
155     domctl.domain = domain_id;
156     domctl.u.monitor_op.op = enable ? XEN_DOMCTL_MONITOR_OP_ENABLE
157                                     : XEN_DOMCTL_MONITOR_OP_DISABLE;
158     domctl.u.monitor_op.event = XEN_DOMCTL_MONITOR_EVENT_GUEST_REQUEST;
159     domctl.u.monitor_op.u.guest_request.sync = sync;
160     domctl.u.monitor_op.u.guest_request.allow_userspace = enable ? allow_userspace : false;
161 
162     return do_domctl(xch, &domctl);
163 }
164 
xc_monitor_emulate_each_rep(xc_interface * xch,uint32_t domain_id,bool enable)165 int xc_monitor_emulate_each_rep(xc_interface *xch, uint32_t domain_id,
166                                 bool enable)
167 {
168     DECLARE_DOMCTL;
169 
170     domctl.cmd = XEN_DOMCTL_monitor_op;
171     domctl.domain = domain_id;
172     domctl.u.monitor_op.op = XEN_DOMCTL_MONITOR_OP_EMULATE_EACH_REP;
173     domctl.u.monitor_op.event = enable;
174 
175     return do_domctl(xch, &domctl);
176 }
177 
xc_monitor_debug_exceptions(xc_interface * xch,uint32_t domain_id,bool enable,bool sync)178 int xc_monitor_debug_exceptions(xc_interface *xch, uint32_t domain_id,
179                                 bool enable, bool sync)
180 {
181     DECLARE_DOMCTL;
182 
183     domctl.cmd = XEN_DOMCTL_monitor_op;
184     domctl.domain = domain_id;
185     domctl.u.monitor_op.op = enable ? XEN_DOMCTL_MONITOR_OP_ENABLE
186                                     : XEN_DOMCTL_MONITOR_OP_DISABLE;
187     domctl.u.monitor_op.event = XEN_DOMCTL_MONITOR_EVENT_DEBUG_EXCEPTION;
188     domctl.u.monitor_op.u.debug_exception.sync = sync;
189 
190     return do_domctl(xch, &domctl);
191 }
192 
xc_monitor_cpuid(xc_interface * xch,uint32_t domain_id,bool enable)193 int xc_monitor_cpuid(xc_interface *xch, uint32_t domain_id, bool enable)
194 {
195     DECLARE_DOMCTL;
196 
197     domctl.cmd = XEN_DOMCTL_monitor_op;
198     domctl.domain = domain_id;
199     domctl.u.monitor_op.op = enable ? XEN_DOMCTL_MONITOR_OP_ENABLE
200                                     : XEN_DOMCTL_MONITOR_OP_DISABLE;
201     domctl.u.monitor_op.event = XEN_DOMCTL_MONITOR_EVENT_CPUID;
202 
203     return do_domctl(xch, &domctl);
204 }
205 
xc_monitor_privileged_call(xc_interface * xch,uint32_t domain_id,bool enable)206 int xc_monitor_privileged_call(xc_interface *xch, uint32_t domain_id,
207                                bool enable)
208 {
209     DECLARE_DOMCTL;
210 
211     domctl.cmd = XEN_DOMCTL_monitor_op;
212     domctl.domain = domain_id;
213     domctl.u.monitor_op.op = enable ? XEN_DOMCTL_MONITOR_OP_ENABLE
214                                     : XEN_DOMCTL_MONITOR_OP_DISABLE;
215     domctl.u.monitor_op.event = XEN_DOMCTL_MONITOR_EVENT_PRIVILEGED_CALL;
216 
217     return do_domctl(xch, &domctl);
218 }
219 
xc_monitor_emul_unimplemented(xc_interface * xch,uint32_t domain_id,bool enable)220 int xc_monitor_emul_unimplemented(xc_interface *xch, uint32_t domain_id,
221                                   bool enable)
222 {
223     DECLARE_DOMCTL;
224 
225     domctl.cmd = XEN_DOMCTL_monitor_op;
226     domctl.domain = domain_id;
227     domctl.u.monitor_op.op = enable ? XEN_DOMCTL_MONITOR_OP_ENABLE
228                                     : XEN_DOMCTL_MONITOR_OP_DISABLE;
229     domctl.u.monitor_op.event = XEN_DOMCTL_MONITOR_EVENT_EMUL_UNIMPLEMENTED;
230 
231     return do_domctl(xch, &domctl);
232 }
233 
234 /*
235  * Local variables:
236  * mode: C
237  * c-file-style: "BSD"
238  * c-basic-offset: 4
239  * tab-width: 4
240  * indent-tabs-mode: nil
241  * End:
242  */
243