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

📄 io.c

📁 xen 3.2.2 源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * io.c: Handling I/O and interrupts. * * Copyright (c) 2004, Intel Corporation. * Copyright (c) 2005, International Business Machines Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, * version 2, as published by the Free Software Foundation. * * This program is distributed in the hope it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program; if not, write to the Free Software Foundation, Inc., 59 Temple * Place - Suite 330, Boston, MA 02111-1307 USA. */#include <xen/config.h>#include <xen/init.h>#include <xen/mm.h>#include <xen/lib.h>#include <xen/errno.h>#include <xen/trace.h>#include <xen/event.h>#include <xen/hypercall.h>#include <asm/current.h>#include <asm/cpufeature.h>#include <asm/processor.h>#include <asm/msr.h>#include <asm/apic.h>#include <asm/paging.h>#include <asm/shadow.h>#include <asm/p2m.h>#include <asm/hvm/hvm.h>#include <asm/hvm/support.h>#include <asm/hvm/vpt.h>#include <asm/hvm/vpic.h>#include <asm/hvm/vlapic.h>#include <asm/hvm/trace.h>#include <public/sched.h>#include <xen/iocap.h>#include <public/hvm/ioreq.h>#if defined (__i386__)static void set_reg_value (int size, int index, int seg, struct cpu_user_regs *regs, long value){    switch (size) {    case BYTE:        switch (index) {        case 0:            regs->eax &= 0xFFFFFF00;            regs->eax |= (value & 0xFF);            break;        case 1:            regs->ecx &= 0xFFFFFF00;            regs->ecx |= (value & 0xFF);            break;        case 2:            regs->edx &= 0xFFFFFF00;            regs->edx |= (value & 0xFF);            break;        case 3:            regs->ebx &= 0xFFFFFF00;            regs->ebx |= (value & 0xFF);            break;        case 4:            regs->eax &= 0xFFFF00FF;            regs->eax |= ((value & 0xFF) << 8);            break;        case 5:            regs->ecx &= 0xFFFF00FF;            regs->ecx |= ((value & 0xFF) << 8);            break;        case 6:            regs->edx &= 0xFFFF00FF;            regs->edx |= ((value & 0xFF) << 8);            break;        case 7:            regs->ebx &= 0xFFFF00FF;            regs->ebx |= ((value & 0xFF) << 8);            break;        default:            goto crash;        }        break;    case WORD:        switch (index) {        case 0:            regs->eax &= 0xFFFF0000;            regs->eax |= (value & 0xFFFF);            break;        case 1:            regs->ecx &= 0xFFFF0000;            regs->ecx |= (value & 0xFFFF);            break;        case 2:            regs->edx &= 0xFFFF0000;            regs->edx |= (value & 0xFFFF);            break;        case 3:            regs->ebx &= 0xFFFF0000;            regs->ebx |= (value & 0xFFFF);            break;        case 4:            regs->esp &= 0xFFFF0000;            regs->esp |= (value & 0xFFFF);            break;        case 5:            regs->ebp &= 0xFFFF0000;            regs->ebp |= (value & 0xFFFF);            break;        case 6:            regs->esi &= 0xFFFF0000;            regs->esi |= (value & 0xFFFF);            break;        case 7:            regs->edi &= 0xFFFF0000;            regs->edi |= (value & 0xFFFF);            break;        default:            goto crash;        }        break;    case LONG:        switch (index) {        case 0:            regs->eax = value;            break;        case 1:            regs->ecx = value;            break;        case 2:            regs->edx = value;            break;        case 3:            regs->ebx = value;            break;        case 4:            regs->esp = value;            break;        case 5:            regs->ebp = value;            break;        case 6:            regs->esi = value;            break;        case 7:            regs->edi = value;            break;        default:            goto crash;        }        break;    default:    crash:        gdprintk(XENLOG_ERR, "size:%x, index:%x are invalid!\n", size, index);        domain_crash_synchronous();    }}#elsestatic inline void __set_reg_value(unsigned long *reg, int size, long value){    switch (size) {    case BYTE_64:        *reg &= ~0xFF;        *reg |= (value & 0xFF);        break;    case WORD:        *reg &= ~0xFFFF;        *reg |= (value & 0xFFFF);        break;    case LONG:        *reg &= ~0xFFFFFFFF;        *reg |= (value & 0xFFFFFFFF);        break;    case QUAD:        *reg = value;        break;    default:        gdprintk(XENLOG_ERR, "size:%x is invalid\n", size);        domain_crash_synchronous();    }}static void set_reg_value (int size, int index, int seg, struct cpu_user_regs *regs, long value){    if (size == BYTE) {        switch (index) {        case 0:            regs->rax &= ~0xFF;            regs->rax |= (value & 0xFF);            break;        case 1:            regs->rcx &= ~0xFF;            regs->rcx |= (value & 0xFF);            break;        case 2:            regs->rdx &= ~0xFF;            regs->rdx |= (value & 0xFF);            break;        case 3:            regs->rbx &= ~0xFF;            regs->rbx |= (value & 0xFF);            break;        case 4:            regs->rax &= 0xFFFFFFFFFFFF00FF;            regs->rax |= ((value & 0xFF) << 8);            break;        case 5:            regs->rcx &= 0xFFFFFFFFFFFF00FF;            regs->rcx |= ((value & 0xFF) << 8);            break;        case 6:            regs->rdx &= 0xFFFFFFFFFFFF00FF;            regs->rdx |= ((value & 0xFF) << 8);            break;        case 7:            regs->rbx &= 0xFFFFFFFFFFFF00FF;            regs->rbx |= ((value & 0xFF) << 8);            break;        default:            gdprintk(XENLOG_ERR, "size:%x, index:%x are invalid!\n",                     size, index);            domain_crash_synchronous();            break;        }        return;    }    switch (index) {    case 0:        __set_reg_value(&regs->rax, size, value);        break;    case 1:        __set_reg_value(&regs->rcx, size, value);        break;    case 2:        __set_reg_value(&regs->rdx, size, value);        break;    case 3:        __set_reg_value(&regs->rbx, size, value);        break;    case 4:        __set_reg_value(&regs->rsp, size, value);        break;    case 5:        __set_reg_value(&regs->rbp, size, value);        break;    case 6:        __set_reg_value(&regs->rsi, size, value);        break;    case 7:        __set_reg_value(&regs->rdi, size, value);        break;    case 8:        __set_reg_value(&regs->r8, size, value);        break;    case 9:        __set_reg_value(&regs->r9, size, value);        break;    case 10:        __set_reg_value(&regs->r10, size, value);        break;    case 11:        __set_reg_value(&regs->r11, size, value);        break;    case 12:        __set_reg_value(&regs->r12, size, value);        break;    case 13:        __set_reg_value(&regs->r13, size, value);        break;    case 14:        __set_reg_value(&regs->r14, size, value);        break;    case 15:        __set_reg_value(&regs->r15, size, value);        break;    default:        gdprintk(XENLOG_ERR, "Invalid index\n");        domain_crash_synchronous();    }    return;}#endiflong get_reg_value(int size, int index, int seg, struct cpu_user_regs *regs);static inline void set_eflags_CF(int size,                                 unsigned int instr,                                 unsigned long result,                                 unsigned long src,                                 unsigned long dst,                                 struct cpu_user_regs *regs){    unsigned long mask;    if ( size == BYTE_64 )        size = BYTE;    ASSERT((size <= sizeof(mask)) && (size > 0));    mask = ~0UL >> (8 * (sizeof(mask) - size));    if ( instr == INSTR_ADD )    {        /* CF=1 <==> result is less than the augend and addend) */        if ( (result & mask) < (dst & mask) )        {            ASSERT((result & mask) < (src & mask));            regs->eflags |= X86_EFLAGS_CF;        }    }    else    {        ASSERT( instr == INSTR_CMP || instr == INSTR_SUB );        if ( (src & mask) > (dst & mask) )            regs->eflags |= X86_EFLAGS_CF;    }}static inline void set_eflags_OF(int size,                                 unsigned int instr,                                 unsigned long result,                                 unsigned long src,                                 unsigned long dst,                                 struct cpu_user_regs *regs){    unsigned long mask;    if ( size == BYTE_64 )        size = BYTE;    ASSERT((size <= sizeof(mask)) && (size > 0));    mask =  1UL << ((8*size) - 1);    if ( instr == INSTR_ADD )    {        if ((src ^ result) & (dst ^ result) & mask);            regs->eflags |= X86_EFLAGS_OF;    }    else    {        ASSERT(instr == INSTR_CMP || instr == INSTR_SUB);        if ((dst ^ src) & (dst ^ result) & mask)            regs->eflags |= X86_EFLAGS_OF;    }}static inline void set_eflags_AF(int size,                                 unsigned long result,                                 unsigned long src,                                 unsigned long dst,                                 struct cpu_user_regs *regs){    if ((result ^ src ^ dst) & 0x10)        regs->eflags |= X86_EFLAGS_AF;}static inline void set_eflags_ZF(int size, unsigned long result,                                 struct cpu_user_regs *regs){    unsigned long mask;    if ( size == BYTE_64 )        size = BYTE;    ASSERT((size <= sizeof(mask)) && (size > 0));    mask = ~0UL >> (8 * (sizeof(mask) - size));    if ((result & mask) == 0)        regs->eflags |= X86_EFLAGS_ZF;}static inline void set_eflags_SF(int size, unsigned long result,                                 struct cpu_user_regs *regs){    unsigned long mask;    if ( size == BYTE_64 )        size = BYTE;    ASSERT((size <= sizeof(mask)) && (size > 0));    mask = 1UL << ((8*size) - 1);    if (result & mask)        regs->eflags |= X86_EFLAGS_SF;}static char parity_table[256] = {    1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,    0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,    0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,    1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,    0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,    1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,    1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,    0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,    0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,    1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,    1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,    0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,    1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,    0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,    0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,    1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1};static inline void set_eflags_PF(int size, unsigned long result,                                 struct cpu_user_regs *regs){    if (parity_table[result & 0xFF])        regs->eflags |= X86_EFLAGS_PF;}static void hvm_pio_assist(struct cpu_user_regs *regs, ioreq_t *p,                           struct hvm_io_op *pio_opp){    if ( p->data_is_ptr || (pio_opp->flags & OVERLAP) )    {        int sign = p->df ? -1 : 1;        if ( pio_opp->flags & REPZ )            regs->ecx -= p->count;        if ( p->dir == IOREQ_READ )        {            if ( pio_opp->flags & OVERLAP )            {                unsigned long addr = pio_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->edi += sign * p->count * p->size;        }        else /* p->dir == IOREQ_WRITE */        {            ASSERT(p->dir == IOREQ_WRITE);            regs->esi += sign * p->count * p->size;        }    }    else if ( p->dir == IOREQ_READ )    {        unsigned long old_eax = regs->eax;        switch ( p->size )        {        case 1:            regs->eax = (old_eax & ~0xff) | (p->data & 0xff);            break;        case 2:            regs->eax = (old_eax & ~0xffff) | (p->data & 0xffff);            break;        case 4:            regs->eax = (p->data & 0xffffffff);            break;        default:            printk("Error: %s unknown port size\n", __FUNCTION__);            domain_crash_synchronous();        }        HVMTRACE_1D(IO_ASSIST, current, p->data);    }}static void hvm_mmio_assist(struct cpu_user_regs *regs, ioreq_t *p,                            struct hvm_io_op *mmio_opp){    int sign = p->df ? -1 : 1;    int size = -1, index = -1;    unsigned long value = 0, result = 0;    unsigned long src, dst;    src = mmio_opp->operand[0];    dst = mmio_opp->operand[1];    size = operand_size(src);    HVMTRACE_1D(MMIO_ASSIST, current, p->data);            switch (mmio_opp->instr) {    case INSTR_MOV:

⌨️ 快捷键说明

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