Created
March 2, 2023 20:25
-
-
Save ryo/b0432eaf86de7fad1be13ad16aa5bf1f to your computer and use it in GitHub Desktop.
nvmm sample
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdlib.h> | |
#include <stdio.h> | |
#include <string.h> | |
#include <unistd.h> | |
#include <err.h> | |
#include <fcntl.h> | |
#include <sys/mman.h> | |
#include <nvmm.h> | |
#define PAGE_SIZE getpagesize() | |
int main(int argc, char *argv[]) | |
{ | |
const uint32_t instr[] = { | |
0x8b010002, /* add x2, x0, x1 */ | |
0x8b010003, /* add x3, x0, x1 */ | |
0x8b010004, /* add x4, x0, x1 */ | |
0x8b010005, /* add x5, x0, x1 */ | |
0x8b010006, /* add x6, x0, x1 */ | |
0x8b010007, /* add x7, x0, x1 */ | |
0xd5384240, /* mrs x0, currentel */ | |
0xd503207f, /* wfi */ | |
}; | |
struct nvmm_machine mach; | |
struct nvmm_vcpu vcpu; | |
uintptr_t hva; | |
gpaddr_t gpa = 0; | |
unsigned long num1, num2; | |
if (argc != 3) | |
errx(EXIT_FAILURE, "wrong arguments"); | |
num1 = strtoul(argv[1], NULL, 0); | |
num2 = strtoul(argv[2], NULL, 0); | |
printf("num1=0x%lx, num2=0x%lx\n", num1, num2); | |
/* Init NVMM. */ | |
if (nvmm_init() == -1) | |
err(EXIT_FAILURE, "unable to init NVMM"); | |
/* Create the VM. */ | |
if (nvmm_machine_create(&mach) == -1) | |
err(EXIT_FAILURE, "unable to create the VM"); | |
nvmm_vcpu_create(&mach, 0, &vcpu); | |
/* Allocate a HVA. The HVA is writable. */ | |
hva = (uintptr_t)mmap(NULL, PAGE_SIZE * 1024, PROT_READ|PROT_WRITE, | |
MAP_ANON|MAP_PRIVATE, -1, 0); | |
nvmm_hva_map(&mach, hva, PAGE_SIZE * 1024); | |
/* Link the GPA towards the HVA. The GPA is executable. */ | |
nvmm_gpa_map(&mach, hva, gpa, PAGE_SIZE * 1024, PROT_READ|PROT_EXEC); | |
/* Install the guest instructions there. */ | |
memcpy((void *)hva, instr, sizeof(instr)); | |
/* Reset the instruction pointer, and set EAX/EBX. */ | |
nvmm_vcpu_getstate(&mach, &vcpu, NVMM_AARCH64_STATE_ALL); | |
vcpu.state->gprs[NVMM_AARCH64_GPR_X0] = num1; | |
vcpu.state->gprs[NVMM_AARCH64_GPR_X1] = num2; | |
vcpu.state->sprs[NVMM_AARCH64_SPR_PC] = 0; | |
vcpu.state->sprs[NVMM_AARCH64_SPR_SPSR_EL1] = 0x5; /* EL1H */ | |
nvmm_vcpu_setstate(&mach, &vcpu, NVMM_AARCH64_STATE_ALL); | |
while (1) { | |
/* Run VCPU0. */ | |
nvmm_vcpu_run(&mach, &vcpu); | |
/* Process the exit reasons. */ | |
switch (vcpu.exit->reason) { | |
case NVMM_VCPU_EXIT_NONE: | |
/* Nothing to do, keep rolling. */ | |
break; | |
case NVMM_VCPU_EXIT_HALTED: | |
/* Our shutdown point. Fetch the result. */ | |
nvmm_vcpu_getstate(&mach, &vcpu, NVMM_AARCH64_STATE_GPRS); | |
for (int x = 0; x < 32; x++) { | |
uint64_t val = vcpu.state->gprs[NVMM_AARCH64_GPR_X0 + x]; | |
if (val == 0) | |
continue; | |
printf("%sx%d: %016lx\n", (x < 10) ? " " : "", x, val); | |
} | |
return 0; | |
/* THE PROCESS EXITS, THE VM GETS DESTROYED. */ | |
default: | |
errx(EXIT_FAILURE, "unknown exit reason"); | |
} | |
} | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment