首页
社区
课程
招聘
[求助]AMD-V进入虚拟机的时候发生#GP异常
发表于: 2010-11-23 10:05 6604

[求助]AMD-V进入虚拟机的时候发生#GP异常

2010-11-23 10:05
6604
最近学习硬件虚拟化方面的AMD-V部分的, 在执行VMRUN指令的时候, CPU跳到Guest eip的第一条指令的时候机器蓝屏蓝屏代码是0x7F, 后来查了下是#GP异常, 我那框架是参考 nbp-0.32-public 那个代码的,Vmcb 设置应该是没错不然会发生VMEXIT_INVALID错误, 这个问题困扰了我快2个星期了,希望知道的指点下,谢谢了。 下面是我的一些初始化代码:

void InitVmcb(PCPU Cpu, PVOID GuestRip, PVOID GuestRsp)
{
	PVMCB Vmcb;
	ULONG uCs;
	ULONG GdtBase, IdtBase;
	MSR msr;

	GdtBase = GetGdtBase();
	IdtBase = GetIdtBase();

	KdPrint(("GdtBase : %08x Limit : %08x\n", GdtBase, GetGdtLimit()));
	KdPrint(("IdtBase : %08x Limit : %08x\n", IdtBase, GetIdtLimit()));

	Vmcb = Cpu->Vmcb;

	Vmcb->gdtr.base = GdtBase;
	Vmcb->gdtr.limit = GetGdtLimit();

	Vmcb->idtr.base = IdtBase;
	Vmcb->idtr.limit = GetIdtLimit();

	__asm int 3
	
	InitializeSegmentSelector(&Vmcb->cs, RegGetCs(), GdtBase);
	InitializeSegmentSelector(&Vmcb->ds, RegGetDs(), GdtBase);
	InitializeSegmentSelector(&Vmcb->es, RegGetEs(), GdtBase);
	InitializeSegmentSelector(&Vmcb->fs, RegGetFs(), GdtBase);
	InitializeSegmentSelector(&Vmcb->ss, RegGetSs(), GdtBase);
	InitializeSegmentSelector(&Vmcb->tr, RegGetTr(), GdtBase);

	*((PUCHAR)Vmcb + 0x403) |= 4;
	*((PUCHAR)Vmcb + 0x413) |= 4;
	*((PUCHAR)Vmcb + 0x423) |= 4;
	*((PUCHAR)Vmcb + 0x433) |= 4;
	*((PUCHAR)Vmcb + 0x443) |= 4;

	*((PUCHAR)Vmcb + 0x403) |= 8;
	*((PUCHAR)Vmcb + 0x413) |= 8;
	*((PUCHAR)Vmcb + 0x423) |= 8;
	*((PUCHAR)Vmcb + 0x433) |= 8;
	*((PUCHAR)Vmcb + 0x443) |= 8;


	Vmcb->rflags = RegGetRflags();
	Vmcb->cr0 = RegGetCr0();
	Cpu->HostCr0 = (ULONG)Vmcb->cr0;
	Vmcb->cr2 = RegGetCr2();	
	Vmcb->cr3 = RegGetCr3();
	Vmcb->cr4 = RegGetCr4();

	Vmcb->rax = 0;

	Vmcb->rip = (ULONG64)GuestRip;
	Vmcb->rsp = (ULONG64)GuestRsp;

	Vmcb->dr6 = RegGetDr6();
	Vmcb->dr7 = RegGetDr7();

	ReadMsr(MSR_IA32_EFER, &msr);
	Vmcb->efer = msr.value;

	ReadMsr(MSR_IA32_SYSENTER_CS, &msr);
	Vmcb->sysenter_cs = msr.value;
	
	ReadMsr(MSR_IA32_SYSENTER_ESP, &msr);
	Vmcb->sysenter_esp = msr.value;
	
	ReadMsr(MSR_IA32_SYSENTER_EIP, &msr);
	Vmcb->sysenter_eip = msr.value;

	Vmcb->guest_asid = 1;

	Vmcb->h_cr3 = 0;

	Vmcb->cr_intercepts = 0;
	Vmcb->exception_intercepts = 0;
	Vmcb->general1_intercepts = 0;
	Vmcb->general2_intercepts = (1 << 0);// VMRUN
	Vmcb->tsc_offset = 0;

	Vmcb->msrpm_base_pa = 0;

} 

void __declspec(naked) VmSvmRun(ULONG Vmcb_Low_PhysicalAddress, ULONG HostStackBottom)
{
	__asm
	{
		mov ax, ds
		and ax, 0x0FFFC
		mov ds, ax
		mov ax, es
		and ax, 0x0FFFC
		mov es, ax
		
		mov eax, [esp + 04h]
		int 3
		mov esp, [esp + 08h]

		//vmsave
		__emit 0x0F
		__emit 0x01
		__emit 0xDB 

l_loop:


		//vmload
		__emit 0x0F
		__emit 0x01
		__emit 0xDA 
		
		//vmrun
		__emit 0x0F
		__emit 0x01
		__emit 0xD8
		
		int 3

		//vmsave
		__emit 0x0F
		__emit 0x01
		__emit 0xDB 
		 cli
		 pushad
		 pushf
		 mov eax, esp
		 push eax
		
		 
		 popfd
		 popad
		 sti
		 jmp l_loop
		

	}
}

void Virtualization(PCPU Cpu)
{

	KdPrint(("Cpu->VmcbPA.LowPart = %08X Cpu->Vmcb = %08X\n", Cpu->VmcbPA.LowPart, Cpu->Vmcb));
	VmSvmRun((ULONG)Cpu->VmcbPA.LowPart, Cpu->HostStack);
}

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

收藏
免费 0
支持
分享
最新回复 (4)
雪    币: 1115
活跃值: (122)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
2
GuestRip 指向的代码和vmrun后面的代码都设置为死循环(EB FE )试试。VMCB有没有4KB对齐?
2010-11-23 11:26
0
雪    币: 538
活跃值: (460)
能力值: ( LV9,RANK:290 )
在线值:
发帖
回帖
粉丝
3
Cpu->Vmcb =        AllocateContiguousMemory(PAGE_SIZE);

用AllocateContiguousMemory分配的应该是有对齐的, 我看了调试信息 Vmcb 的后3位是0

EB FE  不行试过了,我还在GuestRip 的第一条指令用int3, 发生压根都还没开始执行那一条指令就出现#GP异常
2010-11-23 11:35
0
雪    币: 1115
活跃值: (122)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
4
那就应该是vmcb设置的问题了,EFER.SVME不知道开启没有?Vmcb->efer.svme应该是0
2010-11-23 11:49
0
雪    币: 538
活跃值: (460)
能力值: ( LV9,RANK:290 )
在线值:
发帖
回帖
粉丝
5
Vmcb->efer.svme 有设置, 是1  不然执行 vmload 就会异常
2010-11-23 13:20
0
游客
登录 | 注册 方可回帖
返回
//