162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * ucall support. A ucall is a "hypercall to userspace". 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (C) 2021 Western Digital Corporation or its affiliates. 662306a36Sopenharmony_ci */ 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci#include <linux/kvm.h> 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci#include "kvm_util.h" 1162306a36Sopenharmony_ci#include "processor.h" 1262306a36Sopenharmony_ci 1362306a36Sopenharmony_cistruct sbiret sbi_ecall(int ext, int fid, unsigned long arg0, 1462306a36Sopenharmony_ci unsigned long arg1, unsigned long arg2, 1562306a36Sopenharmony_ci unsigned long arg3, unsigned long arg4, 1662306a36Sopenharmony_ci unsigned long arg5) 1762306a36Sopenharmony_ci{ 1862306a36Sopenharmony_ci register uintptr_t a0 asm ("a0") = (uintptr_t)(arg0); 1962306a36Sopenharmony_ci register uintptr_t a1 asm ("a1") = (uintptr_t)(arg1); 2062306a36Sopenharmony_ci register uintptr_t a2 asm ("a2") = (uintptr_t)(arg2); 2162306a36Sopenharmony_ci register uintptr_t a3 asm ("a3") = (uintptr_t)(arg3); 2262306a36Sopenharmony_ci register uintptr_t a4 asm ("a4") = (uintptr_t)(arg4); 2362306a36Sopenharmony_ci register uintptr_t a5 asm ("a5") = (uintptr_t)(arg5); 2462306a36Sopenharmony_ci register uintptr_t a6 asm ("a6") = (uintptr_t)(fid); 2562306a36Sopenharmony_ci register uintptr_t a7 asm ("a7") = (uintptr_t)(ext); 2662306a36Sopenharmony_ci struct sbiret ret; 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_ci asm volatile ( 2962306a36Sopenharmony_ci "ecall" 3062306a36Sopenharmony_ci : "+r" (a0), "+r" (a1) 3162306a36Sopenharmony_ci : "r" (a2), "r" (a3), "r" (a4), "r" (a5), "r" (a6), "r" (a7) 3262306a36Sopenharmony_ci : "memory"); 3362306a36Sopenharmony_ci ret.error = a0; 3462306a36Sopenharmony_ci ret.value = a1; 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_ci return ret; 3762306a36Sopenharmony_ci} 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_civoid *ucall_arch_get_ucall(struct kvm_vcpu *vcpu) 4062306a36Sopenharmony_ci{ 4162306a36Sopenharmony_ci struct kvm_run *run = vcpu->run; 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_ci if (run->exit_reason == KVM_EXIT_RISCV_SBI && 4462306a36Sopenharmony_ci run->riscv_sbi.extension_id == KVM_RISCV_SELFTESTS_SBI_EXT) { 4562306a36Sopenharmony_ci switch (run->riscv_sbi.function_id) { 4662306a36Sopenharmony_ci case KVM_RISCV_SELFTESTS_SBI_UCALL: 4762306a36Sopenharmony_ci return (void *)run->riscv_sbi.args[0]; 4862306a36Sopenharmony_ci case KVM_RISCV_SELFTESTS_SBI_UNEXP: 4962306a36Sopenharmony_ci vcpu_dump(stderr, vcpu, 2); 5062306a36Sopenharmony_ci TEST_ASSERT(0, "Unexpected trap taken by guest"); 5162306a36Sopenharmony_ci break; 5262306a36Sopenharmony_ci default: 5362306a36Sopenharmony_ci break; 5462306a36Sopenharmony_ci } 5562306a36Sopenharmony_ci } 5662306a36Sopenharmony_ci return NULL; 5762306a36Sopenharmony_ci} 58