From 1c060e9bbf429ecd1c20e7d6a7ccad995a9dd8cc Mon Sep 17 00:00:00 2001 From: Miod Vallat Date: Mon, 14 May 2007 17:00:41 +0000 Subject: Work in progress IPI mechanism, currently only implemented on MVME188, to send clock ticks to secondary processors. --- sys/arch/m88k/include/cpu.h | 11 +- sys/arch/mvme88k/include/cpu.h | 3 +- sys/arch/mvme88k/include/mvme188.h | 14 ++- sys/arch/mvme88k/mvme88k/m188_machdep.c | 179 +++++++++++++++++++++----------- sys/arch/mvme88k/mvme88k/machdep.c | 34 +++++- 5 files changed, 174 insertions(+), 67 deletions(-) diff --git a/sys/arch/m88k/include/cpu.h b/sys/arch/m88k/include/cpu.h index 36ea3083ac0..bcad10ecee2 100644 --- a/sys/arch/m88k/include/cpu.h +++ b/sys/arch/m88k/include/cpu.h @@ -1,4 +1,4 @@ -/* $OpenBSD: cpu.h,v 1.20 2007/04/18 21:21:19 miod Exp $ */ +/* $OpenBSD: cpu.h,v 1.21 2007/05/14 17:00:38 miod Exp $ */ /* * Copyright (c) 1996 Nivas Madhur * Copyright (c) 1992, 1993 @@ -104,6 +104,13 @@ struct cpu_info { #define CI_DDB_RUNNING 0 #define CI_DDB_ENTERDDB 1 #define CI_DDB_INDDB 2 +#define CI_DDB_PAUSE 3 + + volatile int ci_ipi; /* pending ipis */ +#define CI_IPI_NOTIFY 0x00000001 +#define CI_IPI_HARDCLOCK 0x00000002 +#define CI_IPI_STATCLOCK 0x00000004 +#define CI_IPI_DDB 0x00000008 }; extern cpuid_t master_cpu; @@ -128,6 +135,8 @@ extern struct cpu_info m88k_cpus[MAX_CPUS]; #define CPU_IS_PRIMARY(ci) ((ci)->ci_primary != 0) void cpu_boot_secondary_processors(void); +void m88k_send_ipi(int, cpuid_t); +void m88k_broadcast_ipi(int); #else /* MULTIPROCESSOR */ diff --git a/sys/arch/mvme88k/include/cpu.h b/sys/arch/mvme88k/include/cpu.h index 0ae4bdd0425..72dc6bb1a64 100644 --- a/sys/arch/mvme88k/include/cpu.h +++ b/sys/arch/mvme88k/include/cpu.h @@ -1,4 +1,4 @@ -/* $OpenBSD: cpu.h,v 1.36 2007/03/22 18:52:39 miod Exp $ */ +/* $OpenBSD: cpu.h,v 1.37 2007/05/14 17:00:40 miod Exp $ */ /* * Copyright (c) 1996 Nivas Madhur * Copyright (c) 1992, 1993 @@ -52,6 +52,7 @@ extern u_int (*md_getipl)(void); extern u_int (*md_setipl)(u_int); extern u_int (*md_raiseipl)(u_int); extern void (*md_init_clocks)(void); +extern void (*md_send_ipi)(int, cpuid_t); struct intrhand { SLIST_ENTRY(intrhand) ih_link; diff --git a/sys/arch/mvme88k/include/mvme188.h b/sys/arch/mvme88k/include/mvme188.h index 3f06ba62e3e..aa13449cf5f 100644 --- a/sys/arch/mvme88k/include/mvme188.h +++ b/sys/arch/mvme88k/include/mvme188.h @@ -1,4 +1,4 @@ -/* $OpenBSD: mvme188.h,v 1.28 2006/11/18 22:53:11 miod Exp $ */ +/* $OpenBSD: mvme188.h,v 1.29 2007/05/14 17:00:40 miod Exp $ */ /* * Copyright (c) 1999 Steve Murphree, Jr. * All rights reserved. @@ -149,8 +149,9 @@ /* hardware irq bits */ #define HW_FAILURE_MASK (IRQ_ABORT | IRQ_ACF | IRQ_ARBTO | IRQ_SF) /* software irq bits */ -#define SOFT_INTERRUPT_MASK (IRQ_SWI7 | IRQ_SWI6 | IRQ_SWI5 | IRQ_SWI4 | \ - IRQ_SWI3 | IRQ_SWI2 | IRQ_SWI1 | IRQ_SWI0) +#define SOFT_INTERRUPT_MASK (IRQ_SWI7 | IRQ_SWI6 | IRQ_SWI5 | IRQ_SWI4) +/* IPI bits (see below) */ +#define IPI_MASK (IRQ_SWI3 | IRQ_SWI2 | IRQ_SWI1 | IRQ_SWI0) /* VME irq bits */ #define VME_INTERRUPT_MASK (IRQ_VME7 | IRQ_VME6 | IRQ_VME5 | IRQ_VME4 | \ IRQ_VME3 | IRQ_VME2 | IRQ_VME1) @@ -185,6 +186,13 @@ #define ISR_GET_CURRENT_MASK(cpu) \ (*(volatile u_int *)MVME188_IST & *int_mask_reg[cpu]) +/* + * Software interrupts 0 to 3 are used to deliver IPIs to cpu0-3. + * We rely on the fact that the control bits for these interrupts are + * the same in the interrupt registers and the set/clear SWI registers. + */ +#define IPI_BIT(cpuid) (1 << (cpuid)) + /* * ISTATE and CLRINT register bits */ diff --git a/sys/arch/mvme88k/mvme88k/m188_machdep.c b/sys/arch/mvme88k/mvme88k/m188_machdep.c index 2fc9681c376..7e9d07cafb5 100644 --- a/sys/arch/mvme88k/mvme88k/m188_machdep.c +++ b/sys/arch/mvme88k/mvme88k/m188_machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: m188_machdep.c,v 1.27 2007/05/14 16:57:43 miod Exp $ */ +/* $OpenBSD: m188_machdep.c,v 1.28 2007/05/14 17:00:40 miod Exp $ */ /* * Copyright (c) 1998, 1999, 2000, 2001 Steve Murphree, Jr. * Copyright (c) 1996 Nivas Madhur @@ -137,8 +137,10 @@ void m188_bootstrap(void); void m188_ext_int(u_int, struct trapframe *); u_int m188_getipl(void); void m188_init_clocks(void); +void m188_ipi_handler(struct trapframe *); vaddr_t m188_memsize(void); u_int m188_raiseipl(u_int); +void m188_send_ipi(int, cpuid_t); u_int m188_setipl(u_int); void m188_startup(void); @@ -219,6 +221,9 @@ m188_bootstrap() md_setipl = m188_setipl; md_raiseipl = m188_raiseipl; md_init_clocks = m188_init_clocks; +#ifdef MULTIPROCESSOR + md_send_ipi = m188_send_ipi; +#endif /* clear and disable all interrupts */ *(volatile u_int32_t *)MVME188_IENALL = 0; @@ -259,6 +264,9 @@ safe_level(u_int mask, u_int curlevel) { int i; +#ifdef MULTIPROCESSOR + mask &= ~IPI_MASK; +#endif for (i = curlevel; i < INT_LEVEL; i++) if ((int_mask_val[i] & mask) == 0) return (i); @@ -284,6 +292,7 @@ m188_setipl(u_int level) #ifdef MULTIPROCESSOR if (cpu != master_cpu) mask &= ~SLAVE_MASK; + mask |= IPI_BIT(cpu); #endif *int_mask_reg[cpu] = mask; @@ -304,6 +313,7 @@ m188_raiseipl(u_int level) #ifdef MULTIPROCESSOR if (cpu != master_cpu) mask &= ~SLAVE_MASK; + mask |= IPI_BIT(cpu); #endif *int_mask_reg[cpu] = mask; @@ -312,6 +322,42 @@ m188_raiseipl(u_int level) return curspl; } +#ifdef MULTIPROCESSOR + +void +m188_send_ipi(int ipi, cpuid_t cpu) +{ + struct cpu_info *ci = &m88k_cpus[cpu]; + + atomic_setbits_int(&ci->ci_ipi, ipi); + *(volatile u_int32_t *)MVME188_SETSWI = IPI_BIT(cpu); +} + +/* + * Process inter-processor interrupts. Note that interrupts are disabled + * when this function is invoked. + */ +void +m188_ipi_handler(struct trapframe *eframe) +{ + struct cpu_info *ci = curcpu(); + + if (ci->ci_ipi & CI_IPI_NOTIFY) { + atomic_clearbits_int(&ci->ci_ipi, CI_IPI_NOTIFY); + /* nothing to do */ + } + if (ci->ci_ipi & CI_IPI_HARDCLOCK) { + atomic_clearbits_int(&ci->ci_ipi, CI_IPI_HARDCLOCK); + hardclock((struct clockframe *)eframe); + } + if (ci->ci_ipi & CI_IPI_STATCLOCK) { + atomic_clearbits_int(&ci->ci_ipi, CI_IPI_STATCLOCK); + statclock((struct clockframe *)eframe); + } +} + +#endif + /* * Device interrupt handler for MVME188 */ @@ -376,11 +422,10 @@ m188_ext_int(u_int v, struct trapframe *eframe) cur_mask = ISR_GET_CURRENT_MASK(cpu); ign_mask = 0; - old_spl = m188_curspl[cpu]; - eframe->tf_mask = old_spl; + old_spl = eframe->tf_mask; #ifdef MULTIPROCESSOR - if (eframe->tf_mask < IPL_SCHED) + if (old_spl < IPL_SCHED) __mp_lock(&kernel_lock); #endif @@ -402,27 +447,24 @@ m188_ext_int(u_int v, struct trapframe *eframe) * priority. */ do { - level = safe_level(cur_mask, old_spl); +#ifdef MULTIPROCESSOR + /* + * Check for IPIs first. We rely on the interrupt mask to + * make sure that if we get an IPI, it's really for us and + * no other processor. + */ + if (IPI_MASK & cur_mask) { + *(volatile u_int32_t *)MVME188_CLRSWI = + cur_mask & IPI_MASK; + cur_mask &= ~IPI_MASK; -#ifdef DIAGNOSTIC - if (level != IPL_ABORT && level <= old_spl) { - int i; - - printf("safe level %d <= old level %d\n", level, old_spl); - printf("cur_mask = 0x%b\n", cur_mask, IST_STRING); - for (i = 0; i < 4; i++) - printf("IEN%d = 0x%b ", i, *int_mask_reg[i], IST_STRING); - printf("\nCPU0 spl %d CPU1 spl %d CPU2 spl %d CPU3 spl %d\n", - m188_curspl[0], m188_curspl[1], - m188_curspl[2], m188_curspl[3]); - for (i = 0; i < INT_LEVEL; i++) - printf("int_mask[%d] = 0x%08x\n", i, int_mask_val[i]); - printf("--CPU %d halted--\n", cpu_number()); - m188_setipl(IPL_ABORT); - for(;;) ; + m188_ipi_handler(eframe); + + if (cur_mask == 0) + break; } #endif - + level = safe_level(cur_mask, old_spl); m188_setipl(level); /* @@ -563,7 +605,7 @@ out: set_psr(get_psr() | PSR_IND); #ifdef MULTIPROCESSOR - if (eframe->tf_mask < IPL_SCHED) + if (old_spl < IPL_SCHED) __mp_unlock(&kernel_lock); #endif } @@ -579,10 +621,18 @@ void write_cio(int, u_int); int m188_clockintr(void *); int m188_statintr(void *); -struct simplelock m188_cio_lock; - -#define CIO_LOCK simple_lock(&m188_cio_lock) -#define CIO_UNLOCK simple_unlock(&m188_cio_lock) +#if defined(MULTIPROCESSOR) && 0 +#include +__cpu_simple_lock_t m188_cio_lock; + +#define CIO_LOCK_INIT() __cpu_simple_lock_init(&m188_cio_lock) +#define CIO_LOCK() __cpu_simple_lock(&m188_cio_lock) +#define CIO_UNLOCK() __cpu_simple_unlock(&m188_cio_lock) +#else +#define CIO_LOCK_INIT() do { } while (0) +#define CIO_LOCK() do { } while (0) +#define CIO_UNLOCK() do { } while (0) +#endif /* * Notes on the MVME188 clock usage: @@ -631,7 +681,7 @@ m188_init_clocks(void) volatile u_int8_t imr; int statint, minint; - simple_lock_init(&m188_cio_lock); + CIO_LOCK_INIT(); #ifdef DIAGNOSTIC if (1000000 % hz) { @@ -693,14 +743,23 @@ m188_init_clocks(void) int m188_clockintr(void *eframe) { - CIO_LOCK; + CIO_LOCK(); write_cio(CIO_CSR1, CIO_GCB | CIO_CIP); /* Ack the interrupt */ hardclock(eframe); /* restart counter */ write_cio(CIO_CSR1, CIO_GCB | CIO_TCB | CIO_IE); - CIO_UNLOCK; + CIO_UNLOCK(); + +#ifdef MULTIPROCESSOR + /* + * Send an IPI to all other processors, so they can get their + * own ticks. + */ + if (CPU_IS_PRIMARY(curcpu())) + m88k_broadcast_ipi(CI_IPI_HARDCLOCK); +#endif return (1); } @@ -717,21 +776,35 @@ m188_statintr(void *eframe) statclock((struct clockframe *)eframe); - /* - * Compute new randomized interval. The intervals are uniformly - * distributed on [statint - statvar / 2, statint + statvar / 2], - * and therefore have mean statint, giving a stathz frequency clock. - */ - var = statvar; - do { - r = random() & (var - 1); - } while (r == 0); - newint = statmin + r; +#ifdef MULTIPROCESSOR + if (CPU_IS_PRIMARY(curcpu())) { + /* + * Send an IPI to all other processors as well. + */ + m88k_broadcast_ipi(CI_IPI_STATCLOCK); +#endif - /* setup new value and restart counter */ - *(volatile u_int8_t *)DART_CTUR = (newint >> 8); - *(volatile u_int8_t *)DART_CTLR = (newint & 0xff); - tmp = *(volatile u_int8_t *)DART_STARTC; + /* + * Compute new randomized interval. The intervals are + * uniformly distributed on + * [statint - statvar / 2, statint + statvar / 2], + * and therefore have mean statint, giving a stathz + * frequency clock. + */ + var = statvar; + do { + r = random() & (var - 1); + } while (r == 0); + newint = statmin + r; + + /* setup new value and restart counter */ + *(volatile u_int8_t *)DART_CTUR = (newint >> 8); + *(volatile u_int8_t *)DART_CTLR = (newint & 0xff); + tmp = *(volatile u_int8_t *)DART_STARTC; + +#ifdef MULTIPROCESSOR + } +#endif return (1); } @@ -740,35 +813,25 @@ m188_statintr(void *eframe) void write_cio(int reg, u_int val) { - int s; volatile int i; volatile u_int32_t * cio_ctrl = (volatile u_int32_t *)CIO_CTRL; - s = splclock(); - CIO_LOCK; - i = *cio_ctrl; /* goto state 1 */ *cio_ctrl = 0; /* take CIO out of RESET */ i = *cio_ctrl; /* reset CIO state machine */ *cio_ctrl = (reg & 0xff); /* select register */ *cio_ctrl = (val & 0xff); /* write the value */ - - CIO_UNLOCK; - splx(s); } /* Read CIO register */ u_int read_cio(int reg) { - int c, s; + int c; volatile int i; volatile u_int32_t * cio_ctrl = (volatile u_int32_t *)CIO_CTRL; - s = splclock(); - CIO_LOCK; - /* select register */ *cio_ctrl = (reg & 0xff); /* delay for a short time to allow 8536 to settle */ @@ -776,8 +839,6 @@ read_cio(int reg) ; /* read the value */ c = *cio_ctrl; - CIO_UNLOCK; - splx(s); return (c & 0xff); } @@ -790,8 +851,6 @@ m188_cio_init(unsigned period) { volatile int i; - CIO_LOCK; - /* Start by forcing chip into known state */ read_cio(CIO_MICR); write_cio(CIO_MICR, CIO_MICR_RESET); /* Reset the CTC */ @@ -817,6 +876,4 @@ m188_cio_init(unsigned period) /* enable counter #1 */ write_cio(CIO_MCCR, CIO_MCCR_CT1E | CIO_MCCR_PBE); write_cio(CIO_CSR1, CIO_GCB | CIO_TCB | CIO_IE); - - CIO_UNLOCK; } diff --git a/sys/arch/mvme88k/mvme88k/machdep.c b/sys/arch/mvme88k/mvme88k/machdep.c index 82764f36487..b3038827a2c 100644 --- a/sys/arch/mvme88k/mvme88k/machdep.c +++ b/sys/arch/mvme88k/mvme88k/machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: machdep.c,v 1.186 2007/05/12 20:03:25 miod Exp $ */ +/* $OpenBSD: machdep.c,v 1.187 2007/05/14 17:00:40 miod Exp $ */ /* * Copyright (c) 1998, 1999, 2000, 2001 Steve Murphree, Jr. * Copyright (c) 1996 Nivas Madhur @@ -125,6 +125,9 @@ void (*md_init_clocks)(void); u_int (*md_getipl)(void); u_int (*md_setipl)(u_int); u_int (*md_raiseipl)(u_int); +#ifdef MULTIPROCESSOR +void (*md_send_ipi)(int, cpuid_t); +#endif int physmem; /* available physical memory, in pages */ @@ -1211,3 +1214,32 @@ raiseipl(unsigned level) set_psr(psr); return curspl; } + +#ifdef MULTIPROCESSOR + +void +m88k_send_ipi(int ipi, cpuid_t cpu) +{ + struct cpu_info *ci; + + ci = &m88k_cpus[cpu]; + if (ci->ci_alive) + (*md_send_ipi)(ipi, cpu); +} + +void +m88k_broadcast_ipi(int ipi) +{ + struct cpu_info *ci; + CPU_INFO_ITERATOR cii; + + CPU_INFO_FOREACH(cii, ci) { + if (ci == curcpu()) + continue; + + if (ci->ci_alive) + (*md_send_ipi)(ipi, ci->ci_cpuid); + } +} + +#endif -- cgit v1.2.3