From da1bf45572b76900e3219f2c2c08942d655bfe4c Mon Sep 17 00:00:00 2001 From: Lauri Kasanen Date: Thu, 27 May 2021 15:05:38 +0300 Subject: [PATCH] Start on kvm side --- main.c | 78 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 77 insertions(+), 1 deletion(-) diff --git a/main.c b/main.c index daa48ee..8550e4e 100644 --- a/main.c +++ b/main.c @@ -16,6 +16,7 @@ #define _GNU_SOURCE +#include #include #include #include @@ -25,11 +26,14 @@ #include #include #include +#include #include #include #include #define MAXDUMPS 10 +#define RAMSIZE (64 * 1024 * 1024) +#define PROGSTART 0x20000000 static void nukenewline(char buf[]) { unsigned i; @@ -184,10 +188,15 @@ int main(int argc, char **argv) { }; const char opts[] = "i:g:f:s:l:d:t:h"; - int kvm; + struct kvm_run *run; + struct kvm_regs regs; + struct kvm_sregs sregs; + int kvm, vmfd, vcpu; FILE *binary = NULL, *trace = NULL; char dumps[MAXDUMPS][PATH_MAX]; unsigned num_dumps = 0; + uint8_t *ram, *progmem; + const char *binpath; while (1) { const int c = getopt_long(argc, argv, opts, longopts, NULL); @@ -206,6 +215,8 @@ int main(int argc, char **argv) { printf("Failed to open %s\n", optarg); return 1; } + + binpath = strdup(optarg); break; case 'g': parseregs(optarg, 1); @@ -252,12 +263,24 @@ int main(int argc, char **argv) { help(argv[0]); } + // Yes, we're frugal + if (posix_memalign(&ram, 64 * 1024, RAMSIZE)) + abort(); + memset(ram, 0, RAMSIZE); + fseek(binary, 0, SEEK_END); const unsigned binlen = ftell(binary); rewind(binary); printf("Loading binary %u bytes\n", binlen); // TODO + if (posix_memalign(&progmem, 64 * 1024, binlen)) + abort(); + + if (fread(progmem, binlen, 1, binary) != 1) + abort(); + fclose(binary); + kvm = open("/dev/kvm", O_RDWR | O_CLOEXEC); if (kvm < 0) { printf("Failed to open kvm, perhaps you lack permissions?\n"); @@ -268,6 +291,59 @@ int main(int argc, char **argv) { ret = ioctl(kvm, KVM_GET_API_VERSION, NULL); if (ret == -1 || ret != 12) abort(); + ret = ioctl(kvm, KVM_CHECK_EXTENSION, KVM_CAP_PPC_GUEST_DEBUG_SSTEP); + if (ret == -1 || !ret) { + printf("This system lacks single-stepping!\n"); + return 1; + } + + vmfd = ioctl(kvm, KVM_CREATE_VM, (unsigned long)0); + + struct kvm_userspace_memory_region region = { + .slot = 0, + .guest_phys_addr = 0, + .memory_size = RAMSIZE, + .userspace_addr = ram, + .flags = 0 + }; + ioctl(vmfd, KVM_SET_USER_MEMORY_REGION, ®ion); + + region.slot = 1; + region.guest_phys_addr = PROGSTART; + region.memory_size = binlen; + region.userspace_addr = progmem; + region.flags = KVM_MEM_READONLY; + ioctl(vmfd, KVM_SET_USER_MEMORY_REGION, ®ion); + + vcpu = ioctl(vmfd, KVM_CREATE_VCPU, (unsigned long)0); + const unsigned vcpulen = ioctl(kvm, KVM_GET_VCPU_MMAP_SIZE, NULL); + + run = mmap(NULL, vcpulen, PROT_READ | PROT_WRITE, MAP_SHARED, vcpu, 0); + + if (ioctl(vcpu, KVM_GET_SREGS, &sregs) == -1) + abort(); + if (ioctl(vcpu, KVM_SET_SREGS, &sregs) == -1) + abort(); + + if (ioctl(vcpu, KVM_SET_REGS, ®s) == -1) + abort(); + + const struct kvm_guest_debug dbg = { + .control = KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_SINGLESTEP; + }; + if (ioctl(vcpu, KVM_SET_GUEST_DEBUG, &dbg) == -1) + abort(); + + // Runtime + while (1) { + if (ioctl(vcpu, KVM_RUN, NULL) == -1) + abort(); + printf("Exited because %u\n", run->exit_reason); + } + close(kvm); + free(progmem); + free(ram); + free((char *) binpath); return 0; } -- 2.30.2