diff --git a/executor/common_kvm_arm64_syzos.h b/executor/common_kvm_arm64_syzos.h index 65bbf192b748..24f349d9f1ec 100644 --- a/executor/common_kvm_arm64_syzos.h +++ b/executor/common_kvm_arm64_syzos.h @@ -28,6 +28,7 @@ typedef enum { SYZOS_API_MEMWRITE, SYZOS_API_ITS_SETUP, SYZOS_API_ITS_SEND_CMD, + SYZOS_API_WFI_WFE, SYZOS_API_STOP, // Must be the last one } syzos_api_id; @@ -41,6 +42,11 @@ struct api_call_uexit { uint64 exit_code; }; +struct api_call_1 { + struct api_call_header header; + uint64 arg; +}; + struct api_call_2 { struct api_call_header header; uint64 args[2]; @@ -96,6 +102,7 @@ static void guest_handle_irq_setup(struct api_call_irq_setup* cmd); static void guest_handle_memwrite(struct api_call_memwrite* cmd); static void guest_handle_its_setup(struct api_call_3* cmd); static void guest_handle_its_send_cmd(struct api_call_its_send_cmd* cmd); +static void guest_handle_wfi_wfe(struct api_call_1* cmd); typedef enum { UEXIT_END = (uint64)-1, @@ -157,6 +164,10 @@ guest_main(uint64 size, uint64 cpu) guest_handle_its_send_cmd((struct api_call_its_send_cmd*)cmd); break; } + case SYZOS_API_WFI_WFE: { + guest_handle_wfi_wfe((struct api_call_1*)cmd); + break; + } } addr += cmd->size; size -= cmd->size; @@ -585,6 +596,20 @@ GUEST_CODE static noinline void guest_handle_its_setup(struct api_call_3* cmd) guest_prepare_its(cmd->args[0], cmd->args[1], cmd->args[2]); } +GUEST_CODE static noinline void guest_handle_wfi_wfe(struct api_call_1* cmd) +{ + switch (cmd->arg) { + case 0: { + asm volatile("wfi"); + break; + } + case 1: { + asm volatile("wfe"); + break; + } + } +} + // Registers saved by one_irq_handler() and received by guest_irq_handler(). struct ex_regs { uint64 regs[31]; diff --git a/sys/linux/dev_kvm_arm64.txt b/sys/linux/dev_kvm_arm64.txt index a510041dcb25..2af7f5d2b55e 100644 --- a/sys/linux/dev_kvm_arm64.txt +++ b/sys/linux/dev_kvm_arm64.txt @@ -205,4 +205,5 @@ syzos_api_call [ memwrite syzos_api[6, syzos_api_memwrite] its_setup syzos_api[7, syzos_api_its_setup] its_send_cmd syzos_api[8, syzos_api_its_send_cmd] + wfi_wfe syzos_api[9, int64[0:1]] ] [varlen] diff --git a/sys/linux/test/arm64-syz_kvm_setup_syzos_vm-wfi b/sys/linux/test/arm64-syz_kvm_setup_syzos_vm-wfi new file mode 100644 index 000000000000..88cd78299465 --- /dev/null +++ b/sys/linux/test/arm64-syz_kvm_setup_syzos_vm-wfi @@ -0,0 +1,21 @@ +# +# requires: arch=arm64 -threaded +# +r0 = openat$kvm(0, &AUTO='/dev/kvm\x00', 0x0, 0x0) +r1 = ioctl$KVM_CREATE_VM(r0, AUTO, 0x0) +r2 = syz_kvm_setup_syzos_vm(r1, &(0x7f0000c00000/0x400000)=nil) +r3 = syz_kvm_add_vcpu(r2, &AUTO={0x0, &AUTO=[@wfi_wfe={AUTO, AUTO, 0x1}], AUTO}, 0x0, 0x0) +syz_kvm_vgic_v3_setup(r1, 0x1, 0x100) + +r4 = ioctl$KVM_GET_VCPU_MMAP_SIZE(r0, AUTO) +r5 = mmap$KVM_VCPU(&(0x7f0000009000/0x1000)=nil, r4, 0x3, 0x1, r3, 0x0) + +# Run till the end of guest_main(). 0xffffffffffffffff is UEXIT_END. +# +ioctl$KVM_RUN(r3, AUTO, 0x0) +syz_kvm_assert_syzos_uexit(r5, 0xffffffffffffffff) + +ioctl$KVM_IRQ_LINE(r1, AUTO, &AUTO={0x1000020, 0x1}) (async) + +ioctl$KVM_RUN(r3, AUTO, 0x0) +syz_kvm_assert_syzos_uexit(r5, 0xffffffffffffffff)