Spaces:
Runtime error
Runtime error
| /* | |
| * Async PF test. For the test to actually do anything it needs 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 | |
| * | |
| */ | |
| volatile uint32_t apf_reason __attribute__((aligned(64))); | |
| char *buf; | |
| volatile uint64_t i; | |
| volatile uint64_t phys; | |
| 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: | |
| report("unexpected #PF at %#lx", false, read_cr2()); | |
| 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()); | |
| report("Got not present #PF token %lx virt addr %p phys addr %#" PRIx64, | |
| true, read_cr2(), virt, phys); | |
| while(phys) { | |
| safe_halt(); /* enables irq */ | |
| irq_disable(); | |
| } | |
| break; | |
| case KVM_PV_REASON_PAGE_READY: | |
| report("Got present #PF token %lx", true, read_cr2()); | |
| if ((uint32_t)read_cr2() == ~0) | |
| break; | |
| install_pte(phys_to_virt(read_cr3()), 1, virt, phys | PT_PRESENT_MASK | PT_WRITABLE_MASK, 0); | |
| write_cr3(read_cr3()); | |
| phys = 0; | |
| break; | |
| default: | |
| report("unexpected async pf reason %d", false, reason); | |
| break; | |
| } | |
| } | |
| int main(int ac, char **av) | |
| { | |
| int loop = 2; | |
| setup_vm(); | |
| setup_idt(); | |
| 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(); | |
| return report_summary(); | |
| } | |