Skip to contentSkip to conversation

kvm test: test rmap chains

PATCH RESEND Applied Marcelo Tosatti 2 participants 6 messages Jul 5, 2010 – Jul 6, 2010 KVM

lore
Share & tools
lore
#1 lore raw

PATCH 1/3 kvm test: protect fwfcg accesses with spinlock

kvm/test/lib/x86/fwcfg.c +5 -0
Index: qemu-kvm/kvm/user/test/lib/x86/fwcfg.c
===================================================================
@@ -1,4 +1,7 @@
 #include "fwcfg.h"
+#include "smp.h"
+
+static struct spinlock lock;
 
 uint64_t fwcfg_get_u(uint16_t index, int bytes)
 {
@@ -6,11 +9,13 @@ uint64_t fwcfg_get_u(uint16_t index, int
     uint8_t b;
     int i;
 
+    spin_lock(&lock);
     asm volatile ("out %0, %1" : : "a"(index), "d"((uint16_t)BIOS_CFG_IOPORT));
     for (i = 0; i < bytes; ++i) {
         asm volatile ("in %1, %0" : "=a"(b) : "d"((uint16_t)(BIOS_CFG_IOPORT + 1)));
         r |= (uint64_t)b << (i * 8);
     }
+    spin_unlock(&lock);
     return r;
 }
 
#2 lore raw

PATCH 2/3 kvm test: export vm helpers

In reply to Marcelo Tosatti

To be used by rmap chain patch. Also make install_pte take an argument indicating physical location of pagetable.

kvm/test/x86/vm.c +18 -66
Index: qemu-kvm/kvm/test/x86/vm.c
===================================================================
@@ -14,16 +14,6 @@
 static void *free = 0;
 static void *vfree_top = 0;
 
-static unsigned long virt_to_phys(const void *virt) 
-{ 
-    return (unsigned long)virt;
-}
-
-static void *phys_to_virt(unsigned long phys)
-{
-    return (void *)phys;
-}
-
 void *memset(void *data, int c, unsigned long len)
 {
     char *s = data;
@@ -66,11 +56,6 @@ void free_page(void *page)
 extern char edata;
 static unsigned long end_of_memory;
 
-#define PTE_PRESENT (1ull << 0)
-#define PTE_PSE     (1ull << 7)
-#define PTE_WRITE   (1ull << 1)
-#define PTE_ADDR    (0xffffffffff000ull)
-
 #ifdef __x86_64__
 #define	PAGE_LEVEL	4
 #define	PGDIR_WIDTH	9
@@ -81,10 +66,11 @@ static unsigned long end_of_memory;
 #define	PGDIR_MASK	1023
 #endif
 
-static void install_pte(unsigned long *cr3, 
-			int pte_level, 
-			void *virt,
-			unsigned long pte)
+void install_pte(unsigned long *cr3,
+		 int pte_level,
+		 void *virt,
+		 unsigned long pte,
+		 unsigned long *pt_page)
 {
     int level;
     unsigned long *pt = cr3;
@@ -93,7 +79,11 @@ static void install_pte(unsigned long *c
     for (level = PAGE_LEVEL; level > pte_level; --level) {
 	offset = ((unsigned long)virt >> ((level-1) * PGDIR_WIDTH + 12)) & PGDIR_MASK;
 	if (!(pt[offset] & PTE_PRESENT)) {
-	    unsigned long *new_pt = alloc_page();
+	    unsigned long *new_pt = pt_page;
+            if (!new_pt)
+                new_pt = alloc_page();
+            else
+                pt_page = 0;
 	    memset(new_pt, 0, PAGE_SIZE);
 	    pt[offset] = virt_to_phys(new_pt) | PTE_PRESENT | PTE_WRITE;
 	}
@@ -123,58 +113,20 @@ static unsigned long get_pte(unsigned lo
     return pte;
 }
 
-static void install_large_page(unsigned long *cr3, 
-			       unsigned long phys,
-			       void *virt)
-{
-    install_pte(cr3, 2, virt, phys | PTE_PRESENT | PTE_WRITE | PTE_PSE);
-}
-
-static void install_page(unsigned long *cr3, 
-			 unsigned long phys,
-			 void *virt)
-{
-    install_pte(cr3, 1, virt, phys | PTE_PRESENT | PTE_WRITE);
-}
-
-static inline void load_cr3(unsigned long cr3)
-{
-    asm ( "mov %0, %%cr3" : : "r"(cr3) );
-}
-
-static inline unsigned long read_cr3()
+void install_large_page(unsigned long *cr3,
+                              unsigned long phys,
+                              void *virt)
 {
-    unsigned long cr3;
-
-    asm volatile ( "mov %%cr3, %0" : "=r"(cr3) );
-    return cr3;
+    install_pte(cr3, 2, virt, phys | PTE_PRESENT | PTE_WRITE | PTE_PSE, 0);
 }
 
-static inline void load_cr0(unsigned long cr0)
+void install_page(unsigned long *cr3,
+                  unsigned long phys,
+                  void *virt)
 {
-    asm volatile ( "mov %0, %%cr0" : : "r"(cr0) );
-}
-
-static inline unsigned long read_cr0()
-{
-    unsigned long cr0;
-
-    asm volatile ( "mov %%cr0, %0" : "=r"(cr0) );
-    return cr0;
+    install_pte(cr3, 1, virt, phys | PTE_PRESENT | PTE_WRITE, 0);
 }
 
-static inline void load_cr4(unsigned long cr4)
-{
-    asm volatile ( "mov %0, %%cr4" : : "r"(cr4) );
-}
-
-static inline unsigned long read_cr4()
-{
-    unsigned long cr4;
-
-    asm volatile ( "mov %%cr4, %0" : "=r"(cr4) );
-    return cr4;
-}
 
 struct gdt_table_descr
 {
kvm/test/x86/vm.h +75 -0

85 lines not on this page · raw message

kvm/test/x86/emulator.c +0 -8
Index: qemu-kvm/kvm/test/x86/emulator.c
===================================================================
@@ -220,14 +220,6 @@ jmpf:
     report("ljmp", res);
 }
 
-unsigned long read_cr0(void)
-{
-	unsigned long cr0;
-
-	asm volatile ("mov %%cr0, %0" : "=r"(cr0));
-	return cr0;
-}
-
 void test_smsw(void)
 {
 	char mem[16];
#3 lore raw

PATCH 3/3 kvm test: long rmap chains

In reply to Marcelo Tosatti

test long rmap chains

kvm/test/config-x86-common.mak +3 -0
Index: qemu-kvm/kvm/test/config-x86-common.mak
===================================================================
@@ -65,6 +65,9 @@ $(TEST_DIR)/idt_test.flat: $(cstart.o) $
 
 $(TEST_DIR)/xsave.flat: $(cstart.o) $(TEST_DIR)/idt.o $(TEST_DIR)/xsave.o
 
+$(TEST_DIR)/rmap_chain.flat: $(cstart.o) $(TEST_DIR)/rmap_chain.o \
+			     $(TEST_DIR)/print.o $(TEST_DIR)/vm.o
+
 arch_clean:
 	$(RM) $(TEST_DIR)/*.o $(TEST_DIR)/*.flat \
 	$(TEST_DIR)/.*.d $(TEST_DIR)/lib/.*.d $(TEST_DIR)/lib/*.o
kvm/test/config-x86_64.mak +1 -1
Index: qemu-kvm/kvm/test/config-x86_64.mak
===================================================================
@@ -6,6 +6,6 @@ CFLAGS += -D__x86_64__
 
 tests = $(TEST_DIR)/access.flat $(TEST_DIR)/apic.flat \
 	  $(TEST_DIR)/emulator.flat $(TEST_DIR)/idt_test.flat \
-	  $(TEST_DIR)/xsave.flat
+	  $(TEST_DIR)/xsave.flat $(TEST_DIR)/rmap_chain.flat
 
 include config-x86-common.mak
kvm/test/x86/rmap_chain.c new file +53 -0

53 lines not on this page · raw message

#4 lore raw

Re: [patch 3/3] kvm test: long rmap chains

Quoted 4 lines · Marcelo Tosatti

test long rmap chains

kvm/test/x86/rmap_chain.c new file +1 -0
+

kvm/test/x86/rmap_chain.c line 25

Quoted 10 lines
kvm/test/x86/rmap_chain.c new file +10 -0
+int main (void)
+{
+    int i;
+    int nr_pages;
+    void *target_page, *virt_addr;
+
+    setup_vm();
+
+    nr_pages = inl(0xd1) / PAGE_SIZE;
+    nr_pages -= 1000;

No need to depend on the number of physical pages, since just one page is used (+ 1/512 page for the pte).

Quoted 17 lines
kvm/test/x86/rmap_chain.c new file +16 -0
+    target_page = alloc_page();
+
+    virt_addr = (void *) 0xfffffa000;
+    for (i = 0; i<  nr_pages; i++) {
+        install_page(phys_to_virt(read_cr3()), virt_to_phys(target_page),
+                     virt_addr);
+        virt_addr += PAGE_SIZE;
+    }
+    printf("created %d mappings\n", nr_pages);
+
+    virt_addr = (void *) 0xfffffa000;
+    for (i = 0; i<  nr_pages; i++) {
+        unsigned long *touch = virt_addr;
+
+        *touch = 0;
+        virt_addr += PAGE_SIZE;

kvm/test/x86/rmap_chain.c line 51

Quoted 10 lines
kvm/test/x86/rmap_chain.c new file +10 -0
+    }
+    printf("instantiated mappings\n");
+
+    virt_addr += PAGE_SIZE;
+    install_pte(phys_to_virt(read_cr3()), 1, virt_addr,
+                0 | PTE_PRESENT | PTE_WRITE, target_page);
+
+    *(unsigned long *)virt_addr = 0;
+    printf("PASS\n");
+

Would be nice to add measure the time for this, and fail above some threshold. Of course it's problematic in automated scenarios where the host can be overloaded, but still.

Signature · 1 line
error compiling committee.c: too many arguments to function