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