Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion arch/riscv/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ config RISCV
select ARCH_USE_MEMTEST
select ARCH_USE_QUEUED_RWLOCKS
select ARCH_USES_CFI_TRAPS if CFI_CLANG
select ARCH_WANT_BATCHED_UNMAP_TLB_FLUSH if SMP && MMU
select ARCH_WANT_BATCHED_UNMAP_TLB_FLUSH if MMU
select ARCH_WANT_DEFAULT_TOPDOWN_MMAP_LAYOUT if MMU
select ARCH_WANT_FRAME_POINTERS
select ARCH_WANT_GENERAL_HUGETLB if !RISCV_ISA_SVNAPOT
Expand Down
9 changes: 7 additions & 2 deletions arch/riscv/boot/dts/thead/th1520.dtsi
Original file line number Diff line number Diff line change
Expand Up @@ -452,10 +452,15 @@
<&cpu3_intc 3>, <&cpu3_intc 7>;
};

aclint_sswi: aclint-sswi@ffdc00c000 {
compatible = "riscv,aclint-sswi";
aclint_sswi: interrupt-controller@ffdc00c000 {
compatible = "thead,c900-aclint-sswi";
reg = <0xff 0xdc00c000 0x0 0x00010000>;
#interrupt-cells = <0>;
interrupt-controller;
interrupts-extended = <&cpu0_intc 1>,
<&cpu1_intc 1>,
<&cpu2_intc 1>,
<&cpu3_intc 1>;
};

secsys_reg: secsys-reg@ffff200000 {
Expand Down
5 changes: 5 additions & 0 deletions arch/riscv/errata/sifive/errata.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,11 @@ static bool errata_cip_1200_check_func(unsigned long arch_id, unsigned long imp
return false;
if ((impid & 0xffffff) > 0x200630 || impid == 0x1200626)
return false;

#ifdef CONFIG_MMU
tlb_flush_all_threshold = 0;
#endif

return true;
}

Expand Down
3 changes: 3 additions & 0 deletions arch/riscv/include/asm/mmu.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ typedef struct {
/* Lock the pointer masking mode because this mm is multithreaded */
#define MM_CONTEXT_LOCK_PMLEN 0

#define cntx2asid(cntx) ((cntx) & SATP_ASID_MASK)
#define cntx2version(cntx) ((cntx) & ~SATP_ASID_MASK)

void __meminit create_pgd_mapping(pgd_t *pgdp, uintptr_t va, phys_addr_t pa, phys_addr_t sz,
pgprot_t prot);
#endif /* __ASSEMBLY__ */
Expand Down
32 changes: 14 additions & 18 deletions arch/riscv/include/asm/pgalloc.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,22 @@
#define _ASM_RISCV_PGALLOC_H

#include <linux/mm.h>
#include <asm/sbi.h>
#include <asm/tlb.h>

#ifdef CONFIG_MMU
#define __HAVE_ARCH_PUD_ALLOC_ONE
#define __HAVE_ARCH_PUD_FREE
#include <asm-generic/pgalloc.h>

static inline void riscv_tlb_remove_ptdesc(struct mmu_gather *tlb, void *pt)
{
if (riscv_use_sbi_for_rfence())
tlb_remove_ptdesc(tlb, pt);
else
tlb_remove_page_ptdesc(tlb, pt);
}

static inline void pmd_populate_kernel(struct mm_struct *mm,
pmd_t *pmd, pte_t *pte)
{
Expand Down Expand Up @@ -102,10 +111,7 @@ static inline void __pud_free_tlb(struct mmu_gather *tlb, pud_t *pud,
struct ptdesc *ptdesc = virt_to_ptdesc(pud);

pagetable_pud_dtor(ptdesc);
if (riscv_use_ipi_for_rfence())
tlb_remove_page_ptdesc(tlb, ptdesc);
else
tlb_remove_ptdesc(tlb, ptdesc);
riscv_tlb_remove_ptdesc(tlb, ptdesc);
}
}

Expand Down Expand Up @@ -139,12 +145,8 @@ static inline void p4d_free(struct mm_struct *mm, p4d_t *p4d)
static inline void __p4d_free_tlb(struct mmu_gather *tlb, p4d_t *p4d,
unsigned long addr)
{
if (pgtable_l5_enabled) {
if (riscv_use_ipi_for_rfence())
tlb_remove_page_ptdesc(tlb, virt_to_ptdesc(p4d));
else
tlb_remove_ptdesc(tlb, virt_to_ptdesc(p4d));
}
if (pgtable_l5_enabled)
riscv_tlb_remove_ptdesc(tlb, virt_to_ptdesc(p4d));
}
#endif /* __PAGETABLE_PMD_FOLDED */

Expand Down Expand Up @@ -176,10 +178,7 @@ static inline void __pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmd,
struct ptdesc *ptdesc = virt_to_ptdesc(pmd);

pagetable_pmd_dtor(ptdesc);
if (riscv_use_ipi_for_rfence())
tlb_remove_page_ptdesc(tlb, ptdesc);
else
tlb_remove_ptdesc(tlb, ptdesc);
riscv_tlb_remove_ptdesc(tlb, ptdesc);
}

#endif /* __PAGETABLE_PMD_FOLDED */
Expand All @@ -190,10 +189,7 @@ static inline void __pte_free_tlb(struct mmu_gather *tlb, pgtable_t pte,
struct ptdesc *ptdesc = page_ptdesc(pte);

pagetable_pte_dtor(ptdesc);
if (riscv_use_ipi_for_rfence())
tlb_remove_page_ptdesc(tlb, ptdesc);
else
tlb_remove_ptdesc(tlb, ptdesc);
riscv_tlb_remove_ptdesc(tlb, ptdesc);
}
#endif /* CONFIG_MMU */

Expand Down
4 changes: 4 additions & 0 deletions arch/riscv/include/asm/sbi.h
Original file line number Diff line number Diff line change
Expand Up @@ -728,8 +728,12 @@ unsigned long riscv_cached_marchid(unsigned int cpu_id);
unsigned long riscv_cached_mimpid(unsigned int cpu_id);

#if IS_ENABLED(CONFIG_SMP) && IS_ENABLED(CONFIG_RISCV_SBI)
DECLARE_STATIC_KEY_FALSE(riscv_sbi_for_rfence);
#define riscv_use_sbi_for_rfence() \
static_branch_unlikely(&riscv_sbi_for_rfence)
void sbi_ipi_init(void);
#else
static inline bool riscv_use_sbi_for_rfence(void) { return false; }
static inline void sbi_ipi_init(void) { }
#endif

Expand Down
15 changes: 2 additions & 13 deletions arch/riscv/include/asm/smp.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,12 +49,7 @@ void riscv_ipi_disable(void);
bool riscv_ipi_have_virq_range(void);

/* Set the IPI interrupt numbers for arch (called by irqchip drivers) */
void riscv_ipi_set_virq_range(int virq, int nr, bool use_for_rfence);

/* Check if we can use IPIs for remote FENCEs */
DECLARE_STATIC_KEY_FALSE(riscv_ipi_for_rfence);
#define riscv_use_ipi_for_rfence() \
static_branch_unlikely(&riscv_ipi_for_rfence)
void riscv_ipi_set_virq_range(int virq, int nr);

/* Check other CPUs stop or not */
bool smp_crash_stop_failed(void);
Expand Down Expand Up @@ -104,16 +99,10 @@ static inline bool riscv_ipi_have_virq_range(void)
return false;
}

static inline void riscv_ipi_set_virq_range(int virq, int nr,
bool use_for_rfence)
static inline void riscv_ipi_set_virq_range(int virq, int nr)
{
}

static inline bool riscv_use_ipi_for_rfence(void)
{
return false;
}

#endif /* CONFIG_SMP */

#if defined(CONFIG_HOTPLUG_CPU) && (CONFIG_SMP)
Expand Down
33 changes: 4 additions & 29 deletions arch/riscv/include/asm/tlbflush.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,6 @@
#define FLUSH_TLB_NO_ASID ((unsigned long)-1)

#ifdef CONFIG_MMU
extern unsigned long asid_mask;

static inline void local_flush_tlb_all(void)
{
__asm__ __volatile__ ("sfence.vma" : : : "memory");
Expand Down Expand Up @@ -44,12 +42,7 @@ static inline void local_flush_tlb_page_asid(unsigned long addr,
else
local_flush_tlb_page(addr);
}
#else /* CONFIG_MMU */
#define local_flush_tlb_all() do { } while (0)
#define local_flush_tlb_page(addr) do { } while (0)
#endif /* CONFIG_MMU */

#if defined(CONFIG_SMP) && defined(CONFIG_MMU)
void flush_tlb_all(void);
void flush_tlb_mm(struct mm_struct *mm);
void flush_tlb_mm_range(struct mm_struct *mm, unsigned long start,
Expand All @@ -72,27 +65,9 @@ void arch_tlbbatch_add_pending(struct arch_tlbflush_unmap_batch *batch,
void arch_flush_tlb_batched_pending(struct mm_struct *mm);
void arch_tlbbatch_flush(struct arch_tlbflush_unmap_batch *batch);

#else /* CONFIG_SMP && CONFIG_MMU */

#define flush_tlb_all() local_flush_tlb_all()
#define flush_tlb_page(vma, addr) local_flush_tlb_page(addr)

static inline void flush_tlb_range(struct vm_area_struct *vma,
unsigned long start, unsigned long end)
{
local_flush_tlb_all();
}

/* Flush a range of kernel pages */
static inline void flush_tlb_kernel_range(unsigned long start,
unsigned long end)
{
local_flush_tlb_all();
}

#define flush_tlb_mm(mm) flush_tlb_all()
#define flush_tlb_mm_range(mm, start, end, page_size) flush_tlb_all()
#define local_flush_tlb_kernel_range(start, end) flush_tlb_all()
#endif /* !CONFIG_SMP || !CONFIG_MMU */
extern unsigned long tlb_flush_all_threshold;
#else /* CONFIG_MMU */
#define local_flush_tlb_all() do { } while (0)
#endif /* CONFIG_MMU */

#endif /* _ASM_RISCV_TLBFLUSH_H */
51 changes: 11 additions & 40 deletions arch/riscv/kernel/sbi-ipi.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,34 +3,20 @@
* Multiplex several IPIs over a single HW IPI.
*
* Copyright (c) 2022 Ventana Micro Systems Inc.
* Copyright (C) 2024 Alibaba Group Holding Limited.
*/

#define pr_fmt(fmt) "riscv: " fmt
#include <linux/cpu.h>
#include <linux/init.h>
#include <linux/irq.h>
#include <linux/irqchip.h>
#include <linux/irqchip/chained_irq.h>
#include <linux/irqdomain.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_irq.h>
#include <asm/sbi.h>

static int sbi_ipi_virq;

static u32 __iomem *sswi_base;

static void sswi_send_ipi(unsigned int cpu)
{
writel(1, sswi_base + cpuid_to_hartid_map(cpu));
}
DEFINE_STATIC_KEY_FALSE(riscv_sbi_for_rfence);
EXPORT_SYMBOL_GPL(riscv_sbi_for_rfence);

static void sswi_clear_ipi(void)
{
writel(0, sswi_base + cpuid_to_hartid_map(smp_processor_id()));
}
static int sbi_ipi_virq;

static void sbi_ipi_handle(struct irq_desc *desc)
{
Expand All @@ -39,9 +25,6 @@ static void sbi_ipi_handle(struct irq_desc *desc)
chained_irq_enter(chip, desc);

csr_clear(CSR_IP, IE_SIE);
if (sswi_base)
sswi_clear_ipi();

ipi_mux_process();

chained_irq_exit(chip, desc);
Expand Down Expand Up @@ -74,8 +57,7 @@ void __init sbi_ipi_init(void)
return;
}

virq = ipi_mux_create(BITS_PER_BYTE, sswi_base ? sswi_send_ipi
: sbi_send_ipi);
virq = ipi_mux_create(BITS_PER_BYTE, sbi_send_ipi);
if (virq <= 0) {
pr_err("unable to create muxed IPIs\n");
irq_dispose_mapping(sbi_ipi_virq);
Expand All @@ -90,26 +72,15 @@ void __init sbi_ipi_init(void)
* via generic IPI-Mux
*/
cpuhp_setup_state(CPUHP_AP_IRQ_RISCV_SBI_IPI_STARTING,
sswi_base ?
"irqchip/sswi-ipi:starting" :
"irqchip/sbi-ipi:starting",
sbi_ipi_starting_cpu, NULL);

riscv_ipi_set_virq_range(virq, BITS_PER_BYTE,
sswi_base ? true : false);
pr_info("providing IPIs using %s IPI extension\n",
sswi_base ? "ACLINT SSWI" : "SBI");
}

static int __init aclint_sswi_probe(struct device_node *node,
struct device_node *parent)
{
sswi_base = of_iomap(node, 0);
if (!sswi_base) {
pr_err("RISC-V ACLINT SSWI device probe failure\n");
return -ENODEV;
}
riscv_ipi_set_virq_range(virq, BITS_PER_BYTE);
pr_info("providing IPIs using SBI IPI extension\n");

return 0;
/*
* Use the SBI remote fence extension to avoid
* the extra context switch needed to handle IPIs.
*/
static_branch_enable(&riscv_sbi_for_rfence);
}
IRQCHIP_DECLARE(riscv_aclint_sswi, "riscv,aclint-sswi", aclint_sswi_probe);
11 changes: 1 addition & 10 deletions arch/riscv/kernel/smp.c
Original file line number Diff line number Diff line change
Expand Up @@ -176,10 +176,7 @@ bool riscv_ipi_have_virq_range(void)
return (ipi_virq_base) ? true : false;
}

DEFINE_STATIC_KEY_FALSE(riscv_ipi_for_rfence);
EXPORT_SYMBOL_GPL(riscv_ipi_for_rfence);

void riscv_ipi_set_virq_range(int virq, int nr, bool use_for_rfence)
void riscv_ipi_set_virq_range(int virq, int nr)
{
int i, err;

Expand All @@ -202,12 +199,6 @@ void riscv_ipi_set_virq_range(int virq, int nr, bool use_for_rfence)

/* Enabled IPIs for boot CPU immediately */
riscv_ipi_enable();

/* Update RFENCE static key */
if (use_for_rfence)
static_branch_enable(&riscv_ipi_for_rfence);
else
static_branch_disable(&riscv_ipi_for_rfence);
}

static const char * const ipi_names[] = {
Expand Down
7 changes: 4 additions & 3 deletions arch/riscv/kernel/smpboot.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
#include <linux/sched/task_stack.h>
#include <linux/sched/mm.h>

#include <asm/cpufeature.h>
#include <asm/cacheflush.h>
#include <asm/cpu_ops.h>
#include <asm/cpufeature.h>
#include <asm/irq.h>
Expand Down Expand Up @@ -266,9 +266,10 @@ asmlinkage __visible void smp_callin(void)
}

/*
* Remote TLB flushes are ignored while the CPU is offline, so emit
* a local TLB flush right now just in case.
* Remote cache and TLB flushes are ignored while the CPU is offline,
* so flush them both right now just in case.
*/
local_flush_icache_all();
local_flush_tlb_all();
#ifndef CONFIG_HOTPLUG_PARALLEL
complete(&cpu_running);
Expand Down
5 changes: 1 addition & 4 deletions arch/riscv/mm/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,11 @@ endif
KCOV_INSTRUMENT_init.o := n

obj-y += init.o
obj-$(CONFIG_MMU) += extable.o fault.o pageattr.o pgtable.o
obj-$(CONFIG_MMU) += extable.o fault.o pageattr.o pgtable.o tlbflush.o
obj-y += cacheflush.o
obj-y += context.o
obj-y += pmem.o

ifeq ($(CONFIG_MMU),y)
obj-$(CONFIG_SMP) += tlbflush.o
endif
obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o
obj-$(CONFIG_PTDUMP_CORE) += ptdump.o
obj-$(CONFIG_KASAN) += kasan_init.o
Expand Down
7 changes: 4 additions & 3 deletions arch/riscv/mm/cacheflush.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@ void flush_icache_all(void)
{
local_flush_icache_all();

if (IS_ENABLED(CONFIG_RISCV_SBI) && !riscv_use_ipi_for_rfence())
if (num_online_cpus() < 2)
return;
else if (riscv_use_sbi_for_rfence())
sbi_remote_fence_i(NULL);
else
on_each_cpu(ipi_remote_fence_i, NULL, 1);
Expand Down Expand Up @@ -69,8 +71,7 @@ void flush_icache_mm(struct mm_struct *mm, bool local)
* with flush_icache_deferred().
*/
smp_mb();
} else if (IS_ENABLED(CONFIG_RISCV_SBI) &&
!riscv_use_ipi_for_rfence()) {
} else if (riscv_use_sbi_for_rfence()) {
sbi_remote_fence_i(&others);
} else {
on_each_cpu_mask(&others, ipi_remote_fence_i, NULL, 1);
Expand Down
Loading
Loading