📄 traps.c
字号:
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(®, arg, 1) ) break; ret = register_guest_callback(®); } 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 + -