1 #include "libcflat.h" 2 #include "vm.h" 3 #include "desc.h" 4 #include "alloc_page.h" 5 #include "fwcfg.h" 6 7 #define KVM_HYPERCALL_INTEL ".byte 0x0f,0x01,0xc1" 8 #define KVM_HYPERCALL_AMD ".byte 0x0f,0x01,0xd9" 9 10 static inline long kvm_hypercall0_intel(unsigned int nr) 11 { 12 long ret; 13 asm volatile(KVM_HYPERCALL_INTEL 14 : "=a"(ret) 15 : "a"(nr)); 16 return ret; 17 } 18 19 static inline long kvm_hypercall0_amd(unsigned int nr) 20 { 21 long ret; 22 asm volatile(KVM_HYPERCALL_AMD 23 : "=a"(ret) 24 : "a"(nr)); 25 return ret; 26 } 27 28 29 volatile unsigned long test_rip; 30 #ifdef __x86_64__ 31 extern void gp_tss(void); 32 asm ("gp_tss: \n\t" 33 "add $8, %rsp\n\t" // discard error code 34 "popq test_rip(%rip)\n\t" // pop return address 35 "pushq %rsi\n\t" // new return address 36 "iretq\n\t" 37 "jmp gp_tss\n\t" 38 ); 39 40 static inline int 41 test_edge(void) 42 { 43 test_rip = 0; 44 asm volatile ("movq $-1, %%rax\n\t" // prepare for vmcall 45 "leaq 1f(%%rip), %%rsi\n\t" // save return address for gp_tss 46 "movabsq $0x7ffffffffffd, %%rbx\n\t" 47 "jmp *%%rbx; 1:" : : : "rax", "rbx", "rsi"); 48 printf("Return from int 13, test_rip = %lx\n", test_rip); 49 return test_rip == (1ul << 47); 50 } 51 #endif 52 53 int main(int ac, char **av) 54 { 55 bool test_vmcall = !no_test_device || is_intel(); 56 bool test_vmmcall = !no_test_device || !is_intel(); 57 58 if (test_vmcall) { 59 kvm_hypercall0_intel(-1u); 60 printf("Hypercall via VMCALL: OK\n"); 61 } 62 63 if (test_vmmcall) { 64 kvm_hypercall0_amd(-1u); 65 printf("Hypercall via VMMCALL: OK\n"); 66 } 67 68 #ifdef __x86_64__ 69 setup_vm(); 70 setup_alt_stack(); 71 set_intr_alt_stack(13, gp_tss); 72 73 u8 *data1 = alloc_page(); 74 u8 *topmost = (void *) ((1ul << 47) - PAGE_SIZE); 75 76 install_pte(phys_to_virt(read_cr3()), 1, topmost, 77 virt_to_phys(data1) | PT_PRESENT_MASK | PT_WRITABLE_MASK, 0); 78 memset(topmost, 0xcc, PAGE_SIZE); 79 topmost[4093] = 0x0f; 80 topmost[4094] = 0x01; 81 topmost[4095] = 0xc1; 82 83 if (test_vmcall) { 84 report(test_edge(), 85 "VMCALL on edge of canonical address space (intel)"); 86 } 87 88 topmost[4095] = 0xd9; 89 90 if (test_vmmcall) { 91 report(test_edge(), 92 "VMMCALL on edge of canonical address space (AMD)"); 93 } 94 #endif 95 96 return report_summary(); 97 } 98