From: Gleb Natapov <gleb@redhat.com>
To: kvm@vger.kernel.org
Cc: avi@redhat.com, mtosatti@redhat.com
Subject: [PATCH unit-tests] Add async page fault test
Date: Tue, 8 May 2012 14:24:46 +0300 [thread overview]
Message-ID: <20120508112446.GB8988@redhat.com> (raw)
Signed-off-by: Gleb Natapov <gleb@redhat.com>
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..f700e9c 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 halt(void)
+{
+ asm volatile("hlt");
+}
#endif
diff --git a/lib/x86/vm.c b/lib/x86/vm.c
index 550ec9b..b030934 100644
--- a/lib/x86/vm.c
+++ b/lib/x86/vm.c
@@ -219,6 +219,11 @@ void *vmalloc(unsigned long size)
return mem;
}
+unsigned long 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..ff4842f 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);
+unsigned long 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..f02f983
--- /dev/null
+++ b/x86/asyncpf.c
@@ -0,0 +1,98 @@
+/*
+ * 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.
+ */
+#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 unsigned long 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) & ~4095ul);
+
+ switch (get_apf_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) {
+ irq_enable();
+ halt();
+ 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;
+ }
+}
+
+#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-08 11:24 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-05-08 11:24 Gleb Natapov [this message]
2012-05-09 8:29 ` [PATCH unit-tests] Add async page fault test Avi Kivity
2012-05-09 8:41 ` Gleb Natapov
2012-05-09 8:52 ` Avi Kivity
2012-05-09 8:59 ` Gleb Natapov
2012-05-09 13:18 ` Takuya Yoshikawa
2012-05-09 13:20 ` Avi Kivity
2012-05-09 13:31 ` Takuya Yoshikawa
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=20120508112446.GB8988@redhat.com \
--to=gleb@redhat.com \
--cc=avi@redhat.com \
--cc=kvm@vger.kernel.org \
--cc=mtosatti@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.