Skip to content

Commit f99fb60

Browse files
atishp04palmer-dabbelt
authored andcommitted
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>
1 parent 6825c7a commit f99fb60

File tree

8 files changed

+71
-32
lines changed

8 files changed

+71
-32
lines changed

arch/riscv/include/asm/tlbflush.h

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#define _ASM_RISCV_TLBFLUSH_H
1717

1818
#include <linux/mm_types.h>
19+
#include <asm/smp.h>
1920

2021
/*
2122
* 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,
4950

5051
#include <asm/sbi.h>
5152

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+
5263
#define flush_tlb_all() sbi_remote_sfence_vma(NULL, 0, -1)
5364
#define flush_tlb_page(vma, addr) flush_tlb_range(vma, addr, 0)
5465
#define flush_tlb_range(vma, start, end) \
55-
sbi_remote_sfence_vma(mm_cpumask((vma)->vm_mm)->bits, \
56-
start, (end) - (start))
66+
remote_sfence_vma(mm_cpumask((vma)->vm_mm), start, (end) - (start))
5767
#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)
5969

6070
#endif /* CONFIG_SMP */
6171

arch/riscv/kernel/cpu.c

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include <linux/init.h>
1515
#include <linux/seq_file.h>
1616
#include <linux/of.h>
17+
#include <asm/smp.h>
1718

1819
/*
1920
* 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)
138139

139140
static int c_show(struct seq_file *m, void *v)
140141
{
141-
unsigned long hart_id = (unsigned long)v - 1;
142-
struct device_node *node = of_get_cpu_node(hart_id, NULL);
142+
unsigned long cpu_id = (unsigned long)v - 1;
143+
struct device_node *node = of_get_cpu_node(cpuid_to_hartid_map(cpu_id),
144+
NULL);
143145
const char *compat, *isa, *mmu;
144146

145-
seq_printf(m, "hart\t: %lu\n", hart_id);
147+
seq_printf(m, "hart\t: %lu\n", cpu_id);
146148
if (!of_property_read_string(node, "riscv,isa", &isa))
147149
print_isa(m, isa);
148150
if (!of_property_read_string(node, "mmu-type", &mmu))

arch/riscv/kernel/head.S

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ ENTRY(_start)
4747
/* Save hart ID and DTB physical address */
4848
mv s0, a0
4949
mv s1, a1
50+
la a2, boot_cpu_hartid
51+
REG_S a0, (a2)
5052

5153
/* Initialize page tables and relocate to virtual addresses */
5254
la sp, init_thread_union + THREAD_SIZE
@@ -55,7 +57,7 @@ ENTRY(_start)
5557

5658
/* Restore C environment */
5759
la tp, init_task
58-
sw s0, TASK_TI_CPU(tp)
60+
sw zero, TASK_TI_CPU(tp)
5961

6062
la sp, init_thread_union
6163
li a0, ASM_THREAD_SIZE

arch/riscv/kernel/setup.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,11 +81,17 @@ EXPORT_SYMBOL(empty_zero_page);
8181

8282
/* The lucky hart to first increment this variable will boot the other cores */
8383
atomic_t hart_lottery;
84+
unsigned long boot_cpu_hartid;
8485

8586
unsigned long __cpuid_to_hartid_map[NR_CPUS] = {
8687
[0 ... NR_CPUS-1] = INVALID_HARTID
8788
};
8889

90+
void __init smp_setup_processor_id(void)
91+
{
92+
cpuid_to_hartid_map(0) = boot_cpu_hartid;
93+
}
94+
8995
#ifdef CONFIG_BLK_DEV_INITRD
9096
static void __init setup_initrd(void)
9197
{

arch/riscv/kernel/smp.c

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -97,14 +97,18 @@ void riscv_software_interrupt(void)
9797
static void
9898
send_ipi_message(const struct cpumask *to_whom, enum ipi_message_type operation)
9999
{
100-
int i;
100+
int cpuid, hartid;
101+
struct cpumask hartid_mask;
101102

103+
cpumask_clear(&hartid_mask);
102104
mb();
103-
for_each_cpu(i, to_whom)
104-
set_bit(operation, &ipi_data[i].bits);
105-
105+
for_each_cpu(cpuid, to_whom) {
106+
set_bit(operation, &ipi_data[cpuid].bits);
107+
hartid = cpuid_to_hartid_map(cpuid);
108+
cpumask_set_cpu(hartid, &hartid_mask);
109+
}
106110
mb();
107-
sbi_send_ipi(cpumask_bits(to_whom));
111+
sbi_send_ipi(cpumask_bits(&hartid_mask));
108112
}
109113

110114
void arch_send_call_function_ipi_mask(struct cpumask *mask)
@@ -146,7 +150,7 @@ void smp_send_reschedule(int cpu)
146150
void flush_icache_mm(struct mm_struct *mm, bool local)
147151
{
148152
unsigned int cpu;
149-
cpumask_t others, *mask;
153+
cpumask_t others, hmask, *mask;
150154

151155
preempt_disable();
152156

@@ -164,9 +168,11 @@ void flush_icache_mm(struct mm_struct *mm, bool local)
164168
*/
165169
cpumask_andnot(&others, mm_cpumask(mm), cpumask_of(cpu));
166170
local |= cpumask_empty(&others);
167-
if (mm != current->active_mm || !local)
168-
sbi_remote_fence_i(others.bits);
169-
else {
171+
if (mm != current->active_mm || !local) {
172+
cpumask_clear(&hmask);
173+
riscv_cpuid_to_hartid_mask(&others, &hmask);
174+
sbi_remote_fence_i(hmask.bits);
175+
} else {
170176
/*
171177
* It's assumed that at least one strongly ordered operation is
172178
* performed on this hart between setting a hart's cpumask bit

arch/riscv/kernel/smpboot.c

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -53,24 +53,31 @@ void __init setup_smp(void)
5353
struct device_node *dn = NULL;
5454
int hart;
5555
bool found_boot_cpu = false;
56+
int cpuid = 1;
5657

5758
while ((dn = of_find_node_by_type(dn, "cpu"))) {
5859
hart = riscv_of_processor_hartid(dn);
59-
if (hart >= 0) {
60-
set_cpu_possible(hart, true);
61-
set_cpu_present(hart, true);
62-
if (hart == smp_processor_id()) {
63-
BUG_ON(found_boot_cpu);
64-
found_boot_cpu = true;
65-
}
60+
if (hart < 0)
61+
continue;
62+
63+
if (hart == cpuid_to_hartid_map(0)) {
64+
BUG_ON(found_boot_cpu);
65+
found_boot_cpu = 1;
66+
continue;
6667
}
68+
69+
cpuid_to_hartid_map(cpuid) = hart;
70+
set_cpu_possible(cpuid, true);
71+
set_cpu_present(cpuid, true);
72+
cpuid++;
6773
}
6874

6975
BUG_ON(!found_boot_cpu);
7076
}
7177

7278
int __cpu_up(unsigned int cpu, struct task_struct *tidle)
7379
{
80+
int hartid = cpuid_to_hartid_map(cpu);
7481
tidle->thread_info.cpu = cpu;
7582

7683
/*
@@ -81,9 +88,9 @@ int __cpu_up(unsigned int cpu, struct task_struct *tidle)
8188
* the spinning harts that they can continue the boot process.
8289
*/
8390
smp_mb();
84-
WRITE_ONCE(__cpu_up_stack_pointer[cpu],
91+
WRITE_ONCE(__cpu_up_stack_pointer[hartid],
8592
task_stack_page(tidle) + THREAD_SIZE);
86-
WRITE_ONCE(__cpu_up_task_pointer[cpu], tidle);
93+
WRITE_ONCE(__cpu_up_task_pointer[hartid], tidle);
8794

8895
while (!cpu_online(cpu))
8996
cpu_relax();

drivers/clocksource/riscv_timer.c

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include <linux/cpu.h>
99
#include <linux/delay.h>
1010
#include <linux/irq.h>
11+
#include <asm/smp.h>
1112
#include <asm/sbi.h>
1213

1314
/*
@@ -84,21 +85,24 @@ void riscv_timer_interrupt(void)
8485

8586
static int __init riscv_timer_init_dt(struct device_node *n)
8687
{
87-
int cpu_id = riscv_of_processor_hartid(n), error;
88+
int cpuid, hartid, error;
8889
struct clocksource *cs;
8990

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())
9195
return 0;
9296

93-
cs = per_cpu_ptr(&riscv_clocksource, cpu_id);
97+
cs = per_cpu_ptr(&riscv_clocksource, cpuid);
9498
clocksource_register_hz(cs, riscv_timebase);
9599

96100
error = cpuhp_setup_state(CPUHP_AP_RISCV_TIMER_STARTING,
97101
"clockevents/riscv/timer:starting",
98102
riscv_timer_starting_cpu, riscv_timer_dying_cpu);
99103
if (error)
100104
pr_err("RISCV timer register failed [%d] for cpu = [%d]\n",
101-
error, cpu_id);
105+
error, cpuid);
102106
return error;
103107
}
104108

drivers/irqchip/irq-sifive-plic.c

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include <linux/of_irq.h>
1616
#include <linux/platform_device.h>
1717
#include <linux/spinlock.h>
18+
#include <asm/smp.h>
1819

1920
/*
2021
* 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,
218219
struct of_phandle_args parent;
219220
struct plic_handler *handler;
220221
irq_hw_number_t hwirq;
221-
int cpu;
222+
int cpu, hartid;
222223

223224
if (of_irq_parse_one(node, i, &parent)) {
224225
pr_err("failed to parse parent for context %d.\n", i);
@@ -229,12 +230,13 @@ static int __init plic_init(struct device_node *node,
229230
if (parent.args[0] == -1)
230231
continue;
231232

232-
cpu = plic_find_hart_id(parent.np);
233-
if (cpu < 0) {
233+
hartid = plic_find_hart_id(parent.np);
234+
if (hartid < 0) {
234235
pr_warn("failed to parse hart ID for context %d.\n", i);
235236
continue;
236237
}
237238

239+
cpu = riscv_hartid_to_cpuid(hartid);
238240
handler = per_cpu_ptr(&plic_handlers, cpu);
239241
handler->present = true;
240242
handler->ctxid = i;

0 commit comments

Comments
 (0)