hv_demo.m 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162
  1. @import Darwin;
  2. #include <Hypervisor/Hypervisor.h>
  3. const char kVMCode[] = {
  4. // Compute ((2 + 2) - 1)
  5. 0x40, 0x00, 0x80, 0xD2, // mov x0, #2
  6. 0x00, 0x08, 0x00, 0x91, // add x0, x0, #2
  7. 0x00, 0x04, 0x00, 0xD1, // sub x0, x0, #1
  8. // Write it to memory pointed by x1
  9. 0x20, 0x00, 0x00, 0xF9, // str x0, [x1]
  10. // Reboot the computer with PSCI/SMCCC
  11. // 0x84000009 is PSCI SYSTEM_RESET using SMC32 calling convention
  12. 0x20, 0x01, 0x80, 0xd2, // mov x0, 0x0009
  13. 0x00, 0x80, 0xb0, 0xf2, // movk x0, 0x8400, lsl #16
  14. 0x02, 0x00, 0x00, 0xD4, // hvc #0
  15. // Infinite loop
  16. 0x00, 0x00, 0x00, 0x14, // b .
  17. };
  18. int main() {
  19. // https://github.com/zhuowei/FakeHVF/blob/main/simplevm.c
  20. // https://gist.github.com/imbushuo/51b09e61ecd7b7ac063853ad65cedf34
  21. // allocate 1MB of RAM, aligned to page size, for the VM
  22. const uint64_t kMemSize = 0x100000;
  23. const uint64_t kMemStart = 0x69420000;
  24. const uint64_t kMemResultOutOffset = 0x100;
  25. const uint64_t kMemGuestResultOut = kMemStart + kMemResultOutOffset;
  26. char* vm_ram = mmap(NULL, kMemSize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
  27. if (vm_ram == MAP_FAILED) {
  28. abort();
  29. }
  30. // copy our code into the VM's RAM
  31. memcpy(vm_ram, kVMCode, sizeof(kVMCode));
  32. hv_return_t err = hv_vm_create(nil);
  33. printf("vm create %x\n", err);
  34. err = hv_vm_map(vm_ram, kMemStart, kMemSize, HV_MEMORY_READ | HV_MEMORY_WRITE | HV_MEMORY_EXEC);
  35. printf("hv_vm_map %x\n", err);
  36. hv_vcpu_t vcpu = 0;
  37. hv_vcpu_exit_t* exit = nil;
  38. err = hv_vcpu_create(&vcpu, &exit, nil);
  39. printf("vcpu create %x\n", err);
  40. // Set the CPU's PC to execute code from our RAM
  41. err = hv_vcpu_set_reg(vcpu, HV_REG_PC, kMemStart);
  42. printf("vcpu set reg pc %x\n", err);
  43. // Set CPU's x1 register to point to where we want to read the result
  44. err = hv_vcpu_set_reg(vcpu, HV_REG_X1, kMemGuestResultOut);
  45. printf("vcpu set reg x1 %x\n", err);
  46. // Set CPU's CPSR to EL1
  47. err = hv_vcpu_set_reg(vcpu, HV_REG_CPSR, 0x3c4);
  48. printf("vcpu set reg cpsr %x\n", err);
  49. err = hv_vcpu_run(vcpu);
  50. printf("run %x\n", err);
  51. uint64_t result_out = *((uint64_t*)(vm_ram + kMemResultOutOffset));
  52. printf("The result of (2 + 2) - 1 is %d\n", (int)result_out);
  53. }