Ejemplo n.º 1
0
/*
 * Returns: bytes that could not be written. 0 => wrote all bytes, ie, success.
 */
int 
xg_write_mem(uint64_t guestva, char *frombuf, int buflen, uint64_t pgd3val)
{
    struct xen_domctl_gdbsx_memio *iop = &domctl.u.gdbsx_guest_memio;
    union {uint64_t llbuf8; char buf8[8];} u = {0};
    int i, rc;

    for(i=0; i < XGMIN(8, buflen); u.buf8[i]=frombuf[i], i++);
    XGTRC("E:gva:%llx frombuf:%lx len:%d buf8:0x%llx\n", guestva, frombuf, 
          buflen, u.llbuf8);

    memset(&domctl.u, 0, sizeof(domctl.u));
    iop->pgd3val = pgd3val;
    iop->gva = guestva;
    iop->uva = (uint64_aligned_t)((unsigned long)frombuf);
    iop->len = buflen;
    iop->gwr = 1;       /* writing to guest */

    if ((rc=_domctl_hcall(XEN_DOMCTL_gdbsx_guestmemio, frombuf, buflen)))
    {
        XGERR("ERROR: failed to write bytes to %llx. errno:%d rc:%d\n",
              guestva, errno, rc);
        return buflen;
    }
    return iop->remain;
}
Ejemplo n.º 2
0
/*
 * write registers for the given vcpu
 * Returns: 0 success, 1 failure with errno
 */
int 
xg_regs_write(regstype_t which_regs, vcpuid_t which_vcpu, 
              union xg_gdb_regs *regsp, int guest_bitness)
{
    union vcpu_guest_context_any anyc;
    struct cpu_user_regs_x86_32 *cr32p = &anyc.ctxt32.user_regs;
    struct cpu_user_regs_x86_64 *cr64p = &anyc.ctxt64.user_regs;
    struct xg_gdb_regs32 *r32p = &regsp->gregs_32;
    struct xg_gdb_regs64 *r64p = &regsp->gregs_64;
    int rc, sz = sizeof(anyc);

    if (which_regs != XG_GPRS) {
        errno = EINVAL;
        XGERR("regs got: %d. Expected GPRS:%d\n", which_regs, XG_GPRS);
        return 1;
    }
    if ((rc=_get_vcpu_ctxt(which_vcpu, &anyc)))
        return rc;

    if (guest_bitness == 32) {
        if (_32bit_hyp || !_hvm_guest)
            _cp_32gdb_to_32ctxt(r32p, cr32p);
        else 
            _cp_32gdb_to_64ctxt(r32p, cr64p);
    } else
        _cp_64gdb_to_64ctxt(r64p, cr64p);

    /* set vcpu context back */
    if ((rc =_domctl_hcall(XEN_DOMCTL_setvcpucontext, &anyc, sz))) {
        XGERR("Failed hcall to set vcpu ctxt. errno:%d\n", errno);
        return rc;
    }
    XGTRC("X:vcpu:%d bitness:%d rc:%d\n", which_vcpu, guest_bitness, rc);
    return rc;
}
Ejemplo n.º 3
0
/*
 * Returns: bytes remaining to be read. 0 => read all bytes, ie, success.
 */
int 
xg_read_mem(uint64_t guestva, char *tobuf, int tobuf_len, uint64_t pgd3val)
{
    struct xen_domctl_gdbsx_memio *iop = &domctl.u.gdbsx_guest_memio;
    union {uint64_t llbuf8; char buf8[8];} u = {0};
    int i, rc;

    XGTRC("E:gva:%llx tobuf:%lx len:%d\n", guestva, tobuf, tobuf_len);

    memset(&domctl.u, 0, sizeof(domctl.u));
    iop->pgd3val = pgd3val;
    iop->gva = guestva;
    iop->uva = (uint64_aligned_t)((unsigned long)tobuf);
    iop->len = tobuf_len;
    iop->gwr = 0;       /* not writing to guest */

    if ( (rc = _domctl_hcall(XEN_DOMCTL_gdbsx_guestmemio, tobuf, tobuf_len)) )
    {
        XGTRC("ERROR: failed to read bytes. errno:%d rc:%d\n", errno, rc);
        return tobuf_len;
    }

    for(i=0; i < XGMIN(8, tobuf_len); u.buf8[i]=tobuf[i], i++);
    XGTRC("X:remain:%d buf8:0x%llx\n", iop->remain, u.llbuf8);

    return iop->remain;
}
Ejemplo n.º 4
0
/*
 * Change the TF flag for single step.   TF = (setit ? 1 : 0);
 * Returns: 0 Success
 */
static int
_change_TF(vcpuid_t which_vcpu, int guest_bitness, int setit)
{
    union vcpu_guest_context_any anyc;
    int sz = sizeof(anyc);

    /* first try the MTF for hvm guest. otherwise do manually */
    if (_hvm_guest) {
        domctl.u.debug_op.vcpu = which_vcpu;
        domctl.u.debug_op.op = setit ? XEN_DOMCTL_DEBUG_OP_SINGLE_STEP_ON :
                                       XEN_DOMCTL_DEBUG_OP_SINGLE_STEP_OFF;

        if (_domctl_hcall(XEN_DOMCTL_debug_op, NULL, 0) == 0) {
            XGTRC("vcpu:%d:MTF success setit:%d\n", which_vcpu, setit);
            return 0;
        }
        XGTRC("vcpu:%d:MTF failed. setit:%d\n", which_vcpu, setit);
    }

    memset(&anyc, 0, sz);
    domctl.u.vcpucontext.vcpu = (uint16_t)which_vcpu;
    set_xen_guest_handle(domctl.u.vcpucontext.ctxt, &anyc.ctxt);

    if (_domctl_hcall(XEN_DOMCTL_getvcpucontext, &anyc, sz)) {
        XGERR("Failed hcall to get vcpu ctxt for TF. errno:%d\n",errno);
        return 1;
    }
    if (_32bit_hyp || (guest_bitness == 32 && !_hvm_guest)) {
        if (setit)
            anyc.ctxt32.user_regs.eflags |= X86_EFLAGS_TF;
        else
            anyc.ctxt32.user_regs.eflags &= ~X86_EFLAGS_TF;
    } else {
        if (setit)
            anyc.ctxt64.user_regs.rflags |= X86_EFLAGS_TF;
        else
            anyc.ctxt64.user_regs.rflags &= ~X86_EFLAGS_TF;
    }

    if (_domctl_hcall(XEN_DOMCTL_setvcpucontext, &anyc, sz)) {
        XGERR("Failed hcall to set vcpu ctxt for TF. errno:%d\n",errno);
        return 1;
    }
    return 0;
}
Ejemplo n.º 5
0
/*
 * Attach to the given domid for debugging.
 * Returns: max vcpu id : Success
 *                   -1 : Failure
 */
int 
xg_attach(int domid, int guest_bitness)
{
    XGTRC("E:domid:%d\n", domid);

    _dom_id = domctl.domain = domid;
    domctl.interface_version = XEN_DOMCTL_INTERFACE_VERSION;

    if (mlock(&domctl, sizeof(domctl))) {
        XGERR("Unable to pin domctl in memory. errno:%d\n", errno);
        return -1;
    }
    if (_check_hyp(guest_bitness))
        return -1;

    if (_domctl_hcall(XEN_DOMCTL_pausedomain, NULL, 0)) {
        XGERR("Unable to pause domain:%d\n", _dom_id);
        return -1;
    } 

    memset(&domctl.u, 0, sizeof(domctl.u));
    domctl.u.setdebugging.enable = 1;
    if (_domctl_hcall(XEN_DOMCTL_setdebugging, NULL, 0)) {
        XGERR("Unable to set domain to debug mode: errno:%d\n", errno);
        _unpause_domain();
        return -1;
    }

    memset(&domctl.u, 0, sizeof(domctl.u));
    if (_domctl_hcall(XEN_DOMCTL_getdomaininfo, NULL, 0)) {
        XGERR("Unable to get domain info: domid:%d errno:%d\n", 
              domid, errno);
        _unpause_domain();
        return -1;
    }
    if (!_domain_ok(&domctl.u.getdomaininfo)) {
        _unpause_domain();
        return -1;
    }

    _max_vcpu_id = domctl.u.getdomaininfo.max_vcpu_id;
    _hvm_guest = (domctl.u.getdomaininfo.flags & XEN_DOMINF_hvm_guest);
    _pvh_guest = (domctl.u.getdomaininfo.flags & XEN_DOMINF_pvh_guest);
    return _max_vcpu_id;
}
Ejemplo n.º 6
0
/* Returns: 1 : domain is paused.  0 otherwise */
static int
_domain_is_paused(void)
{
    memset(&domctl.u, 0, sizeof(domctl.u));
    if (_domctl_hcall(XEN_DOMCTL_getdomaininfo, NULL, 0)) {
        XGERR("ERROR: Unable to get domain paused info:%d\n", _dom_id);
        return 0;
    } 
    return (domctl.u.getdomaininfo.flags & XEN_DOMINF_paused);
}
Ejemplo n.º 7
0
/* Returns: 0 : success */
static int
_unpause_domain(void)
{
    memset(&domctl.u, 0, sizeof(domctl.u));
    if (_domctl_hcall(XEN_DOMCTL_unpausedomain, NULL, 0)) {
        XGERR("Unable to unpause domain:%d errno:%d\n", _dom_id, errno);
        return -1;
    } 
    return 0;
}
Ejemplo n.º 8
0
/*
 * check if any one of the vcpus is in a breakpoint
 * Returns:      vcpuid   :  if a vcpu found in a bp
 *                    -1  : otherwise
 */
static vcpuid_t
_vcpu_in_bp(void)
{
    memset(&domctl.u, 0, sizeof(domctl.u));
    if (_domctl_hcall(XEN_DOMCTL_gdbsx_domstatus, NULL, 0)) {
        XGERR("ERROR: Unable to check vcpu bp status:%d errno:%d\n", 
              _dom_id, errno);
        return -1;
    } 
    return domctl.u.gdbsx_domstatus.vcpu_id;
}
Ejemplo n.º 9
0
/* Detach from guest for debugger exit */
void
xg_detach_deinit(void)
{
    memset(&domctl.u, 0, sizeof(domctl.u));
    domctl.u.setdebugging.enable = 0;
    if (_domctl_hcall(XEN_DOMCTL_setdebugging, NULL, 0)) {
        XGERR("Unable to reset domain debug mode: errno:%d\n", errno);
    }
    if (_domain_is_paused()) 
        _unpause_domain();
        
    close(_dom0_fd);
}
Ejemplo n.º 10
0
/* get vcpu context from xen and return it in *ctxtp
 * RETURNS: 0 for success
 */
static int
_get_vcpu_ctxt(vcpuid_t vcpu_id, union vcpu_guest_context_any *anycp)
{
    int sz = sizeof(union vcpu_guest_context_any);

    memset(anycp, 0, sz);
    domctl.u.vcpucontext.vcpu = (uint16_t)vcpu_id;
    set_xen_guest_handle(domctl.u.vcpucontext.ctxt, &anycp->ctxt);

    if (_domctl_hcall(XEN_DOMCTL_getvcpucontext, anycp, sz)) {
        XGERR("Failed hcall to get vcpu ctxt. errno:%d\n", errno);
        return 1;
    }
    return 0;
}
Ejemplo n.º 11
0
/* Do the given DOMCTL hcall action(pause or unpause) on all but the given vcpu
 * Returns: 0 success */
static int
_allbutone_vcpu(uint32_t hcall, vcpuid_t which_vcpu)
{
    int i;
    for (i=0; i <= _max_vcpu_id; i++) {
        if (i == which_vcpu)
            continue;

        memset(&domctl.u, 0, sizeof(domctl.u));
        domctl.u.gdbsx_pauseunp_vcpu.vcpu = i;
        if (_domctl_hcall(hcall, NULL, 0)) {
            XGERR("Unable to do:%d vcpu:%d errno:%d\n", 
                  hcall, i, errno); 
            return 1;
        } 
    }
    return 0;
}
Ejemplo n.º 12
0
/* 
 * Make sure we are running on hyp enabled for gdbsx. Also, note whether
 * its 32bit. Fail if user typed 64bit for guest in case of 32bit hyp.
 *
 * RETURNS: 0 : everything OK. 
 */
static int
_check_hyp(int guest_bitness)
{
    xen_capabilities_info_t xen_caps = "";
    privcmd_hypercall_t hypercall;
    int rc;

    /*
     * Try to unpause an invalid vcpu. If hypervisor supports gdbsx then
     * this should fail with an error other than ENOSYS.
     */
    domctl.u.gdbsx_pauseunp_vcpu.vcpu = ~0u;
    (void)_domctl_hcall(XEN_DOMCTL_gdbsx_unpausevcpu, NULL, 0);
    if (errno == ENOSYS) {
        XGERR("Hyp is NOT enabled for gdbsx\n");
        return -1;
    } 

    if (mlock(&xen_caps, sizeof(xen_caps))) {
        XGERR("Unable to pin xen_caps in memory. errno:%d\n", errno);
        return -1;
    }
    memset(&xen_caps, 0, sizeof(xen_caps));

    hypercall.op = __HYPERVISOR_xen_version;
    hypercall.arg[0] = (unsigned long)XENVER_capabilities;
    hypercall.arg[1] = (unsigned long)&xen_caps;

    rc = ioctl(_dom0_fd, IOCTL_PRIVCMD_HYPERCALL, &hypercall);
    munlock(&xen_caps, sizeof(xen_caps));
    XGTRC("XENCAPS:%s\n", xen_caps);

    if (rc != 0) {
        XGERR("Failed xen_version hcall. errno:%d\n", errno);
        return -1;
    }

    _32bit_hyp = (strstr(xen_caps, "x86_64") == NULL);
    if (_32bit_hyp && guest_bitness !=32) {
        XGERR("32bit hyp can only run 32bit guests\n");
        return -1;
    }
    return 0;
}