github.com/google/syzkaller@v0.0.0-20251211124644-a066d2bc4b02/sys/linux/dev_kvm_arm64.txt (about)

     1  # Copyright 2024 syzkaller project authors. All rights reserved.
     2  # Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
     3  
     4  # ARM64-specific KVM syscall declarations.
     5  
     6  meta arches["arm64"]
     7  
     8  include <linux/irqchip/arm-gic-v3.h>
     9  include <linux/kvm.h>
    10  include <linux/arm-smccc.h>
    11  include <uapi/linux/psci.h>
    12  include <asm/kvm.h>
    13  
    14  # kvm_syz_vm is a VM handler used by syzos-related pseudo-syscalls. It is actually an opaque pointer under the hood.
    15  resource kvm_syz_vm$arm64[int64]
    16  
    17  # Map the given memory into the VM and set up syzos there.
    18  syz_kvm_setup_syzos_vm$arm64(fd fd_kvmvm, usermem vma[1024]) kvm_syz_vm$arm64
    19  
    20  # Create a VCPU inside a kvm_syz_vm VM.
    21  # Prohibit flattening the input arguments, so that it is easier to reason about them.
    22  syz_kvm_add_vcpu$arm64(vm kvm_syz_vm$arm64, text ptr[in, kvm_text_arm64], opts ptr[in, array[kvm_setup_opt_arm64, 1]], nopt len[opts]) fd_kvmcpu (no_squash)
    23  
    24  kvm_num_irqs = 32, 64, 128, 256, 512
    25  
    26  # Set up the VGICv3 IRQ controller inside a VM.
    27  syz_kvm_vgic_v3_setup(fd fd_kvmvm, ncpus intptr[0:4], nirqs flags[kvm_num_irqs]) fd_kvmdev
    28  
    29  # Test assertions, will not be used by the fuzzer.
    30  syz_kvm_assert_syzos_uexit$arm64(run kvm_run_ptr, exitcode int64) (no_generate)
    31  syz_kvm_assert_reg(fd fd_kvmcpu, reg int64, value int64) (no_generate)
    32  syz_kvm_assert_syzos_kvm_exit$arm64(run kvm_run_ptr, exitcode int64) (no_generate)
    33  
    34  # Old-style way to set up a CPU inside a KVM VM.
    35  syz_kvm_setup_cpu$arm64(fd fd_kvmvm, cpufd fd_kvmcpu, usermem vma[1024], text ptr[in, array[kvm_text_arm64, 1]], ntext len[text], flags const[0], opts ptr[in, array[kvm_setup_opt_arm64, 1]], nopt len[opts])
    36  
    37  kvm_setup_opt_arm64 [
    38  # unions need at least 2 fields, but we have only 1 now, but we want to have it as union for future extention
    39  	featur1	kvm_setup_opt_feature
    40  	featur2	kvm_setup_opt_feature
    41  ]
    42  
    43  kvm_vcpu_target = KVM_ARM_TARGET_CORTEX_A53, KVM_ARM_TARGET_AEM_V8, KVM_ARM_TARGET_FOUNDATION_V8, KVM_ARM_TARGET_CORTEX_A57, KVM_ARM_TARGET_XGENE_POTENZA, KVM_ARM_TARGET_GENERIC_V8
    44  # `feature` is a set of feature bits: https://docs.kernel.org/virt/kvm/api.html#kvm-arm-vcpu-init
    45  kvm_vcpu_init {
    46  	target	flags[kvm_vcpu_target, int32]
    47  	feature	flags[kvm_vcpu_feature_bits_arm64, int32]
    48  	pad	array[const[0, int32], 6]
    49  }
    50  
    51  kvm_arm_counter_offset {
    52  	counter_offset	int64
    53  	reserved	int64
    54  }
    55  
    56  kvm_arm_device_addr {
    57  	id	int64
    58  	addr	flags[kvm_guest_addrs, int64]
    59  }
    60  
    61  kvm_guest_debug_arch_arm64 {
    62  	dbg_bcr	array[int64, 16]
    63  	dbg_bvr	array[int64, 16]
    64  	dbg_wcr	array[int64, 16]
    65  	dbg_wvr	array[int64, 16]
    66  }
    67  
    68  ioctl$KVM_SET_GUEST_DEBUG_arm64(fd fd_kvmcpu, cmd const[KVM_SET_GUEST_DEBUG], arg ptr[in, kvm_guest_debug[kvm_guest_debug_arch_arm64]])
    69  
    70  ioctl$KVM_ARM_VCPU_INIT(fd fd_kvmcpu, cmd const[KVM_ARM_VCPU_INIT], arg ptr[in, kvm_vcpu_init])
    71  ioctl$KVM_ARM_PREFERRED_TARGET(fd fd_kvmcpu, cmd const[KVM_ARM_PREFERRED_TARGET], arg ptr[out, kvm_vcpu_init])
    72  # KVM_ARM_VCPU_FINALIZE accepts a single CPU feature encoded as a bit number: https://docs.kernel.org/virt/kvm/api.html#kvm-arm-vcpu-finalize.
    73  ioctl$KVM_ARM_VCPU_FINALIZE(fd fd_kvmcpu, cmd const[KVM_ARM_VCPU_FINALIZE], arg ptr[in, flags[kvm_vcpu_features_arm64, int32]])
    74  ioctl$KVM_ARM_SET_DEVICE_ADDR(fd fd_kvmcpu, cmd const[KVM_ARM_SET_DEVICE_ADDR], arg ptr[in, kvm_arm_device_addr])
    75  ioctl$KVM_ARM_SET_COUNTER_OFFSET(fd fd_kvmvm, cmd const[KVM_ARM_SET_COUNTER_OFFSET], arg ptr[in, kvm_arm_counter_offset])
    76  
    77  # ARM-specific VM capabilities.
    78  ioctl$KVM_CAP_ARM_MTE(fd fd_kvmvm, cmd const[KVM_ENABLE_CAP], arg ptr[in, kvm_enable_cap[KVM_CAP_ARM_MTE, void]])
    79  ioctl$KVM_CAP_ARM_USER_IRQ(fd fd_kvmvm, cmd const[KVM_ENABLE_CAP], arg ptr[in, kvm_enable_cap[KVM_CAP_ARM_USER_IRQ, void]])
    80  ioctl$KVM_CAP_ARM_INJECT_SERROR_ESR(fd fd_kvmvm, cmd const[KVM_ENABLE_CAP], arg ptr[in, kvm_enable_cap[KVM_CAP_ARM_INJECT_SERROR_ESR, void]])
    81  ioctl$KVM_CAP_ARM_SYSTEM_SUSPEND(fd fd_kvmvm, cmd const[KVM_ENABLE_CAP], arg ptr[in, kvm_enable_cap[KVM_CAP_ARM_SYSTEM_SUSPEND, void]])
    82  ioctl$KVM_CAP_ARM_EAGER_SPLIT_CHUNK_SIZE(fd fd_kvmvm, cmd const[KVM_ENABLE_CAP], arg ptr[in, kvm_enable_cap[KVM_CAP_ARM_EAGER_SPLIT_CHUNK_SIZE, int64]])
    83  
    84  # syz_kvm_setup_cpu$arm64 takes the same feature bitmap as ioctl$KVM_ARM_VCPU_INIT.
    85  kvm_setup_opt_feature {
    86  	typ	const[1, int64]
    87  	val	flags[kvm_vcpu_feature_bits_arm64, int64]
    88  }
    89  
    90  # Some ioctls accept single CPU features as `bitnr`, whereas others take a set of `1 << bitnr`.
    91  define KVM_ARM_VCPU_POWER_OFF_BIT	(1 << KVM_ARM_VCPU_POWER_OFF)
    92  define KVM_ARM_VCPU_EL1_32BIT_BIT	(1 << KVM_ARM_VCPU_EL1_32BIT)
    93  define KVM_ARM_VCPU_PSCI_0_2_BIT	(1 << KVM_ARM_VCPU_PSCI_0_2)
    94  define KVM_ARM_VCPU_PMU_V3_BIT	(1 << KVM_ARM_VCPU_PMU_V3)
    95  define KVM_ARM_VCPU_PTRAUTH_ADDRESS_BIT	(1 << KVM_ARM_VCPU_PTRAUTH_ADDRESS)
    96  define KVM_ARM_VCPU_PTRAUTH_GENERIC_BIT	(1 << KVM_ARM_VCPU_PTRAUTH_GENERIC)
    97  define KVM_ARM_VCPU_SVE_BIT	(1 << KVM_ARM_VCPU_SVE)
    98  define KVM_ARM_VCPU_HAS_EL2_BIT	(1 << KVM_ARM_VCPU_HAS_EL2)
    99  kvm_vcpu_features_arm64 = KVM_ARM_VCPU_POWER_OFF, KVM_ARM_VCPU_EL1_32BIT, KVM_ARM_VCPU_PSCI_0_2, KVM_ARM_VCPU_PMU_V3, KVM_ARM_VCPU_PTRAUTH_ADDRESS, KVM_ARM_VCPU_PTRAUTH_GENERIC, KVM_ARM_VCPU_SVE, KVM_ARM_VCPU_HAS_EL2
   100  kvm_vcpu_feature_bits_arm64 = KVM_ARM_VCPU_POWER_OFF_BIT, KVM_ARM_VCPU_EL1_32BIT_BIT, KVM_ARM_VCPU_PSCI_0_2_BIT, KVM_ARM_VCPU_PMU_V3_BIT, KVM_ARM_VCPU_PTRAUTH_ADDRESS_BIT, KVM_ARM_VCPU_PTRAUTH_GENERIC_BIT, KVM_ARM_VCPU_SVE_BIT, KVM_ARM_VCPU_HAS_EL2_BIT
   101  
   102  # Unlike on other architectures, ARM64 text is a sequence of commands, each starting with
   103  # the call number and the command length.
   104  kvm_text_arm64 {
   105  	typ	const[0, intptr]
   106  	text	ptr[in, array[syzos_api_call, 1:32]]
   107  	size	bytesize[text, int64]
   108  }
   109  
   110  syzos_api_code {
   111  	insns	text[arm64]
   112  	ret	const[0xd65f03c0, int32]
   113  } [packed]
   114  
   115  syzos_api_mrs {
   116  	arg_reg	flags[kvm_regs_arm64_sys, int64]
   117  }
   118  
   119  syzos_api_msr {
   120  	arg_reg		flags[kvm_regs_arm64_sys, int64]
   121  	arg_value	int64
   122  }
   123  
   124  # Based on the "SMC Calling Convention" doc, https://documentation-service.arm.com/static/5f8edaeff86e16515cdbe4c6
   125  # Bit 31 is Standard (0) / Fast Call (1)
   126  # Bit 30 is SMC32 (0) / SMC64 (1)
   127  # Bits 29:24 denote the owning entity (relevant constants below are 0x01000000-0x3f000000
   128  # Bits 23:16 are ignored (must be zero in most cases)
   129  # Bits 15:0 denote the function number (0-0xffff) within the specified range, so we list all the possible bit values
   130  # here and hope that the fuzzer will be able to combine them into a number.
   131  #
   132  # Numeric constants are used to help the fuzzer construct arbitrary SMC function IDs.
   133  # We also include IDs from include/linux/arm-smccc.h here.
   134  kvm_smc_id = 0x80000000, 0x40000000, 0x1000000, 0x2000000, 0x3000000, 0x4000000, 0x5000000, 0x6000000, 0x30000000, 0x31000000, 0x32000000, 0x3f000000, 0x0, 0x1, 0x2, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80, 0x100, 0x200, 0x400, 0x800, 0x1000, 0x2000, 0x4000, 0x8000, 0xffff, ARM_SMCCC_VERSION_FUNC_ID, ARM_SMCCC_ARCH_FEATURES_FUNC_ID, ARM_SMCCC_ARCH_SOC_ID, ARM_SMCCC_ARCH_WORKAROUND_1, ARM_SMCCC_ARCH_WORKAROUND_2, ARM_SMCCC_ARCH_WORKAROUND_3, ARM_SMCCC_VENDOR_HYP_CALL_UID_FUNC_ID, ARM_SMCCC_VENDOR_HYP_KVM_FEATURES_FUNC_ID, ARM_SMCCC_VENDOR_HYP_KVM_PTP_FUNC_ID, ARM_SMCCC_HV_PV_TIME_FEATURES, ARM_SMCCC_HV_PV_TIME_ST, ARM_SMCCC_TRNG_VERSION, ARM_SMCCC_TRNG_FEATURES, ARM_SMCCC_TRNG_GET_UUID, ARM_SMCCC_TRNG_RND32, ARM_SMCCC_TRNG_RND64, PSCI_0_2_FN_PSCI_VERSION, PSCI_0_2_FN_CPU_SUSPEND, PSCI_0_2_FN_CPU_OFF, PSCI_0_2_FN_CPU_ON, PSCI_0_2_FN_AFFINITY_INFO, PSCI_0_2_FN_MIGRATE, PSCI_0_2_FN_MIGRATE_INFO_TYPE, PSCI_0_2_FN_MIGRATE_INFO_UP_CPU, PSCI_0_2_FN_SYSTEM_OFF, PSCI_0_2_FN_SYSTEM_RESET, PSCI_0_2_FN64_CPU_SUSPEND, PSCI_0_2_FN64_CPU_ON, PSCI_0_2_FN64_AFFINITY_INFO, PSCI_0_2_FN64_MIGRATE, PSCI_0_2_FN64_MIGRATE_INFO_UP_CPU, PSCI_1_0_FN_PSCI_FEATURES, PSCI_1_0_FN_CPU_FREEZE, PSCI_1_0_FN_CPU_DEFAULT_SUSPEND, PSCI_1_0_FN_NODE_HW_STATE, PSCI_1_0_FN_SYSTEM_SUSPEND, PSCI_1_0_FN_SET_SUSPEND_MODE, PSCI_1_0_FN_STAT_RESIDENCY, PSCI_1_0_FN_STAT_COUNT, PSCI_1_1_FN_SYSTEM_RESET2, PSCI_1_1_FN_MEM_PROTECT, PSCI_1_1_FN_MEM_PROTECT_CHECK_RANGE, PSCI_1_0_FN64_CPU_DEFAULT_SUSPEND, PSCI_1_0_FN64_NODE_HW_STATE, PSCI_1_0_FN64_SYSTEM_SUSPEND, PSCI_1_0_FN64_STAT_RESIDENCY, PSCI_1_0_FN64_STAT_COUNT, PSCI_1_1_FN64_SYSTEM_RESET2, PSCI_1_1_FN64_MEM_PROTECT_CHECK_RANGE
   135  
   136  syzos_api_smccc {
   137  	arg_id		flags[kvm_smc_id, int32]
   138  	arg_params	array[int64, 5]
   139  }
   140  
   141  syzos_api_irq_setup {
   142  	nr_cpus	int32[0:4]
   143  	nr_spis	int32[0:987]
   144  }
   145  
   146  syzos_memwrite_len = 1, 2, 4, 8
   147  
   148  syzos_api_memwrite [
   149  	generic		syzos_api_memwrite_generic
   150  	vgic_gicd	syzos_api_memwrite_vgic_gicd
   151  	vgic_gicr	syzos_api_memwrite_vgic_gicr
   152  	vgic_gits	syzos_api_memwrite_vgic_gits
   153  ]
   154  
   155  syzos_api_memwrite_generic {
   156  	base	flags[kvm_guest_addrs, int64]
   157  	offset	int64[0:4096]
   158  	value	int64
   159  	len	flags[syzos_memwrite_len, int64]
   160  }
   161  
   162  syzos_api_its_setup {
   163  	nr_cpus		int64[0:4]
   164  	nr_devices	int64[0:4]
   165  	nr_ints		int64[0:1024]
   166  }
   167  
   168  kvm_vgic_gicr_regs = GICR_CTLR, GICR_IIDR, GICR_TYPER, GICR_STATUSR, GICR_WAKER, GICR_SETLPIR, GICR_CLRLPIR, GICR_PROPBASER, GICR_PENDBASER, GICR_INVLPIR, GICR_INVALLR, GICR_SYNCR, GICR_IDREGS, GICR_PIDR2, GICR_IGROUPR0, GICR_ISENABLER0, GICR_ICENABLER0, GICR_ISPENDR0, GICR_ICPENDR0, GICR_ISACTIVER0, GICR_ICACTIVER0, GICR_IPRIORITYR0, GICR_ICFGR0, GICR_IGRPMODR0, GICR_NSACR
   169  
   170  # 0x080a0000 is ARM64_ADDR_GICR_BASE from executor/kvm.h, 0x20000 is redistributor size. We assume the maximum number of VCPUs is 4.
   171  syzos_api_memwrite_vgic_gicr {
   172  	base	int64[0x80a0000:0x8100000, 0x20000]
   173  	offset	flags[kvm_vgic_gicr_regs, int64]
   174  	value	int64
   175  	len	flags[syzos_memwrite_len, int64]
   176  }
   177  
   178  gits_commands = GITS_CMD_MAPD, GITS_CMD_MAPC, GITS_CMD_MAPTI, GITS_CMD_MAPI, GITS_CMD_MOVI, GITS_CMD_DISCARD, GITS_CMD_INV, GITS_CMD_MOVALL, GITS_CMD_INVALL, GITS_CMD_INT, GITS_CMD_CLEAR, GITS_CMD_SYNC
   179  
   180  syzos_api_its_send_cmd {
   181  	type	flags[gits_commands, int8]
   182  	valid	int8[0:1]
   183  	cpuid	int32[0:4]
   184  	devid	int32[0:16]
   185  	eventid	int32
   186  	intid	int32
   187  	cpuid2	int32[0:4]
   188  } [packed]
   189  
   190  kvm_vgic_gicd_regs = GICD_CTLR, GICD_TYPER, GICD_IIDR, GICD_TYPER2, GICD_STATUSR, GICD_SETSPI_NSR, GICD_CLRSPI_NSR, GICD_SETSPI_SR, GICD_CLRSPI_SR, GICD_IGROUPR, GICD_ISENABLER, GICD_ICENABLER, GICD_ISPENDR, GICD_ICPENDR, GICD_ISACTIVER, GICD_ICACTIVER, GICD_IPRIORITYR, GICD_ICFGR, GICD_IGRPMODR, GICD_NSACR, GICD_IGROUPRnE, GICD_ISENABLERnE, GICD_ICENABLERnE, GICD_ISPENDRnE, GICD_ICPENDRnE, GICD_ISACTIVERnE, GICD_ICACTIVERnE, GICD_IPRIORITYRnE, GICD_ICFGRnE, GICD_IROUTER, GICD_IROUTERnE, GICD_IDREGS, GICD_PIDR2, GICD_ITARGETSR, GICD_SGIR, GICD_CPENDSGIR, GICD_SPENDSGIR
   191  
   192  # 0x08000000 is ARM64_ADDR_GICD_BASE from executor/kvm.h
   193  syzos_api_memwrite_vgic_gicd {
   194  	base	const[0x8000000, int64]
   195  	offset	flags[kvm_vgic_gicd_regs, int64]
   196  	value	int64
   197  	len	flags[syzos_memwrite_len, int64]
   198  }
   199  
   200  kvm_vgic_gits_regs = GITS_CTLR, GITS_IIDR, GITS_TYPER, GITS_MPIDR, GITS_CBASER, GITS_CWRITER, GITS_CREADR, GITS_BASER, GITS_IDREGS_BASE, GITS_PIDR0, GITS_PIDR1, GITS_PIDR2, GITS_PIDR4, GITS_CIDR0, GITS_CIDR1, GITS_CIDR2, GITS_CIDR3, GITS_TRANSLATER, GITS_SGIR
   201  
   202  # 0x08080000 is ARM64_ADDR_GITS_BASE from executor/kvm.h
   203  syzos_api_memwrite_vgic_gits {
   204  	base	const[0x8080000, int64]
   205  	offset	flags[kvm_vgic_gits_regs, int64]
   206  	value	int64
   207  	len	flags[syzos_memwrite_len, int64]
   208  }
   209  
   210  type syzos_api[NUM, PAYLOAD] {
   211  	call	const[NUM, int64]
   212  	size	bytesize[parent, int64]
   213  	payload	PAYLOAD
   214  }
   215  
   216  syzos_api_call [
   217  	uexit		syzos_api[0, intptr]
   218  	code		syzos_api[10, syzos_api_code]
   219  	msr		syzos_api[20, syzos_api_msr]
   220  	smc		syzos_api[30, syzos_api_smccc]
   221  	hvc		syzos_api[50, syzos_api_smccc]
   222  	irq_setup	syzos_api[70, syzos_api_irq_setup]
   223  	memwrite	syzos_api[110, syzos_api_memwrite]
   224  	its_setup	syzos_api[130, syzos_api_its_setup]
   225  	its_send_cmd	syzos_api[170, syzos_api_its_send_cmd]
   226  	mrs		syzos_api[190, syzos_api_mrs]
   227  	eret		syzos_api[230, intptr]
   228  	svc		syzos_api[290, syzos_api_smccc]
   229  ] [varlen]