[PATCH kvm-unit-tests v2 1/3] svm: Add ability to execute test via test_run on a vcpu other than vcpu 0

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



When running tests that can result in a vcpu being left in an
indeterminate state it is useful to be able to run the test on
a vcpu other than 0. This patch allows test_run to be executed
on any vcpu indicated by the on_vcpu member of the svm_test struct.
The initialized state of the vcpu0 registers used to populate the
vmcb is carried forward to the other vcpus.

Signed-off-by: Cathy Avery <cavery@xxxxxxxxxx>
---
 lib/x86/vm.c | 18 ++++++++++++++++++
 lib/x86/vm.h |  7 +++++++
 x86/svm.c    | 24 +++++++++++++++++++++++-
 x86/svm.h    |  2 ++
 4 files changed, 50 insertions(+), 1 deletion(-)

diff --git a/lib/x86/vm.c b/lib/x86/vm.c
index 41d6d96..e223bb4 100644
--- a/lib/x86/vm.c
+++ b/lib/x86/vm.c
@@ -2,6 +2,7 @@
 #include "libcflat.h"
 #include "vmalloc.h"
 #include "alloc_page.h"
+#include "smp.h"
 
 pteval_t *install_pte(pgd_t *cr3,
 		      int pte_level,
@@ -139,9 +140,18 @@ static void setup_mmu_range(pgd_t *cr3, phys_addr_t start, size_t len)
 	install_pages(cr3, phys, max - phys, (void *)(ulong)phys);
 }
 
+static void set_additional_vcpu_vmregs(struct vm_vcpu_info *info)
+{
+	write_cr3(info->cr3);
+	write_cr4(info->cr4);
+	write_cr0(info->cr0);
+}
+
 void *setup_mmu(phys_addr_t end_of_memory)
 {
     pgd_t *cr3 = alloc_page();
+    struct vm_vcpu_info info;
+    int i;
 
     memset(cr3, 0, PAGE_SIZE);
 
@@ -166,6 +176,14 @@ void *setup_mmu(phys_addr_t end_of_memory)
     printf("cr0 = %lx\n", read_cr0());
     printf("cr3 = %lx\n", read_cr3());
     printf("cr4 = %lx\n", read_cr4());
+
+    info.cr3 = read_cr3();
+    info.cr4 = read_cr4();
+    info.cr0 = read_cr0();
+
+    for (i = 1; i < cpu_count(); i++)
+        on_cpu(i, (void *)set_additional_vcpu_vmregs, &info);
+
     return cr3;
 }
 
diff --git a/lib/x86/vm.h b/lib/x86/vm.h
index 8750a1e..3a1432f 100644
--- a/lib/x86/vm.h
+++ b/lib/x86/vm.h
@@ -45,4 +45,11 @@ static inline void *current_page_table(void)
 
 void split_large_page(unsigned long *ptep, int level);
 void force_4k_page(void *addr);
+
+struct vm_vcpu_info {
+        u64 cr3;
+        u64 cr4;
+        u64 cr0;
+};
+
 #endif
diff --git a/x86/svm.c b/x86/svm.c
index d8c8272..975c477 100644
--- a/x86/svm.c
+++ b/x86/svm.c
@@ -275,6 +275,17 @@ static void test_run(struct svm_test *test)
 	irq_enable();
 
 	report(test->succeeded(test), "%s", test->name);
+
+        if (test->on_vcpu)
+	    test->on_vcpu_done = true;
+}
+
+static void set_additional_vpcu_msr(void *msr_efer)
+{
+	void *hsave = alloc_page();
+
+	wrmsr(MSR_VM_HSAVE_PA, virt_to_phys(hsave));
+	wrmsr(MSR_EFER, (ulong)msr_efer | EFER_SVME | EFER_NX);
 }
 
 static void setup_svm(void)
@@ -294,6 +305,9 @@ static void setup_svm(void)
 	if (!npt_supported())
 		return;
 
+	for (i = 1; i < cpu_count(); i++)
+		on_cpu(i, (void *)set_additional_vpcu_msr, (void *)rdmsr(MSR_EFER));
+
 	printf("NPT detected - running all tests with NPT enabled\n");
 
 	/*
@@ -396,7 +410,15 @@ int main(int ac, char **av)
 		if (svm_tests[i].supported && !svm_tests[i].supported())
 			continue;
 		if (svm_tests[i].v2 == NULL) {
-			test_run(&svm_tests[i]);
+			if (svm_tests[i].on_vcpu) {
+				if (cpu_count() <= svm_tests[i].on_vcpu)
+					continue;
+				on_cpu_async(svm_tests[i].on_vcpu, (void *)test_run, &svm_tests[i]);
+				while (!svm_tests[i].on_vcpu_done)
+					cpu_relax();
+			}
+			else
+				test_run(&svm_tests[i]);
 		} else {
 			vmcb_ident(vmcb);
 			v2_test = &(svm_tests[i]);
diff --git a/x86/svm.h b/x86/svm.h
index f8e7429..1e60d52 100644
--- a/x86/svm.h
+++ b/x86/svm.h
@@ -348,6 +348,8 @@ struct svm_test {
 	ulong scratch;
 	/* Alternative test interface. */
 	void (*v2)(void);
+	int on_vcpu;
+	bool on_vcpu_done;
 };
 
 struct regs {
-- 
2.20.1




[Index of Archives]     [KVM ARM]     [KVM ia64]     [KVM ppc]     [Virtualization Tools]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Questions]     [Linux Kernel]     [Linux SCSI]     [XFree86]

  Powered by Linux