From patchwork Thu Oct 17 17:37:37 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christoph Hellwig X-Patchwork-Id: 11196463 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 97AAC912 for ; Thu, 17 Oct 2019 17:38:12 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 7650F21925 for ; Thu, 17 Oct 2019 17:38:12 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="TBnfF5FU" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 7650F21925 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=lst.de Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-riscv-bounces+patchwork-linux-riscv=patchwork.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:Cc:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=LEnW21sX984WVmG1e1lzSJwzIIlrdLm/JZRx+dLhLUA=; b=TBnfF5FUSmXmuO 9O/brawhUpPVNJV2QujMHe9EIPI7F5MFtbp/9qqG+eQUYKbJ1pXGnSvkQUAzXoKtNMWX3hKXhPn7e mmRoqFQS1PnVt3DmZIHitdbSEEV1PeffIJ1Ew7hbKumn6xhi/l1kcF5Nqa2wulSrN4JLwiv3OTFoS YkdFJww8nkoqA08EMYLX+eKaYi9tghWJVwMaoQwBqKMUrmC7rnFAH476lFpLSDEb8nv2kF/didPXK ceCIufblxI/s3I3QS0rTuNpJshw2/BF+6pZOQBibc+QFn5rZbaAZWZQIICtBkyhSAZXdCStdnS6v7 M12YNC9OP4to/26d3vnA==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1iL9j1-0007xJ-Dy; Thu, 17 Oct 2019 17:38:11 +0000 Received: from [2001:4bb8:18c:d7b:c70:4a89:bc61:3] (helo=localhost) by bombadil.infradead.org with esmtpsa (Exim 4.92.3 #3 (Red Hat Linux)) id 1iL9iy-0007pp-C1; Thu, 17 Oct 2019 17:38:08 +0000 From: Christoph Hellwig To: Palmer Dabbelt , Paul Walmsley Subject: [PATCH 09/15] riscv: provide native clint access for M-mode Date: Thu, 17 Oct 2019 19:37:37 +0200 Message-Id: <20191017173743.5430-10-hch@lst.de> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20191017173743.5430-1-hch@lst.de> References: <20191017173743.5430-1-hch@lst.de> MIME-Version: 1.0 X-BeenThere: linux-riscv@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Damien Le Moal , linux-riscv@lists.infradead.org, linux-kernel@vger.kernel.org Sender: "linux-riscv" Errors-To: linux-riscv-bounces+patchwork-linux-riscv=patchwork.kernel.org@lists.infradead.org RISC-V has the concept of a cpu level interrupt controller. The interface for it is split between a standardized part that is exposed as bits in the mstatus/sstatus register and the mie/mip/sie/sip CRS. But the bit to actually trigger IPIs is not standardized and just mentioned as implementable using MMIO. Add support for IPIs using MMIO using the SiFive clint layout (which is also shared by Ariane, Kendrye and the Qemu virt platform). Additional the MMIO block also support the time value and timer compare registers, so they are also set up using the same OF node. Support for other layouts should also be relatively easy to add in the future. Signed-off-by: Christoph Hellwig Reviewed-by: Anup Patel Signed-off-by: Christoph Hellwig Reviewed-by: Anup Patel Signed-off-by: Paul Walmsley --- arch/riscv/include/asm/clint.h | 39 ++++++++++++++++++++++++++++++ arch/riscv/include/asm/sbi.h | 2 ++ arch/riscv/kernel/Makefile | 1 + arch/riscv/kernel/clint.c | 44 ++++++++++++++++++++++++++++++++++ arch/riscv/kernel/setup.c | 2 ++ arch/riscv/kernel/smp.c | 16 ++++++++++--- arch/riscv/kernel/smpboot.c | 4 ++++ 7 files changed, 105 insertions(+), 3 deletions(-) create mode 100644 arch/riscv/include/asm/clint.h create mode 100644 arch/riscv/kernel/clint.c diff --git a/arch/riscv/include/asm/clint.h b/arch/riscv/include/asm/clint.h new file mode 100644 index 000000000000..02a26b68f21d --- /dev/null +++ b/arch/riscv/include/asm/clint.h @@ -0,0 +1,39 @@ +// SPDX-License-Identifier: GPL-2.0 +#ifndef _ASM_CLINT_H +#define _ASM_CLINT_H 1 + +#include +#include + +#ifdef CONFIG_RISCV_M_MODE +extern u32 __iomem *clint_ipi_base; + +void clint_init_boot_cpu(void); + +static inline void clint_send_ipi_single(unsigned long hartid) +{ + writel(1, clint_ipi_base + hartid); +} + +static inline void clint_send_ipi_mask(const struct cpumask *hartid_mask) +{ + int hartid; + + for_each_cpu(hartid, hartid_mask) + clint_send_ipi_single(hartid); +} + +static inline void clint_clear_ipi(unsigned long hartid) +{ + writel(0, clint_ipi_base + hartid); +} +#else /* CONFIG_RISCV_M_MODE */ +#define clint_init_boot_cpu() do { } while (0) + +/* stubs to for code is only reachable under IS_ENABLED(CONFIG_RISCV_M_MODE): */ +void clint_send_ipi_single(unsigned long hartid); +void clint_send_ipi_mask(const struct cpumask *hartid_mask); +void clint_clear_ipi(unsigned long hartid); +#endif /* CONFIG_RISCV_M_MODE */ + +#endif /* _ASM_CLINT_H */ diff --git a/arch/riscv/include/asm/sbi.h b/arch/riscv/include/asm/sbi.h index a4774bafe033..407d1024f9eb 100644 --- a/arch/riscv/include/asm/sbi.h +++ b/arch/riscv/include/asm/sbi.h @@ -97,6 +97,8 @@ static inline void sbi_remote_sfence_vma_asid(const unsigned long *hart_mask, #else /* CONFIG_RISCV_SBI */ /* stubs to for code is only reachable under IS_ENABLED(CONFIG_RISCV_SBI): */ void sbi_set_timer(uint64_t stime_value); +void sbi_clear_ipi(void); +void sbi_send_ipi(const unsigned long *hart_mask); void sbi_remote_fence_i(const unsigned long *hart_mask); #endif /* CONFIG_RISCV_SBI */ #endif /* _ASM_RISCV_SBI_H */ diff --git a/arch/riscv/kernel/Makefile b/arch/riscv/kernel/Makefile index d8c35fa93cc6..2dca51046899 100644 --- a/arch/riscv/kernel/Makefile +++ b/arch/riscv/kernel/Makefile @@ -29,6 +29,7 @@ obj-y += vdso.o obj-y += cacheinfo.o obj-y += vdso/ +obj-$(CONFIG_RISCV_M_MODE) += clint.o obj-$(CONFIG_FPU) += fpu.o obj-$(CONFIG_SMP) += smpboot.o obj-$(CONFIG_SMP) += smp.o diff --git a/arch/riscv/kernel/clint.c b/arch/riscv/kernel/clint.c new file mode 100644 index 000000000000..3647980d14c3 --- /dev/null +++ b/arch/riscv/kernel/clint.c @@ -0,0 +1,44 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2019 Christoph Hellwig. + */ + +#include +#include +#include +#include +#include +#include +#include + +/* + * This is the layout used by the SiFive clint, which is also shared by the qemu + * virt platform, and the Kendryte KD210 at least. + */ +#define CLINT_IPI_OFF 0 +#define CLINT_TIME_CMP_OFF 0x4000 +#define CLINT_TIME_VAL_OFF 0xbff8 + +u32 __iomem *clint_ipi_base; + +void clint_init_boot_cpu(void) +{ + struct device_node *np; + void __iomem *base; + + np = of_find_compatible_node(NULL, NULL, "riscv,clint0"); + if (!np) { + panic("clint not found"); + return; + } + + base = of_iomap(np, 0); + if (!base) + panic("could not map CLINT"); + + clint_ipi_base = base + CLINT_IPI_OFF; + riscv_time_cmp = base + CLINT_TIME_CMP_OFF; + riscv_time_val = base + CLINT_TIME_VAL_OFF; + + clint_clear_ipi(boot_cpu_hartid); +} diff --git a/arch/riscv/kernel/setup.c b/arch/riscv/kernel/setup.c index a990a6cb184f..f4ba71b66c73 100644 --- a/arch/riscv/kernel/setup.c +++ b/arch/riscv/kernel/setup.c @@ -17,6 +17,7 @@ #include #include +#include #include #include #include @@ -65,6 +66,7 @@ void __init setup_arch(char **cmdline_p) setup_bootmem(); paging_init(); unflatten_device_tree(); + clint_init_boot_cpu(); #ifdef CONFIG_SWIOTLB swiotlb_init(1); diff --git a/arch/riscv/kernel/smp.c b/arch/riscv/kernel/smp.c index b18cd6c8e8fb..c46df9c2e927 100644 --- a/arch/riscv/kernel/smp.c +++ b/arch/riscv/kernel/smp.c @@ -14,6 +14,7 @@ #include #include +#include #include #include #include @@ -90,7 +91,10 @@ static void send_ipi_mask(const struct cpumask *mask, enum ipi_message_type op) smp_mb__after_atomic(); riscv_cpuid_to_hartid_mask(mask, &hartid_mask); - sbi_send_ipi(cpumask_bits(&hartid_mask)); + if (IS_ENABLED(CONFIG_RISCV_SBI)) + sbi_send_ipi(cpumask_bits(&hartid_mask)); + else + clint_send_ipi_mask(&hartid_mask); } static void send_ipi_single(int cpu, enum ipi_message_type op) @@ -101,12 +105,18 @@ static void send_ipi_single(int cpu, enum ipi_message_type op) set_bit(op, &ipi_data[cpu].bits); smp_mb__after_atomic(); - sbi_send_ipi(cpumask_bits(cpumask_of(hartid))); + if (IS_ENABLED(CONFIG_RISCV_SBI)) + sbi_send_ipi(cpumask_bits(cpumask_of(hartid))); + else + clint_send_ipi_single(hartid); } static inline void clear_ipi(void) { - csr_clear(CSR_SIP, SIE_SSIE); + if (IS_ENABLED(CONFIG_RISCV_SBI)) + csr_clear(CSR_SIP, SIE_SSIE); + else + clint_clear_ipi(cpuid_to_hartid_map(smp_processor_id())); } void riscv_software_interrupt(void) diff --git a/arch/riscv/kernel/smpboot.c b/arch/riscv/kernel/smpboot.c index 18ae6da5115e..6300b09f1d1d 100644 --- a/arch/riscv/kernel/smpboot.c +++ b/arch/riscv/kernel/smpboot.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -134,6 +135,9 @@ asmlinkage void __init smp_callin(void) { struct mm_struct *mm = &init_mm; + if (!IS_ENABLED(CONFIG_RISCV_SBI)) + clint_clear_ipi(cpuid_to_hartid_map(smp_processor_id())); + /* All kernel threads share the same mm context. */ mmgrab(mm); current->active_mm = mm;