aboutsummaryrefslogtreecommitdiffstats
path: root/executor/common_kvm_arm64.h
diff options
context:
space:
mode:
authorDmitry Vyukov <dvyukov@google.com>2017-01-12 11:57:17 +0100
committerDmitry Vyukov <dvyukov@google.com>2017-01-12 11:57:17 +0100
commitff8c0180ab432ad1bf8671407f828078cda86551 (patch)
treef2f6472e985c51cbf8125198cd562db715d69468 /executor/common_kvm_arm64.h
parentbcfae12bec951e6e4261a9910eab4b971f767329 (diff)
sys, executor: more kvm improvements
1. Basic support for arm64 kvm testing. 2. Fix compiler warnings in x86 kvm code. 3. Test all pseudo syz calls in csource. 4. Fix handling of real code in x86.
Diffstat (limited to 'executor/common_kvm_arm64.h')
-rw-r--r--executor/common_kvm_arm64.h84
1 files changed, 84 insertions, 0 deletions
diff --git a/executor/common_kvm_arm64.h b/executor/common_kvm_arm64.h
new file mode 100644
index 000000000..b3dadc87c
--- /dev/null
+++ b/executor/common_kvm_arm64.h
@@ -0,0 +1,84 @@
+// Copyright 2017 syzkaller project authors. All rights reserved.
+// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
+
+// This file is shared between executor and csource package.
+
+// Implementation of syz_kvm_setup_cpu pseudo-syscall.
+
+struct kvm_text {
+ uintptr_t typ;
+ const void* text;
+ uintptr_t size;
+};
+
+struct kvm_opt {
+ uint64_t typ;
+ uint64_t val;
+};
+
+// syz_kvm_setup_cpu(fd fd_kvmvm, cpufd fd_kvmcpu, usermem vma[24], text ptr[in, array[kvm_text, 1]], ntext len[text], flags flags[kvm_setup_flags], opts ptr[in, array[kvm_setup_opt, 0:2]], nopt len[opts])
+static uintptr_t syz_kvm_setup_cpu(uintptr_t a0, uintptr_t a1, uintptr_t a2, uintptr_t a3, uintptr_t a4, uintptr_t a5, uintptr_t a6, uintptr_t a7)
+{
+ const int vmfd = a0;
+ const int cpufd = a1;
+ char* const host_mem = (char*)a2;
+ const struct kvm_text* const text_array_ptr = (struct kvm_text*)a3;
+ const uintptr_t text_count = a4;
+ const uintptr_t flags = a5;
+ const struct kvm_opt* const opt_array_ptr = (struct kvm_opt*)a6;
+ uintptr_t opt_count = a7;
+
+ (void)flags;
+ (void)opt_count;
+
+ const uintptr_t page_size = 4 << 10;
+ const uintptr_t guest_mem = 0;
+ const uintptr_t guest_mem_size = 24 * page_size;
+
+ (void)text_count; // fuzzer can spoof count and we need just 1 text, so ignore text_count
+ int text_type = 0;
+ const void* text = 0;
+ int text_size = 0;
+ NONFAILING(text_type = text_array_ptr[0].typ);
+ NONFAILING(text = text_array_ptr[0].text);
+ NONFAILING(text_size = text_array_ptr[0].size);
+ (void)text_type;
+ (void)opt_array_ptr;
+
+ uint32_t features = 0;
+ if (opt_count > 1)
+ opt_count = 1;
+ uintptr_t i;
+ for (i = 0; i < opt_count; i++) {
+ uint64_t typ = 0;
+ uint64_t val = 0;
+ NONFAILING(typ = opt_array_ptr[i].typ);
+ NONFAILING(val = opt_array_ptr[i].val);
+ switch (typ) {
+ case 1:
+ features = val;
+ break;
+ }
+ }
+
+ for (i = 0; i < guest_mem_size / page_size; i++) {
+ struct kvm_userspace_memory_region memreg;
+ memreg.slot = i;
+ memreg.flags = 0; // can be KVM_MEM_LOG_DIRTY_PAGES | KVM_MEM_READONLY
+ memreg.guest_phys_addr = guest_mem + i * page_size;
+ memreg.memory_size = page_size;
+ memreg.userspace_addr = (uintptr_t)host_mem + i * page_size;
+ ioctl(vmfd, KVM_SET_USER_MEMORY_REGION, &memreg);
+ }
+
+ struct kvm_vcpu_init init;
+ ioctl(cpufd, KVM_ARM_PREFERRED_TARGET, &init);
+ init.features[0] = features;
+ ioctl(cpufd, KVM_ARM_VCPU_INIT, &init);
+
+ if (text_size > 1000)
+ text_size = 1000;
+ NONFAILING(memcpy(host_mem, text, text_size));
+
+ return 0;
+}