📄 io.c
字号:
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 + -