1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980 |
- #include "libcflat.h"
- #include "vm.h"
- #include "desc.h"
- #define KVM_HYPERCALL_INTEL ".byte 0x0f,0x01,0xc1"
- #define KVM_HYPERCALL_AMD ".byte 0x0f,0x01,0xd9"
- static inline long kvm_hypercall0_intel(unsigned int nr)
- {
- long ret;
- asm volatile(KVM_HYPERCALL_INTEL
- : "=a"(ret)
- : "a"(nr));
- return ret;
- }
- static inline long kvm_hypercall0_amd(unsigned int nr)
- {
- long ret;
- asm volatile(KVM_HYPERCALL_AMD
- : "=a"(ret)
- : "a"(nr));
- return ret;
- }
- volatile unsigned long test_rip;
- #ifdef __x86_64__
- extern void gp_tss(void);
- asm ("gp_tss: \n\t"
- "add $8, %rsp\n\t" // discard error code
- "popq test_rip(%rip)\n\t" // pop return address
- "pushq %rsi\n\t" // new return address
- "iretq\n\t"
- "jmp gp_tss\n\t"
- );
- static inline int
- test_edge(void)
- {
- test_rip = 0;
- asm volatile ("movq $-1, %%rax\n\t" // prepare for vmcall
- "leaq 1f(%%rip), %%rsi\n\t" // save return address for gp_tss
- "movabsq $0x7ffffffffffd, %%rbx\n\t"
- "jmp *%%rbx; 1:" : : : "rax", "rbx", "rsi");
- printf("Return from int 13, test_rip = %lx\n", test_rip);
- return test_rip == (1ul << 47);
- }
- #endif
- int main(int ac, char **av)
- {
- kvm_hypercall0_intel(-1u);
- printf("Hypercall via VMCALL: OK\n");
- kvm_hypercall0_amd(-1u);
- printf("Hypercall via VMMCALL: OK\n");
- #ifdef __x86_64__
- setup_vm();
- setup_idt();
- setup_alt_stack();
- set_intr_alt_stack(13, gp_tss);
- u8 *data1 = alloc_page();
- u8 *topmost = (void *) ((1ul << 47) - PAGE_SIZE);
- install_pte(phys_to_virt(read_cr3()), 1, topmost,
- virt_to_phys(data1) | PT_PRESENT_MASK | PT_WRITABLE_MASK, 0);
- memset(topmost, 0xcc, PAGE_SIZE);
- topmost[4093] = 0x0f;
- topmost[4094] = 0x01;
- topmost[4095] = 0xc1;
- report("VMCALL on edge of canonical address space (intel)", test_edge());
- topmost[4095] = 0xd9;
- report("VMMCALL on edge of canonical address space (AMD)", test_edge());
- #endif
- return report_summary();
- }
|