aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAtish Patra <atish.patra@wdc.com>2018-10-02 15:15:05 -0400
committerPalmer Dabbelt <palmer@sifive.com>2018-10-22 20:03:37 -0400
commitf99fb607fb2bc0d4ce6b9adb764c65e37f40a92b (patch)
tree082100e81815f6c2fa5d152821d24351aa16a871
parent6825c7a80f1863b975a00042abe140ea24813af2 (diff)
RISC-V: Use Linux logical CPU number instead of hartid
Setup the cpu_logical_map during boot. Moreover, every SBI call and PLIC context are based on the physical hartid. Use the logical CPU to hartid mapping to pass correct hartid to respective functions. Signed-off-by: Atish Patra <atish.patra@wdc.com> Reviewed-by: Anup Patel <anup@brainfault.org> Reviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Palmer Dabbelt <palmer@sifive.com>
-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;