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);
 
   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));
 
  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 {
 
  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 {
 
  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 {
 
  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);
 
  306    volatile unsigned char *shared_page;        
 
  308    evtchn_port_t event_port;                   
 
std::uint64_t Address
Address.