[BACK]Return to m88k_machdep.c CVS log [TXT][DIR] Up to [local] / sys / arch / m88k / m88k

Annotation of sys/arch/m88k/m88k/m88k_machdep.c, Revision 1.1.1.1

1.1       nbrk        1: /*     $OpenBSD: m88k_machdep.c,v 1.21 2007/05/29 18:10:42 miod Exp $  */
                      2: /*
                      3:  * Copyright (c) 1998, 1999, 2000, 2001 Steve Murphree, Jr.
                      4:  * Copyright (c) 1996 Nivas Madhur
                      5:  * All rights reserved.
                      6:  *
                      7:  * Redistribution and use in source and binary forms, with or without
                      8:  * modification, are permitted provided that the following conditions
                      9:  * are met:
                     10:  * 1. Redistributions of source code must retain the above copyright
                     11:  *    notice, this list of conditions and the following disclaimer.
                     12:  * 2. Redistributions in binary form must reproduce the above copyright
                     13:  *    notice, this list of conditions and the following disclaimer in the
                     14:  *    documentation and/or other materials provided with the distribution.
                     15:  * 3. All advertising materials mentioning features or use of this software
                     16:  *    must display the following acknowledgement:
                     17:  *      This product includes software developed by Nivas Madhur.
                     18:  * 4. The name of the author may not be used to endorse or promote products
                     19:  *    derived from this software without specific prior written permission
                     20:  *
                     21:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
                     22:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
                     23:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
                     24:  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
                     25:  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
                     26:  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
                     27:  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
                     28:  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
                     29:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
                     30:  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
                     31:  *
                     32:  */
                     33: /*
                     34:  * Mach Operating System
                     35:  * Copyright (c) 1993-1991 Carnegie Mellon University
                     36:  * Copyright (c) 1991 OMRON Corporation
                     37:  * All Rights Reserved.
                     38:  *
                     39:  * Permission to use, copy, modify and distribute this software and its
                     40:  * documentation is hereby granted, provided that both the copyright
                     41:  * notice and this permission notice appear in all copies of the
                     42:  * software, derivative works or modified versions, and any portions
                     43:  * thereof, and that both notices appear in supporting documentation.
                     44:  *
                     45:  */
                     46:
                     47: #include <sys/param.h>
                     48: #include <sys/systm.h>
                     49: #include <sys/kernel.h>
                     50: #include <sys/proc.h>
                     51: #include <sys/user.h>
                     52: #include <sys/msgbuf.h>
                     53: #include <sys/exec.h>
                     54: #include <sys/errno.h>
                     55: #include <sys/lock.h>
                     56: #ifdef MULTIPROCESSOR
                     57: #include <sys/mplock.h>
                     58: #endif
                     59:
                     60: #include <machine/asm.h>
                     61: #include <machine/asm_macro.h>
                     62: #include <machine/atomic.h>
                     63: #include <machine/cmmu.h>
                     64: #include <machine/cpu.h>
                     65: #include <machine/reg.h>
                     66: #ifdef M88100
                     67: #include <machine/m88100.h>
                     68: #endif
                     69:
                     70: #include <uvm/uvm_extern.h>
                     71:
                     72: #include <net/netisr.h>
                     73:
                     74: #ifdef DDB
                     75: #include <machine/db_machdep.h>
                     76: #include <ddb/db_extern.h>
                     77: #include <ddb/db_interface.h>
                     78: #endif /* DDB */
                     79:
                     80: typedef struct {
                     81:        u_int32_t word_one, word_two;
                     82: } m88k_exception_vector_area;
                     83:
                     84: void   dosoftint(void);
                     85: void   dumpconf(void);
                     86: void   dumpsys(void);
                     87: void   regdump(struct trapframe *f);
                     88: void   vector_init(m88k_exception_vector_area *, u_int32_t *);
                     89:
                     90: /*
                     91:  * CMMU and CPU variables
                     92:  */
                     93:
                     94: #ifdef MULTIPROCESSOR
                     95: __cpu_simple_lock_t cmmu_cpu_lock = __SIMPLELOCK_UNLOCKED;
                     96: cpuid_t        master_cpu;
                     97: struct __mp_lock sir_lock;
                     98: #endif
                     99:
                    100: struct cpu_info m88k_cpus[MAX_CPUS];
                    101: u_int  max_cpus;
                    102:
                    103: struct cmmu_p *cmmu;
                    104:
                    105: /*
                    106:  * safepri is a safe priority for sleep to set for a spin-wait
                    107:  * during autoconfiguration or after a panic.
                    108:  */
                    109: int   safepri = IPL_NONE;
                    110:
                    111: /*
                    112:  * Set registers on exec.
                    113:  * Clear all except sp and pc.
                    114:  */
                    115: void
                    116: setregs(p, pack, stack, retval)
                    117:        struct proc *p;
                    118:        struct exec_package *pack;
                    119:        u_long stack;
                    120:        int retval[2];
                    121: {
                    122:        struct trapframe *tf = (struct trapframe *)USER_REGS(p);
                    123:
                    124:        /*
                    125:         * The syscall will ``return'' to snip; set it.
                    126:         * argc, argv, envp are placed on the stack by copyregs.
                    127:         * Point r2 to the stack. crt0 should extract envp from
                    128:         * argc & argv before calling user's main.
                    129:         */
                    130:
                    131:        bzero((caddr_t)tf, sizeof *tf);
                    132:
                    133: #ifdef M88110
                    134:        if (CPU_IS88110) {
                    135:                /*
                    136:                 * user mode, serialize mem, interrupts enabled,
                    137:                 * graphics unit, fp enabled
                    138:                 */
                    139:                tf->tf_epsr = PSR_SRM | PSR_SFD;
                    140:                /*
                    141:                 * XXX disable OoO for now...
                    142:                 */
                    143:                tf->tf_epsr |= PSR_SER;
                    144:        }
                    145: #endif
                    146: #ifdef M88100
                    147:        if (CPU_IS88100) {
                    148:                /*
                    149:                 * user mode, interrupts enabled,
                    150:                 * no graphics unit, fp enabled
                    151:                 */
                    152:                tf->tf_epsr = PSR_SFD | PSR_SFD2;
                    153:        }
                    154: #endif
                    155:
                    156:        /*
                    157:         * We want to start executing at pack->ep_entry. The way to
                    158:         * do this is force the processor to fetch from ep_entry. Set
                    159:         * NIP to something bogus and invalid so that it will be a NOOP.
                    160:         * And set sfip to ep_entry with valid bit on so that it will be
                    161:         * fetched.  mc88110 - just set exip to pack->ep_entry.
                    162:         */
                    163: #ifdef M88110
                    164:        if (CPU_IS88110) {
                    165:                tf->tf_exip = pack->ep_entry & XIP_ADDR;
                    166:        }
                    167: #endif
                    168: #ifdef M88100
                    169:        if (CPU_IS88100) {
                    170:                tf->tf_snip = pack->ep_entry & NIP_ADDR;
                    171:                tf->tf_sfip = (pack->ep_entry & FIP_ADDR) | FIP_V;
                    172:        }
                    173: #endif
                    174:        tf->tf_r[2] = stack;
                    175:        tf->tf_r[31] = stack;
                    176:        retval[1] = 0;
                    177: }
                    178:
                    179: int
                    180: copystr(fromaddr, toaddr, maxlength, lencopied)
                    181:        const void *fromaddr;
                    182:        void *toaddr;
                    183:        size_t maxlength;
                    184:        size_t *lencopied;
                    185: {
                    186:        u_int tally;
                    187:
                    188:        tally = 0;
                    189:
                    190:        while (maxlength--) {
                    191:                *(u_char *)toaddr = *(u_char *)fromaddr++;
                    192:                tally++;
                    193:                if (*(u_char *)toaddr++ == 0) {
                    194:                        if (lencopied) *lencopied = tally;
                    195:                        return (0);
                    196:                }
                    197:        }
                    198:
                    199:        if (lencopied)
                    200:                *lencopied = tally;
                    201:
                    202:        return (ENAMETOOLONG);
                    203: }
                    204:
                    205: void
                    206: setrunqueue(p)
                    207:        struct proc *p;
                    208: {
                    209:        struct prochd *q;
                    210:        struct proc *oldlast;
                    211:        int which = p->p_priority >> 2;
                    212:
                    213: #ifdef DIAGNOSTIC
                    214:        if (p->p_back != NULL)
                    215:                panic("setrunqueue %p", p);
                    216: #endif
                    217:        q = &qs[which];
                    218:        whichqs |= 1 << which;
                    219:        p->p_forw = (struct proc *)q;
                    220:        p->p_back = oldlast = q->ph_rlink;
                    221:        q->ph_rlink = p;
                    222:        oldlast->p_forw = p;
                    223: }
                    224:
                    225: /*
                    226:  * Remove process p from its run queue, which should be the one
                    227:  * indicated by its priority.  Calls should be made at splstatclock().
                    228:  */
                    229: void
                    230: remrunqueue(vp)
                    231:        struct proc *vp;
                    232: {
                    233:        struct proc *p = vp;
                    234:        int which = p->p_priority >> 2;
                    235:        struct prochd *q;
                    236:
                    237: #ifdef DIAGNOSTIC
                    238:        if ((whichqs & (1 << which)) == 0)
                    239:                panic("remrq %p", p);
                    240: #endif
                    241:        p->p_forw->p_back = p->p_back;
                    242:        p->p_back->p_forw = p->p_forw;
                    243:        p->p_back = NULL;
                    244:        q = &qs[which];
                    245:        if (q->ph_link == (struct proc *)q)
                    246:                whichqs &= ~(1 << which);
                    247: }
                    248:
                    249: #ifdef DDB
                    250: int longformat = 1;
                    251: void
                    252: regdump(struct trapframe *f)
                    253: {
                    254: #define R(i) f->tf_r[i]
                    255:        printf("R00-05: 0x%08x  0x%08x  0x%08x  0x%08x  0x%08x  0x%08x\n",
                    256:               R(0),R(1),R(2),R(3),R(4),R(5));
                    257:        printf("R06-11: 0x%08x  0x%08x  0x%08x  0x%08x  0x%08x  0x%08x\n",
                    258:               R(6),R(7),R(8),R(9),R(10),R(11));
                    259:        printf("R12-17: 0x%08x  0x%08x  0x%08x  0x%08x  0x%08x  0x%08x\n",
                    260:               R(12),R(13),R(14),R(15),R(16),R(17));
                    261:        printf("R18-23: 0x%08x  0x%08x  0x%08x  0x%08x  0x%08x  0x%08x\n",
                    262:               R(18),R(19),R(20),R(21),R(22),R(23));
                    263:        printf("R24-29: 0x%08x  0x%08x  0x%08x  0x%08x  0x%08x  0x%08x\n",
                    264:               R(24),R(25),R(26),R(27),R(28),R(29));
                    265:        printf("R30-31: 0x%08x  0x%08x\n",R(30),R(31));
                    266: #ifdef M88110
                    267:        if (CPU_IS88110) {
                    268:                printf("exip %x enip %x\n", f->tf_exip, f->tf_enip);
                    269:        }
                    270: #endif
                    271: #ifdef M88100
                    272:        if (CPU_IS88100) {
                    273:                printf("sxip %x snip %x sfip %x\n",
                    274:                    f->tf_sxip, f->tf_snip, f->tf_sfip);
                    275:        }
                    276:        if (CPU_IS88100 && f->tf_vector == 0x3) {
                    277:                /* print dmt stuff for data access fault */
                    278:                printf("dmt0 %x dmd0 %x dma0 %x\n",
                    279:                    f->tf_dmt0, f->tf_dmd0, f->tf_dma0);
                    280:                printf("dmt1 %x dmd1 %x dma1 %x\n",
                    281:                    f->tf_dmt1, f->tf_dmd1, f->tf_dma1);
                    282:                printf("dmt2 %x dmd2 %x dma2 %x\n",
                    283:                    f->tf_dmt2, f->tf_dmd2, f->tf_dma2);
                    284:                printf("fault type %d\n", (f->tf_dpfsr >> 16) & 0x7);
                    285:                dae_print((unsigned *)f);
                    286:        }
                    287:        if (CPU_IS88100 && longformat != 0) {
                    288:                printf("fpsr %x fpcr %x epsr %x ssbr %x\n",
                    289:                    f->tf_fpsr, f->tf_fpcr, f->tf_epsr, f->tf_ssbr);
                    290:                printf("fpecr %x fphs1 %x fpls1 %x fphs2 %x fpls2 %x\n",
                    291:                    f->tf_fpecr, f->tf_fphs1, f->tf_fpls1,
                    292:                    f->tf_fphs2, f->tf_fpls2);
                    293:                printf("fppt %x fprh %x fprl %x fpit %x\n",
                    294:                    f->tf_fppt, f->tf_fprh, f->tf_fprl, f->tf_fpit);
                    295:                printf("vector %d mask %x mode %x scratch1 %x cpu %p\n",
                    296:                    f->tf_vector, f->tf_mask, f->tf_mode,
                    297:                    f->tf_scratch1, f->tf_cpu);
                    298:        }
                    299: #endif
                    300: #ifdef M88110
                    301:        if (CPU_IS88110 && longformat != 0) {
                    302:                printf("fpsr %x fpcr %x fpecr %x epsr %x\n",
                    303:                    f->tf_fpsr, f->tf_fpcr, f->tf_fpecr, f->tf_epsr);
                    304:                printf("dsap %x duap %x dsr %x dlar %x dpar %x\n",
                    305:                    f->tf_dsap, f->tf_duap, f->tf_dsr, f->tf_dlar, f->tf_dpar);
                    306:                printf("isap %x iuap %x isr %x ilar %x ipar %x\n",
                    307:                    f->tf_isap, f->tf_iuap, f->tf_isr, f->tf_ilar, f->tf_ipar);
                    308:                printf("vector %d mask %x mode %x scratch1 %x cpu %p\n",
                    309:                    f->tf_vector, f->tf_mask, f->tf_mode,
                    310:                    f->tf_scratch1, f->tf_cpu);
                    311:        }
                    312: #endif
                    313: }
                    314: #endif /* DDB */
                    315:
                    316: /*
                    317:  * Set up the cpu_info pointer and the cpu number for the current processor.
                    318:  */
                    319: void
                    320: set_cpu_number(cpuid_t number)
                    321: {
                    322:        struct cpu_info *ci;
                    323:        extern struct pcb idle_u;
                    324:
                    325: #ifdef MULTIPROCESSOR
                    326:        ci = &m88k_cpus[number];
                    327: #else
                    328:        ci = &m88k_cpus[0];
                    329: #endif
                    330:        ci->ci_cpuid = number;
                    331:
                    332:        __asm__ __volatile__ ("stcr %0, cr17" :: "r" (ci));
                    333:        flush_pipeline();
                    334:
                    335: #ifdef MULTIPROCESSOR
                    336:        if (number == master_cpu)
                    337: #endif
                    338:        {
                    339:                ci->ci_primary = 1;
                    340:                ci->ci_idle_pcb = &idle_u;
                    341:
                    342: #ifdef MULTIPROCESSOR
                    343:                /*
                    344:                 * Specific initialization for the master processor.
                    345:                 */
                    346:                __mp_lock_init(&sir_lock);
                    347: #endif
                    348:        }
                    349:
                    350:        ci->ci_alive = 1;
                    351: }
                    352:
                    353: /*
                    354:  * Notify the current process (p) that it has a signal pending,
                    355:  * process as soon as possible.
                    356:  */
                    357: void
                    358: signotify(struct proc *p)
                    359: {
                    360:        aston(p);
                    361: #ifdef MULTIPROCESSOR
                    362:        if (p->p_cpu != curcpu() && p->p_cpu != NULL)
                    363:                m88k_send_ipi(CI_IPI_NOTIFY, p->p_cpu->ci_cpuid);
                    364: #endif
                    365: }
                    366:
                    367: /*
                    368:  * Soft interrupt interface
                    369:  */
                    370:
                    371: unsigned int ssir;
                    372: int netisr;
                    373:
                    374: void
                    375: dosoftint()
                    376: {
                    377:        int sir, n;
                    378:
                    379:        if ((sir = ssir) == 0)
                    380:                return;
                    381:
                    382:        atomic_clearbits_int(&ssir, sir);
                    383:        uvmexp.softs++;
                    384:
                    385:        if (ISSET(sir, SIR_NET)) {
                    386:                while ((n = netisr) != 0) {
                    387:                        atomic_clearbits_int(&netisr, n);
                    388:
                    389: #define DONETISR(bit, fn)                                              \
                    390:                        do {                                            \
                    391:                                if (n & (1 << bit))                     \
                    392:                                        fn();                           \
                    393:                        } while (0)
                    394:
                    395: #include <net/netisr_dispatch.h>
                    396:
                    397: #undef DONETISR
                    398:                }
                    399:        }
                    400:
                    401:        if (ISSET(sir, SIR_CLOCK))
                    402:                softclock();
                    403: }
                    404:
                    405: int
                    406: spl0()
                    407: {
                    408:        int s;
                    409:
                    410:        s = setipl(IPL_SOFTCLOCK);
                    411:
                    412:        dosoftint();
                    413:
                    414:        setipl(IPL_NONE);
                    415:        return (s);
                    416: }
                    417:
                    418: #define EMPTY_BR       0xc0000000      /* empty "br" instruction */
                    419: #define NO_OP          0xf4005800      /* "or r0, r0, r0" */
                    420:
                    421: #define BRANCH(FROM, TO) \
                    422:        (EMPTY_BR | ((vaddr_t)(TO) - (vaddr_t)(FROM)) >> 2)
                    423:
                    424: #define SET_VECTOR(NUM, VALUE) \
                    425:        do { \
                    426:                vbr[NUM].word_one = NO_OP; \
                    427:                vbr[NUM].word_two = BRANCH(&vbr[NUM].word_two, VALUE); \
                    428:        } while (0)
                    429:
                    430: /*
                    431:  * vector_init(vector, vector_init_list)
                    432:  *
                    433:  * This routine sets up the m88k vector table for the running processor.
                    434:  * This is the first C code to run, before anything is initialized.
                    435:  *
                    436:  * It fills the exception vectors page. I would add an extra four bytes
                    437:  * to the page pointed to by the vbr, since the 88100 may execute the
                    438:  * first instruction of the next trap handler, as documented in its
                    439:  * Errata. Processing trap #511 would then fall into the next page,
                    440:  * unless the address computation wraps, or software traps can not trigger
                    441:  * the issue - the Errata does not provide more detail. And since the
                    442:  * MVME BUG does not add an extra NOP after their VBR page, I'll assume this
                    443:  * is safe for now -- miod
                    444:  */
                    445: void
                    446: vector_init(m88k_exception_vector_area *vbr, u_int32_t *vector_init_list)
                    447: {
                    448:        u_int num;
                    449:        u_int32_t vec;
                    450:
                    451:        for (num = 0; (vec = vector_init_list[num]) != 0; num++)
                    452:                SET_VECTOR(num, vec);
                    453:
                    454:        switch (cputyp) {
                    455:        default:
                    456: #ifdef M88110
                    457:        case CPU_88110:
                    458:            {
                    459:                extern void m88110_sigsys(void);
                    460:                extern void m88110_syscall_handler(void);
                    461:                extern void m88110_cache_flush_handler(void);
                    462:                extern void m88110_stepbpt(void);
                    463:                extern void m88110_userbpt(void);
                    464:
                    465:                for (; num < 512; num++)
                    466:                        SET_VECTOR(num, m88110_sigsys);
                    467:
                    468:                SET_VECTOR(450, m88110_syscall_handler);
                    469:                SET_VECTOR(451, m88110_cache_flush_handler);
                    470:                SET_VECTOR(504, m88110_stepbpt);
                    471:                SET_VECTOR(511, m88110_userbpt);
                    472:            }
                    473:                break;
                    474: #endif
                    475: #ifdef M88100
                    476:        case CPU_88100:
                    477:            {
                    478:                extern void sigsys(void);
                    479:                extern void syscall_handler(void);
                    480:                extern void cache_flush_handler(void);
                    481:                extern void stepbpt(void);
                    482:                extern void userbpt(void);
                    483:
                    484:                for (; num < 512; num++)
                    485:                        SET_VECTOR(num, sigsys);
                    486:
                    487:                SET_VECTOR(450, syscall_handler);
                    488:                SET_VECTOR(451, cache_flush_handler);
                    489:                SET_VECTOR(504, stepbpt);
                    490:                SET_VECTOR(511, userbpt);
                    491:            }
                    492:                break;
                    493: #endif
                    494:        }
                    495:
                    496:        /* GCC will by default produce explicit trap 503 for division by zero */
                    497:        SET_VECTOR(503, vector_init_list[8]);
                    498: }

CVSweb