diff options
author | Visa Hankala <visa@cvs.openbsd.org> | 2017-02-19 08:59:42 +0000 |
---|---|---|
committer | Visa Hankala <visa@cvs.openbsd.org> | 2017-02-19 08:59:42 +0000 |
commit | 2af95003a6848ab8b9c968daad70fd5580e8fb96 (patch) | |
tree | cdf05c776cbb6ed305b659c39c8187f5c02417f7 /sys/arch/loongson | |
parent | 18e943d3e510adc284583b9559af489301098bcd (diff) |
Add SMP config and IPI control logic for Loongson 3A.
Diffstat (limited to 'sys/arch/loongson')
-rw-r--r-- | sys/arch/loongson/include/autoconf.h | 7 | ||||
-rw-r--r-- | sys/arch/loongson/include/intr.h | 5 | ||||
-rw-r--r-- | sys/arch/loongson/loongson/generic3a_machdep.c | 145 |
3 files changed, 149 insertions, 8 deletions
diff --git a/sys/arch/loongson/include/autoconf.h b/sys/arch/loongson/include/autoconf.h index 3de86536b7b..48e651d1055 100644 --- a/sys/arch/loongson/include/autoconf.h +++ b/sys/arch/loongson/include/autoconf.h @@ -1,4 +1,4 @@ -/* $OpenBSD: autoconf.h,v 1.14 2017/01/19 15:09:04 visa Exp $ */ +/* $OpenBSD: autoconf.h,v 1.15 2017/02/19 08:59:41 visa Exp $ */ /* * Copyright (c) 2001-2003 Opsycon AB (www.opsycon.se / www.opsycon.com) @@ -94,6 +94,11 @@ extern uint loongson_cpumask; extern uint loongson_ver; extern int nnodes; +#ifdef MULTIPROCESSOR +extern uint64_t cpu_spinup_a0; +extern uint64_t cpu_spinup_sp; +#endif + struct mainbus_attach_args { const char *maa_name; }; diff --git a/sys/arch/loongson/include/intr.h b/sys/arch/loongson/include/intr.h index f0aa4b8f9cd..cbd81ff538d 100644 --- a/sys/arch/loongson/include/intr.h +++ b/sys/arch/loongson/include/intr.h @@ -1,4 +1,4 @@ -/* $OpenBSD: intr.h,v 1.11 2017/01/19 15:09:04 visa Exp $ */ +/* $OpenBSD: intr.h,v 1.12 2017/02/19 08:59:41 visa Exp $ */ /* * Copyright (c) 2001-2004 Opsycon AB (www.opsycon.se / www.opsycon.com) @@ -176,7 +176,8 @@ void intr_barrier(void *); */ /* Schedule priorities for base interrupts (CPU) */ -#define INTPRI_CLOCK 0 +#define INTPRI_IPI 0 +#define INTPRI_CLOCK 1 /* other values are system-specific */ #define NLOWINT 4 /* Number of low level registrations possible */ diff --git a/sys/arch/loongson/loongson/generic3a_machdep.c b/sys/arch/loongson/loongson/generic3a_machdep.c index d6cb1b01afd..5bc6b9a6456 100644 --- a/sys/arch/loongson/loongson/generic3a_machdep.c +++ b/sys/arch/loongson/loongson/generic3a_machdep.c @@ -1,8 +1,8 @@ -/* $OpenBSD: generic3a_machdep.c,v 1.3 2016/12/11 07:57:14 visa Exp $ */ +/* $OpenBSD: generic3a_machdep.c,v 1.4 2017/02/19 08:59:41 visa Exp $ */ /* * Copyright (c) 2009, 2010, 2012 Miodrag Vallat. - * Copyright (c) 2016 Visa Hankala. + * Copyright (c) 2016, 2017 Visa Hankala. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -24,14 +24,16 @@ #include <sys/param.h> #include <sys/systm.h> #include <sys/device.h> +#include <sys/proc.h> #include <mips64/archtype.h> +#include <mips64/loongson3.h> +#include <mips64/mips_cpu.h> + #include <machine/autoconf.h> #include <machine/cpu.h> #include <machine/pmon.h> -#include <mips64/loongson3.h> - #include <dev/ic/i8259reg.h> #include <dev/isa/isareg.h> #include <dev/isa/isavar.h> @@ -51,6 +53,18 @@ void generic3a_powerdown(void); void generic3a_reset(void); void generic3a_setup(void); +#ifdef MULTIPROCESSOR +void generic3a_config_secondary_cpus(struct device *, cfprint_t); +void generic3a_boot_secondary_cpu(struct cpu_info *); +int generic3a_ipi_establish(int (*)(void *), cpuid_t); +void generic3a_ipi_set(cpuid_t); +void generic3a_ipi_clear(cpuid_t); +uint32_t generic3a_ipi_intr(uint32_t, struct trapframe *); + +paddr_t ls3_ipi_base[MAXCPUS]; +int (*ls3_ipi_handler)(void *); +#endif /* MULTIPROCESSOR */ + void rs780e_setup(void); void rs780e_isa_attach_hook(struct device *, struct device *, @@ -104,7 +118,15 @@ const struct platform rs780e_platform = { .device_register = generic3a_device_register, .powerdown = generic3a_powerdown, - .reset = generic3a_reset + .reset = generic3a_reset, + +#ifdef MULTIPROCESSOR + .config_secondary_cpus = generic3a_config_secondary_cpus, + .boot_secondary_cpu = generic3a_boot_secondary_cpu, + .ipi_establish = generic3a_ipi_establish, + .ipi_set = generic3a_ipi_set, + .ipi_clear = generic3a_ipi_clear, +#endif /* MULTIPROCESSOR */ }; const struct pic rs780e_pic = { @@ -151,6 +173,11 @@ generic3a_setup(void) } loongson3_intr_init(); + +#ifdef MULTIPROCESSOR + ipi_mask = CR_INT_4; + set_intr(INTPRI_IPI, CR_INT_4, generic3a_ipi_intr); +#endif } void @@ -195,6 +222,114 @@ generic3a_device_register(struct device *dev, void *aux) #endif } +#ifdef MULTIPROCESSOR + +void +generic3a_config_secondary_cpus(struct device *parent, cfprint_t print) +{ + struct cpu_attach_args caa; + struct cpu_hwinfo hw; + uint32_t boot_cpu = loongson3_get_cpuid(); + uint32_t cpu, unit = 0; + + ls3_ipi_base[unit++] = LS3_IPI_BASE(0, boot_cpu); + + memset(&caa, 0, sizeof(caa)); + hw = bootcpu_hwinfo; + for (cpu = 0; cpu < LOONGSON_MAXCPUS && ncpus < MAXCPUS; cpu++) { + if (!ISSET(loongson_cpumask, 1u << cpu)) + continue; + if (cpu == boot_cpu) + continue; + + ls3_ipi_base[unit++] = LS3_IPI_BASE(LS3_NODEID(cpu), + LS3_COREID(cpu)); + + caa.caa_maa.maa_name = "cpu"; + caa.caa_hw = &hw; + config_found(parent, &caa, print); + } +} + +void +generic3a_boot_secondary_cpu(struct cpu_info *ci) +{ + vaddr_t kstack; + + kstack = alloc_contiguous_pages(USPACE); + if (kstack == 0) + panic("unable to allocate idle stack"); + ci->ci_curprocpaddr = (void *)kstack; + + /* + * The firmware has put the secondary core into a wait loop which + * terminates when a non-zero value is written to mailbox0. + * After the core exits the loop, the firmware initializes the core's + * pc, sp, gp and a1 registers as follows: + * + * pc = mailbox0 | 0xffffffff00000000u; + * sp = mailbox1 | 0x9800000000000000u; + * gp = mailbox2 | 0x9800000000000000u; + * a1 = mailbox3; + */ + + cpu_spinup_a0 = (uint64_t)ci; + cpu_spinup_sp = kstack; + mips_sync(); + + REGVAL64(ls3_ipi_base[ci->ci_cpuid] + LS3_IPI_MBOX0) = + (uint64_t)hw_cpu_spinup_trampoline; /* pc */ + + while (!cpuset_isset(&cpus_running, ci)) + continue; +} + +int +generic3a_ipi_establish(int (*func)(void *), cpuid_t cpuid) +{ + if (cpuid == 0) + ls3_ipi_handler = func; + + /* Clear any pending IPIs. */ + REGVAL32(ls3_ipi_base[cpuid] + LS3_IPI_CLEAR) = ~0u; + + /* Enable the IPI. */ + REGVAL32(ls3_ipi_base[cpuid] + LS3_IPI_IMR) = 1u; + + return 0; +} + +void +generic3a_ipi_set(cpuid_t cpuid) +{ + REGVAL32(ls3_ipi_base[cpuid] + LS3_IPI_SET) = 1; +} + +void +generic3a_ipi_clear(cpuid_t cpuid) +{ + REGVAL32(ls3_ipi_base[cpuid] + LS3_IPI_CLEAR) = 1; +} + +uint32_t +generic3a_ipi_intr(uint32_t hwpend, struct trapframe *frame) +{ + cpuid_t cpuid = cpu_number(); + + /* Mask all IPIs. */ + REGVAL32(ls3_ipi_base[cpuid] + LS3_IPI_IMR) = ~0u; + + if (ls3_ipi_handler != NULL) + ls3_ipi_handler((void *)cpuid); + + /* Enable the IPI. */ + REGVAL32(ls3_ipi_base[cpuid] + LS3_IPI_IMR) = 1u; + + return hwpend; +} + +#endif /* MULTIPROCESSOR */ + /* * Routines for RS780E-based systems */ |