⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 io.c

📁 xen 3.2.2 源码
💻 C
📖 第 1 页 / 共 2 页
字号:
        if (dst & REGISTER) {            index = operand_index(dst);            set_reg_value(size, index, 0, regs, p->data);        }        break;    case INSTR_MOVZX:        if (dst & REGISTER) {            switch (size) {            case BYTE:                p->data &= 0xFFULL;                break;            case WORD:                p->data &= 0xFFFFULL;                break;            case LONG:                p->data &= 0xFFFFFFFFULL;                break;            default:                printk("Impossible source operand size of movzx instr: %d\n", size);                domain_crash_synchronous();            }            index = operand_index(dst);            set_reg_value(operand_size(dst), index, 0, regs, p->data);        }        break;    case INSTR_MOVSX:        if (dst & REGISTER) {            switch (size) {            case BYTE:                p->data &= 0xFFULL;                if ( p->data & 0x80ULL )                    p->data |= 0xFFFFFFFFFFFFFF00ULL;                break;            case WORD:                p->data &= 0xFFFFULL;                if ( p->data & 0x8000ULL )                    p->data |= 0xFFFFFFFFFFFF0000ULL;                break;            case LONG:                p->data &= 0xFFFFFFFFULL;                if ( p->data & 0x80000000ULL )                    p->data |= 0xFFFFFFFF00000000ULL;                break;            default:                printk("Impossible source operand size of movsx instr: %d\n", size);                domain_crash_synchronous();            }            index = operand_index(dst);            set_reg_value(operand_size(dst), index, 0, regs, p->data);        }        break;    case INSTR_MOVS:        sign = p->df ? -1 : 1;        if (mmio_opp->flags & REPZ)            regs->ecx -= p->count;        if ((mmio_opp->flags & OVERLAP) && p->dir == IOREQ_READ) {            unsigned long addr = mmio_opp->addr;            if (hvm_paging_enabled(current))            {                int rv = hvm_copy_to_guest_virt(addr, &p->data, p->size);                if ( rv == HVMCOPY_bad_gva_to_gfn )                    return; /* exception already injected */            }            else                (void)hvm_copy_to_guest_phys(addr, &p->data, p->size);        }        regs->esi += sign * p->count * p->size;        regs->edi += sign * p->count * p->size;        break;    case INSTR_STOS:        sign = p->df ? -1 : 1;        regs->edi += sign * p->count * p->size;        if (mmio_opp->flags & REPZ)            regs->ecx -= p->count;        break;    case INSTR_LODS:        set_reg_value(size, 0, 0, regs, p->data);        sign = p->df ? -1 : 1;        regs->esi += sign * p->count * p->size;        if (mmio_opp->flags & REPZ)            regs->ecx -= p->count;        break;    case INSTR_AND:        if (src & REGISTER) {            index = operand_index(src);            value = get_reg_value(size, index, 0, regs);            result = (unsigned long) p->data & value;        } else if (src & IMMEDIATE) {            value = mmio_opp->immediate;            result = (unsigned long) p->data & value;        } else if (src & MEMORY) {            index = operand_index(dst);            value = get_reg_value(size, index, 0, regs);            result = (unsigned long) p->data & value;            set_reg_value(size, index, 0, regs, result);        }        /*         * The OF and CF flags are cleared; the SF, ZF, and PF         * flags are set according to the result. The state of         * the AF flag is undefined.         */        regs->eflags &= ~(X86_EFLAGS_CF|X86_EFLAGS_PF|                          X86_EFLAGS_ZF|X86_EFLAGS_SF|X86_EFLAGS_OF);        set_eflags_ZF(size, result, regs);        set_eflags_SF(size, result, regs);        set_eflags_PF(size, result, regs);        break;    case INSTR_ADD:        if (src & REGISTER) {            index = operand_index(src);            value = get_reg_value(size, index, 0, regs);            result = (unsigned long) p->data + value;        } else if (src & IMMEDIATE) {            value = mmio_opp->immediate;            result = (unsigned long) p->data + value;        } else if (src & MEMORY) {            index = operand_index(dst);            value = get_reg_value(size, index, 0, regs);            result = (unsigned long) p->data + value;            set_reg_value(size, index, 0, regs, result);        }        /*         * The CF, OF, SF, ZF, AF, and PF flags are set according         * to the result         */        regs->eflags &= ~(X86_EFLAGS_CF|X86_EFLAGS_PF|X86_EFLAGS_AF|                          X86_EFLAGS_ZF|X86_EFLAGS_SF|X86_EFLAGS_OF);        set_eflags_CF(size, mmio_opp->instr, result, value,                      (unsigned long) p->data, regs);        set_eflags_OF(size, mmio_opp->instr, result, value,                      (unsigned long) p->data, regs);        set_eflags_AF(size, result, value, (unsigned long) p->data, regs);        set_eflags_ZF(size, result, regs);        set_eflags_SF(size, result, regs);        set_eflags_PF(size, result, regs);        break;    case INSTR_OR:        if (src & REGISTER) {            index = operand_index(src);            value = get_reg_value(size, index, 0, regs);            result = (unsigned long) p->data | value;        } else if (src & IMMEDIATE) {            value = mmio_opp->immediate;            result = (unsigned long) p->data | value;        } else if (src & MEMORY) {            index = operand_index(dst);            value = get_reg_value(size, index, 0, regs);            result = (unsigned long) p->data | value;            set_reg_value(size, index, 0, regs, result);        }        /*         * The OF and CF flags are cleared; the SF, ZF, and PF         * flags are set according to the result. The state of         * the AF flag is undefined.         */        regs->eflags &= ~(X86_EFLAGS_CF|X86_EFLAGS_PF|                          X86_EFLAGS_ZF|X86_EFLAGS_SF|X86_EFLAGS_OF);        set_eflags_ZF(size, result, regs);        set_eflags_SF(size, result, regs);        set_eflags_PF(size, result, regs);        break;    case INSTR_XOR:        if (src & REGISTER) {            index = operand_index(src);            value = get_reg_value(size, index, 0, regs);            result = (unsigned long) p->data ^ value;        } else if (src & IMMEDIATE) {            value = mmio_opp->immediate;            result = (unsigned long) p->data ^ value;        } else if (src & MEMORY) {            index = operand_index(dst);            value = get_reg_value(size, index, 0, regs);            result = (unsigned long) p->data ^ value;            set_reg_value(size, index, 0, regs, result);        }        /*         * The OF and CF flags are cleared; the SF, ZF, and PF         * flags are set according to the result. The state of         * the AF flag is undefined.         */        regs->eflags &= ~(X86_EFLAGS_CF|X86_EFLAGS_PF|                          X86_EFLAGS_ZF|X86_EFLAGS_SF|X86_EFLAGS_OF);        set_eflags_ZF(size, result, regs);        set_eflags_SF(size, result, regs);        set_eflags_PF(size, result, regs);        break;    case INSTR_CMP:    case INSTR_SUB:        if (src & REGISTER) {            index = operand_index(src);            value = get_reg_value(size, index, 0, regs);            result = (unsigned long) p->data - value;        } else if (src & IMMEDIATE) {            value = mmio_opp->immediate;            result = (unsigned long) p->data - value;        } else if (src & MEMORY) {            index = operand_index(dst);            value = get_reg_value(size, index, 0, regs);            result = value - (unsigned long) p->data;            if ( mmio_opp->instr == INSTR_SUB )                set_reg_value(size, index, 0, regs, result);        }        /*         * The CF, OF, SF, ZF, AF, and PF flags are set according         * to the result         */        regs->eflags &= ~(X86_EFLAGS_CF|X86_EFLAGS_PF|X86_EFLAGS_AF|                          X86_EFLAGS_ZF|X86_EFLAGS_SF|X86_EFLAGS_OF);        if ( src & (REGISTER | IMMEDIATE) )        {            set_eflags_CF(size, mmio_opp->instr, result, value,                          (unsigned long) p->data, regs);            set_eflags_OF(size, mmio_opp->instr, result, value,                          (unsigned long) p->data, regs);        }        else        {            set_eflags_CF(size, mmio_opp->instr, result,                          (unsigned long) p->data, value, regs);            set_eflags_OF(size, mmio_opp->instr, result,                          (unsigned long) p->data, value, regs);        }        set_eflags_AF(size, result, value, (unsigned long) p->data, regs);        set_eflags_ZF(size, result, regs);        set_eflags_SF(size, result, regs);        set_eflags_PF(size, result, regs);        break;    case INSTR_TEST:        if (src & REGISTER) {            index = operand_index(src);            value = get_reg_value(size, index, 0, regs);        } else if (src & IMMEDIATE) {            value = mmio_opp->immediate;        } else if (src & MEMORY) {            index = operand_index(dst);            value = get_reg_value(size, index, 0, regs);        }        result = (unsigned long) p->data & value;        /*         * Sets the SF, ZF, and PF status flags. CF and OF are set to 0         */        regs->eflags &= ~(X86_EFLAGS_CF|X86_EFLAGS_PF|                          X86_EFLAGS_ZF|X86_EFLAGS_SF|X86_EFLAGS_OF);        set_eflags_ZF(size, result, regs);        set_eflags_SF(size, result, regs);        set_eflags_PF(size, result, regs);        break;    case INSTR_BT:        if ( src & REGISTER )        {            index = operand_index(src);            value = get_reg_value(size, index, 0, regs);        }        else if ( src & IMMEDIATE )            value = mmio_opp->immediate;        if (p->data & (1 << (value & ((1 << 5) - 1))))            regs->eflags |= X86_EFLAGS_CF;        else            regs->eflags &= ~X86_EFLAGS_CF;        break;    case INSTR_XCHG:        if (src & REGISTER) {            index = operand_index(src);            set_reg_value(size, index, 0, regs, p->data);        } else {            index = operand_index(dst);            set_reg_value(size, index, 0, regs, p->data);        }        break;    case INSTR_PUSH:        mmio_opp->addr += hvm_get_segment_base(current, x86_seg_ss);        {            unsigned long addr = mmio_opp->addr;            int rv = hvm_copy_to_guest_virt(addr, &p->data, size);            if ( rv == HVMCOPY_bad_gva_to_gfn )                return; /* exception already injected */        }        break;    }}void hvm_io_assist(void){    vcpu_iodata_t *vio;    ioreq_t *p;    struct cpu_user_regs *regs;    struct hvm_io_op *io_opp;    struct vcpu *v = current;    io_opp = &v->arch.hvm_vcpu.io_op;    regs   = &io_opp->io_context;    vio    = get_ioreq(v);    p = &vio->vp_ioreq;    if ( p->state != STATE_IORESP_READY )    {        gdprintk(XENLOG_ERR, "Unexpected HVM iorequest state %d.\n", p->state);        domain_crash(v->domain);        goto out;    }    rmb(); /* see IORESP_READY /then/ read contents of ioreq */    p->state = STATE_IOREQ_NONE;    if ( v->arch.hvm_vcpu.io_complete && v->arch.hvm_vcpu.io_complete() )        goto out;    switch ( p->type )    {    case IOREQ_TYPE_INVALIDATE:        goto out;    case IOREQ_TYPE_PIO:        hvm_pio_assist(regs, p, io_opp);        break;    default:        hvm_mmio_assist(regs, p, io_opp);        break;    }    /* Copy register changes back into current guest state. */    regs->eflags &= ~X86_EFLAGS_RF;    memcpy(guest_cpu_user_regs(), regs, HVM_CONTEXT_STACK_BYTES);    if ( regs->eflags & X86_EFLAGS_TF )        hvm_inject_exception(TRAP_debug, HVM_DELIVER_NO_ERROR_CODE, 0); out:    vcpu_end_shutdown_deferral(v);}void dpci_ioport_read(uint32_t mport, ioreq_t *p){    uint64_t i;    uint64_t z_data;    uint64_t length = (p->count * p->size);    for ( i = 0; i < length; i += p->size )    {        z_data = ~0ULL;                switch ( p->size )        {        case BYTE:            z_data = (uint64_t)inb(mport);            break;        case WORD:            z_data = (uint64_t)inw(mport);            break;        case LONG:            z_data = (uint64_t)inl(mport);            break;        default:            gdprintk(XENLOG_ERR, "Error: unable to handle size: %"                     PRId64 "\n", p->size);            return;        }        p->data = z_data;        if ( p->data_is_ptr &&             hvm_copy_to_guest_phys(p->data + i, (void *)&z_data,                                    (int)p->size) )        {            gdprintk(XENLOG_ERR, "Error: couldn't copy to hvm phys\n");            return;        }    }}void dpci_ioport_write(uint32_t mport, ioreq_t *p){    uint64_t i;    uint64_t z_data = 0;    uint64_t length = (p->count * p->size);    for ( i = 0; i < length; i += p->size )    {        z_data = p->data;        if ( p->data_is_ptr &&             hvm_copy_from_guest_phys((void *)&z_data,                                      p->data + i, (int)p->size) )        {            gdprintk(XENLOG_ERR, "Error: couldn't copy from hvm phys\n");            return;        }        switch ( p->size )        {        case BYTE:            outb((uint8_t) z_data, mport);            break;        case WORD:            outw((uint16_t) z_data, mport);            break;        case LONG:            outl((uint32_t) z_data, mport);            break;        default:            gdprintk(XENLOG_ERR, "Error: unable to handle size: %"                     PRId64 "\n", p->size);            break;        }    }}int dpci_ioport_intercept(ioreq_t *p){    struct domain *d = current->domain;    struct hvm_iommu *hd = domain_hvm_iommu(d);    struct g2m_ioport *g2m_ioport;    unsigned int mport, gport = p->addr;    unsigned int s = 0, e = 0;    list_for_each_entry( g2m_ioport, &hd->g2m_ioport_list, list )    {        s = g2m_ioport->gport;        e = s + g2m_ioport->np;        if ( (gport >= s) && (gport < e) )            goto found;    }    return 0; found:    mport = (gport - s) + g2m_ioport->mport;    if ( !ioports_access_permitted(d, mport, mport + p->size - 1) )     {        gdprintk(XENLOG_ERR, "Error: access to gport=0x%x denied!\n",                 (uint32_t)p->addr);        return 0;    }    switch ( p->dir )    {    case IOREQ_READ:        dpci_ioport_read(mport, p);        break;    case IOREQ_WRITE:        dpci_ioport_write(mport, p);        break;    default:        gdprintk(XENLOG_ERR, "Error: couldn't handle p->dir = %d", p->dir);    }    return 1;}/* * Local variables: * mode: C * c-set-style: "BSD" * c-basic-offset: 4 * tab-width: 4 * indent-tabs-mode: nil * End: */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -