Skip to content

Instantly share code, notes, and snippets.

@ryo
Created March 2, 2023 20:25
Show Gist options
  • Save ryo/b0432eaf86de7fad1be13ad16aa5bf1f to your computer and use it in GitHub Desktop.
Save ryo/b0432eaf86de7fad1be13ad16aa5bf1f to your computer and use it in GitHub Desktop.
nvmm sample
#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