10#include <xen/hvm/ether.h>
21 Exception(
const std::string &mesg)
28 : xc_iface(-1), xc_event_iface(-1), dom(0), shared_page_mfn(0), shared_page(NULL), event_port(-1) {
30 if ((xc_iface = xc_interface_open())<0)
31 throw Exception(
"cannot contact Xen hypervisor");
32 if ((xc_event_iface = xc_evtchn_open())<0)
33 throw Exception(
"cannot open event channel");
38 shared_page_mfn = cmd.u.ether.comm.shared_page_mfn;
42 shared_page = (
volatile unsigned char*)xc_map_foreign_range(xc_iface, DOMID_XEN, getpagesize(),
43 PROT_READ|PROT_WRITE, shared_page_mfn);
45 throw(
"cannot map shared page");
50 event_port = xc_evtchn_bind_interdomain(xc_event_iface, DOMID_SELF, cmd.u.ether.comm.event_channel_port);
52 throw(
"cannot bind ether event port");
55 printf(
"After init:\n");
56 printf(
" domain: %d\n", dom);
57 printf(
" xc_iface: %d\n", xc_iface);
58 printf(
" xc_event_iface: %d\n", xc_event_iface);
59 printf(
" shared_page: %p\n", shared_page);
60 printf(
" shared_page_mfn: 0x%lx\n", shared_page_mfn);
61 printf(
" event_channel_port: %d\n", cmd.u.ether.comm.event_channel_port);
62 printf(
" event_port: %u\n", event_port);
67 if (shared_page!=NULL) {
68 domctl(CmdTerminate());
69 xc_domain_unpause(xc_iface, dom);
72 xc_evtchn_unbind(xc_event_iface, event_port);
75 if (shared_page!=NULL) {
78 munmap((
void*)shared_page, getpagesize());
82 if (xc_event_iface>=0) {
83 xc_evtchn_close(xc_event_iface);
87 xc_interface_close(xc_iface);
93 void readguest(rose_addr_t va,
unsigned char *buffer,
size_t size) {
94 domctl(CmdReadGuest(va, buffer, size));
99 void set_single_step(
bool status) {
100 domctl(CmdSingleStep(status));
105 void set_single_step_notify(
bool status) {
106 domctl(CmdSingleStepNotify(status));
110 void set_memwrite_notify(
bool status) {
111 domctl(CmdMemwriteNotify(status));
115 void set_unpack_notify(
bool status) {
116 domctl(CmdUnpackNotify(status));
122 void set_sysenter(
bool new_eip) {
123 domctl(CmdSysenter(new_eip));
127 void add_name_filter(
const std::string &name) {
128 domctl(CmdAddName(name));
132 void add_cr3_filter(rose_addr_t cr3) {
133 domctl(CmdAddCR3(cr3));
138 bool is_lock_held() {
139 if (shared_page==NULL)
140 throw Exception(
"no shared page");
141 return *(
volatile uint32_t*)shared_page ?
true : false;
147 void release_lock() {
148 if (shared_page==NULL)
149 throw Exception(
"no shared page");
151 throw Exception(
"shared page lock is not set\n");
152 *(
volatile uint32_t*)shared_page = 0;
159 if (shared_page==NULL)
160 throw Exception(
"no shared page");
162 if (xc_evtchn_pending(xc_event_iface)!=event_port) {
163 xc_domain_unpause(xc_iface, dom);
164 }
else if (xc_evtchn_unmask(xc_event_iface, event_port)<0) {
165 throw Exception(
"cannot unmask ether event");
166 }
else if (!is_lock_held()) {
167 xc_domain_unpause(xc_iface, dom);
168 throw Exception(
"ether event but shared page lock is clear");
171 return ((
volatile uint32_t*)shared_page)[1];
176 const void *event_data() {
178 throw Exception(
"shared page lock is not set");
180 throw Exception(
"no shared page");
181 return (
const void*)(shared_page+8);
189 xc_domain_unpause(xc_iface, dom);
193 struct CmdInit:
public xen_domctl {
195 u.ether.command_code = XEN_DOMCTL_ETHER_INIT;
196 memset(&u.ether.comm, 0,
sizeof(u.ether.comm));
200 struct CmdTerminate:
public xen_domctl {
202 u.ether.command_code = XEN_DOMCTL_ETHER_TERMINATE;
206 struct CmdReadGuest:
public xen_domctl {
207 CmdReadGuest(rose_addr_t va,
void *buffer,
size_t size) {
208 u.ether.command_code = XEN_DOMCTL_ETHER_READ_GUEST;
209 u.ether.guest_va = va;
210 u.ether.guest_buffer = (
unsigned char*)buffer;
211 u.ether.data_length = size;
213 memset(buffer, 0, size);
217 struct CmdSingleStep:
public xen_domctl {
218 CmdSingleStep(
bool status) {
219 u.ether.command_code = XEN_DOMCTL_ETHER_SINGLE_STEP;
220 u.ether.on_or_off = status;
224 struct CmdSingleStepNotify:
public xen_domctl {
225 CmdSingleStepNotify(
bool status) {
226 u.ether.command_code = XEN_DOMCTL_ETHER_SS_DETECT;
227 u.ether.on_or_off = status;
231 struct CmdMemwriteNotify:
public xen_domctl {
232 CmdMemwriteNotify(
bool status) {
233 u.ether.command_code = XEN_DOMCTL_ETHER_MEMWRITE;
234 u.ether.on_or_off = status;
238 struct CmdUnpackNotify:
public xen_domctl {
239 CmdUnpackNotify(
bool status) {
240 u.ether.command_code = XEN_DOMCTL_ETHER_UNPACK;
241 u.ether.on_or_off = status;
245 struct CmdSysenter:
public xen_domctl {
246 CmdSysenter(rose_addr_t eip) {
247 u.ether.command_code = XEN_DOMCTL_ETHER_SET_SYSENTER;
248 u.ether.sysenter_cs = 0;
249 u.ether.sysenter_eip = eip;
253 struct CmdAddCR3:
public xen_domctl {
254 CmdAddCR3(rose_addr_t cr3) {
255 u.ether.command_code = XEN_DOMCTL_ETHER_ADD_CR3;
256 u.ether.cr3_value = cr3;
260 struct CmdAddName:
public xen_domctl {
261 CmdAddName(
const std::string &name) {
262 u.ether.command_code = XEN_DOMCTL_ETHER_ADD_NAME;
263 u.ether.data_length = name.size() + 1;
264 u.ether.guest_buffer = (
unsigned char*)(name.c_str());
269 return xc_iface>=0 && dom>0;
275 void domctl(
const xen_domctl &cmd, domid_t dom=0) {
276 domctl(
const_cast<xen_domctl*
>(&cmd), dom);
278 void domctl(xen_domctl &cmd, domid_t dom=0) {
281 void domctl(xen_domctl *cmd, domid_t dom=0) {
283 if (dom>0 && dom!=this->dom)
284 throw Exception(
"contradicting domain IDs");
287 throw Exception(
"not connected");
291 cmd->cmd = XEN_DOMCTL_ether;
292 int result = xc_domctl(xc_iface, cmd);
295 snprintf(buf,
sizeof(buf),
"xc_domctl(request=%u) failed", cmd->u.ether.command_code);
296 throw Exception(buf);
305 rose_addr_t shared_page_mfn;
306 volatile unsigned char *shared_page;
308 evtchn_port_t event_port;