aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/riscv/include/asm/tlbflush.h16
-rw-r--r--arch/riscv/kernel/cpu.c8
-rw-r--r--arch/riscv/kernel/head.S4
-rw-r--r--arch/riscv/kernel/setup.c6
-rw-r--r--arch/riscv/kernel/smp.c24
-rw-r--r--arch/riscv/kernel/smpboot.c25
-rw-r--r--drivers/clocksource/riscv_timer.c12
-rw-r--r--drivers/irqchip/irq-sifive-plic.c8
8 files changed, 71 insertions, 32 deletions
diff --git a/arch/riscv/include/asm/tlbflush.h b/arch/riscv/include/asm/tlbflush.h
index 85c2d8bae957..54fee0cadb1e 100644
--- a/arch/riscv/include/asm/tlbflush.h
+++ b/arch/riscv/include/asm/tlbflush.h
@@ -16,6 +16,7 @@
16#define _ASM_RISCV_TLBFLUSH_H 16#define _ASM_RISCV_TLBFLUSH_H
17 17
18#include <linux/mm_types.h> 18#include <linux/mm_types.h>
19#include <asm/smp.h>
19 20
20/* 21/*
21 * Flush entire local TLB. 'sfence.vma' implicitly fences with the instruction 22 * Flush entire local TLB. 'sfence.vma' implicitly fences with the instruction
@@ -49,13 +50,22 @@ static inline void flush_tlb_range(struct vm_area_struct *vma,
49 50
50#include <asm/sbi.h> 51#include <asm/sbi.h>
51 52
53static inline void remote_sfence_vma(struct cpumask *cmask, unsigned long start,
54 unsigned long size)
55{
56 struct cpumask hmask;
57
58 cpumask_clear(&hmask);
59 riscv_cpuid_to_hartid_mask(cmask, &hmask);
60 sbi_remote_sfence_vma(hmask.bits, start, size);
61}
62
52#define flush_tlb_all() sbi_remote_sfence_vma(NULL, 0, -1) 63#define flush_tlb_all() sbi_remote_sfence_vma(NULL, 0, -1)
53#define flush_tlb_page(vma, addr) flush_tlb_range(vma, addr, 0) 64#define flush_tlb_page(vma, addr) flush_tlb_range(vma, addr, 0)
54#define flush_tlb_range(vma, start, end) \ 65#define flush_tlb_range(vma, start, end) \
55 sbi_remote_sfence_vma(mm_cpumask((vma)->vm_mm)->bits, \ 66 remote_sfence_vma(mm_cpumask((vma)->vm_mm), start, (end) - (start))
56 start, (end) - (start))
57#define flush_tlb_mm(mm) \ 67#define flush_tlb_mm(mm) \
58 sbi_remote_sfence_vma(mm_cpumask(mm)->bits, 0, -1) 68 remote_sfence_vma(mm_cpumask(mm), 0, -1)
59 69
60#endif /* CONFIG_SMP */ 70#endif /* CONFIG_SMP */
61 71
diff --git a/arch/riscv/kernel/cpu.c b/arch/riscv/kernel/cpu.c
index 4723e235dcaa..cccc6f61c538 100644
--- a/arch/riscv/kernel/cpu.c
+++ b/arch/riscv/kernel/cpu.c
@@ -14,6 +14,7 @@
14#include <linux/init.h> 14#include <linux/init.h>
15#include <linux/seq_file.h> 15#include <linux/seq_file.h>
16#include <linux/of.h> 16#include <linux/of.h>
17#include <asm/smp.h>
17 18
18/* 19/*
19 * Returns the hart ID of the given device tree node, or -1 if the device tree 20 * Returns the hart ID of the given device tree node, or -1 if the device tree
@@ -138,11 +139,12 @@ static void c_stop(struct seq_file *m, void *v)
138 139
139static int c_show(struct seq_file *m, void *v) 140static int c_show(struct seq_file *m, void *v)
140{ 141{
141 unsigned long hart_id = (unsigned long)v - 1; 142 unsigned long cpu_id = (unsigned long)v - 1;
142 struct device_node *node = of_get_cpu_node(hart_id, NULL); 143 struct device_node *node = of_get_cpu_node(cpuid_to_hartid_map(cpu_id),
144 NULL);
143 const char *compat, *isa, *mmu; 145 const char *compat, *isa, *mmu;
144 146
145 seq_printf(m, "hart\t: %lu\n", hart_id); 147 seq_printf(m, "hart\t: %lu\n", cpu_id);
146 if (!of_property_read_string(node, "riscv,isa", &isa)) 148 if (!of_property_read_string(node, "riscv,isa", &isa))
147 print_isa(m, isa); 149 print_isa(m, isa);
148 if (!of_property_read_string(node, "mmu-type", &mmu)) 150 if (!of_property_read_string(node, "mmu-type", &mmu))
diff --git a/arch/riscv/kernel/head.S b/arch/riscv/kernel/head.S
index c4d2c63f9a29..711190d473d4 100644
--- a/arch/riscv/kernel/head.S
+++ b/arch/riscv/kernel/head.S
@@ -47,6 +47,8 @@ ENTRY(_start)
47 /* Save hart ID and DTB physical address */ 47 /* Save hart ID and DTB physical address */
48 mv s0, a0 48 mv s0, a0
49 mv s1, a1 49 mv s1, a1
50 la a2, boot_cpu_hartid
51 REG_S a0, (a2)
50 52
51 /* Initialize page tables and relocate to virtual addresses */ 53 /* Initialize page tables and relocate to virtual addresses */
52 la sp, init_thread_union + THREAD_SIZE 54 la sp, init_thread_union + THREAD_SIZE
@@ -55,7 +57,7 @@ ENTRY(_start)
55 57
56 /* Restore C environment */ 58 /* Restore C environment */
57 la tp, init_task 59 la tp, init_task
58 sw s0, TASK_TI_CPU(tp) 60 sw zero, TASK_TI_CPU(tp)
59 61
60 la sp, init_thread_union 62 la sp, init_thread_union
61 li a0, ASM_THREAD_SIZE 63 li a0, ASM_THREAD_SIZE
diff --git a/arch/riscv/kernel/setup.c b/arch/riscv/kernel/setup.c
index d5d8611066d5..5e9e6f934cc0 100644
--- a/arch/riscv/kernel/setup.c
+++ b/arch/riscv/kernel/setup.c
@@ -81,11 +81,17 @@ EXPORT_SYMBOL(empty_zero_page);
81 81
82/* The lucky hart to first increment this variable will boot the other cores */ 82/* The lucky hart to first increment this variable will boot the other cores */
83atomic_t hart_lottery; 83atomic_t hart_lottery;
84unsigned long boot_cpu_hartid;
84 85
85unsigned long __cpuid_to_hartid_map[NR_CPUS] = { 86unsigned long __cpuid_to_hartid_map[NR_CPUS] = {
86 [0 ... NR_CPUS-1] = INVALID_HARTID 87 [0 ... NR_CPUS-1] = INVALID_HARTID
87}; 88};
88 89
90void __init smp_setup_processor_id(void)
91{
92 cpuid_to_hartid_map(0) = boot_cpu_hartid;
93}
94
89#ifdef CONFIG_BLK_DEV_INITRD 95#ifdef CONFIG_BLK_DEV_INITRD
90static void __init setup_initrd(void) 96static void __init setup_initrd(void)
91{ 97{
diff --git a/arch/riscv/kernel/smp.c b/arch/riscv/kernel/smp.c
index 0bd48935f886..4eac0094f47e 100644
--- a/arch/riscv/kernel/smp.c
+++ b/arch/riscv/kernel/smp.c
@@ -97,14 +97,18 @@ void riscv_software_interrupt(void)
97static void 97static void
98send_ipi_message(const struct cpumask *to_whom, enum ipi_message_type operation) 98send_ipi_message(const struct cpumask *to_whom, enum ipi_message_type operation)
99{ 99{
100 int i; 100 int cpuid, hartid;
101 struct cpumask hartid_mask;
101 102
103 cpumask_clear(&hartid_mask);
102 mb(); 104 mb();
103 for_each_cpu(i, to_whom) 105 for_each_cpu(cpuid, to_whom) {
104 set_bit(operation, &ipi_data[i].bits); 106 set_bit(operation, &ipi_data[cpuid].bits);
105 107 hartid = cpuid_to_hartid_map(cpuid);
108 cpumask_set_cpu(hartid, &hartid_mask);
109 }
106 mb(); 110 mb();
107 sbi_send_ipi(cpumask_bits(to_whom)); 111 sbi_send_ipi(cpumask_bits(&hartid_mask));
108} 112}
109 113
110void arch_send_call_function_ipi_mask(struct cpumask *mask) 114void arch_send_call_function_ipi_mask(struct cpumask *mask)
@@ -146,7 +150,7 @@ void smp_send_reschedule(int cpu)
146void flush_icache_mm(struct mm_struct *mm, bool local) 150void flush_icache_mm(struct mm_struct *mm, bool local)
147{ 151{
148 unsigned int cpu; 152 unsigned int cpu;
149 cpumask_t others, *mask; 153 cpumask_t others, hmask, *mask;
150 154
151 preempt_disable(); 155 preempt_disable();
152 156
@@ -164,9 +168,11 @@ void flush_icache_mm(struct mm_struct *mm, bool local)
164 */ 168 */
165 cpumask_andnot(&others, mm_cpumask(mm), cpumask_of(cpu)); 169 cpumask_andnot(&others, mm_cpumask(mm), cpumask_of(cpu));
166 local |= cpumask_empty(&others); 170 local |= cpumask_empty(&others);
167 if (mm != current->active_mm || !local) 171 if (mm != current->active_mm || !local) {
168 sbi_remote_fence_i(others.bits); 172 cpumask_clear(&hmask);
169 else { 173 riscv_cpuid_to_hartid_mask(&others, &hmask);
174 sbi_remote_fence_i(hmask.bits);
175 } else {
170 /* 176 /*
171 * It's assumed that at least one strongly ordered operation is 177 * It's assumed that at least one strongly ordered operation is
172 * performed on this hart between setting a hart's cpumask bit 178 * performed on this hart between setting a hart's cpumask bit
diff --git a/arch/riscv/kernel/smpboot.c b/arch/riscv/kernel/smpboot.c
index 1e478615017c..18cda0e8cf94 100644
--- a/arch/riscv/kernel/smpboot.c
+++ b/arch/riscv/kernel/smpboot.c
@@ -53,17 +53,23 @@ void __init setup_smp(void)
53 struct device_node *dn = NULL; 53 struct device_node *dn = NULL;
54 int hart; 54 int hart;
55 bool found_boot_cpu = false; 55 bool found_boot_cpu = false;
56 int cpuid = 1;
56 57
57 while ((dn = of_find_node_by_type(dn, "cpu"))) { 58 while ((dn = of_find_node_by_type(dn, "cpu"))) {
58 hart = riscv_of_processor_hartid(dn); 59 hart = riscv_of_processor_hartid(dn);
59 if (hart >= 0) { 60 if (hart < 0)
60 set_cpu_possible(hart, true); 61 continue;
61 set_cpu_present(hart, true); 62
62 if (hart == smp_processor_id()) { 63 if (hart == cpuid_to_hartid_map(0)) {
63 BUG_ON(found_boot_cpu); 64 BUG_ON(found_boot_cpu);
64 found_boot_cpu = true; 65 found_boot_cpu = 1;
65 } 66 continue;
66 } 67 }
68
69 cpuid_to_hartid_map(cpuid) = hart;
70 set_cpu_possible(cpuid, true);
71 set_cpu_present(cpuid, true);
72 cpuid++;
67 } 73 }
68 74
69 BUG_ON(!found_boot_cpu); 75 BUG_ON(!found_boot_cpu);
@@ -71,6 +77,7 @@ void __init setup_smp(void)
71 77
72int __cpu_up(unsigned int cpu, struct task_struct *tidle) 78int __cpu_up(unsigned int cpu, struct task_struct *tidle)
73{ 79{
80 int hartid = cpuid_to_hartid_map(cpu);
74 tidle->thread_info.cpu = cpu; 81 tidle->thread_info.cpu = cpu;
75 82
76 /* 83 /*
@@ -81,9 +88,9 @@ int __cpu_up(unsigned int cpu, struct task_struct *tidle)
81 * the spinning harts that they can continue the boot process. 88 * the spinning harts that they can continue the boot process.
82 */ 89 */
83 smp_mb(); 90 smp_mb();
84 WRITE_ONCE(__cpu_up_stack_pointer[cpu], 91 WRITE_ONCE(__cpu_up_stack_pointer[hartid],
85 task_stack_page(tidle) + THREAD_SIZE); 92 task_stack_page(tidle) + THREAD_SIZE);
86 WRITE_ONCE(__cpu_up_task_pointer[cpu], tidle); 93 WRITE_ONCE(__cpu_up_task_pointer[hartid], tidle);
87 94
88 while (!cpu_online(cpu)) 95 while (!cpu_online(cpu))
89 cpu_relax(); 96 cpu_relax();
diff --git a/drivers/clocksource/riscv_timer.c b/drivers/clocksource/riscv_timer.c
index ad7453fc3129..084e97dc10ed 100644
--- a/drivers/clocksource/riscv_timer.c
+++ b/drivers/clocksource/riscv_timer.c
@@ -8,6 +8,7 @@
8#include <linux/cpu.h> 8#include <linux/cpu.h>
9#include <linux/delay.h> 9#include <linux/delay.h>
10#include <linux/irq.h> 10#include <linux/irq.h>
11#include <asm/smp.h>
11#include <asm/sbi.h> 12#include <asm/sbi.h>
12 13
13/* 14/*
@@ -84,13 +85,16 @@ void riscv_timer_interrupt(void)
84 85
85static int __init riscv_timer_init_dt(struct device_node *n) 86static int __init riscv_timer_init_dt(struct device_node *n)
86{ 87{
87 int cpu_id = riscv_of_processor_hartid(n), error; 88 int cpuid, hartid, error;
88 struct clocksource *cs; 89 struct clocksource *cs;
89 90
90 if (cpu_id != smp_processor_id()) 91 hartid = riscv_of_processor_hartid(n);
92 cpuid = riscv_hartid_to_cpuid(hartid);
93
94 if (cpuid != smp_processor_id())
91 return 0; 95 return 0;
92 96
93 cs = per_cpu_ptr(&riscv_clocksource, cpu_id); 97 cs = per_cpu_ptr(&riscv_clocksource, cpuid);
94 clocksource_register_hz(cs, riscv_timebase); 98 clocksource_register_hz(cs, riscv_timebase);
95 99
96 error = cpuhp_setup_state(CPUHP_AP_RISCV_TIMER_STARTING, 100 error = cpuhp_setup_state(CPUHP_AP_RISCV_TIMER_STARTING,
@@ -98,7 +102,7 @@ static int __init riscv_timer_init_dt(struct device_node *n)
98 riscv_timer_starting_cpu, riscv_timer_dying_cpu); 102 riscv_timer_starting_cpu, riscv_timer_dying_cpu);
99 if (error) 103 if (error)
100 pr_err("RISCV timer register failed [%d] for cpu = [%d]\n", 104 pr_err("RISCV timer register failed [%d] for cpu = [%d]\n",
101 error, cpu_id); 105 error, cpuid);
102 return error; 106 return error;
103} 107}
104 108
diff --git a/drivers/irqchip/irq-sifive-plic.c b/drivers/irqchip/irq-sifive-plic.c
index c55eaa31cde2..357e9daf94ae 100644
--- a/drivers/irqchip/irq-sifive-plic.c
+++ b/drivers/irqchip/irq-sifive-plic.c
@@ -15,6 +15,7 @@
15#include <linux/of_irq.h> 15#include <linux/of_irq.h>
16#include <linux/platform_device.h> 16#include <linux/platform_device.h>
17#include <linux/spinlock.h> 17#include <linux/spinlock.h>
18#include <asm/smp.h>
18 19
19/* 20/*
20 * This driver implements a version of the RISC-V PLIC with the actual layout 21 * This driver implements a version of the RISC-V PLIC with the actual layout
@@ -218,7 +219,7 @@ static int __init plic_init(struct device_node *node,
218 struct of_phandle_args parent; 219 struct of_phandle_args parent;
219 struct plic_handler *handler; 220 struct plic_handler *handler;
220 irq_hw_number_t hwirq; 221 irq_hw_number_t hwirq;
221 int cpu; 222 int cpu, hartid;
222 223
223 if (of_irq_parse_one(node, i, &parent)) { 224 if (of_irq_parse_one(node, i, &parent)) {
224 pr_err("failed to parse parent for context %d.\n", i); 225 pr_err("failed to parse parent for context %d.\n", i);
@@ -229,12 +230,13 @@ static int __init plic_init(struct device_node *node,
229 if (parent.args[0] == -1) 230 if (parent.args[0] == -1)
230 continue; 231 continue;
231 232
232 cpu = plic_find_hart_id(parent.np); 233 hartid = plic_find_hart_id(parent.np);
233 if (cpu < 0) { 234 if (hartid < 0) {
234 pr_warn("failed to parse hart ID for context %d.\n", i); 235 pr_warn("failed to parse hart ID for context %d.\n", i);
235 continue; 236 continue;
236 } 237 }
237 238
239 cpu = riscv_hartid_to_cpuid(hartid);
238 handler = per_cpu_ptr(&plic_handlers, cpu); 240 handler = per_cpu_ptr(&plic_handlers, cpu);
239 handler->present = true; 241 handler->present = true;
240 handler->ctxid = i; 242 handler->ctxid = i;