riscv: memcpy: check src and dst before copy
[platform/kernel/u-boot.git] / arch / riscv / lib / smp.c
index ac22136..4f073a0 100644 (file)
@@ -8,6 +8,7 @@
 #include <cpu_func.h>
 #include <dm.h>
 #include <asm/barrier.h>
+#include <asm/global_data.h>
 #include <asm/smp.h>
 
 DECLARE_GLOBAL_DATA_PTR;
@@ -26,7 +27,7 @@ static int send_ipi_many(struct ipi_data *ipi, int wait)
 
        ofnode_for_each_subnode(node, cpus) {
                /* skip if hart is marked as not available in the device tree */
-               if (!ofnode_is_available(node))
+               if (!ofnode_is_enabled(node))
                        continue;
 
                /* read hart ID of CPU */
@@ -44,16 +45,26 @@ static int send_ipi_many(struct ipi_data *ipi, int wait)
                        continue;
                }
 
-#ifndef CONFIG_XIP
+#if !CONFIG_IS_ENABLED(XIP)
+#ifdef CONFIG_AVAILABLE_HARTS
                /* skip if hart is not available */
                if (!(gd->arch.available_harts & (1 << reg)))
                        continue;
 #endif
+#endif
 
                gd->arch.ipi[reg].addr = ipi->addr;
                gd->arch.ipi[reg].arg0 = ipi->arg0;
                gd->arch.ipi[reg].arg1 = ipi->arg1;
 
+               /*
+                * Ensure valid only becomes set when the IPI parameters are
+                * set. An IPI may already be pending on other harts, so we
+                * need a way to signal that the IPI device has been
+                * initialized, and that it is ok to call the function.
+                */
+               __smp_store_release(&gd->arch.ipi[reg].valid, 1);
+
                ret = riscv_send_ipi(reg);
                if (ret) {
                        pr_err("Cannot send IPI to hart %d\n", reg);
@@ -81,7 +92,13 @@ void handle_ipi(ulong hart)
        if (hart >= CONFIG_NR_CPUS)
                return;
 
-       __smp_mb();
+       /*
+        * If valid is not set, then U-Boot has not requested the IPI. The
+        * IPI device may not be initialized, so all we can do is wait for
+        * U-Boot to initialize it and send an IPI
+        */
+       if (!__smp_load_acquire(&gd->arch.ipi[hart].valid))
+               return;
 
        smp_function = (void (*)(ulong, ulong, ulong))gd->arch.ipi[hart].addr;
        invalidate_icache_all();