Пример #1
0
bool_t hvm_monitor_cr(unsigned int index, unsigned long value, unsigned long old)
{
    struct vcpu *curr = current;
    struct arch_domain *ad = &curr->domain->arch;
    unsigned int ctrlreg_bitmask = monitor_ctrlreg_bitmask(index);

    if ( (ad->monitor.write_ctrlreg_enabled & ctrlreg_bitmask) &&
         (!(ad->monitor.write_ctrlreg_onchangeonly & ctrlreg_bitmask) ||
          value != old) )
    {
        bool_t sync = !!(ad->monitor.write_ctrlreg_sync & ctrlreg_bitmask);

        vm_event_request_t req = {
            .reason = VM_EVENT_REASON_WRITE_CTRLREG,
            .u.write_ctrlreg.index = index,
            .u.write_ctrlreg.new_value = value,
            .u.write_ctrlreg.old_value = old
        };

        if ( monitor_traps(curr, sync, &req) >= 0 )
            return 1;
    }

    return 0;
}
Пример #2
0
int arch_monitor_domctl_event(struct domain *d,
                              struct xen_domctl_monitor_op *mop)
{
    struct arch_domain *ad = &d->arch;
    bool_t requested_status = (XEN_DOMCTL_MONITOR_OP_ENABLE == mop->op);

    switch ( mop->event )
    {
    case XEN_DOMCTL_MONITOR_EVENT_WRITE_CTRLREG:
    {
        unsigned int ctrlreg_bitmask;
        bool_t old_status;

        /* sanity check: avoid left-shift undefined behavior */
        if ( unlikely(mop->u.mov_to_cr.index > 31) )
            return -EINVAL;

        ctrlreg_bitmask = monitor_ctrlreg_bitmask(mop->u.mov_to_cr.index);
        old_status = !!(ad->monitor.write_ctrlreg_enabled & ctrlreg_bitmask);

        if ( unlikely(old_status == requested_status) )
            return -EEXIST;

        domain_pause(d);

        if ( mop->u.mov_to_cr.sync )
            ad->monitor.write_ctrlreg_sync |= ctrlreg_bitmask;
        else
            ad->monitor.write_ctrlreg_sync &= ~ctrlreg_bitmask;

        if ( mop->u.mov_to_cr.onchangeonly )
            ad->monitor.write_ctrlreg_onchangeonly |= ctrlreg_bitmask;
        else
            ad->monitor.write_ctrlreg_onchangeonly &= ~ctrlreg_bitmask;

        if ( requested_status )
            ad->monitor.write_ctrlreg_enabled |= ctrlreg_bitmask;
        else
            ad->monitor.write_ctrlreg_enabled &= ~ctrlreg_bitmask;

        if ( VM_EVENT_X86_CR3 == mop->u.mov_to_cr.index )
        {
            struct vcpu *v;
            /* Latches new CR3 mask through CR0 code. */
            for_each_vcpu ( d, v )
                hvm_update_guest_cr(v, 0);
        }

        domain_unpause(d);

        break;
    }

    case XEN_DOMCTL_MONITOR_EVENT_MOV_TO_MSR:
    {
        bool_t old_status;
        int rc;
        u32 msr = mop->u.mov_to_msr.msr;

        domain_pause(d);

        old_status = monitored_msr(d, msr);

        if ( unlikely(old_status == requested_status) )
        {
            domain_unpause(d);
            return -EEXIST;
        }

        if ( requested_status )
            rc = monitor_enable_msr(d, msr);
        else
            rc = monitor_disable_msr(d, msr);

        domain_unpause(d);

        return rc;
    }

    case XEN_DOMCTL_MONITOR_EVENT_SINGLESTEP:
    {
        bool_t old_status = ad->monitor.singlestep_enabled;

        if ( unlikely(old_status == requested_status) )
            return -EEXIST;

        domain_pause(d);
        ad->monitor.singlestep_enabled = requested_status;
        domain_unpause(d);
        break;
    }

    case XEN_DOMCTL_MONITOR_EVENT_SOFTWARE_BREAKPOINT:
    {
        bool_t old_status = ad->monitor.software_breakpoint_enabled;

        if ( unlikely(old_status == requested_status) )
            return -EEXIST;

        domain_pause(d);
        ad->monitor.software_breakpoint_enabled = requested_status;
        domain_unpause(d);
        break;
    }

    case XEN_DOMCTL_MONITOR_EVENT_DEBUG_EXCEPTION:
    {
        bool_t old_status = ad->monitor.debug_exception_enabled;

        if ( unlikely(old_status == requested_status) )
            return -EEXIST;

        domain_pause(d);
        ad->monitor.debug_exception_enabled = requested_status;
        ad->monitor.debug_exception_sync = requested_status ?
                                            mop->u.debug_exception.sync :
                                            0;
        domain_unpause(d);
        break;
    }

    case XEN_DOMCTL_MONITOR_EVENT_CPUID:
    {
        bool_t old_status = ad->monitor.cpuid_enabled;

        if ( unlikely(old_status == requested_status) )
            return -EEXIST;

        domain_pause(d);
        ad->monitor.cpuid_enabled = requested_status;
        domain_unpause(d);
        break;
    }

    default:
        /*
         * Should not be reached unless arch_monitor_get_capabilities() is
         * not properly implemented.
         */
        ASSERT_UNREACHABLE();
        return -EOPNOTSUPP;
    }

    return 0;
}
Пример #3
0
int monitor_domctl(struct domain *d, struct xen_domctl_monitor_op *mop)
{
    int rc;
    struct arch_domain *ad = &d->arch;
    uint32_t capabilities = get_capabilities(d);

    rc = xsm_vm_event_control(XSM_PRIV, d, mop->op, mop->event);
    if ( rc )
        return rc;

    switch ( mop->op )
    {
    case XEN_DOMCTL_MONITOR_OP_GET_CAPABILITIES:
        mop->event = capabilities;
        return 0;

    case XEN_DOMCTL_MONITOR_OP_EMULATE_EACH_REP:
        d->arch.mem_access_emulate_each_rep = !!mop->event;
        return 0;
    }

    /*
     * Sanity check
     */
    if ( mop->op != XEN_DOMCTL_MONITOR_OP_ENABLE &&
         mop->op != XEN_DOMCTL_MONITOR_OP_DISABLE )
        return -EOPNOTSUPP;

    /* Check if event type is available. */
    if ( !(capabilities & (1 << mop->event)) )
        return -EOPNOTSUPP;

    switch ( mop->event )
    {
    case XEN_DOMCTL_MONITOR_EVENT_WRITE_CTRLREG:
    {
        unsigned int ctrlreg_bitmask =
            monitor_ctrlreg_bitmask(mop->u.mov_to_cr.index);
        bool_t status =
            !!(ad->monitor.write_ctrlreg_enabled & ctrlreg_bitmask);
        struct vcpu *v;

        rc = status_check(mop, status);
        if ( rc )
            return rc;

        if ( mop->u.mov_to_cr.sync )
            ad->monitor.write_ctrlreg_sync |= ctrlreg_bitmask;
        else
            ad->monitor.write_ctrlreg_sync &= ~ctrlreg_bitmask;

        if ( mop->u.mov_to_cr.onchangeonly )
            ad->monitor.write_ctrlreg_onchangeonly |= ctrlreg_bitmask;
        else
            ad->monitor.write_ctrlreg_onchangeonly &= ~ctrlreg_bitmask;

        domain_pause(d);

        if ( !status )
            ad->monitor.write_ctrlreg_enabled |= ctrlreg_bitmask;
        else
            ad->monitor.write_ctrlreg_enabled &= ~ctrlreg_bitmask;

        domain_unpause(d);

        if ( mop->u.mov_to_cr.index == VM_EVENT_X86_CR3 )
            /* Latches new CR3 mask through CR0 code */
            for_each_vcpu ( d, v )
                hvm_update_guest_cr(v, 0);

        break;
    }

    case XEN_DOMCTL_MONITOR_EVENT_MOV_TO_MSR:
    {
        bool_t status = ad->monitor.mov_to_msr_enabled;

        rc = status_check(mop, status);
        if ( rc )
            return rc;

        if ( mop->op == XEN_DOMCTL_MONITOR_OP_ENABLE &&
             mop->u.mov_to_msr.extended_capture )
        {
            if ( hvm_enable_msr_exit_interception(d) )
                ad->monitor.mov_to_msr_extended = 1;
            else
                return -EOPNOTSUPP;
        } else
            ad->monitor.mov_to_msr_extended = 0;

        domain_pause(d);
        ad->monitor.mov_to_msr_enabled = !status;
        domain_unpause(d);
        break;
    }

    case XEN_DOMCTL_MONITOR_EVENT_SINGLESTEP:
    {
        bool_t status = ad->monitor.singlestep_enabled;

        rc = status_check(mop, status);
        if ( rc )
            return rc;

        domain_pause(d);
        ad->monitor.singlestep_enabled = !status;
        domain_unpause(d);
        break;
    }

    case XEN_DOMCTL_MONITOR_EVENT_SOFTWARE_BREAKPOINT:
    {
        bool_t status = ad->monitor.software_breakpoint_enabled;

        rc = status_check(mop, status);
        if ( rc )
            return rc;

        domain_pause(d);
        ad->monitor.software_breakpoint_enabled = !status;
        domain_unpause(d);
        break;
    }

    case XEN_DOMCTL_MONITOR_EVENT_GUEST_REQUEST:
    {
        bool_t status = ad->monitor.guest_request_enabled;

        rc = status_check(mop, status);
        if ( rc )
            return rc;

        ad->monitor.guest_request_sync = mop->u.guest_request.sync;

        domain_pause(d);
        ad->monitor.guest_request_enabled = !status;
        domain_unpause(d);
        break;
    }

    default:
        return -EOPNOTSUPP;

    };

    return 0;
}