diff options
-rw-r--r-- | arch/riscv/include/asm/tlbflush.h | 16 | ||||
-rw-r--r-- | arch/riscv/kernel/cpu.c | 8 | ||||
-rw-r--r-- | arch/riscv/kernel/head.S | 4 | ||||
-rw-r--r-- | arch/riscv/kernel/setup.c | 6 | ||||
-rw-r--r-- | arch/riscv/kernel/smp.c | 24 | ||||
-rw-r--r-- | arch/riscv/kernel/smpboot.c | 25 | ||||
-rw-r--r-- | drivers/clocksource/riscv_timer.c | 12 | ||||
-rw-r--r-- | drivers/irqchip/irq-sifive-plic.c | 8 |
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 | ||
53 | static 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 | ||
139 | static int c_show(struct seq_file *m, void *v) | 140 | static 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 */ |
83 | atomic_t hart_lottery; | 83 | atomic_t hart_lottery; |
84 | unsigned long boot_cpu_hartid; | ||
84 | 85 | ||
85 | unsigned long __cpuid_to_hartid_map[NR_CPUS] = { | 86 | unsigned 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 | ||
90 | void __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 |
90 | static void __init setup_initrd(void) | 96 | static 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) | |||
97 | static void | 97 | static void |
98 | send_ipi_message(const struct cpumask *to_whom, enum ipi_message_type operation) | 98 | send_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 | ||
110 | void arch_send_call_function_ipi_mask(struct cpumask *mask) | 114 | void arch_send_call_function_ipi_mask(struct cpumask *mask) |
@@ -146,7 +150,7 @@ void smp_send_reschedule(int cpu) | |||
146 | void flush_icache_mm(struct mm_struct *mm, bool local) | 150 | void 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 | ||
72 | int __cpu_up(unsigned int cpu, struct task_struct *tidle) | 78 | int __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 | ||
85 | static int __init riscv_timer_init_dt(struct device_node *n) | 86 | static 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; |