From: Gleb Natapov <gleb@redhat.com>
To: kvm@vger.kernel.org
Cc: avi@redhat.com, marcelo@redhat.com
Subject: [PATCHv2] Add async page fault test
Date: Wed, 9 May 2012 13:33:14 +0300 [thread overview]
Message-ID: <20120509103314.GU15960@redhat.com> (raw)
The test checks that when hypervisor prefaults swapped in page it does
not generates spurious #PFs in case page was unmapped while it was
swapped out.
diff --git a/config-x86-common.mak b/config-x86-common.mak
index c8fbda7..6976f78 100644
--- a/config-x86-common.mak
+++ b/config-x86-common.mak
@@ -34,7 +34,7 @@ tests-common = $(TEST_DIR)/vmexit.flat $(TEST_DIR)/tsc.flat \
$(TEST_DIR)/realmode.flat $(TEST_DIR)/msr.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
+ $(TEST_DIR)/s3.flat $(TEST_DIR)/pmu.flat $(TEST_DIR)/asyncpf.flat
ifdef API
tests-common += api/api-sample
@@ -90,6 +90,8 @@ $(TEST_DIR)/s3.elf: $(cstart.o) $(TEST_DIR)/s3.o
$(TEST_DIR)/pmu.elf: $(cstart.o) $(TEST_DIR)/pmu.o
+$(TEST_DIR)/asyncpf.elf: $(cstart.o) $(TEST_DIR)/asyncpf.o
+
arch_clean:
$(RM) $(TEST_DIR)/*.o $(TEST_DIR)/*.flat $(TEST_DIR)/*.elf \
$(TEST_DIR)/.*.d $(TEST_DIR)/lib/.*.d $(TEST_DIR)/lib/*.o
diff --git a/lib/x86/processor.h b/lib/x86/processor.h
index c7e1afb..e46d8d0 100644
--- a/lib/x86/processor.h
+++ b/lib/x86/processor.h
@@ -302,4 +302,9 @@ static inline void invlpg(void *va)
{
asm volatile("invlpg (%0)" ::"r" (va) : "memory");
}
+
+static inline void safe_halt(void)
+{
+ asm volatile("sti; hlt");
+}
#endif
diff --git a/lib/x86/vm.c b/lib/x86/vm.c
index 550ec9b..71b70fd 100644
--- a/lib/x86/vm.c
+++ b/lib/x86/vm.c
@@ -219,6 +219,11 @@ void *vmalloc(unsigned long size)
return mem;
}
+uint64_t virt_to_phys_cr3(void *mem)
+{
+ return (get_pte(phys_to_virt(read_cr3()), mem) & PTE_ADDR) + ((ulong)mem & (PAGE_SIZE - 1));
+}
+
void vfree(void *mem)
{
unsigned long size = ((unsigned long *)mem)[-1];
diff --git a/lib/x86/vm.h b/lib/x86/vm.h
index 71ab4a8..3473f8d 100644
--- a/lib/x86/vm.h
+++ b/lib/x86/vm.h
@@ -22,6 +22,7 @@ void vfree(void *mem);
void *vmap(unsigned long long phys, unsigned long size);
void *alloc_vpage(void);
void *alloc_vpages(ulong nr);
+uint64_t virt_to_phys_cr3(void *mem);
void install_pte(unsigned long *cr3,
int pte_level,
diff --git a/x86/asyncpf.c b/x86/asyncpf.c
new file mode 100644
index 0000000..62c0455
--- /dev/null
+++ b/x86/asyncpf.c
@@ -0,0 +1,113 @@
+/*
+ * Async PF test. For the test to actually do anywathing it ineeds to be started
+ * in memory cgroup with 512M of memory and with more then 1G memory provided
+ * to the guest.
+ *
+ * To create cgroup do as root:
+ * mkdir /dev/cgroup
+ * mount -t cgroup none -omemory /dev/cgroup
+ * chmod a+rxw /dev/cgroup/
+ *
+ * From a shell you will start qemu from:
+ * mkdir /dev/cgroup/1
+ * echo $$ > /dev/cgroup/1/tasks
+ * echo 512M > /dev/cgroup/1/memory.limit_in_bytes
+ *
+ */
+#include "x86/msr.h"
+#include "x86/processor.h"
+#include "x86/apic-defs.h"
+#include "x86/apic.h"
+#include "x86/desc.h"
+#include "x86/isr.h"
+#include "x86/vm.h"
+
+#include "libcflat.h"
+#include <stdint.h>
+
+#define KVM_PV_REASON_PAGE_NOT_PRESENT 1
+#define KVM_PV_REASON_PAGE_READY 2
+
+#define MSR_KVM_ASYNC_PF_EN 0x4b564d02
+
+#define KVM_ASYNC_PF_ENABLED (1 << 0)
+#define KVM_ASYNC_PF_SEND_ALWAYS (1 << 1)
+
+volatile uint32_t apf_reason __attribute__((aligned(64)));
+char *buf;
+volatile uint64_t i;
+volatile uint64_t phys;
+bool fail;
+
+static inline uint32_t get_apf_reason(void)
+{
+ uint32_t r = apf_reason;
+ apf_reason = 0;
+ return r;
+}
+
+static void pf_isr(struct ex_regs *r)
+{
+ void* virt = (void*)((ulong)(buf+i) & ~(PAGE_SIZE-1));
+ uint32_t reason = get_apf_reason();
+
+ switch (reason) {
+ case 0:
+ printf("unexpected #PF at %p\n", read_cr2());
+ fail = true;
+ break;
+ case KVM_PV_REASON_PAGE_NOT_PRESENT:
+ phys = virt_to_phys_cr3(virt);
+ install_pte(phys_to_virt(read_cr3()), 1, virt, phys, 0);
+ write_cr3(read_cr3());
+ printf("Got not present #PF token %x virt addr %p phys addr %p\n", read_cr2(), virt, phys);
+ while(phys) {
+ safe_halt(); /* enables irq */
+ irq_disable();
+ }
+ break;
+ case KVM_PV_REASON_PAGE_READY:
+ printf("Got present #PF token %x\n", read_cr2());
+ if ((uint32_t)read_cr2() == ~0)
+ break;
+ install_pte(phys_to_virt(read_cr3()), 1, virt, phys | PTE_PRESENT | PTE_WRITE, 0);
+ write_cr3(read_cr3());
+ phys = 0;
+ break;
+ default:
+ printf("unexpected async pf reason %d\n", reason);
+ fail = true;
+ break;
+ }
+}
+
+#define MEM 1ull*1024*1024*1024
+
+int main(int ac, char **av)
+{
+ int loop = 2;
+
+ setup_vm();
+ setup_idt();
+ setup_gdt();
+ printf("install handler\n");
+ handle_exception(14, pf_isr);
+ apf_reason = 0;
+ printf("enable async pf\n");
+ wrmsr(MSR_KVM_ASYNC_PF_EN, virt_to_phys((void*)&apf_reason) |
+ KVM_ASYNC_PF_SEND_ALWAYS | KVM_ASYNC_PF_ENABLED);
+ printf("alloc memory\n");
+ buf = vmalloc(MEM);
+ irq_enable();
+ while(loop--) {
+ printf("start loop\n");
+ /* access a lot of memory to make host swap it out */
+ for (i=0; i < MEM; i+=4096)
+ buf[i] = 1;
+ printf("end loop\n");
+ }
+ irq_disable();
+
+ printf("%s\n", fail ? "FAIL" : "PASS");
+ return fail;
+}
--
Gleb.
next reply other threads:[~2012-05-09 10:33 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-05-09 10:33 Gleb Natapov [this message]
2012-05-09 12:44 ` [PATCHv2] Add async page fault test Igor Mammedov
2012-05-09 12:45 ` Gleb Natapov
2012-05-14 22:30 ` Marcelo Tosatti
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20120509103314.GU15960@redhat.com \
--to=gleb@redhat.com \
--cc=avi@redhat.com \
--cc=kvm@vger.kernel.org \
--cc=marcelo@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.