From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.6 required=3.0 tests=DKIM_INVALID,DKIM_SIGNED, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH,MAILING_LIST_MULTI,SIGNED_OFF_BY, SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 1A47FC432C3 for ; Tue, 26 Nov 2019 19:05:35 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id CE4F62075C for ; Tue, 26 Nov 2019 19:05:34 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=wdc.com header.i=@wdc.com header.b="JPW6rmQw" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727216AbfKZTFe (ORCPT ); Tue, 26 Nov 2019 14:05:34 -0500 Received: from esa3.hgst.iphmx.com ([216.71.153.141]:62448 "EHLO esa3.hgst.iphmx.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727165AbfKZTFb (ORCPT ); Tue, 26 Nov 2019 14:05:31 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=wdc.com; i=@wdc.com; q=dns/txt; s=dkim.wdc.com; t=1574795131; x=1606331131; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=yKOTF+GCSs6nbJNoJs6kHfpbalUWcXa02Lk071ru3Uk=; b=JPW6rmQwA5dEih5beDvAa4BOZcxzYL82IlQ1CpzuY/aNLLA1dYXf4k3q JJAPmUPwIou5VJObn1+47699tG2TQ2C2/w1/evy0VbQR9KZHpVzoNte2k B9LIr3flt9E7jf3IYH0KrfZQM34zRTfWQN/8cT9cTMehGc50ElyD/XL37 UBu8nO2L5b6GqqgE5q9OEXggqBTujfaSPjCvLcxs3Qde1nFuNaDbRM4Dz qLSbUBF3lOw9rky9MGtFOHuXHd1QeTkIC6Wga6GrEe0I7kJzsc5tGa2hV czILQ7/JXsmPqwrdRXOeKeHyAmXHKj2B46UD/s0oA7Xjd30U0oh++lgoM w==; IronPort-SDR: XLJ0HvfXUAhH3nZHwt+8ks4nd3OsJLHF1e1t7syC7HYCbO7npCX2ABDkdP7RJX+vbsCX0pcq31 vDA/2o6X56TGQDMoFt8L+GNVDSVO9BJFnRv7SCty1d0btrCcNDGAsrLVCzhNpmAtq9N++63ewN 56x2LNl8/aOLbiPVJLGJ9b+dTU6ZRDaWN2D6jgtVBIHyoibaJ/2HS9hOnQlF/HZYQs+HAxd6aN pDYEP5N8ddn14ZAKENWeGBRViPmtPCc63qEWpwYFq38ldwPjSDkppao9JCcY4vetIWsgdA3NR8 d7g= X-IronPort-AV: E=Sophos;i="5.69,246,1571673600"; d="scan'208";a="128481938" Received: from h199-255-45-15.hgst.com (HELO uls-op-cesaep02.wdc.com) ([199.255.45.15]) by ob1.hgst.iphmx.com with ESMTP; 27 Nov 2019 03:05:31 +0800 IronPort-SDR: 1jQ3An7Ei0t4mxzvCZcrHCl4urMOjNNwRLjieHRyy0exO8K7sniJ7bIER2pEl/CFJNMao9BD1x t0jbMJxM4yk22M/W1VjXhokSaG1ee5zX3+nK6QuX5z0s0V6yKfwjiIBfQZTGf8avbxIFYpiuaw IXA/NmpYxfELsUg8Z/L9mc8Dcjdr4M0cCdLzPwg8IfN6g9S1cj8E4sBJ0J21PE3iQtv2zLtoEO 16pvFiih/pSud8eeMv0a8YieUK8f7K08Ic7zzbvPHY4mRFO+BR4Z+pL+b72svsZnmxN+49yQj2 nEw0on+Q3jDJ3TFkaH3c5O47 Received: from uls-op-cesaip02.wdc.com ([10.248.3.37]) by uls-op-cesaep02.wdc.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 26 Nov 2019 11:00:08 -0800 IronPort-SDR: u2MmJIFf7NloOdDU92JSzs09Dxcub3v4QUwQaOkChqW7kbLCk4BdI2WfbRWvU+LFE8lvCp83TV 6ZUCISLUseEwZuU7SEAuDcJOJ6Fhnjwq4z1yWlTG6UP2qhQjrVFsC+Me0isQTIQd5wM4ckt4M6 /fTNdtONAcZzMwAkH1Ezhm8FxfG72Bwkx2AbGx2D/cXwrsXGfo2fvSoY+9S2rx1+eBXl1aqSJ4 aD2+aX/uuqEpGmwNmQK9tmCB+8SNqLPh8ibOsdhSrWTeeSruIml8C60mbboCoW4PU2Yc0gMWPn T2M= WDCIronportException: Internal Received: from usa003951.ad.shared (HELO yoda.hgst.com) ([10.86.50.226]) by uls-op-cesaip02.wdc.com with ESMTP; 26 Nov 2019 11:05:30 -0800 From: Atish Patra To: linux-kernel@vger.kernel.org Cc: Atish Patra , Anup Patel , Albert Ou , Alexios Zavras , linux-riscv@lists.infradead.org, Mao Han , Mike Rapoport , Palmer Dabbelt , Paul Walmsley , Thomas Gleixner Subject: [PATCH v5 4/4] RISC-V: Implement new SBI v0.2 extensions Date: Tue, 26 Nov 2019 11:05:03 -0800 Message-Id: <20191126190503.19303-5-atish.patra@wdc.com> X-Mailer: git-send-email 2.23.0 In-Reply-To: <20191126190503.19303-1-atish.patra@wdc.com> References: <20191126190503.19303-1-atish.patra@wdc.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Few v0.1 SBI calls are being replaced by new SBI calls that follows v0.2 calling convention. The specification changes can be found at riscv/riscv-sbi-doc#27 Implement the replacement extensions and few additional new SBI function calls that makes way for a better SBI interface in future. Signed-off-by: Atish Patra Reviewed-by: Anup Patel --- arch/riscv/include/asm/sbi.h | 35 ++++++ arch/riscv/kernel/sbi.c | 208 +++++++++++++++++++++++++++++++++-- 2 files changed, 236 insertions(+), 7 deletions(-) diff --git a/arch/riscv/include/asm/sbi.h b/arch/riscv/include/asm/sbi.h index cc82ae63f8e0..54ba9eebec11 100644 --- a/arch/riscv/include/asm/sbi.h +++ b/arch/riscv/include/asm/sbi.h @@ -22,6 +22,9 @@ enum sbi_ext_id { SBI_EXT_0_1_SHUTDOWN = 0x8, #endif SBI_EXT_BASE = 0x10, + SBI_EXT_TIME = 0x54494D45, + SBI_EXT_IPI = 0x735049, + SBI_EXT_RFENCE = 0x52464E43, }; enum sbi_ext_base_fid { @@ -34,6 +37,24 @@ enum sbi_ext_base_fid { SBI_BASE_GET_MIMPID, }; +enum sbi_ext_time_fid { + SBI_EXT_TIME_SET_TIMER = 0, +}; + +enum sbi_ext_ipi_fid { + SBI_EXT_IPI_SEND_IPI = 0, +}; + +enum sbi_ext_rfence_fid { + SBI_EXT_RFENCE_REMOTE_FENCE_I = 0, + SBI_EXT_RFENCE_REMOTE_SFENCE_VMA, + SBI_EXT_RFENCE_REMOTE_SFENCE_VMA_ASID, + SBI_EXT_RFENCE_REMOTE_HFENCE_GVMA, + SBI_EXT_RFENCE_REMOTE_HFENCE_GVMA_VMID, + SBI_EXT_RFENCE_REMOTE_HFENCE_VVMA, + SBI_EXT_RFENCE_REMOTE_HFENCE_VVMA_ASID, +}; + #define SBI_SPEC_VERSION_DEFAULT 0x1 #define SBI_SPEC_VERSION_MAJOR_OFFSET 24 #define SBI_SPEC_VERSION_MAJOR_MASK 0x7f @@ -74,6 +95,20 @@ void sbi_remote_sfence_vma_asid(const unsigned long *hart_mask, unsigned long start, unsigned long size, unsigned long asid); +int sbi_remote_hfence_gvma(const unsigned long *hart_mask, + unsigned long start, + unsigned long size); +int sbi_remote_hfence_gvma_vmid(const unsigned long *hart_mask, + unsigned long start, + unsigned long size, + unsigned long vmid); +int sbi_remote_hfence_vvma(const unsigned long *hart_mask, + unsigned long start, + unsigned long size); +int sbi_remote_hfence_vvma_asid(const unsigned long *hart_mask, + unsigned long start, + unsigned long size, + unsigned long asid); int sbi_probe_extension(long ext); /* Check if current SBI specification version is 0.1 or not */ diff --git a/arch/riscv/kernel/sbi.c b/arch/riscv/kernel/sbi.c index ee710bfe0b0e..af3d5f8d8af7 100644 --- a/arch/riscv/kernel/sbi.c +++ b/arch/riscv/kernel/sbi.c @@ -205,6 +205,101 @@ static int __sbi_rfence_v01(unsigned long ext, unsigned long fid, } #endif /* CONFIG_RISCV_SBI_V01 */ +static void __sbi_set_timer_v02(uint64_t stime_value) +{ +#if __riscv_xlen == 32 + sbi_ecall(SBI_EXT_TIME, SBI_EXT_TIME_SET_TIMER, stime_value, + stime_value >> 32, 0, 0, 0, 0); +#else + sbi_ecall(SBI_EXT_TIME, SBI_EXT_TIME_SET_TIMER, stime_value, 0, + 0, 0, 0, 0); +#endif +} + +static int __sbi_send_ipi_v02(const unsigned long *hart_mask) +{ + unsigned long hmask_val; + struct sbiret ret = {0}; + int result; + + if (!hart_mask) + hmask_val = *(cpumask_bits(cpu_online_mask)); + else + hmask_val = *hart_mask; + + ret = sbi_ecall(SBI_EXT_IPI, SBI_EXT_IPI_SEND_IPI, hmask_val, + 0, 0, 0, 0, 0); + if (ret.error) { + pr_err("%s: failed with error [%d]\n", __func__, + sbi_err_map_linux_errno(ret.error)); + result = ret.error; + } else + result = ret.value; + + return result; +} + +static int __sbi_rfence_v02(unsigned long extid, unsigned long fid, + const unsigned long *hart_mask, + unsigned long hbase, unsigned long start, + unsigned long size, unsigned long arg4, + unsigned long arg5) +{ + unsigned long hmask_val; + struct sbiret ret = {0}; + int result; + unsigned long ext = SBI_EXT_RFENCE; + + if (!hart_mask) + hmask_val = *(cpumask_bits(cpu_online_mask)); + else + hmask_val = *hart_mask; + + switch (fid) { + case SBI_EXT_RFENCE_REMOTE_FENCE_I: + ret = sbi_ecall(ext, fid, hmask_val, 0, 0, 0, 0, 0); + break; + case SBI_EXT_RFENCE_REMOTE_SFENCE_VMA: + ret = sbi_ecall(ext, fid, hmask_val, 0, start, + size, 0, 0); + break; + case SBI_EXT_RFENCE_REMOTE_SFENCE_VMA_ASID: + ret = sbi_ecall(ext, fid, hmask_val, 0, start, + size, arg4, 0); + break; + /*TODO: Handle non zero hbase cases */ + case SBI_EXT_RFENCE_REMOTE_HFENCE_GVMA: + ret = sbi_ecall(ext, fid, hmask_val, 0, start, + size, 0, 0); + break; + case SBI_EXT_RFENCE_REMOTE_HFENCE_GVMA_VMID: + ret = sbi_ecall(ext, fid, hmask_val, 0, start, + size, arg4, 0); + break; + case SBI_EXT_RFENCE_REMOTE_HFENCE_VVMA: + ret = sbi_ecall(ext, fid, hmask_val, 0, start, + size, 0, 0); + break; + case SBI_EXT_RFENCE_REMOTE_HFENCE_VVMA_ASID: + ret = sbi_ecall(ext, fid, hmask_val, 0, start, + size, arg4, 0); + break; + default: + pr_err("unknown function ID [%lu] for SBI extension [%lu]\n", + fid, ext); + result = -EINVAL; + } + + if (ret.error) { + pr_err("%s: failed with error [%d]\n", __func__, + sbi_err_map_linux_errno(ret.error)); + result = ret.error; + } else + result = ret.value; + + return result; +} + /** * sbi_set_timer() - Program the timer for next timer event. * @stime_value: The value after which next timer event should fire. @@ -237,7 +332,7 @@ EXPORT_SYMBOL(sbi_send_ipi); */ void sbi_remote_fence_i(const unsigned long *hart_mask) { - __sbi_rfence(SBI_EXT_0_1_REMOTE_FENCE_I, 0, + __sbi_rfence(SBI_EXT_0_1_REMOTE_FENCE_I, SBI_EXT_RFENCE_REMOTE_FENCE_I, hart_mask, 0, 0, 0, 0, 0); } EXPORT_SYMBOL(sbi_remote_fence_i); @@ -255,7 +350,8 @@ void sbi_remote_sfence_vma(const unsigned long *hart_mask, unsigned long start, unsigned long size) { - __sbi_rfence(SBI_EXT_0_1_REMOTE_SFENCE_VMA, 0, + __sbi_rfence(SBI_EXT_0_1_REMOTE_SFENCE_VMA, + SBI_EXT_RFENCE_REMOTE_SFENCE_VMA, hart_mask, 0, start, size, 0, 0); } EXPORT_SYMBOL(sbi_remote_sfence_vma); @@ -276,11 +372,93 @@ void sbi_remote_sfence_vma_asid(const unsigned long *hart_mask, unsigned long size, unsigned long asid) { - __sbi_rfence(SBI_EXT_0_1_REMOTE_SFENCE_VMA_ASID, 0, + __sbi_rfence(SBI_EXT_0_1_REMOTE_SFENCE_VMA_ASID, + SBI_EXT_RFENCE_REMOTE_SFENCE_VMA_ASID, hart_mask, 0, start, size, asid, 0); } EXPORT_SYMBOL(sbi_remote_sfence_vma_asid); +/** + * sbi_remote_hfence_gvma() - Execute HFENCE.GVMA instructions on given remote + * harts for the specified guest physical address range. + * @hart_mask: A cpu mask containing all the target harts. + * @start: Start of the guest physical address + * @size: Total size of the guest physical address range. + * + * Return: None + */ +int sbi_remote_hfence_gvma(const unsigned long *hart_mask, + unsigned long start, + unsigned long size) +{ + return __sbi_rfence(SBI_EXT_RFENCE, SBI_EXT_RFENCE_REMOTE_HFENCE_GVMA, + hart_mask, 0, start, size, 0, 0); +} +EXPORT_SYMBOL_GPL(sbi_remote_hfence_gvma); + +/** + * sbi_remote_hfence_gvma_vmid() - Execute HFENCE.GVMA instructions on given + * remote harts for a guest physical address range belonging to a specific VMID. + * + * @hart_mask: A cpu mask containing all the target harts. + * @start: Start of the guest physical address + * @size: Total size of the guest physical address range. + * @vmid: The value of guest ID (VMID). + * + * Return: 0 if success, Error otherwise. + */ +int sbi_remote_hfence_gvma_vmid(const unsigned long *hart_mask, + unsigned long start, + unsigned long size, + unsigned long vmid) +{ + return __sbi_rfence(SBI_EXT_RFENCE, + SBI_EXT_RFENCE_REMOTE_HFENCE_GVMA_VMID, + hart_mask, 0, start, size, vmid, 0); +} +EXPORT_SYMBOL(sbi_remote_hfence_gvma_vmid); + +/** + * sbi_remote_hfence_vvma() - Execute HFENCE.VVMA instructions on given remote + * harts for the current guest virtual address range. + * @hart_mask: A cpu mask containing all the target harts. + * @start: Start of the current guest virtual address + * @size: Total size of the current guest virtual address range. + * + * Return: None + */ +int sbi_remote_hfence_vvma(const unsigned long *hart_mask, + unsigned long start, + unsigned long size) +{ + return __sbi_rfence(SBI_EXT_RFENCE, SBI_EXT_RFENCE_REMOTE_HFENCE_VVMA, + hart_mask, 0, start, size, 0, 0); +} +EXPORT_SYMBOL(sbi_remote_hfence_vvma); + +/** + * sbi_remote_hfence_vvma_asid() - Execute HFENCE.VVMA instructions on given + * remote harts for current guest virtual address range belonging to a specific + * ASID. + * + * @hart_mask: A cpu mask containing all the target harts. + * @start: Start of the current guest virtual address + * @size: Total size of the current guest virtual address range. + * @asid: The value of address space identifier (ASID). + * + * Return: None + */ +int sbi_remote_hfence_vvma_asid(const unsigned long *hart_mask, + unsigned long start, + unsigned long size, + unsigned long asid) +{ + return __sbi_rfence(SBI_EXT_RFENCE, + SBI_EXT_RFENCE_REMOTE_HFENCE_VVMA_ASID, + hart_mask, 0, start, size, asid, 0); +} +EXPORT_SYMBOL(sbi_remote_hfence_vvma_asid); + /** * sbi_probe_extension() - Check if an SBI extension ID is supported or not. * @extid: The extension ID to be probed. @@ -356,11 +534,27 @@ int __init sbi_init(void) if (!sbi_spec_is_0_1()) { pr_info("SBI implementation ID=0x%lx Version=0x%lx\n", sbi_get_firmware_id(), sbi_get_firmware_version()); + if (sbi_probe_extension(SBI_EXT_TIME) > 0) { + __sbi_set_timer = __sbi_set_timer_v02; + pr_info("SBI v0.2 TIME extension detected\n"); + } else + __sbi_set_timer = __sbi_set_timer_dummy_warn; + if (sbi_probe_extension(SBI_EXT_IPI) > 0) { + __sbi_send_ipi = __sbi_send_ipi_v02; + pr_info("SBI v0.2 IPI extension detected\n"); + } else + __sbi_send_ipi = __sbi_send_ipi_dummy_warn; + if (sbi_probe_extension(SBI_EXT_RFENCE) > 0) { + __sbi_rfence = __sbi_rfence_v02; + pr_info("SBI v0.2 RFENCE extension detected\n"); + } else + __sbi_rfence = __sbi_rfence_dummy_warn; + + } else { + __sbi_set_timer = __sbi_set_timer_v01; + __sbi_send_ipi = __sbi_send_ipi_v01; + __sbi_rfence = __sbi_rfence_v01; } - __sbi_set_timer = __sbi_set_timer_v01; - __sbi_send_ipi = __sbi_send_ipi_v01; - __sbi_rfence = __sbi_rfence_v01; - return 0; } -- 2.23.0