aboutsummaryrefslogtreecommitdiffstats
path: root/executor
diff options
context:
space:
mode:
authorAlexander Potapenko <glider@google.com>2024-08-08 17:12:18 +0200
committerAlexander Potapenko <glider@google.com>2024-09-03 12:16:36 +0000
commit89418520e59f2957dbb192c9db4eb45f108459a4 (patch)
tree1704e0524bcf12e712d793d6624a497864eaecdc /executor
parentbe562dffcc62a7644ab55833c9650774fb462ebe (diff)
executor: pkg/vminfo: sys/linux: define syz_kvm_vgic_v3_setup
The new pseudo-syscall sets up VGICv3 IRQ controller on the host. That still requires guest setup code, which will be submitted separately.
Diffstat (limited to 'executor')
-rw-r--r--executor/common_kvm_arm64.h80
-rw-r--r--executor/common_linux.h10
-rw-r--r--executor/kvm.h3
3 files changed, 90 insertions, 3 deletions
diff --git a/executor/common_kvm_arm64.h b/executor/common_kvm_arm64.h
index a4fe7c57a..94f0ac9cb 100644
--- a/executor/common_kvm_arm64.h
+++ b/executor/common_kvm_arm64.h
@@ -5,14 +5,16 @@
// Implementation of syz_kvm_setup_cpu pseudo-syscall.
-#include "common_kvm_arm64_syzos.h"
#include "kvm.h"
+#if SYZ_EXECUTOR || __NR_syz_kvm_setup_cpu
+
// Register encodings from https://docs.kernel.org/virt/kvm/api.html.
#define KVM_ARM64_REGS_X0 0x6030000000100000UL
#define KVM_ARM64_REGS_PC 0x6030000000100040UL
#define KVM_ARM64_REGS_SP_EL1 0x6030000000100044UL
+#include "common_kvm_arm64_syzos.h"
struct kvm_text {
uintptr_t typ;
const void* text;
@@ -149,3 +151,79 @@ static volatile long syz_kvm_setup_cpu(volatile long a0, volatile long a1, volat
return 0;
}
+#endif
+
+#if SYZ_EXECUTOR || __NR_syz_kvm_vgic_v3_setup
+static int kvm_set_device_attr(int dev_fd, uint32 group, uint64 attr, void* val)
+{
+ struct kvm_device_attr kvmattr = {
+ .flags = 0,
+ .group = group,
+ .attr = attr,
+ .addr = (uintptr_t)val,
+ };
+
+ return ioctl(dev_fd, KVM_SET_DEVICE_ATTR, &kvmattr);
+}
+
+static int kvm_create_device(int vm_fd, int type)
+{
+ struct kvm_create_device create_dev = {
+ .type = (uint32)type,
+ .fd = (uint32)-1,
+ .flags = 0,
+ };
+
+ if (ioctl(vm_fd, KVM_CREATE_DEVICE, &create_dev) != -1)
+ return create_dev.fd;
+ else
+ return -1;
+}
+
+#define REDIST_REGION_ATTR_ADDR(count, base, flags, index) \
+ (((uint64)(count) << 52) | \
+ ((uint64)((base) >> 16) << 16) | \
+ ((uint64)(flags) << 12) | \
+ index)
+
+// Set up the VGICv3 interrupt controller.
+// syz_kvm_vgic_v3_setup(fd fd_kvmvm, ncpus flags[kvm_num_cpus], nirqs flags[kvm_num_irqs])
+static long syz_kvm_vgic_v3_setup(volatile long a0, volatile long a1, volatile long a2)
+{
+ const int vm_fd = a0;
+ const int nr_vcpus = a1;
+ const int want_nr_irq = a2;
+
+ int vgic_fd = kvm_create_device(vm_fd, KVM_DEV_TYPE_ARM_VGIC_V3);
+ if (vgic_fd == -1)
+ return -1;
+
+ uint32 nr_irq = want_nr_irq;
+ int ret = kvm_set_device_attr(vgic_fd, KVM_DEV_ARM_VGIC_GRP_NR_IRQS, 0, &nr_irq);
+ if (ret == -1) {
+ close(vgic_fd);
+ return -1;
+ }
+
+ uint64 gicd_base_gpa = ARM64_ADDR_GICD_BASE;
+ ret = kvm_set_device_attr(vgic_fd, KVM_DEV_ARM_VGIC_GRP_ADDR, KVM_VGIC_V3_ADDR_TYPE_DIST, &gicd_base_gpa);
+ if (ret == -1) {
+ close(vgic_fd);
+ return -1;
+ }
+ uint64 redist_attr = REDIST_REGION_ATTR_ADDR(nr_vcpus, ARM64_ADDR_GICR_BASE, 0, 0);
+ ret = kvm_set_device_attr(vgic_fd, KVM_DEV_ARM_VGIC_GRP_ADDR, KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION, &redist_attr);
+ if (ret == -1) {
+ close(vgic_fd);
+ return -1;
+ }
+
+ ret = kvm_set_device_attr(vgic_fd, KVM_DEV_ARM_VGIC_GRP_CTRL, KVM_DEV_ARM_VGIC_CTRL_INIT, NULL);
+ if (ret == -1) {
+ close(vgic_fd);
+ return -1;
+ }
+
+ return vgic_fd;
+}
+#endif
diff --git a/executor/common_linux.h b/executor/common_linux.h
index 3669dee0f..9e7d9717d 100644
--- a/executor/common_linux.h
+++ b/executor/common_linux.h
@@ -3173,7 +3173,7 @@ error_clear_loop:
}
#endif
-#if SYZ_EXECUTOR || __NR_syz_kvm_setup_cpu
+#if SYZ_EXECUTOR || __NR_syz_kvm_setup_cpu || __NR_syz_kvm_vgic_v3_setup
// KVM is not yet supported on RISC-V
#if !GOARCH_riscv64 && !GOARCH_arm
#include <errno.h>
@@ -3190,12 +3190,18 @@ error_clear_loop:
#include "common_kvm_arm64.h"
#elif GOARCH_ppc64 || GOARCH_ppc64le
#include "common_kvm_ppc64.h"
-#elif !GOARCH_arm
+#elif !GOARCH_arm && (SYZ_EXECUTOR || __NR_syz_kvm_setup_cpu)
static volatile long syz_kvm_setup_cpu(volatile long a0, volatile long a1, volatile long a2, volatile long a3, volatile long a4, volatile long a5, volatile long a6, volatile long a7)
{
return 0;
}
#endif
+#if !GOARCH_arm64 && (SYZ_EXECUTOR || __NR_syz_kvm_vgic_v3_setup)
+static long syz_kvm_vgic_v3_setup(volatile long a0, volatile long a1, volatile long a2)
+{
+ return 0;
+}
+#endif
#endif
#endif
diff --git a/executor/kvm.h b/executor/kvm.h
index a66aa6727..32fda309d 100644
--- a/executor/kvm.h
+++ b/executor/kvm.h
@@ -76,6 +76,9 @@
#define NEXT_INSN $0xbadc0de
#define PREFIX_SIZE 0xba1d
+// GICv3 distributor/redistributor addresses.
+#define ARM64_ADDR_GICD_BASE 0x08000000
+#define ARM64_ADDR_GICR_BASE 0x080A0000
// Write to this page to trigger a page fault and stop KVM_RUN.
#define ARM64_ADDR_EXIT 0xdddd0000
// Dedicated address within the exit page for the uexit command.