博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
硬件虚拟化之vmm接管异常中断
阅读量:2344 次
发布时间:2019-05-10

本文共 16148 字,大约阅读时间需要 53 分钟。

上一篇讲到了虚拟cpu的构建过程,接下来就要利用vmm接管vcpu的中断,异常等行为。

一、vcpu退出状态记录

struct kvm_vcpu *vcpu_k;kvm_run->exit_reason/* for KVM_RUN, returned by mmap(vcpu_fd, offset=0) */struct kvm_run {	/* in */	__u8 request_interrupt_window;	__u8 padding1[7];	/* out */	__u32 exit_reason;.......#define KVM_EXIT_UNKNOWN          0#define KVM_EXIT_EXCEPTION        1#define KVM_EXIT_IO               2#define KVM_EXIT_HYPERCALL        3#define KVM_EXIT_DEBUG            4#define KVM_EXIT_HLT              5#define KVM_EXIT_MMIO             6#define KVM_EXIT_IRQ_WINDOW_OPEN  7#define KVM_EXIT_SHUTDOWN         8#define KVM_EXIT_FAIL_ENTRY       9#define KVM_EXIT_INTR             10#define KVM_EXIT_SET_TPR          11#define KVM_EXIT_TPR_ACCESS       12
vcpu_init    kvm_vm_create_vcpu        vmx_create_vcpu            kvm_vcpu_init_vtvoid vcpu_init(struct vm *vm, struct vcpu *vcpu){	int vcpu_mmap_size;    long r = 0;	if(vm->kvm)		r= kvm_vm_create_vcpu(vm->kvm, 0);	vcpu->vcpu_k = vm->kvm->vcpus[0];	vcpu->kvm_run = vcpu->vcpu_k->run;

kvm_run 记录了vcpu 运行的各种状态,并且在create_vcpu的时候进行了初始化,分配了page。

int run_vm(struct vm *vm, struct vcpu *vcpu, size_t sz){    struct kvm_vcpu *vcpu_k;	struct kvm_regs regs;	uint64_t memval = 0;    //long r =0;    vcpu_k = vcpu->vcpu_k;	for (;;) {		if (kvm_vcpu_ioctl_s(vcpu_k, (unsigned int)KVM_RUN, 0) < 0) {			printk("KVM_RUN error \n");			return -1;		}		printk("exit_reason %lx\n", vcpu->kvm_run);		switch (vcpu->kvm_run->exit_reason) {		case KVM_EXIT_HLT:		 	goto check;		case KVM_EXIT_IO:		// 	if (vcpu->kvm_run->io.direction == KVM_EXIT_IO_OUT		// 	    && vcpu->kvm_run->io.port == 0xE9) {		// 		//char *p = (char *)vcpu->kvm_run;		// 		// fwrite(p + vcpu->kvm_run->io.data_offset,		// 		//        vcpu->kvm_run->io.size, 1, stdout);		// 		// fflush(stdout);		// 		continue;		// 	}			/* fall through */		default:			//printk(	"Got exit_reason %d,"			//	" expected KVM_EXIT_HLT (%d)\n",			//	vcpu->kvm_run->exit_reason, KVM_EXIT_HLT);			return 0;		}	} check:	if (kvm_vcpu_ioctl_s(vcpu_k,(unsigned int)KVM_GET_REGS, (unsigned long)&regs) < 0) {		printk("KVM_GET_REGS error \n");		return 0;	}	printk("excute success \n");	return 1;}

由于虚拟机和VMM存在同一份代码,vcpu运行的的逻辑需要区别于VMM。我们需要标记vcpu的状态,处于vcpu将不运行VMM的vm_run逻辑,而跟模式将会进行中断检测处理。

 

二、kvm中的vm_exit逻辑

int kvm_emulate_halt(struct kvm_vcpu *vcpu){	++vcpu->stat.halt_exits;	if (irqchip_in_kernel(vcpu->kvm)) {		vcpu->arch.mp_state = VCPU_MP_STATE_HALTED;		kvm_vcpu_block(vcpu);		if (vcpu->arch.mp_state != VCPU_MP_STATE_RUNNABLE)			return -EINTR;		return 1;	} else {		vcpu->run->exit_reason = KVM_EXIT_HLT;		return 0;	}}static int handle_halt(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run){	skip_emulated_instruction(vcpu);	return kvm_emulate_halt(vcpu);}handle_exception    kvm_emulate_halt(vcpu);static int halt_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run){	svm->next_rip = svm->vmcb->save.rip + 1;	skip_emulated_instruction(&svm->vcpu);	return kvm_emulate_halt(&svm->vcpu);}

 

__vcpu_run    kvm_x86_ops_vt->prepare_guest_switch(vcpu);    kvm_x86_ops_vt->run(vcpu, kvm_run);

但是,中断这里还没反应。

 

三、判断代码运行状态

首先我们的代码会运行在两种状态下,跟模式状态,非根模式状态。

static void vmx_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0){	vmx_fpu_deactivate(vcpu);	if (vcpu->arch.rmode.active && (cr0 & X86_CR0_PE))		enter_pmode(vcpu);	if (!vcpu->arch.rmode.active && !(cr0 & X86_CR0_PE))		enter_rmode(vcpu);#ifdef CONFIG_X86_64	if (vcpu->arch.shadow_efer & EFER_LME) {		if (!is_paging(vcpu) && (cr0 & X86_CR0_PG))			enter_lmode(vcpu);		if (is_paging(vcpu) && !(cr0 & X86_CR0_PG))			exit_lmode(vcpu);	}#endif	vmcs_writel(CR0_READ_SHADOW, cr0);	vmcs_writel(GUEST_CR0,		    (cr0 & ~KVM_GUEST_CR0_MASK) | KVM_VM_CR0_ALWAYS_ON);	vcpu->arch.cr0 = cr0;	if (!(cr0 & X86_CR0_TS) || !(cr0 & X86_CR0_PE))		vmx_fpu_activate(vcpu);}

 

static void hardware_enable(void *garbage){	int cpu = raw_smp_processor_id();	u64 phys_addr = __pa(per_cpu(vmxarea, cpu));	u64 old;	rdmsrl(MSR_IA32_FEATURE_CONTROL, old);	if ((old & (MSR_IA32_FEATURE_CONTROL_LOCKED |		    MSR_IA32_FEATURE_CONTROL_VMXON_ENABLED))	    != (MSR_IA32_FEATURE_CONTROL_LOCKED |		MSR_IA32_FEATURE_CONTROL_VMXON_ENABLED))		/* enable and lock */		wrmsrl(MSR_IA32_FEATURE_CONTROL, old |		       MSR_IA32_FEATURE_CONTROL_LOCKED |		       MSR_IA32_FEATURE_CONTROL_VMXON_ENABLED);	write_cr4(read_cr4() | X86_CR4_VMXE); /* FIXME: not cpu hotplug safe */	asm volatile (ASM_VMX_VMXON_RAX : : "a"(&phys_addr), "m"(phys_addr)		      : "memory", "cc");}

VMXON开启根模式

kvm 利用vmx_vcpu_run启动guest虚拟机也就是非根模式开始。

static void vmx_vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run){	struct vcpu_vmx *vmx = to_vmx(vcpu);	u32 intr_info; 	/*	 * Loading guest fpu may have cleared host cr0.ts	 */	vmcs_writel(HOST_CR0, read_cr0()); 	asm(		/* Store host registers */#ifdef CONFIG_X86_64		"push %%rdx; push %%rbp;"		"push %%rcx \n\t"#else		"push %%edx; push %%ebp;"		"push %%ecx \n\t"#endif		ASM_VMX_VMWRITE_RSP_RDX "\n\t"		/* Check if vmlaunch of vmresume is needed */		"cmpl $0, %c[launched](%0) \n\t"		/* Load guest registers.  Don't clobber flags. */#ifdef CONFIG_X86_64		"mov %c[cr2](%0), %%rax \n\t"		"mov %%rax, %%cr2 \n\t"		"mov %c[rax](%0), %%rax \n\t"		"mov %c[rbx](%0), %%rbx \n\t"		"mov %c[rdx](%0), %%rdx \n\t"		"mov %c[rsi](%0), %%rsi \n\t"		"mov %c[rdi](%0), %%rdi \n\t"		"mov %c[rbp](%0), %%rbp \n\t"		"mov %c[r8](%0),  %%r8  \n\t"		"mov %c[r9](%0),  %%r9  \n\t"		"mov %c[r10](%0), %%r10 \n\t"		"mov %c[r11](%0), %%r11 \n\t"		"mov %c[r12](%0), %%r12 \n\t"		"mov %c[r13](%0), %%r13 \n\t"		"mov %c[r14](%0), %%r14 \n\t"		"mov %c[r15](%0), %%r15 \n\t"		"mov %c[rcx](%0), %%rcx \n\t" /* kills %0 (rcx) */#else		"mov %c[cr2](%0), %%eax \n\t"		"mov %%eax,   %%cr2 \n\t"		"mov %c[rax](%0), %%eax \n\t"		"mov %c[rbx](%0), %%ebx \n\t"		"mov %c[rdx](%0), %%edx \n\t"		"mov %c[rsi](%0), %%esi \n\t"		"mov %c[rdi](%0), %%edi \n\t"		"mov %c[rbp](%0), %%ebp \n\t"		"mov %c[rcx](%0), %%ecx \n\t" /* kills %0 (ecx) */#endif		/* Enter guest mode */		"jne .Llaunched \n\t"		ASM_VMX_VMLAUNCH "\n\t"		"jmp .Lkvm_vmx_return \n\t"		".Llaunched: " ASM_VMX_VMRESUME "\n\t"		".Lkvm_vmx_return: "		/* Save guest registers, load host registers, keep flags */#ifdef CONFIG_X86_64		"xchg %0,     (%%rsp) \n\t"		"mov %%rax, %c[rax](%0) \n\t"		"mov %%rbx, %c[rbx](%0) \n\t"		"pushq (%%rsp); popq %c[rcx](%0) \n\t"		"mov %%rdx, %c[rdx](%0) \n\t"		"mov %%rsi, %c[rsi](%0) \n\t"		"mov %%rdi, %c[rdi](%0) \n\t"		"mov %%rbp, %c[rbp](%0) \n\t"		"mov %%r8,  %c[r8](%0) \n\t"		"mov %%r9,  %c[r9](%0) \n\t"		"mov %%r10, %c[r10](%0) \n\t"		"mov %%r11, %c[r11](%0) \n\t"		"mov %%r12, %c[r12](%0) \n\t"		"mov %%r13, %c[r13](%0) \n\t"		"mov %%r14, %c[r14](%0) \n\t"		"mov %%r15, %c[r15](%0) \n\t"		"mov %%cr2, %%rax   \n\t"		"mov %%rax, %c[cr2](%0) \n\t" 		"pop  %%rbp; pop  %%rbp; pop  %%rdx \n\t"#else		"xchg %0, (%%esp) \n\t"		"mov %%eax, %c[rax](%0) \n\t"		"mov %%ebx, %c[rbx](%0) \n\t"		"pushl (%%esp); popl %c[rcx](%0) \n\t"		"mov %%edx, %c[rdx](%0) \n\t"		"mov %%esi, %c[rsi](%0) \n\t"		"mov %%edi, %c[rdi](%0) \n\t"		"mov %%ebp, %c[rbp](%0) \n\t"		"mov %%cr2, %%eax  \n\t"		"mov %%eax, %c[cr2](%0) \n\t" 		"pop %%ebp; pop %%ebp; pop %%edx \n\t"#endif		"setbe %c[fail](%0) \n\t"	      : : "c"(vmx), "d"((unsigned long)HOST_RSP),		[launched]"i"(offsetof(struct vcpu_vmx, launched)),		[fail]"i"(offsetof(struct vcpu_vmx, fail)),		[rax]"i"(offsetof(struct vcpu_vmx, vcpu.arch.regs[VCPU_REGS_RAX])),		[rbx]"i"(offsetof(struct vcpu_vmx, vcpu.arch.regs[VCPU_REGS_RBX])),		[rcx]"i"(offsetof(struct vcpu_vmx, vcpu.arch.regs[VCPU_REGS_RCX])),		[rdx]"i"(offsetof(struct vcpu_vmx, vcpu.arch.regs[VCPU_REGS_RDX])),		[rsi]"i"(offsetof(struct vcpu_vmx, vcpu.arch.regs[VCPU_REGS_RSI])),		[rdi]"i"(offsetof(struct vcpu_vmx, vcpu.arch.regs[VCPU_REGS_RDI])),		[rbp]"i"(offsetof(struct vcpu_vmx, vcpu.arch.regs[VCPU_REGS_RBP])),#ifdef CONFIG_X86_64		[r8]"i"(offsetof(struct vcpu_vmx, vcpu.arch.regs[VCPU_REGS_R8])),		[r9]"i"(offsetof(struct vcpu_vmx, vcpu.arch.regs[VCPU_REGS_R9])),		[r10]"i"(offsetof(struct vcpu_vmx, vcpu.arch.regs[VCPU_REGS_R10])),		[r11]"i"(offsetof(struct vcpu_vmx, vcpu.arch.regs[VCPU_REGS_R11])),		[r12]"i"(offsetof(struct vcpu_vmx, vcpu.arch.regs[VCPU_REGS_R12])),		[r13]"i"(offsetof(struct vcpu_vmx, vcpu.arch.regs[VCPU_REGS_R13])),		[r14]"i"(offsetof(struct vcpu_vmx, vcpu.arch.regs[VCPU_REGS_R14])),		[r15]"i"(offsetof(struct vcpu_vmx, vcpu.arch.regs[VCPU_REGS_R15])),#endif		[cr2]"i"(offsetof(struct vcpu_vmx, vcpu.arch.cr2))	      : "cc", "memory"#ifdef CONFIG_X86_64		, "rbx", "rdi", "rsi"		, "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15"#else		, "ebx", "edi", "rsi"#endif	      ); 	vmx->idt_vectoring_info = vmcs_read32(IDT_VECTORING_INFO_FIELD);	if (vmx->rmode.irq.pending)		fixup_rmode_irq(vmx); 	vcpu->arch.interrupt_window_open =		(vmcs_read32(GUEST_INTERRUPTIBILITY_INFO) & 3) == 0; 	asm("mov %0, %%ds; mov %0, %%es" : : "r"(__USER_DS));	vmx->launched = 1; 	intr_info = vmcs_read32(VM_EXIT_INTR_INFO); 	/* We need to handle NMIs before interrupts are enabled */	if ((intr_info & INTR_INFO_INTR_TYPE_MASK) == 0x200) /* nmi */		asm("int $2");}

在之后就是两种状态的切换。

cr4中有个vmxe的位,用来使能VMX。

read cr4 3426e0 VMXE 2000 & = 2000

11 0100 0010 0110 1110 0000      10 0000 0000 0000

 

 

四. VMCS  cpu管理结构

struct vmcs {	u32 revision_id;	u32 abort;	char data[0];};static DEFINE_PER_CPU(struct vmcs *, current_vmcs_vt);void vcpu_load(struct kvm_vcpu *vcpu){	int cpu;	mutex_lock(&vcpu->mutex);	cpu = get_cpu();	kvm_arch_vcpu_load(vcpu, cpu);	put_cpu();	printk("put cpu \n");}void vcpu_put(struct kvm_vcpu *vcpu){	printk("vcpu_put %lx muxte %lx onwer %lx\n", vcpu, &vcpu->mutex, vcpu->mutex.owner);	preempt_disable();	kvm_arch_vcpu_put(vcpu);	//preempt_notifier_unregister(&vcpu->preempt_notifier);	preempt_enable();	mutex_unlock(&vcpu->mutex);}
static void vmx_vcpu_load(struct kvm_vcpu *vcpu, int cpu){	struct vcpu_vmx *vmx = to_vmx(vcpu);	u64 phys_addr = __pa(vmx->vmcs);	u64 tsc_this, delta;	if (vcpu->cpu != cpu) {		vcpu_clear(vmx);		kvm_migrate_apic_timer(vcpu);	}	if (per_cpu(current_vmcs_vt, cpu) != vmx->vmcs) {		u8 error;		per_cpu(current_vmcs_vt, cpu) = vmx->vmcs;		asm volatile (ASM_VMX_VMPTRLD_RAX "; setna %0"			      : "=g"(error) : "a"(&phys_addr), "m"(phys_addr)			      : "cc");		if (error)			printk(KERN_ERR "kvm: vmptrld %p/%llx fail\n",			       vmx->vmcs, phys_addr);	}	//printk("VMx_VMPTRLD \n");	if (vcpu->cpu != cpu) {		//printk("vcpu->cpu != cpu \n");		struct descriptor_table dt;		unsigned long sysenter_esp;		vcpu->cpu = cpu;		/*		 * Linux uses per-cpu TSS and GDT, so set these when switching		 * processors.		 */		vmcs_writel(HOST_TR_BASE, read_tr_base()); /* 22.2.4 */		get_gdt(&dt);		vmcs_writel(HOST_GDTR_BASE, dt.base);   /* 22.2.4 */		rdmsrl(MSR_IA32_SYSENTER_ESP, sysenter_esp);		vmcs_writel(HOST_IA32_SYSENTER_ESP, sysenter_esp); /* 22.2.3 */		/*		 * Make sure the time stamp counter is monotonous.		 */		rdtscll(tsc_this);		delta = vcpu->arch.host_tsc - tsc_this;		vmcs_write64(TSC_OFFSET, vmcs_read64(TSC_OFFSET) + delta);	}}
static void vmx_load_host_state(struct vcpu_vmx *vmx){	unsigned long flags;	if (!vmx->host_state.loaded)		return;	++vmx->vcpu.stat.host_state_reload;	vmx->host_state.loaded = 0;	if (vmx->host_state.fs_reload_needed)		load_fs(vmx->host_state.fs_sel);	if (vmx->host_state.gs_ldt_reload_needed) {		load_ldt(vmx->host_state.ldt_sel);		/*		 * If we have to reload gs, we must take care to		 * preserve our gs base.		 */		local_irq_save(flags);		load_gs(vmx->host_state.gs_sel);#ifdef CONFIG_X86_64		wrmsrl(MSR_GS_BASE, vmcs_readl(HOST_GS_BASE));#endif		local_irq_restore(flags);	}	reload_tss();	save_msrs(vmx->guest_msrs, vmx->save_nmsrs);	load_msrs(vmx->host_msrs, vmx->save_nmsrs);	reload_host_efer(vmx);}static void vmx_vcpu_put(struct kvm_vcpu *vcpu){	vmx_load_host_state(to_vmx(vcpu));}

struct vmcs {

    u32 revision_id;
    u32 abort;
    char data[0];
};

这个就够有点怪,但其实是kvm的核心。

最后一个data包含了以上6个内容,而且每个cpu都会定义一个current_vmcs变量,用来保存需要切换的状态。

 

五. 设置中断接管

 

setup_vmcs_config 对vm_exit, vm_entry的控制域进行设置。

static __init int setup_vmcs_config(struct vmcs_config *vmcs_conf){	u32 vmx_msr_low, vmx_msr_high;	u32 min, opt;	u32 _pin_based_exec_control = 0;	u32 _cpu_based_exec_control = 0;	u32 _cpu_based_2nd_exec_control = 0;	u32 _vmexit_control = 0;	u32 _vmentry_control = 0;	min = PIN_BASED_EXT_INTR_MASK | PIN_BASED_NMI_EXITING;	opt = 0;	if (adjust_vmx_controls(min, opt, MSR_IA32_VMX_PINBASED_CTLS,				&_pin_based_exec_control) < 0)		return -EIO;	min = CPU_BASED_HLT_EXITING |#ifdef CONFIG_X86_64	      CPU_BASED_CR8_LOAD_EXITING |	      CPU_BASED_CR8_STORE_EXITING |#endif	      CPU_BASED_USE_IO_BITMAPS |	      CPU_BASED_MOV_DR_EXITING |	      CPU_BASED_USE_TSC_OFFSETING;	opt = CPU_BASED_TPR_SHADOW |	      CPU_BASED_ACTIVATE_SECONDARY_CONTROLS;	if (adjust_vmx_controls(min, opt, MSR_IA32_VMX_PROCBASED_CTLS,				&_cpu_based_exec_control) < 0)		return -EIO;#ifdef CONFIG_X86_64	if ((_cpu_based_exec_control & CPU_BASED_TPR_SHADOW))		_cpu_based_exec_control &= ~CPU_BASED_CR8_LOAD_EXITING &					   ~CPU_BASED_CR8_STORE_EXITING;#endif	if (_cpu_based_exec_control & CPU_BASED_ACTIVATE_SECONDARY_CONTROLS) {		min = 0;		opt = SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES |			SECONDARY_EXEC_WBINVD_EXITING;		if (adjust_vmx_controls(min, opt, MSR_IA32_VMX_PROCBASED_CTLS2,					&_cpu_based_2nd_exec_control) < 0)			return -EIO;	}#ifndef CONFIG_X86_64	if (!(_cpu_based_2nd_exec_control &				SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES))		_cpu_based_exec_control &= ~CPU_BASED_TPR_SHADOW;#endif	min = 0;#ifdef CONFIG_X86_64	min |= VM_EXIT_HOST_ADDR_SPACE_SIZE;#endif	opt = 0;	if (adjust_vmx_controls(min, opt, MSR_IA32_VMX_EXIT_CTLS,				&_vmexit_control) < 0)		return -EIO;	min = opt = 0;	if (adjust_vmx_controls(min, opt, MSR_IA32_VMX_ENTRY_CTLS,				&_vmentry_control) < 0)		return -EIO;	rdmsr(MSR_IA32_VMX_BASIC, vmx_msr_low, vmx_msr_high);	/* IA-32 SDM Vol 3B: VMCS size is never greater than 4kB. */	if ((vmx_msr_high & 0x1fff) > PAGE_SIZE)		return -EIO;#ifdef CONFIG_X86_64	/* IA-32 SDM Vol 3B: 64-bit CPUs always have VMX_BASIC_MSR[48]==0. */	if (vmx_msr_high & (1u<<16))		return -EIO;#endif	/* Require Write-Back (WB) memory type for VMCS accesses. */	if (((vmx_msr_high >> 18) & 15) != 6)		return -EIO;	vmcs_conf->size = vmx_msr_high & 0x1fff;	vmcs_conf->order = get_order(vmcs_config.size);	vmcs_conf->revision_id = vmx_msr_low;	vmcs_conf->pin_based_exec_ctrl = _pin_based_exec_control;	vmcs_conf->cpu_based_exec_ctrl = _cpu_based_exec_control;	vmcs_conf->cpu_based_2nd_exec_ctrl = _cpu_based_2nd_exec_control;	vmcs_conf->vmexit_ctrl         = _vmexit_control;	vmcs_conf->vmentry_ctrl        = _vmentry_control;	return 0;}

虽然零星的信息显示,这个vmExit的回调要在这个控制域里设置,但是,并没有在文档中找到办法。

继续读下bluepill

VOID NTAPI HvmEventCallback (  PCPU Cpu,  PGUEST_REGS GuestRegs){  NTSTATUS Status;  if (!Cpu || !GuestRegs)    return;  // FIXME: This should be moved away from the HVM to VMX-specific code!!!  if (Hvm->Architecture == ARCH_VMX)    GuestRegs->rsp = VmxRead (GUEST_RSP);  if (Hvm->ArchIsNestedEvent (Cpu, GuestRegs)) {    // it's an event of a nested guest    Hvm->ArchDispatchNestedEvent (Cpu, GuestRegs);    // FIXME: This should be moved away from the HVM to VMX-specific code!!!    if (Hvm->Architecture == ARCH_VMX)      VmxWrite (GUEST_RSP, GuestRegs->rsp);    return;  }  // it's an original event  Hvm->ArchDispatchEvent (Cpu, GuestRegs);  // FIXME: This should be moved away from the HVM to VMX-specific code!!!  if (Hvm->Architecture == ARCH_VMX)    VmxWrite (GUEST_RSP, GuestRegs->rsp);  return;}

下面还要idt gdt设置的函数,先忽略。

;HvmEventCallback(PCPU Cpu,PGUEST_REGS GuestRegs,ULONG64 Ticks1)VmxVmexitHandler PROC   	HVM_SAVE_ALL_NOSEGREGS		mov     rcx, [rsp + 80h] ;PCPU	mov 	rdx, rsp		;GuestRegs	mov 	r8, 0		;TSC	sub	rsp, 28h	;rdtsc		call	HvmEventCallback	add	rsp, 28h		HVM_RESTORE_ALL_NOSEGREGS		vmx_resume	retVmxVmexitHandler ENDP
static NTSTATUS VmxSetupVMCS (  PCPU Cpu,  PVOID GuestRip,  PVOID GuestRsp){.......#ifdef _X86_  VmxWrite (HOST_RSP, g_HostStackBaseAddress + 0x0C00); //setup host sp at vmxLaunch(...)#else  VmxWrite (HOST_RSP, (ULONG64) Cpu);   //setup host sp at vmxLaunch(...)#endif  VmxWrite (HOST_RIP, (ULONG64) VmxVmexitHandler);      //setup host ip:CmSlipIntoMatrix  _KdPrint (("VmxSetupVMCS(): Exit\n"));  return STATUS_SUCCESS;}

貌似是这个 。这里的host_ip 的描述应该是,guest 中断退出时,rip所应该赋的值。这个应该是写在控制域中的,整理下代码,跑一下。

 

转载地址:http://hnjvb.baihongyu.com/

你可能感兴趣的文章
整型字符常量和字符字面量的区别 sizeof(char) 和 sizeof('a')
查看>>
表的主键特点中,说法不正确的是()
查看>>
用变量a给出下面的定义:一个有10个指针的数组,该指针指向一个函数,该函数有一个整形参数并返回一个整型数
查看>>
冯诺依曼工作方式的基本特点是____
查看>>
下列关于文件索引结构的叙述中,哪些是正确的?
查看>>
Java异常处理
查看>>
JQueryUI实现对话框
查看>>
Java流(Stream)/文件(File)/IO
查看>>
文件处理(压缩与解压)
查看>>
Java中的目录
查看>>
JQuery实现对select选择框的赋值
查看>>
SweetAlert插件
查看>>
JSON学习
查看>>
有关项目的基础知识
查看>>
创建Java工程实现发送邮件(163邮箱)
查看>>
java.lang.NoClassDefFoundError: com/sun/mail/util/MailLogger javax/mail/MessagingException
查看>>
JavaScript学习
查看>>
JavaScript学习总结
查看>>
JQuery学习总结笔记1
查看>>
JQuery学习笔记2
查看>>