Received: by 2002:a05:6a10:d5a5:0:0:0:0 with SMTP id gn37csp1972353pxb; Thu, 7 Oct 2021 20:24:15 -0700 (PDT) X-Google-Smtp-Source: ABdhPJybhrDO1G3jkhR5fh2F0rZjt5uPndBmEyjpDuGXiZ8ev63B29Glwgspjb/IVE6+iRUBHwwL X-Received: by 2002:aa7:cb92:: with SMTP id r18mr11961646edt.282.1633663454997; Thu, 07 Oct 2021 20:24:14 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1633663454; cv=none; d=google.com; s=arc-20160816; b=gj3SKVmVpGXV0DkoyNqRCDwPSb7FuE664w6xYBvQA6iYlcq/xEEBzVj4LkOGadeGvK TMadt5Z3E2TbLZq7NrfxisQ2iZQKLzQfQA+2wAL2YcU+Pu4R0S7ljlnM5JLMwtELG3aq dnBoQHs5vkOYEqzBaTpx7/D8e7SrkxXzwU1hvYi0IyhceESE4QMhJlKW+u8MHADt40lE 7mgkvcmcn4o4oIR0DyqUo4VbtnpSGt0YBP1etuVsieybGtPZZosTBz+ycRxas0hVdPpR cv3UkyQWNptmltXpm/cjQ9gqMIUsYkXx9lOLnW41xNPVZ7TLzvfjuYFjwkHtt7Zz6key vvaw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :wdcironportexception:ironport-sdr:ironport-sdr:dkim-signature; bh=/j4miDsfGc8aP330Zg37dEYHPdS0c9RsB3yICafalg8=; b=NXS230bI0CyMu0BPS/vDebtV5X6SlH2dyCNsXBN+EvpV82lEJYRIgKlCkL3EBrF9ht rr86AYuTDzibhS8WMPOptQDEoe5qjaAN4Ssul70AUqf91NskA3vVUelfgro6jB4NC4yq jUV0mYyXEK/FkYk9ybYoXyFAPzULzdCKv+BwGA73fr89lEuEYktEsj/SEU7+ZUqDHxKa 8x52P0AHo6za8I0TNKvXXOa7KxYYnICKh+PnXUzw7SPP8dvdYWeIEpNTxDyFTpkdMObC 2kz+EYph27QstDBTNUd3LA9i5yS87TeqWjUT6K9tidDBWDuFWy8f4H/9o19RdH7laZTi RTaw== ARC-Authentication-Results: i=1; mx.google.com; dkim=fail header.i=@wdc.com header.s=dkim.wdc.com header.b=lQc7XeDk; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=wdc.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id w6si1666207edj.147.2021.10.07.20.23.51; Thu, 07 Oct 2021 20:24:14 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=fail header.i=@wdc.com header.s=dkim.wdc.com header.b=lQc7XeDk; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=wdc.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S238714AbhJHDWo (ORCPT + 99 others); Thu, 7 Oct 2021 23:22:44 -0400 Received: from esa6.hgst.iphmx.com ([216.71.154.45]:10090 "EHLO esa6.hgst.iphmx.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236399AbhJHDWg (ORCPT ); Thu, 7 Oct 2021 23:22:36 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=wdc.com; i=@wdc.com; q=dns/txt; s=dkim.wdc.com; t=1633663241; x=1665199241; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=wYr3tPPA33uGMGpjWZVhQiedgL+oUfLO1SRIQkQYMgk=; b=lQc7XeDkyEa2LMzUYFX9qwDwqJBC2MvKSd1vFe8seHqwzTe4Ttm4Uy3v dPRwbNfGaPo/CTriSvb4SiWzc/T1palJ+sx8/awcuRWX0kp3YJUoAkuV2 bHM/L9GIpWXiKSO8aIpXXWxnSTdZVXTuaeEJOzBwR6mWlPkdi+m0fLlq2 GM3cynoM4Vjdge1FYIwq+vJ37eBkHIVu/fQdT3Rl+sc5xv26VJkALRRL4 szILJo38s6WAhdHhGir0go+cbr1TIkLj+Fvo/xOXoVgW577lLBxlWoRhO iAs1Sv3p1YzXj4kS/nBtsT8glceLw8fD4bHgoRNWXFFqTtAJMU5osK0/3 Q==; X-IronPort-AV: E=Sophos;i="5.85,356,1624291200"; d="scan'208";a="182972379" Received: from h199-255-45-14.hgst.com (HELO uls-op-cesaep01.wdc.com) ([199.255.45.14]) by ob1.hgst.iphmx.com with ESMTP; 08 Oct 2021 11:20:39 +0800 IronPort-SDR: r4ezpLJzDg7NaOJvuYzZ/u3UzfcRMG3uQ24CuPujsHzKuY87mljSr0KxDcnoyUY1be10hT6MYM 23gWyKkyFh1l2nBA8e0XKzhXr4uC+1V2SGRjJ4hYnHOeT4IVIt5pE6Y7T002LH2wO4yycjfgX4 9f1Go3W7z7oAjcOIWqNVTQF6Thrcp/ZRQdhYviWnThYli7ZpEN7zAtKAaVR4DDVuE/04Ekejly 94Y/0MrnOetPKXixnB3ObCFxp7FeHNlS89RgOYY5eTfT/fJ/EyJDQ7MK1sLs5rAm69maUFQkbv mUUfOvobJB0VGu0/SlITlztA Received: from uls-op-cesaip02.wdc.com ([10.248.3.37]) by uls-op-cesaep01.wdc.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 07 Oct 2021 19:56:32 -0700 IronPort-SDR: IVMrjxXp4jRmsecw2VkeMShfiPMxJ1gTNoz0F2uwqxkRANkYekDCJQrZKkUtzOFuo3XJXhAnWK XKgEFoj/Ig3lEMTrv0XN6m64PilvCWHRltylKxZAHccACO1nFM9Ukrs8KOTCYOrNzPb9skhF26 TVe5pMo/hc4f1Yj0BOaF6opIrCxI1YpzjfovcYBE6hpWuJucGizX9CrvdJvbG/mEda07j/g55g hamO5LG/10TCRVxUfQo3gyyqTD8rzHZvszQFHdvq8J+i2bocU6qpI0cS1RpYISyeVV8XUPVhzF 5rA= WDCIronportException: Internal Received: from unknown (HELO hulk.wdc.com) ([10.225.167.125]) by uls-op-cesaip02.wdc.com with ESMTP; 07 Oct 2021 20:20:40 -0700 From: Atish Patra To: linux-kernel@vger.kernel.org Cc: Atish Patra , Paolo Bonzini , Anup Patel , Kefeng Wang , kvm-riscv@lists.infradead.org, kvm@vger.kernel.org, linux-riscv@lists.infradead.org, Palmer Dabbelt , Paul Walmsley , Vincent Chen Subject: [PATCH v3 1/5] RISC-V: Mark the existing SBI v0.1 implementation as legacy Date: Thu, 7 Oct 2021 20:20:32 -0700 Message-Id: <20211008032036.2201971-2-atish.patra@wdc.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20211008032036.2201971-1-atish.patra@wdc.com> References: <20211008032036.2201971-1-atish.patra@wdc.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org The existing SBI specification impelementation follows v0.1 or legacy specification. The latest specification known as v0.2 allows more scalability and performance improvements. Rename the existing implementation as legacy and provide a way to allow future extensions. Signed-off-by: Atish Patra --- arch/riscv/include/asm/kvm_vcpu_sbi.h | 29 +++++ arch/riscv/kvm/vcpu_sbi.c | 149 ++++++++++++++++++++------ 2 files changed, 148 insertions(+), 30 deletions(-) create mode 100644 arch/riscv/include/asm/kvm_vcpu_sbi.h diff --git a/arch/riscv/include/asm/kvm_vcpu_sbi.h b/arch/riscv/include/asm/kvm_vcpu_sbi.h new file mode 100644 index 000000000000..1a4cb0db2d0b --- /dev/null +++ b/arch/riscv/include/asm/kvm_vcpu_sbi.h @@ -0,0 +1,29 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/** + * Copyright (c) 2021 Western Digital Corporation or its affiliates. + * + * Authors: + * Atish Patra + */ + +#ifndef __RISCV_KVM_VCPU_SBI_H__ +#define __RISCV_KVM_VCPU_SBI_H__ + +#define KVM_SBI_VERSION_MAJOR 0 +#define KVM_SBI_VERSION_MINOR 2 + +struct kvm_vcpu_sbi_extension { + unsigned long extid_start; + unsigned long extid_end; + /** + * SBI extension handler. It can be defined for a given extension or group of + * extension. But it should always return linux error codes rather than SBI + * specific error codes. + */ + int (*handler)(struct kvm_vcpu *vcpu, struct kvm_run *run, + unsigned long *out_val, struct kvm_cpu_trap *utrap, + bool *exit); +}; + +const struct kvm_vcpu_sbi_extension *kvm_vcpu_sbi_find_ext(unsigned long extid); +#endif /* __RISCV_KVM_VCPU_SBI_H__ */ diff --git a/arch/riscv/kvm/vcpu_sbi.c b/arch/riscv/kvm/vcpu_sbi.c index ebdcdbade9c6..8c168d305763 100644 --- a/arch/riscv/kvm/vcpu_sbi.c +++ b/arch/riscv/kvm/vcpu_sbi.c @@ -12,9 +12,25 @@ #include #include #include +#include -#define SBI_VERSION_MAJOR 0 -#define SBI_VERSION_MINOR 1 +static int kvm_linux_err_map_sbi(int err) +{ + switch (err) { + case 0: + return SBI_SUCCESS; + case -EPERM: + return SBI_ERR_DENIED; + case -EINVAL: + return SBI_ERR_INVALID_PARAM; + case -EFAULT: + return SBI_ERR_INVALID_ADDRESS; + case -EOPNOTSUPP: + return SBI_ERR_NOT_SUPPORTED; + default: + return SBI_ERR_FAILURE; + }; +} static void kvm_riscv_vcpu_sbi_forward(struct kvm_vcpu *vcpu, struct kvm_run *run) @@ -72,16 +88,17 @@ static void kvm_sbi_system_shutdown(struct kvm_vcpu *vcpu, run->exit_reason = KVM_EXIT_SYSTEM_EVENT; } -int kvm_riscv_vcpu_sbi_ecall(struct kvm_vcpu *vcpu, struct kvm_run *run) +static int kvm_sbi_ext_legacy_handler(struct kvm_vcpu *vcpu, struct kvm_run *run, + unsigned long *out_val, + struct kvm_cpu_trap *utrap, + bool *exit) { ulong hmask; - int i, ret = 1; + int i, ret = 0; u64 next_cycle; struct kvm_vcpu *rvcpu; - bool next_sepc = true; struct cpumask cm, hm; struct kvm *kvm = vcpu->kvm; - struct kvm_cpu_trap utrap = { 0 }; struct kvm_cpu_context *cp = &vcpu->arch.guest_context; if (!cp) @@ -95,8 +112,7 @@ int kvm_riscv_vcpu_sbi_ecall(struct kvm_vcpu *vcpu, struct kvm_run *run) * handled in kernel so we forward these to user-space */ kvm_riscv_vcpu_sbi_forward(vcpu, run); - next_sepc = false; - ret = 0; + *exit = true; break; case SBI_EXT_0_1_SET_TIMER: #if __riscv_xlen == 32 @@ -104,47 +120,42 @@ int kvm_riscv_vcpu_sbi_ecall(struct kvm_vcpu *vcpu, struct kvm_run *run) #else next_cycle = (u64)cp->a0; #endif - kvm_riscv_vcpu_timer_next_event(vcpu, next_cycle); + ret = kvm_riscv_vcpu_timer_next_event(vcpu, next_cycle); break; case SBI_EXT_0_1_CLEAR_IPI: - kvm_riscv_vcpu_unset_interrupt(vcpu, IRQ_VS_SOFT); + ret = kvm_riscv_vcpu_unset_interrupt(vcpu, IRQ_VS_SOFT); break; case SBI_EXT_0_1_SEND_IPI: if (cp->a0) hmask = kvm_riscv_vcpu_unpriv_read(vcpu, false, cp->a0, - &utrap); + utrap); else hmask = (1UL << atomic_read(&kvm->online_vcpus)) - 1; - if (utrap.scause) { - utrap.sepc = cp->sepc; - kvm_riscv_vcpu_trap_redirect(vcpu, &utrap); - next_sepc = false; + if (utrap->scause) break; - } + for_each_set_bit(i, &hmask, BITS_PER_LONG) { rvcpu = kvm_get_vcpu_by_id(vcpu->kvm, i); - kvm_riscv_vcpu_set_interrupt(rvcpu, IRQ_VS_SOFT); + ret = kvm_riscv_vcpu_set_interrupt(rvcpu, IRQ_VS_SOFT); + if (ret < 0) + break; } break; case SBI_EXT_0_1_SHUTDOWN: kvm_sbi_system_shutdown(vcpu, run, KVM_SYSTEM_EVENT_SHUTDOWN); - next_sepc = false; - ret = 0; + *exit = true; break; case SBI_EXT_0_1_REMOTE_FENCE_I: case SBI_EXT_0_1_REMOTE_SFENCE_VMA: case SBI_EXT_0_1_REMOTE_SFENCE_VMA_ASID: if (cp->a0) hmask = kvm_riscv_vcpu_unpriv_read(vcpu, false, cp->a0, - &utrap); + utrap); else hmask = (1UL << atomic_read(&kvm->online_vcpus)) - 1; - if (utrap.scause) { - utrap.sepc = cp->sepc; - kvm_riscv_vcpu_trap_redirect(vcpu, &utrap); - next_sepc = false; + if (utrap->scause) break; - } + cpumask_clear(&cm); for_each_set_bit(i, &hmask, BITS_PER_LONG) { rvcpu = kvm_get_vcpu_by_id(vcpu->kvm, i); @@ -154,22 +165,100 @@ int kvm_riscv_vcpu_sbi_ecall(struct kvm_vcpu *vcpu, struct kvm_run *run) } riscv_cpuid_to_hartid_mask(&cm, &hm); if (cp->a7 == SBI_EXT_0_1_REMOTE_FENCE_I) - sbi_remote_fence_i(cpumask_bits(&hm)); + ret = sbi_remote_fence_i(cpumask_bits(&hm)); else if (cp->a7 == SBI_EXT_0_1_REMOTE_SFENCE_VMA) - sbi_remote_hfence_vvma(cpumask_bits(&hm), + ret = sbi_remote_hfence_vvma(cpumask_bits(&hm), cp->a1, cp->a2); else - sbi_remote_hfence_vvma_asid(cpumask_bits(&hm), + ret = sbi_remote_hfence_vvma_asid(cpumask_bits(&hm), cp->a1, cp->a2, cp->a3); break; default: - /* Return error for unsupported SBI calls */ - cp->a0 = SBI_ERR_NOT_SUPPORTED; + ret = -EINVAL; break; }; + return ret; +} + +const struct kvm_vcpu_sbi_extension vcpu_sbi_ext_legacy = { + .extid_start = SBI_EXT_0_1_SET_TIMER, + .extid_end = SBI_EXT_0_1_SHUTDOWN, + .handler = kvm_sbi_ext_legacy_handler, +}; + +static const struct kvm_vcpu_sbi_extension *sbi_ext[] = { + &vcpu_sbi_ext_legacy, +}; + +const struct kvm_vcpu_sbi_extension *kvm_vcpu_sbi_find_ext(unsigned long extid) +{ + int i = 0; + + for (i = 0; i < ARRAY_SIZE(sbi_ext); i++) { + if (sbi_ext[i]->extid_start <= extid && + sbi_ext[i]->extid_end >= extid) + return sbi_ext[i]; + } + + return NULL; +} + +int kvm_riscv_vcpu_sbi_ecall(struct kvm_vcpu *vcpu, struct kvm_run *run) +{ + int ret = 1; + bool next_sepc = true; + bool userspace_exit = false; + struct kvm_cpu_context *cp = &vcpu->arch.guest_context; + const struct kvm_vcpu_sbi_extension *sbi_ext; + struct kvm_cpu_trap utrap = { 0 }; + unsigned long out_val = 0; + bool ext_is_v01 = false; + + if (!cp) + return -EINVAL; + + sbi_ext = kvm_vcpu_sbi_find_ext(cp->a7); + if (sbi_ext && sbi_ext->handler) { + if (cp->a7 >= SBI_EXT_0_1_SET_TIMER && + cp->a7 <= SBI_EXT_0_1_SHUTDOWN) + ext_is_v01 = true; + ret = sbi_ext->handler(vcpu, run, &out_val, &utrap, &userspace_exit); + } else { + /* Return error for unsupported SBI calls */ + cp->a0 = SBI_ERR_NOT_SUPPORTED; + goto ecall_done; + } + + /* Handle special error cases i.e trap, exit or userspace forward */ + if (utrap.scause) { + /* No need to increment sepc or exit ioctl loop */ + ret = 1; + utrap.sepc = cp->sepc; + kvm_riscv_vcpu_trap_redirect(vcpu, &utrap); + next_sepc = false; + goto ecall_done; + } + + /* Exit ioctl loop or Propagate the error code the guest */ + if (userspace_exit) { + next_sepc = false; + ret = 0; + } else { + /** + * SBI extension handler always returns an Linux error code. Convert + * it to the SBI specific error code that can be propagated the SBI + * caller. + */ + ret = kvm_linux_err_map_sbi(ret); + cp->a0 = ret; + ret = 1; + } +ecall_done: if (next_sepc) cp->sepc += 4; + if (!ext_is_v01) + cp->a1 = out_val; return ret; } -- 2.31.1