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

📄 traps.c

📁 xen虚拟机源代码安装包
💻 C
📖 第 1 页 / 共 2 页
字号:
}void __devinit subarch_percpu_traps_init(void){    struct tss_struct *tss = &doublefault_tss;    asmlinkage int hypercall(void);    if ( smp_processor_id() != 0 )        return;    /* The hypercall entry vector is only accessible from ring 1. */    _set_gate(idt_table+HYPERCALL_VECTOR, 14, 1, &hypercall);    /*     * Make a separate task for double faults. This will get us debug output if     * we blow the kernel stack.     */    memset(tss, 0, sizeof(*tss));    tss->ds     = __HYPERVISOR_DS;    tss->es     = __HYPERVISOR_DS;    tss->ss     = __HYPERVISOR_DS;    tss->esp    = (unsigned long)&doublefault_stack[DOUBLEFAULT_STACK_SIZE];    tss->__cr3  = __pa(idle_pg_table);    tss->cs     = __HYPERVISOR_CS;    tss->eip    = (unsigned long)do_double_fault;    tss->eflags = 2;    tss->bitmap = IOBMP_INVALID_OFFSET;    _set_tssldt_desc(        gdt_table + __DOUBLEFAULT_TSS_ENTRY - FIRST_RESERVED_GDT_ENTRY,        (unsigned long)tss, 235, 9);    set_task_gate(TRAP_double_fault, __DOUBLEFAULT_TSS_ENTRY<<3);}void init_int80_direct_trap(struct vcpu *v){    struct trap_info *ti = &v->arch.guest_context.trap_ctxt[0x80];    /*     * We can't virtualise interrupt gates, as there's no way to get     * the CPU to automatically clear the events_mask variable. Also we     * must ensure that the CS is safe to poke into an interrupt gate.     *     * When running with supervisor_mode_kernel enabled a direct trap     * to the guest OS cannot be used because the INT instruction will     * switch to the Xen stack and we need to swap back to the guest     * kernel stack before passing control to the system call entry point.     */    if ( TI_GET_IF(ti) || !guest_gate_selector_okay(v->domain, ti->cs) ||         supervisor_mode_kernel )    {        v->arch.int80_desc.a = v->arch.int80_desc.b = 0;        return;    }    v->arch.int80_desc.a = (ti->cs << 16) | (ti->address & 0xffff);    v->arch.int80_desc.b =        (ti->address & 0xffff0000) | 0x8f00 | ((TI_GET_DPL(ti) & 3) << 13);    if ( v == current )        set_int80_direct_trap(v);}#ifdef CONFIG_X86_SUPERVISOR_MODE_KERNELstatic void do_update_sysenter(void *info){    xen_callback_t *address = info;    wrmsr(MSR_IA32_SYSENTER_CS, address->cs, 0);    wrmsr(MSR_IA32_SYSENTER_EIP, address->eip, 0);}#endifstatic long register_guest_callback(struct callback_register *reg){    long ret = 0;    struct vcpu *v = current;    fixup_guest_code_selector(v->domain, reg->address.cs);    switch ( reg->type )    {    case CALLBACKTYPE_event:        v->arch.guest_context.event_callback_cs     = reg->address.cs;        v->arch.guest_context.event_callback_eip    = reg->address.eip;        break;    case CALLBACKTYPE_failsafe:        v->arch.guest_context.failsafe_callback_cs  = reg->address.cs;        v->arch.guest_context.failsafe_callback_eip = reg->address.eip;        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;#ifdef CONFIG_X86_SUPERVISOR_MODE_KERNEL    case CALLBACKTYPE_sysenter_deprecated:        if ( !cpu_has_sep )            ret = -EINVAL;        else if ( on_each_cpu(do_update_sysenter, &reg->address, 1, 1) != 0 )            ret = -EIO;        break;    case CALLBACKTYPE_sysenter:        if ( !cpu_has_sep )            ret = -EINVAL;        else            do_update_sysenter(&reg->address);        break;#endif    case CALLBACKTYPE_nmi:        ret = register_guest_nmi_callback(reg->address.eip);        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:#ifdef CONFIG_X86_SUPERVISOR_MODE_KERNEL    case CALLBACKTYPE_sysenter_deprecated:    case CALLBACKTYPE_sysenter:#endif        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_selector,                      unsigned long event_address,                      unsigned long failsafe_selector,                      unsigned long failsafe_address){    struct callback_register event = {        .type = CALLBACKTYPE_event,        .address = { event_selector, event_address },    };    struct callback_register failsafe = {        .type = CALLBACKTYPE_failsafe,        .address = { failsafe_selector, failsafe_address },    };    register_guest_callback(&event);    register_guest_callback(&failsafe);    return 0;}static void hypercall_page_initialise_ring0_kernel(void *hypercall_page){    extern asmlinkage int hypercall(void);    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) = 0x9c;      /* pushf */        *(u8  *)(p+ 1) = 0xfa;      /* cli */        *(u8  *)(p+ 2) = 0xb8;      /* mov $<i>,%eax */        *(u32 *)(p+ 3) = i;        *(u8  *)(p+ 7) = 0x9a;      /* lcall $__HYPERVISOR_CS,&hypercall */        *(u32 *)(p+ 8) = (u32)&hypercall;        *(u16 *)(p+12) = (u16)__HYPERVISOR_CS;        *(u8  *)(p+14) = 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) = 0x50;      /* push %eax */    *(u8  *)(p+ 1) = 0x9c;      /* pushf */    *(u8  *)(p+ 2) = 0xfa;      /* cli */    *(u8  *)(p+ 3) = 0xb8;      /* mov $<i>,%eax */    *(u32 *)(p+ 4) = __HYPERVISOR_iret;    *(u8  *)(p+ 8) = 0x9a;      /* lcall $__HYPERVISOR_CS,&hypercall */    *(u32 *)(p+ 9) = (u32)&hypercall;    *(u16 *)(p+13) = (u16)__HYPERVISOR_CS;}static void hypercall_page_initialise_ring1_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) = 0xb8;    /* mov  $<i>,%eax */        *(u32 *)(p+ 1) = i;        *(u16 *)(p+ 5) = 0x82cd;  /* int  $0x82 */        *(u8  *)(p+ 7) = 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) = 0x50;    /* push %eax */    *(u8  *)(p+ 1) = 0xb8;    /* mov  $__HYPERVISOR_iret,%eax */    *(u32 *)(p+ 2) = __HYPERVISOR_iret;    *(u16 *)(p+ 6) = 0x82cd;  /* int  $0x82 */}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 ( supervisor_mode_kernel )        hypercall_page_initialise_ring0_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 + -