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

📄 traps.c

📁 xen虚拟机源代码安装包
💻 C
📖 第 1 页 / 共 2 页
字号:
    domain_crash(v->domain);    return 0;}static int write_stack_trampoline(    char *stack, char *stack_bottom, uint16_t cs_seg){    /* movq %rsp, saversp(%rip) */    stack[0] = 0x48;    stack[1] = 0x89;    stack[2] = 0x25;    *(u32 *)&stack[3] = (stack_bottom - &stack[7]) - 16;    /* leaq saversp(%rip), %rsp */    stack[7] = 0x48;    stack[8] = 0x8d;    stack[9] = 0x25;    *(u32 *)&stack[10] = (stack_bottom - &stack[14]) - 16;    /* pushq %r11 */    stack[14] = 0x41;    stack[15] = 0x53;    /* pushq $<cs_seg> */    stack[16] = 0x68;    *(u32 *)&stack[17] = cs_seg;    /* movq $syscall_enter,%r11 */    stack[21] = 0x49;    stack[22] = 0xbb;    *(void **)&stack[23] = (void *)syscall_enter;    /* jmpq *%r11 */    stack[31] = 0x41;    stack[32] = 0xff;    stack[33] = 0xe3;    return 34;}void __devinit subarch_percpu_traps_init(void){    char *stack_bottom, *stack;    int   cpu = smp_processor_id();    if ( cpu == 0 )    {        /* Specify dedicated interrupt stacks for NMI, #DF, and #MC. */        set_intr_gate(TRAP_double_fault, &double_fault);        idt_table[TRAP_double_fault].a  |= IST_DF << 32;        idt_table[TRAP_nmi].a           |= IST_NMI << 32;        idt_table[TRAP_machine_check].a |= IST_MCE << 32;        /*         * The 32-on-64 hypercall entry vector is only accessible from ring 1.         * Also note that this is a trap gate, not an interrupt gate.         */        _set_gate(idt_table+HYPERCALL_VECTOR, 15, 1, &compat_hypercall);        /* Fast trap for int80 (faster than taking the #GP-fixup path). */        _set_gate(idt_table+0x80, 15, 3, &int80_direct_trap);    }    stack_bottom = (char *)get_stack_bottom();    stack        = (char *)((unsigned long)stack_bottom & ~(STACK_SIZE - 1));    /* IST_MAX IST pages + 1 syscall page + 1 guard page + primary stack. */    BUILD_BUG_ON((IST_MAX + 2) * PAGE_SIZE + PRIMARY_STACK_SIZE > STACK_SIZE);    /* Machine Check handler has its own per-CPU 4kB stack. */    init_tss[cpu].ist[IST_MCE] = (unsigned long)&stack[IST_MCE * PAGE_SIZE];    /* Double-fault handler has its own per-CPU 4kB stack. */    init_tss[cpu].ist[IST_DF] = (unsigned long)&stack[IST_DF * PAGE_SIZE];    /* NMI handler has its own per-CPU 4kB stack. */    init_tss[cpu].ist[IST_NMI] = (unsigned long)&stack[IST_NMI * PAGE_SIZE];    /* Trampoline for SYSCALL entry from long mode. */    stack = &stack[IST_MAX * PAGE_SIZE]; /* Skip the IST stacks. */    wrmsrl(MSR_LSTAR, (unsigned long)stack);    stack += write_stack_trampoline(stack, stack_bottom, FLAT_KERNEL_CS64);    if ( boot_cpu_data.x86_vendor == X86_VENDOR_INTEL )    {        /* SYSENTER entry. */        wrmsrl(MSR_IA32_SYSENTER_ESP, (unsigned long)stack_bottom);        wrmsrl(MSR_IA32_SYSENTER_EIP, (unsigned long)sysenter_entry);        wrmsr(MSR_IA32_SYSENTER_CS, __HYPERVISOR_CS, 0);    }    /* Trampoline for SYSCALL entry from compatibility mode. */    stack = (char *)L1_CACHE_ALIGN((unsigned long)stack);    wrmsrl(MSR_CSTAR, (unsigned long)stack);    stack += write_stack_trampoline(stack, stack_bottom, FLAT_USER_CS32);    /* Common SYSCALL parameters. */    wrmsr(MSR_STAR, 0, (FLAT_RING3_CS32<<16) | __HYPERVISOR_CS);    wrmsr(MSR_SYSCALL_MASK, EF_VM|EF_RF|EF_NT|EF_DF|EF_IE|EF_TF, 0U);}void init_int80_direct_trap(struct vcpu *v){    struct trap_info *ti = &v->arch.guest_context.trap_ctxt[0x80];    struct trap_bounce *tb = &v->arch.int80_bounce;    tb->flags = TBF_EXCEPTION;    tb->cs    = ti->cs;    tb->eip   = ti->address;    if ( null_trap_bounce(v, tb) )        tb->flags = 0;}static long register_guest_callback(struct callback_register *reg){    long ret = 0;    struct vcpu *v = current;    if ( !is_canonical_address(reg->address) )        return -EINVAL;    switch ( reg->type )    {    case CALLBACKTYPE_event:        v->arch.guest_context.event_callback_eip    = reg->address;        break;    case CALLBACKTYPE_failsafe:        v->arch.guest_context.failsafe_callback_eip = reg->address;        if ( reg->flags & CALLBACKF_mask_events )            set_bit(_VGCF_failsafe_disables_events,                    &v->arch.guest_context.flags);        else            clear_bit(_VGCF_failsafe_disables_events,                      &v->arch.guest_context.flags);        break;    case CALLBACKTYPE_syscall:        v->arch.guest_context.syscall_callback_eip  = reg->address;        if ( reg->flags & CALLBACKF_mask_events )            set_bit(_VGCF_syscall_disables_events,                    &v->arch.guest_context.flags);        else            clear_bit(_VGCF_syscall_disables_events,                      &v->arch.guest_context.flags);        break;    case CALLBACKTYPE_syscall32:        v->arch.syscall32_callback_eip = reg->address;        v->arch.syscall32_disables_events =            !!(reg->flags & CALLBACKF_mask_events);        break;    case CALLBACKTYPE_sysenter:        v->arch.sysenter_callback_eip = reg->address;        v->arch.sysenter_disables_events =            !!(reg->flags & CALLBACKF_mask_events);        break;    case CALLBACKTYPE_nmi:        ret = register_guest_nmi_callback(reg->address);        break;    default:        ret = -ENOSYS;        break;    }    return ret;}static long unregister_guest_callback(struct callback_unregister *unreg){    long ret;    switch ( unreg->type )    {    case CALLBACKTYPE_event:    case CALLBACKTYPE_failsafe:    case CALLBACKTYPE_syscall:    case CALLBACKTYPE_syscall32:    case CALLBACKTYPE_sysenter:        ret = -EINVAL;        break;    case CALLBACKTYPE_nmi:        ret = unregister_guest_nmi_callback();        break;    default:        ret = -ENOSYS;        break;    }    return ret;}long do_callback_op(int cmd, XEN_GUEST_HANDLE(const_void) arg){    long ret;    switch ( cmd )    {    case CALLBACKOP_register:    {        struct callback_register reg;        ret = -EFAULT;        if ( copy_from_guest(&reg, arg, 1) )            break;        ret = register_guest_callback(&reg);    }    break;    case CALLBACKOP_unregister:    {        struct callback_unregister unreg;        ret = -EFAULT;        if ( copy_from_guest(&unreg, arg, 1) )            break;        ret = unregister_guest_callback(&unreg);    }    break;    default:        ret = -ENOSYS;        break;    }    return ret;}long do_set_callbacks(unsigned long event_address,                      unsigned long failsafe_address,                      unsigned long syscall_address){    struct callback_register event = {        .type = CALLBACKTYPE_event,        .address = event_address,    };    struct callback_register failsafe = {        .type = CALLBACKTYPE_failsafe,        .address = failsafe_address,    };    struct callback_register syscall = {        .type = CALLBACKTYPE_syscall,        .address = syscall_address,    };    register_guest_callback(&event);    register_guest_callback(&failsafe);    register_guest_callback(&syscall);    return 0;}static void hypercall_page_initialise_ring3_kernel(void *hypercall_page){    char *p;    int i;    /* Fill in all the transfer points with template machine code. */    for ( i = 0; i < (PAGE_SIZE / 32); i++ )    {        p = (char *)(hypercall_page + (i * 32));        *(u8  *)(p+ 0) = 0x51;    /* push %rcx */        *(u16 *)(p+ 1) = 0x5341;  /* push %r11 */        *(u8  *)(p+ 3) = 0xb8;    /* mov  $<i>,%eax */        *(u32 *)(p+ 4) = i;        *(u16 *)(p+ 8) = 0x050f;  /* syscall */        *(u16 *)(p+10) = 0x5b41;  /* pop  %r11 */        *(u8  *)(p+12) = 0x59;    /* pop  %rcx */        *(u8  *)(p+13) = 0xc3;    /* ret */    }    /*     * HYPERVISOR_iret is special because it doesn't return and expects a      * special stack frame. Guests jump at this transfer point instead of      * calling it.     */    p = (char *)(hypercall_page + (__HYPERVISOR_iret * 32));    *(u8  *)(p+ 0) = 0x51;    /* push %rcx */    *(u16 *)(p+ 1) = 0x5341;  /* push %r11 */    *(u8  *)(p+ 3) = 0x50;    /* push %rax */    *(u8  *)(p+ 4) = 0xb8;    /* mov  $__HYPERVISOR_iret,%eax */    *(u32 *)(p+ 5) = __HYPERVISOR_iret;    *(u16 *)(p+ 9) = 0x050f;  /* syscall */}#include "compat/traps.c"void hypercall_page_initialise(struct domain *d, void *hypercall_page){    memset(hypercall_page, 0xCC, PAGE_SIZE);    if ( is_hvm_domain(d) )        hvm_hypercall_page_initialise(d, hypercall_page);    else if ( !is_pv_32bit_domain(d) )        hypercall_page_initialise_ring3_kernel(hypercall_page);    else        hypercall_page_initialise_ring1_kernel(hypercall_page);}/* * 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 + -