Thanks for the reply.
I processed with bochs.
But now I have a problem launching my VM.
All what I need is that I want to launch a VM in 64-bit that execute a VMCALL and return to the VM exit.
Code: Select all
/**************************************************************************
VMX test Code
**************************************************************************/
static void vm_exit ()
{
kernel.getVideo()->setPosition(10,10);
kernel.getVideo()->putString("This is VMEXIT",COLOR_WHITE,COLOR_RED);
for (;;);
}
static void vm_entry ()
{
asm volatile("vmcall");
}
extern "C" void bsp_kernel_main(uint64_t p_start_stack,uint64_t p_end_stack)
{
kernel.setupVideo();
kernel.initializePhysicalMemory();
kernel.setupGlobalDescriptorTable();
if ( !kernel.setupACPI ())
{
kernel.getVideo()-> putString("Halting: ACPI Setup Failed \n",COLOR_RED,COLOR_WHITE);
return;
}
kernel.startupMemoryManager(p_start_stack,p_end_stack);
kmalloc_ptr = kernel.getKMallocPTR();
kernel.scanPCIBus();
uint32_t cpuid_eax = 0;
uint32_t cpuid_ebx = 0;
uint32_t cpuid_ecx = 0;
uint32_t cpuid_edx = 0;
asm volatile
("cpuid" : "=a" (cpuid_eax), "=b" (cpuid_ebx), "=c" (cpuid_ecx), "=d" (cpuid_edx)
: "a" (1), "c" (0));
if ( isBitSet(cpuid_ecx,0x5)) // Check if0x480 VMX is supported
{
kernel.getVideo()->putString("\nCPUID ECX: ",COLOR_BLUE,COLOR_WHITE);
kernel.getVideo()->putHexa(cpuid_ecx,COLOR_BLUE,COLOR_WHITE);
// Read MSR and store revision number
uint32_t msr_eax_value,msr_edx_value;
asm volatile ( "rdmsr" : "=a" (msr_eax_value),"=d" (msr_edx_value) : "c" (0x480) );
// Disable A20, set bit 0 of MSR 0x3a, set bit 13 of CR4 and set bit 5 of CR0
asm volatile(" \
in $0x92, %al; \
or $0x02, %al; \
out %al, $0x92; \
mov $0x3a,%ecx; \
rdmsr; \
bts $0, %rax; \
wrmsr; \
mov %cr4,%rax; \
bts $13, %rax; \
mov %rax,%cr4; \
mov %cr0,%rax; \
bts $5, %rax; \
mov %rax,%cr0;");
uint64_t cr0,cr4;
asm volatile("mov %%cr0, %0": "=r"(cr0)); // Get CR0 register value
asm volatile("mov %%cr4, %0": "=r"(cr4)); // Get CR4 register value
// Allocate host and guest VMCS and set VMX revision number
uint64_t vmx_phy_region = 0;
uint64_t vmx_region = kmalloc_ptr->kmalloc_ap(0x1000,&vmx_phy_region);
uint32_t * vmx_region_ptr = (uint32_t *) vmx_region;
vmx_region_ptr[0] = msr_eax_value;
uint64_t vmcs_phy_region = 0;
uint64_t vmcs_region = kmalloc_ptr->kmalloc_ap(0x1000,&vmcs_phy_region);
uint32_t * vmcs_region_ptr = (uint32_t *) vmcs_region;
vmcs_region_ptr[0] = msr_eax_value;
// VMXON and loading the guest VMCS region
asm volatile ("vmxon %0"::"m"(vmx_region));
asm volatile ("vmclear %0"::"m"(vmcs_region));
asm volatile ("vmptrld %0"::"m"(vmcs_region));
//******************************************************************
// Host VMCS Setup
//******************************************************************
uint64_t val = 0x13ff;
uint64_t encoding = 0x4012;
asm volatile ("vmwrite %0, %1"::"r" (val), "r" (encoding):"flags");
val = 0x1f; encoding = 0x4000;
asm volatile ("vmwrite %0, %1"::"r" (val), "r" (encoding):"flags");
val = 0x8401e9f2; encoding = 0x4002;
asm volatile ("vmwrite %0, %1"::"r" (val), "r" (encoding):"flags");
val = 0x2; encoding = 0x401E;
asm volatile ("vmwrite %0, %1"::"r" (val), "r" (encoding):"flags");
val = 0x36fff; encoding = 0x400C;
asm volatile ("vmwrite %0, %1"::"r" (val), "r" (encoding):"flags");
encoding = 0x6C00;
asm volatile ("mov %0,%%rbx;\
mov %%cr0,%%rax;\
vmwrite %%rax,%%rbx;" :: "r" (encoding):"flags");
encoding = 0x6C02;
asm volatile ("mov %0,%%rbx;\
mov %%cr3,%%rax;\
vmwrite %%rax,%%rbx;" :: "r" (encoding):"flags");
encoding = 0x6C04;
asm volatile ("mov %0,%%rbx;\
mov %%cr4,%%rax;\
vmwrite %%rax,%%rbx;" :: "r" (encoding):"flags");
encoding = 0xC02;
asm volatile ("mov %0,%%rbx;\
mov %%cs,%%rax;\
vmwrite %%rax,%%rbx;" :: "r" (encoding):"flags");
encoding = 0x6C16;
asm volatile ("mov %0,%%rax;\
vmwrite %%rax,%1;" :: "r" (vm_exit), "r" (encoding):"flags");
encoding = 0xC04;
asm volatile ("mov %0,%%rbx;\
mov %%ss,%%rax;\
vmwrite %%rax,%%rbx;" :: "r" (encoding):"flags");
encoding = 0x6C14;
asm volatile ("mov %0,%%rbx;\
mov %%rsp,%%rax;\
vmwrite %%rax,%%rbx;" :: "r" (encoding):"flags");
encoding = 0xC06;
asm volatile ("mov %0,%%rbx;\
xor %%rax,%%rax;\
mov %%ds,%%ax;\
vmwrite %%rax,%%rbx;" :: "r" (encoding):"flags");
encoding = 0xC00;
asm volatile ("mov %0,%%rbx;\
xor %%rax,%%rax;\
mov %%es,%%ax;\
vmwrite %%rax,%%rbx;" :: "r" (encoding):"flags");
encoding = 0xC08;
asm volatile ("mov %0,%%rbx;\
xor %%rax,%%rax;\
mov %%fs,%%ax;\
vmwrite %%rax,%%rbx;" :: "r" (encoding):"flags");
encoding = 0xC0A;
asm volatile ("mov %0,%%rbx;\
xor %%rax,%%rax;\
mov %%gs,%%ax;\
vmwrite %%rax,%%rbx;" :: "r" (encoding):"flags");
uint64_t tss_address = (uint64_t) kernel.getGlobalDescriptorTable()->getTSSEntry();
encoding = 0xC0C;
asm volatile ("vmwrite %0, %1"::"r" (tss_address), "r" (encoding):"flags");
encoding = 0x6C0C;
asm volatile ("vmwrite %0, %1"::"r" (m_globalDescriptorTablePointer.getBase()), "r" (encoding):"flags");
encoding = 0x6C0E;
asm volatile ("vmwrite %0, %1"::"r" (m_interruptDescriptorTablePointer.getBase()), "r" (encoding):"flags");
//******************************************************************
// Guest VMCS Setup
//******************************************************************
encoding = 0x6800;
asm volatile ("mov %0,%%rbx;\
mov %%cr0,%%rax;\
vmwrite %%rax,%%rbx;" :: "r" (encoding):"flags");
encoding = 0x6802;
asm volatile ("mov %0,%%rbx;\
mov %%cr3,%%rax;\
vmwrite %%rax,%%rbx;" :: "r" (encoding):"flags");
encoding = 0x6804;
asm volatile ("mov %0,%%rbx;\
mov %%cr4,%%rax;\
vmwrite %%rax,%%rbx;" :: "r" (encoding):"flags");
encoding = 0x6820;
asm volatile ("mov %0,%%rbx;\
mov $0x2,%%rax;\
vmwrite %%rax,%%rbx;" :: "r" (encoding):"flags");
encoding = 0x802;
val = 0x8;
asm volatile ("mov %0,%%rbx;\
mov %1,%%rax;\
vmwrite %%rax,%%rbx;" :: "r" (encoding),"r" (val):"flags");
encoding = 0x4802;
asm volatile ("mov %0,%%rbx;\
mov $0xfffff,%%rax;\
vmwrite %%rax,%%rbx;" :: "r" (encoding):"flags");
encoding = 0x4816;
val = AR_PRESENT | AR_CODE | DPL_KERNEL | AR_READABLE;
asm volatile ("mov %0,%%rbx;\
mov %1,%%rax;\
vmwrite %%rax,%%rbx;" :: "r" (encoding),"r" (val):"flags");
encoding = 0x6808;
asm volatile ("mov %0,%%rbx;\
mov $0x0,%%rax;\
vmwrite %%rax,%%rbx;" :: "r" (encoding):"flags");
encoding = 0x681E;
asm volatile ("mov %0,%%rbx;\
mov %1,%%rax;\
vmwrite %%rax,%%rbx;" :: "r" (encoding),"r" (vm_entry):"flags");
encoding = 0x6816;
asm volatile ("vmwrite %0, %1"::"r" (m_globalDescriptorTablePointer.getBase()), "r" (encoding):"flags");
encoding = 0x4810;
asm volatile ("vmwrite %0, %1"::"r" ((uint64_t)m_globalDescriptorTablePointer.getLimit()), "r" (encoding):"flags");
// Here BOCHS hangs forever
encoding = 0x6818;
asm volatile ("vmwrite %0, %1"::"r" (m_interruptDescriptorTablePointer.getBase()), "r" (encoding):"flags");
encoding = 0x4812;
asm volatile ("vmwrite %0, %1"::"r" ((uint64_t)m_interruptDescriptorTablePointer.getLimit()), "r" (encoding):"flags");
// Setting ES, DS, SS, FS, GS selectors
val = 0x10;
encoding = 0x800;
asm volatile ("mov %0,%%rbx;\
mov %1,%%rax;\
vmwrite %%rax,%%rbx;" :: "r" (encoding),"r" (val):"flags");
encoding = 0x804;
asm volatile ("mov %0,%%rbx;\
mov %1,%%rax;\
vmwrite %%rax,%%rbx;" :: "r" (encoding),"r" (val):"flags");
encoding = 0x806;
asm volatile ("mov %0,%%rbx;\
mov %1,%%rax;\
vmwrite %%rax,%%rbx;" :: "r" (encoding),"r" (val):"flags");
encoding = 0x808;
asm volatile ("mov %0,%%rbx;\
mov %1,%%rax;\
vmwrite %%rax,%%rbx;" :: "r" (encoding),"r" (val):"flags");
encoding = 0x80A;
asm volatile ("mov %0,%%rbx;\
mov %1,%%rax;\
vmwrite %%rax,%%rbx;" :: "r" (encoding),"r" (val):"flags");
// Setting ES, DS, SS, FS, GS limits
val = 0xfffff;
encoding = 0x4800;
asm volatile ("mov %0,%%rbx;\
mov %1,%%rax;\
vmwrite %%rax,%%rbx;" :: "r" (encoding),"r" (val):"flags");
encoding = 0x4804;
asm volatile ("mov %0,%%rbx;\
mov %1,%%rax;\
vmwrite %%rax,%%rbx;" :: "r" (encoding),"r" (val):"flags");
encoding = 0x4806;
asm volatile ("mov %0,%%rbx;\
mov %1,%%rax;\
vmwrite %%rax,%%rbx;" :: "r" (encoding),"r" (val):"flags");
encoding = 0x4808;
asm volatile ("mov %0,%%rbx;\
mov %1,%%rax;\
vmwrite %%rax,%%rbx;" :: "r" (encoding),"r" (val):"flags");
encoding = 0x480A;
asm volatile ("mov %0,%%rbx;\
mov %1,%%rax;\
vmwrite %%rax,%%rbx;" :: "r" (encoding),"r" (val):"flags");
// Setting ES, DS, SS, FS, GS Access
val = AR_PRESENT | AR_DATA | AR_WRITABLE | DPL_KERNEL;
encoding = 0x4814;
asm volatile ("mov %0,%%rbx;\
mov %1,%%rax;\
vmwrite %%rax,%%rbx;" :: "r" (encoding),"r" (val):"flags");
encoding = 0x4818;
asm volatile ("mov %0,%%rbx;\
mov %1,%%rax;\
vmwrite %%rax,%%rbx;" :: "r" (encoding),"r" (val):"flags");
encoding = 0x481A;
asm volatile ("mov %0,%%rbx;\
mov %1,%%rax;\
vmwrite %%rax,%%rbx;" :: "r" (encoding),"r" (val):"flags");
encoding = 0x481C;
asm volatile ("mov %0,%%rbx;\
mov %1,%%rax;\
vmwrite %%rax,%%rbx;" :: "r" (encoding),"r" (val):"flags");
encoding = 0x481E;
asm volatile ("mov %0,%%rbx;\
mov %1,%%rax;\
vmwrite %%rax,%%rbx;" :: "r" (encoding),"r" (val):"flags");
// Setting ES, DS, SS, FS, GS bases
val = 0x0;
encoding = 0x6806;
asm volatile ("mov %0,%%rbx;\
mov %1,%%rax;\
vmwrite %%rax,%%rbx;" :: "r" (encoding),"r" (val):"flags");
encoding = 0x680A;
asm volatile ("mov %0,%%rbx;\
mov %1,%%rax;\
vmwrite %%rax,%%rbx;" :: "r" (encoding),"r" (val):"flags");
encoding = 0x680C;
asm volatile ("mov %0,%%rbx;\
mov %1,%%rax;\
vmwrite %%rax,%%rbx;" :: "r" (encoding),"r" (val):"flags");
encoding = 0x680E;
asm volatile ("mov %0,%%rbx;\
mov %1,%%rax;\
vmwrite %%rax,%%rbx;" :: "r" (encoding),"r" (val):"flags");
encoding = 0x6810;
asm volatile ("mov %0,%%rbx;\
mov %1,%%rax;\
vmwrite %%rax,%%rbx;" :: "r" (encoding),"r" (val):"flags");
// Setting DR7
encoding = 0x681A;
asm volatile ("mov %0,%%rbx;\
mov $0x400,%%rax;\
vmwrite %%rax,%%rbx;" :: "r" (encoding):"flags");
asm volatile ("VMLAUNCH");
asm volatile ("vmxoff");
}
else
{
kernel.getVideo()->putString("\nVMX is not supported: ",COLOR_BLUE,COLOR_WHITE);
}
}
This VMX code is inserted in my kernel main c function after switch to long mode and mapping the whole memory.
Interrupts are not enabled and I start the VM with only one core (BSP).
I run this at bochs and it get stuck running for ever when I try to set the IDT base of the guest as per my code comments above.
Can you please have a look at the code and let me know what is wrong and if there are other problems that will stop the VM from launch.
Karim.