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

📄 platform.c

📁 xen 3.2.2 源码
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * platform.c: handling x86 platform related MMIO instructions * * 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/types.h>#include <xen/mm.h>#include <xen/domain_page.h>#include <asm/page.h>#include <xen/event.h>#include <xen/trace.h>#include <xen/sched.h>#include <asm/regs.h>#include <asm/x86_emulate.h>#include <asm/paging.h>#include <asm/hvm/hvm.h>#include <asm/hvm/support.h>#include <asm/hvm/io.h>#include <public/hvm/ioreq.h>#include <xen/lib.h>#include <xen/sched.h>#include <asm/current.h>#define DECODE_success  1#define DECODE_failure  0#define mk_operand(size_reg, index, seg, flag) \    (((size_reg) << 24) | ((index) << 16) | ((seg) << 8) | (flag))#if defined (__x86_64__)static inline long __get_reg_value(unsigned long reg, int size){    switch ( size ) {    case BYTE_64:        return (char)(reg & 0xFF);    case WORD:        return (short)(reg & 0xFFFF);    case LONG:        return (int)(reg & 0xFFFFFFFF);    case QUAD:        return (long)(reg);    default:        printk("Error: (__get_reg_value) Invalid reg size\n");        domain_crash_synchronous();    }}long get_reg_value(int size, int index, int seg, struct cpu_user_regs *regs){    if ( size == BYTE ) {        switch ( index ) {        case 0: /* %al */            return (char)(regs->rax & 0xFF);        case 1: /* %cl */            return (char)(regs->rcx & 0xFF);        case 2: /* %dl */            return (char)(regs->rdx & 0xFF);        case 3: /* %bl */            return (char)(regs->rbx & 0xFF);        case 4: /* %ah */            return (char)((regs->rax & 0xFF00) >> 8);        case 5: /* %ch */            return (char)((regs->rcx & 0xFF00) >> 8);        case 6: /* %dh */            return (char)((regs->rdx & 0xFF00) >> 8);        case 7: /* %bh */            return (char)((regs->rbx & 0xFF00) >> 8);        default:            printk("Error: (get_reg_value) Invalid index value\n");            domain_crash_synchronous();        }        /* NOTREACHED */    }    switch ( index ) {    case 0: return __get_reg_value(regs->rax, size);    case 1: return __get_reg_value(regs->rcx, size);    case 2: return __get_reg_value(regs->rdx, size);    case 3: return __get_reg_value(regs->rbx, size);    case 4: return __get_reg_value(regs->rsp, size);    case 5: return __get_reg_value(regs->rbp, size);    case 6: return __get_reg_value(regs->rsi, size);    case 7: return __get_reg_value(regs->rdi, size);    case 8: return __get_reg_value(regs->r8, size);    case 9: return __get_reg_value(regs->r9, size);    case 10: return __get_reg_value(regs->r10, size);    case 11: return __get_reg_value(regs->r11, size);    case 12: return __get_reg_value(regs->r12, size);    case 13: return __get_reg_value(regs->r13, size);    case 14: return __get_reg_value(regs->r14, size);    case 15: return __get_reg_value(regs->r15, size);    default:        printk("Error: (get_reg_value) Invalid index value\n");        domain_crash_synchronous();    }}#elif defined (__i386__)static inline long __get_reg_value(unsigned long reg, int size){    switch ( size ) {    case WORD:        return (short)(reg & 0xFFFF);    case LONG:        return (int)(reg & 0xFFFFFFFF);    default:        printk("Error: (__get_reg_value) Invalid reg size\n");        domain_crash_synchronous();    }}long get_reg_value(int size, int index, int seg, struct cpu_user_regs *regs){    if ( size == BYTE ) {        switch ( index ) {        case 0: /* %al */            return (char)(regs->eax & 0xFF);        case 1: /* %cl */            return (char)(regs->ecx & 0xFF);        case 2: /* %dl */            return (char)(regs->edx & 0xFF);        case 3: /* %bl */            return (char)(regs->ebx & 0xFF);        case 4: /* %ah */            return (char)((regs->eax & 0xFF00) >> 8);        case 5: /* %ch */            return (char)((regs->ecx & 0xFF00) >> 8);        case 6: /* %dh */            return (char)((regs->edx & 0xFF00) >> 8);        case 7: /* %bh */            return (char)((regs->ebx & 0xFF00) >> 8);        default:            printk("Error: (get_reg_value) Invalid index value\n");            domain_crash_synchronous();        }    }    switch ( index ) {    case 0: return __get_reg_value(regs->eax, size);    case 1: return __get_reg_value(regs->ecx, size);    case 2: return __get_reg_value(regs->edx, size);    case 3: return __get_reg_value(regs->ebx, size);    case 4: return __get_reg_value(regs->esp, size);    case 5: return __get_reg_value(regs->ebp, size);    case 6: return __get_reg_value(regs->esi, size);    case 7: return __get_reg_value(regs->edi, size);    default:        printk("Error: (get_reg_value) Invalid index value\n");        domain_crash_synchronous();    }}#endifstatic inline unsigned char *check_prefix(unsigned char *inst,                                          struct hvm_io_op *mmio_op,                                          unsigned char *ad_size,                                          unsigned char *op_size,                                          unsigned char *seg_sel,                                          unsigned char *rex_p){    while ( 1 ) {        switch ( *inst ) {            /* rex prefix for em64t instructions */        case 0x40 ... 0x4f:            *rex_p = *inst;            break;        case 0xf3: /* REPZ */            mmio_op->flags = REPZ;            break;        case 0xf2: /* REPNZ */            mmio_op->flags = REPNZ;            break;        case 0xf0: /* LOCK */            break;        case 0x2e: /* CS */        case 0x36: /* SS */        case 0x3e: /* DS */        case 0x26: /* ES */        case 0x64: /* FS */        case 0x65: /* GS */            *seg_sel = *inst;            break;        case 0x66: /* 32bit->16bit */            *op_size = WORD;            break;        case 0x67:            *ad_size = WORD;            break;        default:            return inst;        }        inst++;    }}static inline unsigned long get_immediate(int ad_size, const unsigned char *inst, int op_size){    int mod, reg, rm;    unsigned long val = 0;    int i;    mod = (*inst >> 6) & 3;    reg = (*inst >> 3) & 7;    rm = *inst & 7;    inst++; //skip ModR/M byte    if ( ad_size != WORD && mod != 3 && rm == 4 ) {        rm = *inst & 7;        inst++; //skip SIB byte    }    switch ( mod ) {    case 0:        if ( ad_size == WORD ) {            if ( rm == 6 )                inst = inst + 2; //disp16, skip 2 bytes        }        else {            if ( rm == 5 )                inst = inst + 4; //disp32, skip 4 bytes        }        break;    case 1:        inst++; //disp8, skip 1 byte        break;    case 2:        if ( ad_size == WORD )            inst = inst + 2; //disp16, skip 2 bytes        else            inst = inst + 4; //disp32, skip 4 bytes        break;    }    if ( op_size == QUAD )        op_size = LONG;    for ( i = 0; i < op_size; i++ ) {        val |= (*inst++ & 0xff) << (8 * i);    }    return val;}static inline unsigned long get_immediate_sign_ext(    int ad_size, const unsigned char *inst, int op_size){    unsigned long result = get_immediate(ad_size, inst, op_size);    if ( op_size == BYTE )        return (int8_t)result;    if ( op_size == WORD )        return (int16_t)result;    return (int32_t)result;}static inline int get_index(const unsigned char *inst, unsigned char rex){    int mod, reg, rm;    int rex_r, rex_b;    mod = (*inst >> 6) & 3;    reg = (*inst >> 3) & 7;    rm = *inst & 7;    rex_r = (rex >> 2) & 1;    rex_b = rex & 1;    //Only one operand in the instruction is register    if ( mod == 3 ) {        return (rm + (rex_b << 3));    } else {        return (reg + (rex_r << 3));    }    return 0;}static void init_instruction(struct hvm_io_op *mmio_op){    mmio_op->instr = 0;    mmio_op->flags = 0;    mmio_op->operand[0] = 0;    mmio_op->operand[1] = 0;    mmio_op->immediate = 0;}#define GET_OP_SIZE_FOR_BYTE(size_reg)      \    do {                                    \        if ( rex )                          \            (size_reg) = BYTE_64;           \        else                                \            (size_reg) = BYTE;              \    } while( 0 )#define GET_OP_SIZE_FOR_NONEBYTE(op_size)   \    do {                                    \        if ( rex & 0x8 )                    \            (op_size) = QUAD;               \        else if ( (op_size) != WORD )       \            (op_size) = LONG;               \    } while( 0 )/* * Decode mem,accumulator operands (as in <opcode> m8/m16/m32, al,ax,eax) */static inline int mem_acc(unsigned char size, struct hvm_io_op *mmio){    mmio->operand[0] = mk_operand(size, 0, 0, MEMORY);    mmio->operand[1] = mk_operand(size, 0, 0, REGISTER);    return DECODE_success;}/* * Decode accumulator,mem operands (as in <opcode> al,ax,eax, m8/m16/m32) */static inline int acc_mem(unsigned char size, struct hvm_io_op *mmio){    mmio->operand[0] = mk_operand(size, 0, 0, REGISTER);    mmio->operand[1] = mk_operand(size, 0, 0, MEMORY);    return DECODE_success;}/* * Decode mem,reg operands (as in <opcode> r32/16, m32/16) */static int mem_reg(unsigned char size, unsigned char *opcode,                   struct hvm_io_op *mmio_op, unsigned char rex){    int index = get_index(opcode + 1, rex);    mmio_op->operand[0] = mk_operand(size, 0, 0, MEMORY);    mmio_op->operand[1] = mk_operand(size, index, 0, REGISTER);    return DECODE_success;}/* * Decode reg,mem operands (as in <opcode> m32/16, r32/16) */static int reg_mem(unsigned char size, unsigned char *opcode,                   struct hvm_io_op *mmio_op, unsigned char rex){    int index = get_index(opcode + 1, rex);    mmio_op->operand[0] = mk_operand(size, index, 0, REGISTER);    mmio_op->operand[1] = mk_operand(size, 0, 0, MEMORY);    return DECODE_success;}static int mmio_decode(int address_bytes, unsigned char *opcode,                       struct hvm_io_op *mmio_op,                       unsigned char *ad_size, unsigned char *op_size,                       unsigned char *seg_sel){    unsigned char size_reg = 0;    unsigned char rex = 0;    int index;    *ad_size = 0;    *op_size = 0;    *seg_sel = 0;    init_instruction(mmio_op);    opcode = check_prefix(opcode, mmio_op, ad_size, op_size, seg_sel, &rex);    switch ( address_bytes )    {    case 2:        if ( *op_size == WORD )            *op_size = LONG;        else if ( *op_size == LONG )            *op_size = WORD;        else if ( *op_size == 0 )            *op_size = WORD;        if ( *ad_size == WORD )            *ad_size = LONG;        else if ( *ad_size == LONG )            *ad_size = WORD;        else if ( *ad_size == 0 )            *ad_size = WORD;        break;    case 4:        if ( *op_size == 0 )            *op_size = LONG;        if ( *ad_size == 0 )            *ad_size = LONG;        break;#ifdef __x86_64__    case 8:        if ( *op_size == 0 )            *op_size = rex & 0x8 ? QUAD : LONG;        if ( *ad_size == WORD )            *ad_size = LONG;        else if ( *ad_size == 0 )            *ad_size = QUAD;        break;#endif    }    /* the operands order in comments conforms to AT&T convention */    switch ( *opcode ) {    case 0x00: /* add r8, m8 */        mmio_op->instr = INSTR_ADD;        *op_size = BYTE;        GET_OP_SIZE_FOR_BYTE(size_reg);        return reg_mem(size_reg, opcode, mmio_op, rex);    case 0x03: /* add m32/16, r32/16 */        mmio_op->instr = INSTR_ADD;        GET_OP_SIZE_FOR_NONEBYTE(*op_size);        return mem_reg(*op_size, opcode, mmio_op, rex);    case 0x08: /* or r8, m8 */	        mmio_op->instr = INSTR_OR;        *op_size = BYTE;        GET_OP_SIZE_FOR_BYTE(size_reg);        return reg_mem(size_reg, opcode, mmio_op, rex);    case 0x09: /* or r32/16, m32/16 */        mmio_op->instr = INSTR_OR;        GET_OP_SIZE_FOR_NONEBYTE(*op_size);        return reg_mem(*op_size, opcode, mmio_op, rex);    case 0x0A: /* or m8, r8 */        mmio_op->instr = INSTR_OR;        *op_size = BYTE;        GET_OP_SIZE_FOR_BYTE(size_reg);        return mem_reg(size_reg, opcode, mmio_op, rex);    case 0x0B: /* or m32/16, r32/16 */        mmio_op->instr = INSTR_OR;        GET_OP_SIZE_FOR_NONEBYTE(*op_size);

⌨️ 快捷键说明

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