hypercall.c 1.9 KB

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