Created
October 30, 2020 09:49
-
-
Save sandip4n/de38af02b253e5034e26d05e4c4381c4 to your computer and use it in GitHub Desktop.
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
#ifndef __powerpc64__ | |
#error "unsupported architecture" | |
#endif | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <string.h> | |
#include <errno.h> | |
#include <fcntl.h> | |
#include <assert.h> | |
#include <unistd.h> | |
#include <sys/mman.h> | |
#include <sys/stat.h> | |
#include <sys/ioctl.h> | |
#include <sys/types.h> | |
#include <linux/kvm.h> | |
int main(int argc, char **argv) | |
{ | |
struct kvm_userspace_memory_region vmmreg; | |
int kvmfd, vmfd, vcpufd, ret, i; | |
unsigned long pgsize, vcpumsize; | |
struct kvm_sregs vmsregs; | |
struct kvm_regs vmregs; | |
struct kvm_run *vmrun; | |
void *vmmem; | |
kvmfd = open("/dev/kvm", O_RDWR | O_CLOEXEC); | |
if (kvmfd < 0) { | |
fprintf(stderr, "%s:%d: open() failed: %s\n", | |
__FILE__, __LINE__, strerror(errno)); | |
return EXIT_FAILURE; | |
} | |
ret = ioctl(kvmfd, KVM_GET_API_VERSION, NULL); | |
if (ret < 0) { | |
fprintf(stderr, "%s:%d: ioctl() failed: %s\n", | |
__FILE__, __LINE__, strerror(errno)); | |
} | |
printf("kvm version = %d\n", ret); | |
ret = ioctl(kvmfd, KVM_CHECK_EXTENSION, KVM_CAP_USER_MEMORY); | |
if (ret < 0) { | |
fprintf(stderr, "%s:%d: ioctl() failed: %s\n", | |
__FILE__, __LINE__, strerror(errno)); | |
} | |
printf("kvm user memory capability = %s\n", ret ? "yes" : "no"); | |
vmfd = ioctl(kvmfd, KVM_CREATE_VM, KVM_VM_PPC_HV); | |
if (vmfd < 0) { | |
fprintf(stderr, "%s:%d: ioctl() failed: %s\n", | |
__FILE__, __LINE__, strerror(errno)); | |
} | |
pgsize = sysconf(_SC_PAGESIZE); | |
vmmem = mmap(NULL, pgsize, PROT_READ | PROT_WRITE | PROT_EXEC, | |
MAP_SHARED | MAP_ANONYMOUS, -1, 0); | |
if (vmmem < 0) { | |
fprintf(stderr, "%s:%d: mmap() failed: %s\n", | |
__FILE__, __LINE__, strerror(errno)); | |
} | |
for (i = 0; i < pgsize / sizeof(unsigned int); i++) | |
((unsigned int *) vmmem)[i] = 0x60000000; | |
((unsigned int *) vmmem)[0] = 0x48000000; /* b 0x0 */ | |
memset(&vmmreg, 0, sizeof(struct kvm_userspace_memory_region)); | |
vmmreg.slot = 0; | |
vmmreg.guest_phys_addr = 0x0; | |
vmmreg.memory_size = pgsize; | |
vmmreg.userspace_addr = (unsigned long) vmmem; | |
vmmreg.flags = 0; | |
ret = ioctl(vmfd, KVM_SET_USER_MEMORY_REGION, &vmmreg); | |
if (ret < 0) { | |
fprintf(stderr, "%s:%d: ioctl() failed: %s\n", | |
__FILE__, __LINE__, strerror(errno)); | |
} | |
vcpufd = ioctl(vmfd, KVM_CREATE_VCPU, 0UL); | |
if (vcpufd < 0) { | |
fprintf(stderr, "%s:%d: ioctl() failed: %s\n", | |
__FILE__, __LINE__, strerror(errno)); | |
} | |
ret = ioctl(kvmfd, KVM_GET_VCPU_MMAP_SIZE, NULL); | |
if (ret < 0) { | |
fprintf(stderr, "%s:%d: ioctl() failed: %s\n", | |
__FILE__, __LINE__, strerror(errno)); | |
} | |
vcpumsize = ret; | |
vmrun = mmap(NULL, vcpumsize, PROT_READ | PROT_WRITE, MAP_SHARED, | |
vcpufd, 0); | |
if (vmmem < 0) { | |
fprintf(stderr, "%s:%d: mmap() failed: %s\n", | |
__FILE__, __LINE__, strerror(errno)); | |
} | |
ret = ioctl(vcpufd, KVM_GET_SREGS, &vmsregs); | |
if (ret < 0) { | |
fprintf(stderr, "%s:%d: ioctl() failed: %s\n", | |
__FILE__, __LINE__, strerror(errno)); | |
} | |
// ret = ioctl(vcpufd, KVM_SET_SREGS, &vmsregs); | |
// if (ret < 0) { | |
// fprintf(stderr, "%s:%d: ioctl() failed: %s\n", | |
// __FILE__, __LINE__, strerror(errno)); | |
// } | |
ret = ioctl(vcpufd, KVM_GET_REGS, &vmregs); | |
if (ret < 0) { | |
fprintf(stderr, "%s:%d: ioctl() failed: %s\n", | |
__FILE__, __LINE__, strerror(errno)); | |
} | |
memset(&vmregs, 0, sizeof(struct kvm_regs)); | |
vmregs.msr = (1UL << 63) | (1UL << 60) | (1UL << 0); | |
vmregs.gpr[14] = 0xdead; | |
vmregs.gpr[15] = 0xbeef; | |
vmregs.gpr[16] = 0x0; | |
vmregs.pc = 0x0; | |
printf("kvm pvr = 0x%08x\n", vmsregs.pvr); | |
printf("kvm msr = 0x%016lx\n", vmregs.msr); | |
ret = ioctl(vcpufd, KVM_SET_REGS, &vmregs); | |
if (ret < 0) { | |
fprintf(stderr, "%s:%d: ioctl() failed: %s\n", | |
__FILE__, __LINE__, strerror(errno)); | |
} | |
do { | |
ret = ioctl(vcpufd, KVM_RUN, NULL); | |
if (ret < 0) | |
fprintf(stderr, "%s:%d: ioctl() failed: %s\n", | |
__FILE__, __LINE__, strerror(errno)); | |
} while (ret == -1 && errno == EINTR); | |
switch (vmrun->exit_reason) { | |
case KVM_EXIT_HLT: | |
printf("kvm exited with KVM_EXIT_HLT\n"); | |
break; | |
case KVM_EXIT_FAIL_ENTRY: | |
printf("kvm exited with KVM_EXIT_FAIL_ENTRY\n" | |
"hardware-entry-failure-reason = 0x%lx\n", | |
vmrun->fail_entry.hardware_entry_failure_reason); | |
break; | |
case KVM_EXIT_INTERNAL_ERROR: | |
printf("kvm exited with KVM_EXIT_INTERNAL_ERROR\n" | |
"suberror = 0x%x, ndata = %u\n", | |
vmrun->internal.suberror, vmrun->internal.ndata); | |
break; | |
default: | |
printf("kvm exited with code %d\n", vmrun->exit_reason); | |
} | |
ret = ioctl(vcpufd, KVM_GET_REGS, &vmregs); | |
if (ret < 0) { | |
fprintf(stderr, "%s:%d: ioctl() failed: %s\n", | |
__FILE__, __LINE__, strerror(errno)); | |
} | |
printf("kvm regs gpr[14] = 0x%016lx\n", vmregs.gpr[14]); | |
printf("kvm regs gpr[15] = 0x%016lx\n", vmregs.gpr[15]); | |
printf("kvm regs gpr[16] = 0x%016lx\n", vmregs.gpr[16]); | |
printf("kvm regs pc = 0x%016lx\n", vmregs.pc); | |
munmap(vmrun, vcpumsize); | |
munmap(vmmem, pgsize); | |
close(vcpufd); | |
close(kvmfd); | |
return EXIT_SUCCESS; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment