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

📄 traps.c

📁 xen虚拟机源代码安装包
💻 C
📖 第 1 页 / 共 5 页
字号:
        desc.a = (sel << 20) | 0xffff;        desc.b = vm86attr | (sel >> 12);    }    *ar = desc.b & 0x00f0ff00;    if ( !(desc.b & _SEGMENT_L) )    {        *base = ((desc.a >> 16) + ((desc.b & 0xff) << 16) +                 (desc.b & 0xff000000));        *limit = (desc.a & 0xffff) | (desc.b & 0x000f0000);        if ( desc.b & _SEGMENT_G )            *limit = ((*limit + 1) << 12) - 1;#ifndef NDEBUG        if ( !vm86_mode(regs) && (sel > 3) )        {            unsigned int a, l;            unsigned char valid;            asm volatile (                "larl %2,%0 ; setz %1"                : "=r" (a), "=rm" (valid) : "rm" (sel));            BUG_ON(valid && ((a & 0x00f0ff00) != *ar));            asm volatile (                "lsll %2,%0 ; setz %1"                : "=r" (l), "=rm" (valid) : "rm" (sel));            BUG_ON(valid && (l != *limit));        }#endif    }    else    {        *base = 0UL;        *limit = ~0UL;    }    return 1;}#ifdef __x86_64__static int read_gate_descriptor(unsigned int gate_sel,                                const struct vcpu *v,                                unsigned int *sel,                                unsigned long *off,                                unsigned int *ar){    struct desc_struct desc;    const struct desc_struct *pdesc;    pdesc = (const struct desc_struct *)        (!(gate_sel & 4) ? GDT_VIRT_START(v) : LDT_VIRT_START(v))        + (gate_sel >> 3);    if ( (gate_sel < 4) ||         ((gate_sel >= FIRST_RESERVED_GDT_BYTE) && !(gate_sel & 4)) ||         __get_user(desc, pdesc) )        return 0;    *sel = (desc.a >> 16) & 0x0000fffc;    *off = (desc.a & 0x0000ffff) | (desc.b & 0xffff0000);    *ar = desc.b & 0x0000ffff;    /*     * check_descriptor() clears the DPL field and stores the     * guest requested DPL in the selector's RPL field.     */    if ( *ar & _SEGMENT_DPL )        return 0;    *ar |= (desc.a >> (16 - 13)) & _SEGMENT_DPL;    if ( !is_pv_32bit_vcpu(v) )    {        if ( (*ar & 0x1f00) != 0x0c00 ||             (gate_sel >= FIRST_RESERVED_GDT_BYTE - 8 && !(gate_sel & 4)) ||             __get_user(desc, pdesc + 1) ||             (desc.b & 0x1f00) )            return 0;        *off |= (unsigned long)desc.a << 32;        return 1;    }    switch ( *ar & 0x1f00 )    {    case 0x0400:        *off &= 0xffff;        break;    case 0x0c00:        break;    default:        return 0;    }    return 1;}#endif/* Has the guest requested sufficient permission for this I/O access? */static int guest_io_okay(    unsigned int port, unsigned int bytes,    struct vcpu *v, struct cpu_user_regs *regs){#if defined(__x86_64__)    /* If in user mode, switch to kernel mode just to read I/O bitmap. */    int user_mode = !(v->arch.flags & TF_kernel_mode);#define TOGGLE_MODE() if ( user_mode ) toggle_guest_mode(v)#elif defined(__i386__)#define TOGGLE_MODE() ((void)0)#endif    if ( !vm86_mode(regs) &&         (v->arch.iopl >= (guest_kernel_mode(v, regs) ? 1 : 3)) )        return 1;    if ( v->arch.iobmp_limit > (port + bytes) )    {        union { uint8_t bytes[2]; uint16_t mask; } x;        /*         * Grab permission bytes from guest space. Inaccessible bytes are         * read as 0xff (no access allowed).         */        TOGGLE_MODE();        switch ( __copy_from_guest_offset(x.bytes, v->arch.iobmp,                                          port>>3, 2) )        {        default: x.bytes[0] = ~0;        case 1:  x.bytes[1] = ~0;        case 0:  break;        }        TOGGLE_MODE();        if ( (x.mask & (((1<<bytes)-1) << (port&7))) == 0 )            return 1;    }    return 0;}/* Has the administrator granted sufficient permission for this I/O access? */static int admin_io_okay(    unsigned int port, unsigned int bytes,    struct vcpu *v, struct cpu_user_regs *regs){    /*     * Port 0xcf8 (CONFIG_ADDRESS) is only visible for DWORD accesses.     * We never permit direct access to that register.     */    if ( (port == 0xcf8) && (bytes == 4) )        return 0;    return ioports_access_permitted(v->domain, port, port + bytes - 1);}static uint32_t guest_io_read(    unsigned int port, unsigned int bytes,    struct vcpu *v, struct cpu_user_regs *regs){    extern uint32_t pci_conf_read(        uint32_t cf8, uint8_t offset, uint8_t bytes);    uint32_t data = 0;    unsigned int shift = 0;    if ( admin_io_okay(port, bytes, v, regs) )    {        switch ( bytes )        {        case 1: return inb(port);        case 2: return inw(port);        case 4: return inl(port);        }    }    while ( bytes != 0 )    {        unsigned int size = 1;        uint32_t sub_data = 0xff;        if ( (port == 0x42) || (port == 0x43) || (port == 0x61) )        {            sub_data = pv_pit_handler(port, 0, 0);        }        else if ( (port == 0xcf8) && (bytes == 4) )        {            size = 4;            sub_data = v->domain->arch.pci_cf8;        }        else if ( ((port & 0xfffc) == 0xcfc) && IS_PRIV(v->domain) )        {            size = min(bytes, 4 - (port & 3));            if ( size == 3 )                size = 2;            sub_data = pci_conf_read(v->domain->arch.pci_cf8, port & 3, size);        }        if ( size == 4 )            return sub_data;        data |= (sub_data & ((1u << (size * 8)) - 1)) << shift;        shift += size * 8;        port += size;        bytes -= size;    }    return data;}static void guest_io_write(    unsigned int port, unsigned int bytes, uint32_t data,    struct vcpu *v, struct cpu_user_regs *regs){    extern void pci_conf_write(        uint32_t cf8, uint8_t offset, uint8_t bytes, uint32_t data);    if ( admin_io_okay(port, bytes, v, regs) )    {        switch ( bytes ) {        case 1:            outb((uint8_t)data, port);            if ( pv_post_outb_hook )                pv_post_outb_hook(port, (uint8_t)data);            break;        case 2:            outw((uint16_t)data, port);            break;        case 4:            outl(data, port);            break;        }        return;    }    while ( bytes != 0 )    {        unsigned int size = 1;        if ( (port == 0x42) || (port == 0x43) || (port == 0x61) )        {            pv_pit_handler(port, (uint8_t)data, 1);        }        else if ( (port == 0xcf8) && (bytes == 4) )        {            size = 4;            v->domain->arch.pci_cf8 = data;        }        else if ( ((port & 0xfffc) == 0xcfc) && IS_PRIV(v->domain) )        {            size = min(bytes, 4 - (port & 3));            if ( size == 3 )                size = 2;            pci_conf_write(v->domain->arch.pci_cf8, port & 3, size, data);        }        if ( size == 4 )            return;        port += size;        bytes -= size;        data >>= size * 8;    }}/* I/O emulation support. Helper routines for, and type of, the stack stub.*/void host_to_guest_gpr_switch(struct cpu_user_regs *)    __attribute__((__regparm__(1)));unsigned long guest_to_host_gpr_switch(unsigned long)    __attribute__((__regparm__(1)));void (*pv_post_outb_hook)(unsigned int port, u8 value);/* Instruction fetch with error handling. */#define insn_fetch(type, base, eip, limit)                                  \({  unsigned long _rc, _ptr = (base) + (eip);                               \    type _x;                                                                \    if ( ad_default < 8 )                                                   \        _ptr = (unsigned int)_ptr;                                          \    if ( (limit) < sizeof(_x) - 1 || (eip) > (limit) - (sizeof(_x) - 1) )   \        goto fail;                                                          \    if ( (_rc = copy_from_user(&_x, (type *)_ptr, sizeof(_x))) != 0 )       \    {                                                                       \        propagate_page_fault(_ptr + sizeof(_x) - _rc, 0);                   \        goto skip;                                                          \    }                                                                       \    (eip) += sizeof(_x); _x; })#if defined(CONFIG_X86_32)# define read_sreg(regs, sr) ((regs)->sr)#elif defined(CONFIG_X86_64)# define read_sreg(regs, sr) read_segment_register(sr)#endifstatic int emulate_privileged_op(struct cpu_user_regs *regs){    struct vcpu *v = current;    unsigned long *reg, eip = regs->eip, res;    u8 opcode, modrm_reg = 0, modrm_rm = 0, rep_prefix = 0, lock = 0, rex = 0;    enum { lm_seg_none, lm_seg_fs, lm_seg_gs } lm_ovr = lm_seg_none;    unsigned int port, i, data_sel, ar, data, rc, bpmatch = 0;    unsigned int op_bytes, op_default, ad_bytes, ad_default;#define rd_ad(reg) (ad_bytes >= sizeof(regs->reg) \                    ? regs->reg \                    : ad_bytes == 4 \                      ? (u32)regs->reg \                      : (u16)regs->reg)#define wr_ad(reg, val) (ad_bytes >= sizeof(regs->reg) \                         ? regs->reg = (val) \                         : ad_bytes == 4 \                           ? (*(u32 *)&regs->reg = (val)) \                           : (*(u16 *)&regs->reg = (val)))    unsigned long code_base, code_limit;    char io_emul_stub[32];    void (*io_emul)(struct cpu_user_regs *) __attribute__((__regparm__(1)));    u32 l, h, eax, edx;    if ( !read_descriptor(regs->cs, v, regs,                          &code_base, &code_limit, &ar,                          _SEGMENT_CODE|_SEGMENT_S|_SEGMENT_DPL|_SEGMENT_P) )        goto fail;    op_default = op_bytes = (ar & (_SEGMENT_L|_SEGMENT_DB)) ? 4 : 2;    ad_default = ad_bytes = (ar & _SEGMENT_L) ? 8 : op_default;    if ( !(ar & _SEGMENT_S) ||         !(ar & _SEGMENT_P) ||         !(ar & _SEGMENT_CODE) )        goto fail;    /* emulating only opcodes not allowing SS to be default */    data_sel = read_sreg(regs, ds);    /* Legacy prefixes. */    for ( i = 0; i < 8; i++, rex == opcode || (rex = 0) )    {        switch ( opcode = insn_fetch(u8, code_base, eip, code_limit) )        {        case 0x66: /* operand-size override */            op_bytes = op_default ^ 6; /* switch between 2/4 bytes */            continue;        case 0x67: /* address-size override */            ad_bytes = ad_default != 4 ? 4 : 2; /* switch to 2/4 bytes */            continue;        case 0x2e: /* CS override */            data_sel = regs->cs;            continue;        case 0x3e: /* DS override */            data_sel = read_sreg(regs, ds);            continue;        case 0x26: /* ES override */            data_sel = read_sreg(regs, es);            continue;        case 0x64: /* FS override */            data_sel = read_sreg(regs, fs);            lm_ovr = lm_seg_fs;            continue;        case 0x65: /* GS override */            data_sel = read_sreg(regs, gs);            lm_ovr = lm_seg_gs;            continue;        case 0x36: /* SS override */            data_sel = regs->ss;            continue;        case 0xf0: /* LOCK */            lock = 1;            continue;        case 0xf2: /* REPNE/REPNZ */        case 0xf3: /* REP/REPE/REPZ */            rep_prefix = 1;            continue;        default:            if ( (ar & _SEGMENT_L) && (opcode & 0xf0) == 0x40 )            {                rex = opcode;                continue;            }            break;        }        break;    }    /* REX prefix. */    if ( rex & 8 ) /* REX.W */        op_bytes = 4; /* emulate only opcodes not supporting 64-bit operands */    modrm_reg = (rex & 4) << 1;  /* REX.R */    /* REX.X does not need to be decoded. */    modrm_rm  = (rex & 1) << 3;  /* REX.B */    if ( opcode == 0x0f )        goto twobyte_opcode;        if ( lock )        goto fail;    /* Input/Output String instructions. */    if ( (opcode >= 0x6c) && (opcode <= 0x6f) )    {        unsigned long data_base, data_limit;        if ( rep_prefix && (rd_ad(ecx) == 0) )            goto done;        if ( !(opcode & 2) )        {            data_sel = read_sreg(regs, es);            lm_ovr = lm_seg_none;        }        if ( !(ar & _SEGMENT_L) )        {            if ( !read_descriptor(data_sel, v, regs,                                  &data_base, &data_limit, &ar,                                  _SEGMENT_WR|_SEGMENT_S|_SEGMENT_DPL|                                  _SEGMENT_P) )                goto fail;            if ( !(ar & _SEGMENT_S) ||                 !(ar & _SEGMENT_P) ||                 (opcode & 2 ?                  (ar & _SEGMENT_CODE) && !(ar & _SEGMENT_WR) :                  (ar & _SEGMENT_CODE) || !(ar & _SEGMENT_WR)) )                goto fail;        }#ifdef CONFIG_X86_64        else        {            if ( lm_ovr == lm_seg_none || data_sel < 4 )            {                switch ( lm_ovr )                {                case lm_seg_none:                    data_base = 0UL;                    break;                case lm_seg_fs:                    data_base = v->arch.guest_context.fs_base;                    break;                case lm_seg_gs:                    if ( guest_kernel_mode(v, regs) )                        data_base = v->arch.guest_context.gs_base_kernel;                    else                        data_base = v->arch.guest_context.gs_base_user;                    break;                }

⌨️ 快捷键说明

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