From 536eeefa969a711b0ae55b54032418e3f8453e5a Mon Sep 17 00:00:00 2001
From: Armin Luntzer <armin.luntzer@univie.ac.at>
Date: Tue, 12 Nov 2019 11:14:51 +0100
Subject: [PATCH] SPARC:  - add leon_force_irq()  - set multiprocessor
 interrupt for cross-cpu signalling  - implement SMP functions  - call
 smp_init() in setup_arch()

---
 arch/sparc/include/asm/leon.h      |  4 +++
 arch/sparc/include/asm/switch_to.h |  2 +-
 arch/sparc/kernel/Makefile         |  1 +
 arch/sparc/kernel/irq.c            | 26 +++++++++++++++--
 arch/sparc/kernel/setup.c          | 38 +++++++++++++++---------
 arch/sparc/kernel/smp.c            | 47 ++++++++++++++++++++++++++++++
 6 files changed, 101 insertions(+), 17 deletions(-)
 create mode 100644 arch/sparc/kernel/smp.c

diff --git a/arch/sparc/include/asm/leon.h b/arch/sparc/include/asm/leon.h
index 66d95c7..4bf512e 100644
--- a/arch/sparc/include/asm/leon.h
+++ b/arch/sparc/include/asm/leon.h
@@ -24,6 +24,10 @@
 
 
 
+/* use IRQMP for inter-processor interrupt */
+#define LEON3_IPIRQ		12
+
+
 #define ASI_LEON3_SYSCTRL	0x02
 
 #define ASI_LEON3_SYSCTRL_CCR	0x00
diff --git a/arch/sparc/include/asm/switch_to.h b/arch/sparc/include/asm/switch_to.h
index cb6185c..3b07081 100644
--- a/arch/sparc/include/asm/switch_to.h
+++ b/arch/sparc/include/asm/switch_to.h
@@ -187,7 +187,7 @@ __asm__ __volatile__(							\
 	" nop\n\t"						\
 	"here:\n\t"						\
 	:							\
-	: "r" (&(current_set[leon3_cpuid()])),			\
+	: "r" (&(current_set[smp_cpu_id()])),			\
 	  "r" (&(next->thread_info)),				\
 	  "i" (TI_KSP),						\
 	  "i" (TI_KPC),						\
diff --git a/arch/sparc/kernel/Makefile b/arch/sparc/kernel/Makefile
index 67a1186..69b6ca4 100644
--- a/arch/sparc/kernel/Makefile
+++ b/arch/sparc/kernel/Makefile
@@ -27,6 +27,7 @@ obj-y += stack.o
 obj-y += traps/data_access_exception_trap.o
 obj-y += traps/data_access_exception.o
 obj-y += irq.o
+obj-y += smp.o
 obj-y += time.o
 obj-y += clockevent.o
 
diff --git a/arch/sparc/kernel/irq.c b/arch/sparc/kernel/irq.c
index 8a11735..bb66021 100644
--- a/arch/sparc/kernel/irq.c
+++ b/arch/sparc/kernel/irq.c
@@ -461,7 +461,7 @@ static void leon_mask_irq(unsigned int irq, int cpu)
  * @param cpu the cpu for which the interrupt is to be enabled
  */
 
-static void leon_enable_irq(unsigned int irq, int cpu)
+void leon_enable_irq(unsigned int irq, int cpu)
 {
 	leon_clear_irq(irq);
 
@@ -476,7 +476,7 @@ static void leon_enable_irq(unsigned int irq, int cpu)
  * @param cpu the cpu for which the interrupt is to be disabled
  */
 
-static void leon_disable_irq(unsigned int irq, int cpu)
+void leon_disable_irq(unsigned int irq, int cpu)
 {
 	leon_clear_irq(irq);
 
@@ -484,6 +484,28 @@ static void leon_disable_irq(unsigned int irq, int cpu)
 }
 
 
+
+/**
+ * @brief force an interrupt
+ *
+ * @param irq the interrupt to force
+ * @param cpu the cpu on which to force the interrupt (set < 0 for all)
+ *
+ * @note interrupts must be enabled for this to work
+ */
+
+void leon_force_irq(unsigned int irq, int cpu)
+{
+#ifdef CONFIG_LEON3
+	if (cpu >= 0) {
+		iowrite32be((1 << irq), &leon_irqctrl_regs->irq_mpforce[cpu]);
+		return;
+	}
+#endif
+	iowrite32be((1 << irq), &leon_irqctrl_regs->irq_force);
+}
+
+
 /**
  * @brief queue a handler for delayed exectuion
  *
diff --git a/arch/sparc/kernel/setup.c b/arch/sparc/kernel/setup.c
index 128d22c..0f9c0d8 100644
--- a/arch/sparc/kernel/setup.c
+++ b/arch/sparc/kernel/setup.c
@@ -21,6 +21,10 @@
 #include <stack.h>
 #include <kernel/kmem.h>
 
+#include <kernel/sched.h>
+
+#include <kernel/smp.h>
+
 void *_kernel_stack_top;
 void *_kernel_stack_bottom;
 
@@ -56,8 +60,6 @@ static void reserve_kernel_stack(void)
 	/* the (aligned) top of the stack */
 	_kernel_stack_top = (void *) (char *) _kernel_stack_bottom + k_stack_sz;
 	_kernel_stack_top = ALIGN_PTR(_kernel_stack_top, STACK_ALIGN);
-
-	printk("xxxxx reserved %p to %p\n", _kernel_stack_top, _kernel_stack_bottom);
 }
 
 
@@ -116,26 +118,30 @@ extern struct task_struct *kernel[];
 void smp_cpu_entry(void)
 {
 
-     reserve_kernel_stack();
-     BUG_ON(stack_migrate(NULL, _kernel_stack_top));
+	reserve_kernel_stack();
+	BUG_ON(stack_migrate(NULL, _kernel_stack_top));
+
+	printk("hi i'm cpu %d\n", leon3_cpuid());
 
-     printk("hi i'm cpu %d\n", leon3_cpuid());
+	BUG_ON(!leon3_cpuid());
 
-     BUG_ON(!leon3_cpuid());
-      /* signal ready */
-      iowrite32be(0x1, &cpu1_ready);
+	/* signal ready */
+	iowrite32be(0x1, &cpu1_ready);
 
 	while (ioread32be(&cpu1_ready) != 0x2);
+
 	BUG_ON(clockevents_offer_device());
+
 	kthread_init_main();
 
-      iowrite32be(0x3, &cpu1_ready);
+	iowrite32be(0x3, &cpu1_ready);
+
 	while (ioread32be(&cpu1_ready) != 0x4);
-      while(1) {
-//	     printk(".\n");
-	      cpu_relax();
-      }
-//	      printk("1\n");
+
+	sched_enable();
+
+	while(1)
+		cpu_relax();
 }
 
 
@@ -164,5 +170,9 @@ void setup_arch(void)
 
 	sparc_clockevent_init();
 
+	smp_init();
+
 	boot_cpus();
+
+	sched_enable();
 }
diff --git a/arch/sparc/kernel/smp.c b/arch/sparc/kernel/smp.c
new file mode 100644
index 0000000..f50a053
--- /dev/null
+++ b/arch/sparc/kernel/smp.c
@@ -0,0 +1,47 @@
+/**
+ * @file arch/sparc/kernel/smp.c
+ *
+ * @ingroup sparc
+ * @brief implements architecture-specific @ref kernel_smp interface
+ */
+
+#include <kernel/smp.h>
+#include <irq.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+
+#ifdef CONFIG_LEON3
+#include <asm/leon.h>
+#endif
+
+
+int smp_cpu_id(void)
+{
+#ifdef CONFIG_LEON3
+	return leon3_cpuid();
+#else /* !CONFIG_LEON3 */
+	return 0;
+#endif /* CONFIG_LEON3 */
+}
+
+
+void smp_send_reschedule(int cpu)
+{
+#ifdef CONFIG_LEON3
+	/* trigger reschedule via forced IRQMP extended interrupt */
+	/* TODO sanity check for cpu id */
+	leon_force_irq(LEON3_IPIRQ, cpu);
+#endif /* CONFIG_LEON3 */
+}
+
+
+void smp_init(void)
+{
+#ifdef CONFIG_LEON3
+
+	/* XXX need number of CPUs here */
+	leon_enable_irq(LEON3_IPIRQ, 0);
+	leon_enable_irq(LEON3_IPIRQ, 1);
+
+#endif /* CONFIG_LEON3 */
+}
-- 
GitLab