Hi Jan/ Kashyap/ All, Thanks for the tips! It was really helpful. I was using a very old version of kvm_intel module and it didn't have "nested" capabilities. Now, I am using "-cpu core2duo,+vmx" option and kvm-intel.ko is also inserted using nested=1. And, the CPUID returned the correct info, it had VMX capabilities. Hence the test is passed. Secondly, I am trying to test bit 13 of CR4 register, which is necessary to be set before using instructions like vmxon. I am not sure when and how is this bit set, or it never gets set in the tests? I am attaching the patch, which as of now, first prints the vendor ID, and Passes VMX capabilities test, and Fails for testing CR4.VMXE bit. Command : qemu-kvm -device testdev,chardev=testlog -chardev file,id=testlog,path=msr.out -serial stdio -cpu core2duo,+vmx -kernel ./x86/vmx_test.flat Output : Vendor ID : GenuineIntel VMX_CAPABILITIES_GUEST: PASS CONTROL_REGISTER_VMX_ON: FAIL ---------------------------- Thanks & Regards Mohit Dhingra +919611190435 On 14 April 2013 15:59, Kashyap Chamarthy <kashyap.cv@xxxxxxxxx> wrote: > On Sun, Apr 14, 2013 at 1:48 PM, Jan Kiszka <jan.kiszka@xxxxxx> wrote: >> On 2013-04-13 20:24, Mohit Dhingra wrote: >>> Hi All, >>> >>> I am Mohit Dhingra, planning to work in GSoC project "Improve nested >>> virtualization support for x86". I got in touch with Jan >>> (jan.kiszka@xxxxxx) few days back. >>> >>> As suggested by him, I am trying to write a simple unit test which >>> tests the "vmx" functions. To start with, I have written a small code >>> which checks whether "vmx" functionality is available on the current >>> processor or not[1]. >>> >>> I have used "cpuid" to check the VMX functionality. Before executing >>> cpuid, eax is set to 1. cpuid then puts the feature flags in ecx and >>> edx registers. Bit5 in ecx register tells whether VMX feature is >>> present or not. I am attaching the patch along with this mail. >> >> Hint regarding assembly usage: Try to minimize the number of >> instructions. Check, e.g., how the kernel implements cpuid. Result >> evaluation can perfectly be done in C. >> >>> >>> But there is a problem that I am facing. CPUID behaves differently >>> when I run it using qemu-kvm, and when I run it directly in user mode. >>> Please check the below output. It would be great if someone can >>> please help me out. >> >> To enable nested VMX, you need to tweak two things: first, you need >> nested=1 as parameter for kvm_intel. And, second, you have to select a >> CPU type via QEMU (-cpu) that supports VMX or explicitly add that >> feature to the selected CPU (-cpu ...,+vmx). > > In addendum to Jan's above info, > > I posted some notes here while testing it on Fedora, see if its any helpful: > > - http://kashyapc.wordpress.com/tag/nested-virtualization/ > - https://github.com/kashyapc/nested-virt-notes-intel-f18 > >> >> By default, only core[2]duo and the synthetic KVM type "host" come with >> VMX enabled, not much more modern Intel CPU like Nehalem or SandyBridge. >> That's inconsistent, and if you want to fix something in QEMU, you could >> check which CPU types in qemu/target-i386/cpu.c lack the flag and post a >> patch to change this. >> >> Jan >>
From 01f3cc5e424dca53a94f0cb349447f5c436a301b Mon Sep 17 00:00:00 2001 From: Mohit Dhingra <mohitdhingras@xxxxxxxxx> Date: Sun, 21 Apr 2013 02:18:32 +0530 Subject: [PATCH 1/3] Unit test for checking VMX capabilities --- x86/vmx_test.c | 98 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 98 insertions(+), 0 deletions(-) create mode 100644 x86/vmx_test.c diff --git a/x86/vmx_test.c b/x86/vmx_test.c new file mode 100644 index 0000000..d928f07 --- /dev/null +++ b/x86/vmx_test.c @@ -0,0 +1,98 @@ + +#include "libcflat.h" +#include "processor.h" +#include "msr.h" + + +struct vmx_info { + char *name; + int (*test_case)(); +}; + +int test_vmx_capabilities(); // Returns 1 if VMX capabilities are present in the Guest, else Returns 0 +int test_cr4_vmx_set(); // Returns 1 if VMX bit is set in CR4 Register ( Must before executing instructions like vmxon ) +void VendorId(); // Prints Vendor ID + + +struct vmx_info test_cases_array[]= { + {"VMX_CAPABILITIES_GUEST" , test_vmx_capabilities}, + {"CONTROL_REGISTER_VMX_ON", test_cr4_vmx_set} +}; + + + +int main(int ac, char **av) +{ + int count = 0; + + VendorId(); + + for( count = 0 ; count < (sizeof(test_cases_array)/sizeof(struct vmx_info)) ; count++) + { + printf( "%s: %s\n", test_cases_array[count].name, (test_cases_array[count].test_case() ? "PASS" : "FAIL") ); + } + + + return 1; +} + + +int test_vmx_capabilities() +{ + + int eax_initialize = 1; + uint32_t test_vmx_capabilities = 0; + + asm volatile ("mov %1, %%eax\n\t" // mov source destination + "cpuid\n\t" // When eax = 1, cpuid puts Feature Flags in ecx and edx registers. + "mov %%ecx, %0" // Storing the result into test_vmx_capabilities + + :"=r"(test_vmx_capabilities) // Ouputs : test_vmx_capabilities + :"r"(eax_initialize) // Inputs : eax_initialize + :"eax","ecx"); + +// printf("Feauture Flag returned in ecx : 0x%x ", test_vmx_capabilities); + + if ( test_vmx_capabilities & 0x20 ) // ANDing ecx with 0x20 (00100000), if it results in non-zero, then VMX capabilities are present. + return 1; + else + return 0; + +} + + + +int test_cr4_vmx_set() +{ + unsigned long result; + + //CR4 cr4_reg; + + asm volatile("movq %%cr4, %%rax\n\t" + : "=a"(result) :: ); + + if ( result & 0x2000 ) // Bit 13 of CR4 should be set to use commands like vmxon + return 1; + + return 0; + +} + + +// Prints vendor ID +void VendorId() +{ + int code = 0; + + union { + uint32_t where[4]; + char vendor[17]; + }s; + + asm volatile("cpuid":"=a"(*s.where),"=b"(*(s.where+1)),"=c"(*(s.where+3)),"=d"(*(s.where+2)):"a"(code)); + + s.vendor[16] = '\0'; + + printf("Vendor ID : %s\n\n", (s.vendor+4)); + +} -- 1.7.7 From c36899d742b91c26c7855f7bac4f35746d818622 Mon Sep 17 00:00:00 2001 From: Mohit Dhingra <mohitdhingras@xxxxxxxxx> Date: Sun, 21 Apr 2013 02:18:44 +0530 Subject: [PATCH 2/3] Unit test for checking VMX capabilities --- config-x86-common.mak | 4 +++- 1 files changed, 3 insertions(+), 1 deletions(-) diff --git a/config-x86-common.mak b/config-x86-common.mak index 1f0f1ba..df2a42e 100644 --- a/config-x86-common.mak +++ b/config-x86-common.mak @@ -31,7 +31,7 @@ FLATLIBS = lib/libcflat.a $(libgcc) tests-common = $(TEST_DIR)/vmexit.flat $(TEST_DIR)/tsc.flat \ $(TEST_DIR)/smptest.flat $(TEST_DIR)/port80.flat \ - $(TEST_DIR)/realmode.flat $(TEST_DIR)/msr.flat \ + $(TEST_DIR)/realmode.flat $(TEST_DIR)/msr.flat $(TEST_DIR)/vmx_test.flat \ $(TEST_DIR)/hypercall.flat $(TEST_DIR)/sieve.flat \ $(TEST_DIR)/kvmclock_test.flat $(TEST_DIR)/eventinj.flat \ $(TEST_DIR)/s3.flat $(TEST_DIR)/pmu.flat \ @@ -79,6 +79,8 @@ $(TEST_DIR)/realmode.o: bits = 32 $(TEST_DIR)/msr.elf: $(cstart.o) $(TEST_DIR)/msr.o +$(TEST_DIR)/vmx_test.elf: $(cstart.o) $(TEST_DIR)/vmx_test.o + $(TEST_DIR)/idt_test.elf: $(cstart.o) $(TEST_DIR)/idt_test.o $(TEST_DIR)/xsave.elf: $(cstart.o) $(TEST_DIR)/xsave.o -- 1.7.7 From 1d61a82ec1525c087cbd205fb8ea4576cd30b04b Mon Sep 17 00:00:00 2001 From: Mohit Dhingra <mohitdhingras@xxxxxxxxx> Date: Sun, 21 Apr 2013 02:18:53 +0530 Subject: [PATCH 3/3] Unit test for checking VMX capabilities --- x86/unittests.cfg | 5 ++++- 1 files changed, 4 insertions(+), 1 deletions(-) diff --git a/x86/unittests.cfg b/x86/unittests.cfg index 5e08c55..1a65a14 100644 --- a/x86/unittests.cfg +++ b/x86/unittests.cfg @@ -63,6 +63,9 @@ file = hypercall.flat [idt_test] file = idt_test.flat +[vmx_test] +file = vmx_test.flat + [msr] file = msr.flat @@ -101,4 +104,4 @@ extra_params = --append "10000000 `date +%s`" [pcid] file = pcid.flat -extra_params = -cpu qemu64,+pcid \ No newline at end of file +extra_params = -cpu qemu64,+pcid -- 1.7.7