RISC-V: Use Linux logical CPU number instead of hartid
authorAtish Patra <atish.patra@wdc.com>
Tue, 2 Oct 2018 19:15:05 +0000 (12:15 -0700)
committerPalmer Dabbelt <palmer@sifive.com>
Tue, 23 Oct 2018 00:03:37 +0000 (17:03 -0700)
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>
arch/riscv/include/asm/tlbflush.h
arch/riscv/kernel/cpu.c
arch/riscv/kernel/head.S
arch/riscv/kernel/setup.c
arch/riscv/kernel/smp.c
arch/riscv/kernel/smpboot.c
drivers/clocksource/riscv_timer.c
drivers/irqchip/irq-sifive-plic.c

index 85c2d8bae9571ab2c3557b34b04b59d3355733a6..54fee0cadb1ebf34cc2b91d3d78f127c0b18d177 100644 (file)
@@ -16,6 +16,7 @@
 #define _ASM_RISCV_TLBFLUSH_H
 
 #include <linux/mm_types.h>
+#include <asm/smp.h>
 
 /*
  * 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,
 
 #include <asm/sbi.h>
 
+static inline void remote_sfence_vma(struct cpumask *cmask, unsigned long start,
+                                    unsigned long size)
+{
+       struct cpumask hmask;
+
+       cpumask_clear(&hmask);
+       riscv_cpuid_to_hartid_mask(cmask, &hmask);
+       sbi_remote_sfence_vma(hmask.bits, start, size);
+}
+
 #define flush_tlb_all() sbi_remote_sfence_vma(NULL, 0, -1)
 #define flush_tlb_page(vma, addr) flush_tlb_range(vma, addr, 0)
 #define flush_tlb_range(vma, start, end) \
-       sbi_remote_sfence_vma(mm_cpumask((vma)->vm_mm)->bits, \
-                             start, (end) - (start))
+       remote_sfence_vma(mm_cpumask((vma)->vm_mm), start, (end) - (start))
 #define flush_tlb_mm(mm) \
-       sbi_remote_sfence_vma(mm_cpumask(mm)->bits, 0, -1)
+       remote_sfence_vma(mm_cpumask(mm), 0, -1)
 
 #endif /* CONFIG_SMP */
 
index 4723e235dcaa356710a2707ab0b4237ab4c5104e..cccc6f61c5382b50e95bcdc6c1ffe7877969671c 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/init.h>
 #include <linux/seq_file.h>
 #include <linux/of.h>
+#include <asm/smp.h>
 
 /*
  * 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)
 
 static int c_show(struct seq_file *m, void *v)
 {
-       unsigned long hart_id = (unsigned long)v - 1;
-       struct device_node *node = of_get_cpu_node(hart_id, NULL);
+       unsigned long cpu_id = (unsigned long)v - 1;
+       struct device_node *node = of_get_cpu_node(cpuid_to_hartid_map(cpu_id),
+                                                  NULL);
        const char *compat, *isa, *mmu;
 
-       seq_printf(m, "hart\t: %lu\n", hart_id);
+       seq_printf(m, "hart\t: %lu\n", cpu_id);
        if (!of_property_read_string(node, "riscv,isa", &isa))
                print_isa(m, isa);
        if (!of_property_read_string(node, "mmu-type", &mmu))
index c4d2c63f9a2927396f2d47c23e35a9fdedcd21f9..711190d473d41f47dd52f9fc4720df720ebf57be 100644 (file)
@@ -47,6 +47,8 @@ ENTRY(_start)
        /* Save hart ID and DTB physical address */
        mv s0, a0
        mv s1, a1
+       la a2, boot_cpu_hartid
+       REG_S a0, (a2)
 
        /* Initialize page tables and relocate to virtual addresses */
        la sp, init_thread_union + THREAD_SIZE
@@ -55,7 +57,7 @@ ENTRY(_start)
 
        /* Restore C environment */
        la tp, init_task
-       sw s0, TASK_TI_CPU(tp)
+       sw zero, TASK_TI_CPU(tp)
 
        la sp, init_thread_union
        li a0, ASM_THREAD_SIZE
index d5d8611066d56514c7357d30a1265b6445fa58e9..5e9e6f934cc036af2263bd9444ebed1a62a66139 100644 (file)
@@ -81,11 +81,17 @@ EXPORT_SYMBOL(empty_zero_page);
 
 /* The lucky hart to first increment this variable will boot the other cores */
 atomic_t hart_lottery;
+unsigned long boot_cpu_hartid;
 
 unsigned long __cpuid_to_hartid_map[NR_CPUS] = {
        [0 ... NR_CPUS-1] = INVALID_HARTID
 };
 
+void __init smp_setup_processor_id(void)
+{
+       cpuid_to_hartid_map(0) = boot_cpu_hartid;
+}
+
 #ifdef CONFIG_BLK_DEV_INITRD
 static void __init setup_initrd(void)
 {
index 0bd48935f886fb87b724d3d45ee29f81d68a3c17..4eac0094f47e043a3730720b5c07f62ff706d616 100644 (file)
@@ -97,14 +97,18 @@ void riscv_software_interrupt(void)
 static void
 send_ipi_message(const struct cpumask *to_whom, enum ipi_message_type operation)
 {
-       int i;
+       int cpuid, hartid;
+       struct cpumask hartid_mask;
 
+       cpumask_clear(&hartid_mask);
        mb();
-       for_each_cpu(i, to_whom)
-               set_bit(operation, &ipi_data[i].bits);
-
+       for_each_cpu(cpuid, to_whom) {
+               set_bit(operation, &ipi_data[cpuid].bits);
+               hartid = cpuid_to_hartid_map(cpuid);
+               cpumask_set_cpu(hartid, &hartid_mask);
+       }
        mb();
-       sbi_send_ipi(cpumask_bits(to_whom));
+       sbi_send_ipi(cpumask_bits(&hartid_mask));
 }
 
 void arch_send_call_function_ipi_mask(struct cpumask *mask)
@@ -146,7 +150,7 @@ void smp_send_reschedule(int cpu)
 void flush_icache_mm(struct mm_struct *mm, bool local)
 {
        unsigned int cpu;
-       cpumask_t others, *mask;
+       cpumask_t others, hmask, *mask;
 
        preempt_disable();
 
@@ -164,9 +168,11 @@ void flush_icache_mm(struct mm_struct *mm, bool local)
         */
        cpumask_andnot(&others, mm_cpumask(mm), cpumask_of(cpu));
        local |= cpumask_empty(&others);
-       if (mm != current->active_mm || !local)
-               sbi_remote_fence_i(others.bits);
-       else {
+       if (mm != current->active_mm || !local) {
+               cpumask_clear(&hmask);
+               riscv_cpuid_to_hartid_mask(&others, &hmask);
+               sbi_remote_fence_i(hmask.bits);
+       } else {
                /*
                 * It's assumed that at least one strongly ordered operation is
                 * performed on this hart between setting a hart's cpumask bit
index 1e478615017c84b47a560a3077d2b83b65cf5fb0..18cda0e8cf9414310e0ec594ee30360f7938808c 100644 (file)
@@ -53,17 +53,23 @@ void __init setup_smp(void)
        struct device_node *dn = NULL;
        int hart;
        bool found_boot_cpu = false;
+       int cpuid = 1;
 
        while ((dn = of_find_node_by_type(dn, "cpu"))) {
                hart = riscv_of_processor_hartid(dn);
-               if (hart >= 0) {
-                       set_cpu_possible(hart, true);
-                       set_cpu_present(hart, true);
-                       if (hart == smp_processor_id()) {
-                               BUG_ON(found_boot_cpu);
-                               found_boot_cpu = true;
-                       }
+               if (hart < 0)
+                       continue;
+
+               if (hart == cpuid_to_hartid_map(0)) {
+                       BUG_ON(found_boot_cpu);
+                       found_boot_cpu = 1;
+                       continue;
                }
+
+               cpuid_to_hartid_map(cpuid) = hart;
+               set_cpu_possible(cpuid, true);
+               set_cpu_present(cpuid, true);
+               cpuid++;
        }
 
        BUG_ON(!found_boot_cpu);
@@ -71,6 +77,7 @@ void __init setup_smp(void)
 
 int __cpu_up(unsigned int cpu, struct task_struct *tidle)
 {
+       int hartid = cpuid_to_hartid_map(cpu);
        tidle->thread_info.cpu = cpu;
 
        /*
@@ -81,9 +88,9 @@ int __cpu_up(unsigned int cpu, struct task_struct *tidle)
         * the spinning harts that they can continue the boot process.
         */
        smp_mb();
-       WRITE_ONCE(__cpu_up_stack_pointer[cpu],
+       WRITE_ONCE(__cpu_up_stack_pointer[hartid],
                  task_stack_page(tidle) + THREAD_SIZE);
-       WRITE_ONCE(__cpu_up_task_pointer[cpu], tidle);
+       WRITE_ONCE(__cpu_up_task_pointer[hartid], tidle);
 
        while (!cpu_online(cpu))
                cpu_relax();
index ad7453fc3129f2d3e25dc4379e90e26d35ca6f42..084e97dc10ed9fd8c89004ee16894e93db573ff4 100644 (file)
@@ -8,6 +8,7 @@
 #include <linux/cpu.h>
 #include <linux/delay.h>
 #include <linux/irq.h>
+#include <asm/smp.h>
 #include <asm/sbi.h>
 
 /*
@@ -84,13 +85,16 @@ void riscv_timer_interrupt(void)
 
 static int __init riscv_timer_init_dt(struct device_node *n)
 {
-       int cpu_id = riscv_of_processor_hartid(n), error;
+       int cpuid, hartid, error;
        struct clocksource *cs;
 
-       if (cpu_id != smp_processor_id())
+       hartid = riscv_of_processor_hartid(n);
+       cpuid = riscv_hartid_to_cpuid(hartid);
+
+       if (cpuid != smp_processor_id())
                return 0;
 
-       cs = per_cpu_ptr(&riscv_clocksource, cpu_id);
+       cs = per_cpu_ptr(&riscv_clocksource, cpuid);
        clocksource_register_hz(cs, riscv_timebase);
 
        error = cpuhp_setup_state(CPUHP_AP_RISCV_TIMER_STARTING,
@@ -98,7 +102,7 @@ static int __init riscv_timer_init_dt(struct device_node *n)
                         riscv_timer_starting_cpu, riscv_timer_dying_cpu);
        if (error)
                pr_err("RISCV timer register failed [%d] for cpu = [%d]\n",
-                      error, cpu_id);
+                      error, cpuid);
        return error;
 }
 
index c55eaa31cde24701505e1f9996386378c6fd64be..357e9daf94ae061dad439df9404f9898354d7930 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/of_irq.h>
 #include <linux/platform_device.h>
 #include <linux/spinlock.h>
+#include <asm/smp.h>
 
 /*
  * 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,
                struct of_phandle_args parent;
                struct plic_handler *handler;
                irq_hw_number_t hwirq;
-               int cpu;
+               int cpu, hartid;
 
                if (of_irq_parse_one(node, i, &parent)) {
                        pr_err("failed to parse parent for context %d.\n", i);
@@ -229,12 +230,13 @@ static int __init plic_init(struct device_node *node,
                if (parent.args[0] == -1)
                        continue;
 
-               cpu = plic_find_hart_id(parent.np);
-               if (cpu < 0) {
+               hartid = plic_find_hart_id(parent.np);
+               if (hartid < 0) {
                        pr_warn("failed to parse hart ID for context %d.\n", i);
                        continue;
                }
 
+               cpu = riscv_hartid_to_cpuid(hartid);
                handler = per_cpu_ptr(&plic_handlers, cpu);
                handler->present = true;
                handler->ctxid = i;