From 1da9a914803075567257e914645fcec3cf463f34 Mon Sep 17 00:00:00 2001 From: ragge Date: Sun, 3 Jun 2001 15:07:20 +0000 Subject: [PATCH] A bunch of fixes: - Make generic console routines not relying on running on master cpu. - Add routine to start console transmitter (after IPI). - Use real IPIs instead of the "console doorbell". - Add routines cpu_send_ipi()/cpu_handle_ipi(). --- sys/arch/vax/vax/gencons.c | 87 ++++++++++++++++++++++---------- sys/arch/vax/vax/gencons.h | 5 +- sys/arch/vax/vax/ka820.c | 99 ++++++++++++++++++++++++++----------- sys/arch/vax/vax/multicpu.c | 85 ++++++++++++++++++++++++++++--- sys/arch/vax/vax/subr.s | 20 +++++++- sys/arch/vax/vax/trap.c | 3 +- 6 files changed, 232 insertions(+), 67 deletions(-) diff --git a/sys/arch/vax/vax/gencons.c b/sys/arch/vax/vax/gencons.c index c72478072603..3654023d938e 100644 --- a/sys/arch/vax/vax/gencons.c +++ b/sys/arch/vax/vax/gencons.c @@ -1,4 +1,4 @@ -/* $NetBSD: gencons.c,v 1.33 2001/05/16 05:36:55 matt Exp $ */ +/* $NetBSD: gencons.c,v 1.34 2001/06/03 15:07:20 ragge Exp $ */ /* * Copyright (c) 1994 Gordon W. Ross @@ -37,6 +37,7 @@ #include "opt_ddb.h" #include "opt_cputype.h" +#include "opt_multiprocessor.h" #include #include @@ -47,6 +48,7 @@ #include #include #include +#include #include @@ -56,7 +58,11 @@ #include #include -static struct tty *gencn_tty[4]; +static struct gc_softc { + short alive; + short unit; + struct tty *gencn_tty; +} gc_softc[4]; static int consopened = 0; static int maxttys = 1; @@ -82,10 +88,12 @@ gencnopen(dev_t dev, int flag, int mode, struct proc *p) if (unit >= maxttys) return ENXIO; - if (gencn_tty[unit] == NULL) - gencn_tty[unit] = ttymalloc(); + if (gc_softc[unit].gencn_tty == NULL) + gc_softc[unit].gencn_tty = ttymalloc(); - tp = gencn_tty[unit]; + gc_softc[unit].alive = 1; + gc_softc[unit].unit = unit; + tp = gc_softc[unit].gencn_tty; tp->t_oproc = gencnstart; tp->t_param = gencnparam; @@ -104,8 +112,6 @@ gencnopen(dev_t dev, int flag, int mode, struct proc *p) tp->t_state |= TS_CARR_ON; if (unit == 0) consopened = 1; - mtpr(GC_RIE, pr_rxcs[unit]); /* Turn on interrupts */ - mtpr(GC_TIE, pr_txcs[unit]); return ((*tp->t_linesw->l_open)(dev, tp)); } @@ -113,7 +119,7 @@ gencnopen(dev_t dev, int flag, int mode, struct proc *p) int gencnclose(dev_t dev, int flag, int mode, struct proc *p) { - struct tty *tp = gencn_tty[minor(dev)]; + struct tty *tp = gc_softc[minor(dev)].gencn_tty; if (minor(dev) == 0) consopened = 0; @@ -125,13 +131,13 @@ gencnclose(dev_t dev, int flag, int mode, struct proc *p) struct tty * gencntty(dev_t dev) { - return gencn_tty[minor(dev)]; + return gc_softc[minor(dev)].gencn_tty; } int gencnread(dev_t dev, struct uio *uio, int flag) { - struct tty *tp = gencn_tty[minor(dev)]; + struct tty *tp = gc_softc[minor(dev)].gencn_tty; return ((*tp->t_linesw->l_read)(tp, uio, flag)); } @@ -139,7 +145,7 @@ gencnread(dev_t dev, struct uio *uio, int flag) int gencnwrite(dev_t dev, struct uio *uio, int flag) { - struct tty *tp = gencn_tty[minor(dev)]; + struct tty *tp = gc_softc[minor(dev)].gencn_tty; return ((*tp->t_linesw->l_write)(tp, uio, flag)); } @@ -147,7 +153,7 @@ gencnwrite(dev_t dev, struct uio *uio, int flag) int gencnpoll(dev_t dev, int events, struct proc *p) { - struct tty *tp = gencn_tty[minor(dev)]; + struct tty *tp = gc_softc[minor(dev)].gencn_tty; return ((*tp->t_linesw->l_poll)(tp, events, p)); } @@ -155,7 +161,7 @@ gencnpoll(dev_t dev, int events, struct proc *p) int gencnioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) { - struct tty *tp = gencn_tty[minor(dev)]; + struct tty *tp = gc_softc[minor(dev)].gencn_tty; int error; error = (*tp->t_linesw->l_ioctl)(tp, cmd, data, flag, p); @@ -174,6 +180,11 @@ gencnstart(struct tty *tp) struct clist *cl; int s, ch; +#if defined(MULTIPROCESSOR) + if ((curcpu()->ci_flags & CI_MASTERCPU) == 0) + return cpu_send_ipi(IPI_DEST_MASTER, IPI_START_CNTX); +#endif + s = spltty(); if (tp->t_state & (TS_BUSY|TS_TTSTOP|TS_TIMEOUT)) goto out; @@ -197,18 +208,23 @@ out: splx(s); static void gencnrint(void *arg) { - struct tty *tp = *(struct tty **) arg; - int unit = (struct tty **) arg - gencn_tty; + struct gc_softc *sc = arg; + struct tty *tp = sc->gencn_tty; int i; - i = mfpr(pr_rxdb[unit]) & 0377; /* Mask status flags etc... */ + if (sc->alive == 0) + return; + i = mfpr(pr_rxdb[sc->unit]) & 0377; /* Mask status flags etc... */ + KERNEL_LOCK(LK_CANRECURSE|LK_EXCLUSIVE); #ifdef DDB if (tp->t_dev == cn_tab->cn_dev) { int j = kdbrint(i); - if (j == 1) /* Escape received, just return */ + if (j == 1) { /* Escape received, just return */ + KERNEL_UNLOCK(); return; + } if (j == 2) /* Second char wasn't 'D' */ (*tp->t_linesw->l_rint)(27, tp); @@ -216,7 +232,7 @@ gencnrint(void *arg) #endif (*tp->t_linesw->l_rint)(i, tp); - return; + KERNEL_UNLOCK(); } void @@ -227,11 +243,16 @@ gencnstop(struct tty *tp, int flag) static void gencntint(void *arg) { - struct tty *tp = *(struct tty **) arg; + struct gc_softc *sc = arg; + struct tty *tp = sc->gencn_tty; + if (sc->alive == 0) + return; + KERNEL_LOCK(LK_CANRECURSE|LK_EXCLUSIVE); tp->t_state &= ~TS_BUSY; gencnstart(tp); + KERNEL_UNLOCK(); } int @@ -266,23 +287,27 @@ gencninit(struct consdev *cndev) { /* Allocate interrupt vectors */ - scb_vecalloc(SCB_G0R, gencnrint, &gencn_tty[0], SCB_ISTACK, NULL); - scb_vecalloc(SCB_G0T, gencntint, &gencn_tty[0], SCB_ISTACK, NULL); + scb_vecalloc(SCB_G0R, gencnrint, &gc_softc[0], SCB_ISTACK, NULL); + scb_vecalloc(SCB_G0T, gencntint, &gc_softc[0], SCB_ISTACK, NULL); + mtpr(GC_RIE, pr_rxcs[0]); /* Turn on interrupts */ + mtpr(GC_TIE, pr_txcs[0]); if (vax_cputype == VAX_TYP_8SS) { maxttys = 4; - scb_vecalloc(SCB_G1R, gencnrint, &gencn_tty[1], SCB_ISTACK, NULL); - scb_vecalloc(SCB_G1T, gencntint, &gencn_tty[1], SCB_ISTACK, NULL); + scb_vecalloc(SCB_G1R, gencnrint, &gc_softc[1], SCB_ISTACK, NULL); + scb_vecalloc(SCB_G1T, gencntint, &gc_softc[1], SCB_ISTACK, NULL); - scb_vecalloc(SCB_G2R, gencnrint, &gencn_tty[2], SCB_ISTACK, NULL); - scb_vecalloc(SCB_G2T, gencntint, &gencn_tty[2], SCB_ISTACK, NULL); + scb_vecalloc(SCB_G2R, gencnrint, &gc_softc[2], SCB_ISTACK, NULL); + scb_vecalloc(SCB_G2T, gencntint, &gc_softc[2], SCB_ISTACK, NULL); - scb_vecalloc(SCB_G3R, gencnrint, &gencn_tty[3], SCB_ISTACK, NULL); - scb_vecalloc(SCB_G3T, gencntint, &gencn_tty[3], SCB_ISTACK, NULL); + scb_vecalloc(SCB_G3R, gencnrint, &gc_softc[3], SCB_ISTACK, NULL); + scb_vecalloc(SCB_G3T, gencntint, &gc_softc[3], SCB_ISTACK, NULL); } +#if 0 mtpr(0, PR_RXCS); mtpr(0, PR_TXCS); mtpr(0, PR_TBIA); /* ??? */ +#endif } void @@ -344,3 +369,11 @@ gencnpollc(dev_t dev, int pollflag) mtpr(GC_TIE, PR_TXCS); } } + +#if defined(MULTIPROCESSOR) +void +gencnstarttx() +{ + gencnstart(gc_softc[0].gencn_tty); +} +#endif diff --git a/sys/arch/vax/vax/gencons.h b/sys/arch/vax/vax/gencons.h index 963049ce9e5d..5cc23cee7167 100644 --- a/sys/arch/vax/vax/gencons.h +++ b/sys/arch/vax/vax/gencons.h @@ -1,4 +1,4 @@ -/* $NetBSD: gencons.h,v 1.9 2000/01/20 00:07:49 matt Exp $ */ +/* $NetBSD: gencons.h,v 1.10 2001/06/03 15:07:20 ragge Exp $ */ /* * Copyright (c) 1994 Ludd, University of Lule}, Sweden. @@ -68,4 +68,5 @@ #define SCB_G3T 0xdc /* Prototypes */ -void gencnputc __P((dev_t, int)); +void gencnputc(dev_t, int); +void gencnstarttx(void); diff --git a/sys/arch/vax/vax/ka820.c b/sys/arch/vax/vax/ka820.c index 7fcf1b2761a6..fa21578bb9a6 100644 --- a/sys/arch/vax/vax/ka820.c +++ b/sys/arch/vax/vax/ka820.c @@ -1,4 +1,4 @@ -/* $NetBSD: ka820.c,v 1.30 2000/08/09 03:02:54 tv Exp $ */ +/* $NetBSD: ka820.c,v 1.31 2001/06/03 15:07:20 ragge Exp $ */ /* * Copyright (c) 1988 Regents of the University of California. * All rights reserved. @@ -50,6 +50,8 @@ #include #include #include +#include +#include #include @@ -88,12 +90,14 @@ static void rxcdintr(void *); static void vaxbierr(void *); #if defined(MULTIPROCESSOR) static void ka820_startslave(struct device *, struct cpu_info *); +static void ka820_send_ipi(struct device *); static void ka820_txrx(int, char *, int); static void ka820_sendstr(int, char *); static void ka820_sergeant(int); static int rxchar(void); static void ka820_putc(int); static void ka820_cnintr(void); +static void ka820_ipintr(void *); cons_decl(gen); #endif @@ -111,14 +115,19 @@ struct cpu_dep ka820_calls = { 0, 0, 0, -#if defined(MULTIPROCESSOR) - ka820_startslave, -#endif }; +#if defined(MULTIPROCESSOR) +struct cpu_mp_dep ka820_mp_dep = { + ka820_startslave, + ka820_send_ipi, + ka820_cnintr, +}; +#endif + struct ka820_softc { struct device sc_dev; - struct cpu_info *sc_ci; + struct cpu_info sc_ci; int sc_binid; /* CPU node ID */ }; @@ -165,15 +174,32 @@ ka820_attach(struct device *parent, struct device *self, void *aux) ((rev >> 11) & 15), ((rev >> 1) &1023), rev & 1); sc->sc_binid = ba->ba_nodenr; - if (ba->ba_nodenr != mastercpu) { -#if defined(MULTIPROCESSOR) - sc->sc_ci = cpu_slavesetup(self); - v_putc = ka820_putc; /* Need special console handling */ -#endif - return; - } + /* Allow for IPINTR */ + bus_space_write_4(ba->ba_iot, ba->ba_ioh, + BIREG_IPINTRMSK, BIIPINTR_MASK); +#if defined(MULTIPROCESSOR) + if (ba->ba_nodenr != mastercpu) { + v_putc = ka820_putc; /* Need special console handling */ + return cpu_slavesetup(self); + } +#endif + +#if defined(MULTIPROCESSOR) + /* + * Catch interprocessor interrupts. + */ + scb_vecalloc(KA820_INT_IPINTR, ka820_ipintr, sc, SCB_ISTACK, NULL); +#endif + /* + * Copy cpu_info into new position. + */ + bcopy(curcpu(), &sc->sc_ci, sizeof(struct cpu_info)); + mtpr(&sc->sc_ci, PR_SSP); + proc0.p_addr->u_pcb.SSP = mfpr(PR_SSP); + proc0.p_cpu = curcpu(); curcpu()->ci_dev = self; + /* reset the console and enable the RX50 */ ka820port_ptr = (void *)vax_map_physmem(KA820_PORTADDR, 1); csr = ka820port_ptr->csr; @@ -206,6 +232,9 @@ ka820_conf() /* XXX - should be done somewhere else */ scb_vecalloc(SCB_RX50, crxintr, NULL, SCB_ISTACK, NULL); rx50device_ptr = (void *)vax_map_physmem(KA820_RX50ADDR, 1); +#if defined(MULTIPROCESSOR) + mp_dep_call = &ka820_mp_dep; +#endif } void @@ -442,12 +471,6 @@ rxcdintr(void *arg) return; #if defined(MULTIPROCESSOR) - if ((c & 0xff) == 0) { - if (curcpu()->ci_flags & CI_MASTERCPU) - ka820_cnintr(); - return; - } - if (expect == ((c >> 8) & 0xf)) rxbuf[got++] = c & 0xff; @@ -563,24 +586,26 @@ ka820_txrx(int id, char *fmt, int arg) ka820_sergeant(id); } +static void +ka820_sendchr(int chr) +{ + /* + * It seems like mtpr to TXCD sets the V flag if it fails. + * Cannot check that flag in C... + */ + asm __volatile("1:;mtpr %0,$92;bvs 1b" :: "g"(chr)); +} + void ka820_sendstr(int id, char *buf) { - register u_int utchr; /* Ends up in R11 with PCC */ + u_int utchr; int ch, i; while (*buf) { utchr = *buf | id << 8; - /* - * It seems like mtpr to TXCD sets the V flag if it fails. - * Cannot check that flag in C... - */ -#ifdef __GNUC__ - asm("1:;mtpr %0,$92;bvs 1b" :: "g"(utchr)); -#else - asm("1:;mtpr r11,$92;bvs 1b"); -#endif + ka820_sendchr(utchr); buf++; i = 30000; while ((ch = rxchar()) == 0 && --i) @@ -612,7 +637,6 @@ ka820_sergeant(int id) /* * Write to master console. - * Need no locking here; done in the print functions. */ static volatile int ch = 0; @@ -624,7 +648,8 @@ ka820_putc(int c) return; } ch = c; - mtpr(mastercpu << 8, PR_RXCD); /* Send IPI to mastercpu */ + + cpu_send_ipi(IPI_DEST_MASTER, IPI_SEND_CNCHAR); while (ch != 0) ; /* Wait for master to handle */ } @@ -639,4 +664,18 @@ ka820_cnintr() gencnputc(0, ch); ch = 0; /* Release slavecpu */ } + +void +ka820_send_ipi(struct device *dev) +{ + struct ka820_softc *sc = (void *)dev; + + mtpr(1 << sc->sc_binid, PR_IPIR); +} + +void +ka820_ipintr(void *arg) +{ + cpu_handle_ipi(); +} #endif diff --git a/sys/arch/vax/vax/multicpu.c b/sys/arch/vax/vax/multicpu.c index 673ef6a3f73b..13ea45243a68 100644 --- a/sys/arch/vax/vax/multicpu.c +++ b/sys/arch/vax/vax/multicpu.c @@ -1,4 +1,4 @@ -/* $NetBSD: multicpu.c,v 1.6 2001/05/29 21:55:00 ragge Exp $ */ +/* $NetBSD: multicpu.c,v 1.7 2001/06/03 15:07:20 ragge Exp $ */ /* * Copyright (c) 2000 Ludd, University of Lule}, Sweden. All rights reserved. @@ -46,9 +46,12 @@ #include #include +#include #include "ioconf.h" +struct cpu_mp_dep *mp_dep_call; + static void slaverun(void); struct cpuq { @@ -68,7 +71,7 @@ cpu_boot_secondary_processors() while ((q = SIMPLEQ_FIRST(&cpuq))) { SIMPLEQ_REMOVE_HEAD(&cpuq, q, cq_q); - (*dep_call->cpu_startslave)(q->cq_dev, q->cq_ci); + (*mp_dep_call->cpu_startslave)(q->cq_dev, q->cq_ci); free(q, M_TEMP); } } @@ -78,9 +81,10 @@ cpu_boot_secondary_processors() * struct and fill it in and prepare for getting started by * cpu_boot_secondary_processors(). */ -struct cpu_info * +void cpu_slavesetup(struct device *dev) { + struct cpu_mp_softc *sc = (struct cpu_mp_softc *)dev; struct cpuq *cq; struct cpu_info *ci; struct pglist mlist; @@ -115,8 +119,7 @@ cpu_slavesetup(struct device *dev) scratch = VM_PAGE_TO_PHYS(pg) | KERNBASE; /* Populate the PCB and the cpu_info struct */ - ci = (struct cpu_info *)(scratch + VAX_NBPG); - memset(ci, 0, sizeof(struct cpu_info)); + ci = &sc->sc_ci; ci->ci_dev = dev; ci->ci_exit = scratch; (u_long)ci->ci_pcb = (u_long)pcb & ~KERNBASE; @@ -133,17 +136,87 @@ cpu_slavesetup(struct device *dev) cq->cq_ci = ci; cq->cq_dev = dev; SIMPLEQ_INSERT_TAIL(&cpuq, cq, cq_q); - return ci; } +volatile int sta; + void slaverun() { struct cpu_info *ci = curcpu(); ((volatile struct cpu_info *)ci)->ci_flags |= CI_RUNNING; + cpu_send_ipi(IPI_DEST_MASTER, IPI_RUNNING); printf("%s: running\n", ci->ci_dev->dv_xname); + while (sta != ci->ci_dev->dv_unit) + ; splsched(); sched_lock_idle(); cpu_switch(0); } + +/* + * Send an IPI of type type to the CPU with logical device number cpu. + */ +void +cpu_send_ipi(int cpu, int type) +{ + struct cpu_mp_softc *sc; + int i; + + if (cpu >= 0) { + sc = cpu_cd.cd_devs[cpu]; + bbssi(type, &sc->sc_ci.ci_ipimsgs); + (*mp_dep_call->cpu_send_ipi)(&sc->sc_dev); + return; + } + + for (i = 0; i < cpu_cd.cd_ndevs; i++) { + sc = cpu_cd.cd_devs[i]; + if (sc == NULL) + continue; + switch (cpu) { + case IPI_DEST_MASTER: + if (sc->sc_ci.ci_flags & CI_MASTERCPU) { + bbssi(type, &sc->sc_ci.ci_ipimsgs); + (*mp_dep_call->cpu_send_ipi)(&sc->sc_dev); + } + break; + case IPI_DEST_ALL: + bbssi(type, &sc->sc_ci.ci_ipimsgs); + (*mp_dep_call->cpu_send_ipi)(&sc->sc_dev); + break; + } + } +} + +void +cpu_handle_ipi() +{ + struct cpu_info *ci = curcpu(); + int bitno; + + while ((bitno = ffs(ci->ci_ipimsgs))) { + bitno -= 1; /* ffs() starts from 1 */ + bbcci(bitno, &ci->ci_ipimsgs); + switch (bitno) { + case IPI_START_CNTX: +#ifdef DIAGNOSTIC + if (CPU_IS_PRIMARY(ci) == 0) + panic("cpu_handle_ipi"); +#endif + gencnstarttx(); + break; + case IPI_SEND_CNCHAR: +#ifdef DIAGNOSTIC + if (CPU_IS_PRIMARY(ci) == 0) + panic("cpu_handle_ipi2"); +#endif + (*mp_dep_call->cpu_cnintr)(); + break; + case IPI_RUNNING: + printf("something running\n"); + break; + } + } +} diff --git a/sys/arch/vax/vax/subr.s b/sys/arch/vax/vax/subr.s index 78f3b73ca370..58d8b2a9bf72 100644 --- a/sys/arch/vax/vax/subr.s +++ b/sys/arch/vax/vax/subr.s @@ -1,4 +1,4 @@ -/* $NetBSD: subr.s,v 1.59 2001/05/29 21:25:11 ragge Exp $ */ +/* $NetBSD: subr.s,v 1.60 2001/06/03 15:07:20 ragge Exp $ */ /* * Copyright (c) 1994 Ludd, University of Lule}, Sweden. @@ -587,6 +587,24 @@ ENTRY(blkclr,R6) movc5 $0,(r3),$0,r6,(r3) ret +#if defined(MULTIPROCESSOR) + +JSBENTRY(Slock) +1: bbssi $0,(r1),1b + rsb + +JSBENTRY(Slocktry) + clrl r0 + bbssi $0,(r1),1f + incl r0 +1: rsb + +JSBENTRY(Sunlock) + bbcci $0,(r1),1f +1: rsb + +#endif + # # data department # diff --git a/sys/arch/vax/vax/trap.c b/sys/arch/vax/vax/trap.c index ec11d3085706..43e68c182916 100644 --- a/sys/arch/vax/vax/trap.c +++ b/sys/arch/vax/vax/trap.c @@ -1,4 +1,4 @@ -/* $NetBSD: trap.c,v 1.63 2001/06/02 18:09:24 chs Exp $ */ +/* $NetBSD: trap.c,v 1.64 2001/06/03 15:07:21 ragge Exp $ */ /* * Copyright (c) 1994 Ludd, University of Lule}, Sweden. @@ -235,6 +235,7 @@ if(faultdebug)printf("trap accflt type %lx, code %lx, pc %lx, psl %lx\n", rv = uvm_fault(map, addr, 0, ftype); if (rv != 0) { if (umode == 0) { + KERNEL_UNLOCK(); FAULTCHK; panic("Segv in kernel mode: pc %x addr %x", (u_int)frame->pc, (u_int)frame->code);