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

Annotation of sys/arch/sh/sh/sh_machdep.c, Revision 1.1.1.1

1.1       nbrk        1: /*     $OpenBSD: sh_machdep.c,v 1.16 2007/06/06 17:15:12 deraadt Exp $ */
                      2: /*     $NetBSD: sh3_machdep.c,v 1.59 2006/03/04 01:13:36 uwe Exp $     */
                      3:
                      4: /*
                      5:  * Copyright (c) 2007 Miodrag Vallat.
                      6:  *
                      7:  * Permission to use, copy, modify, and distribute this software for any
                      8:  * purpose with or without fee is hereby granted, provided that the above
                      9:  * copyright notice, this permission notice, and the disclaimer below
                     10:  * appear in all copies.
                     11:  *
                     12:  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
                     13:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
                     14:  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
                     15:  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
                     16:  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
                     17:  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
                     18:  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
                     19:  */
                     20: /*-
                     21:  * Copyright (c) 1996, 1997, 1998, 2002 The NetBSD Foundation, Inc.
                     22:  * All rights reserved.
                     23:  *
                     24:  * This code is derived from software contributed to The NetBSD Foundation
                     25:  * by Charles M. Hannum and by Jason R. Thorpe of the Numerical Aerospace
                     26:  * Simulation Facility, NASA Ames Research Center.
                     27:  *
                     28:  * Redistribution and use in source and binary forms, with or without
                     29:  * modification, are permitted provided that the following conditions
                     30:  * are met:
                     31:  * 1. Redistributions of source code must retain the above copyright
                     32:  *    notice, this list of conditions and the following disclaimer.
                     33:  * 2. Redistributions in binary form must reproduce the above copyright
                     34:  *    notice, this list of conditions and the following disclaimer in the
                     35:  *    documentation and/or other materials provided with the distribution.
                     36:  * 3. All advertising materials mentioning features or use of this software
                     37:  *    must display the following acknowledgement:
                     38:  *     This product includes software developed by the NetBSD
                     39:  *     Foundation, Inc. and its contributors.
                     40:  * 4. Neither the name of The NetBSD Foundation nor the names of its
                     41:  *    contributors may be used to endorse or promote products derived
                     42:  *    from this software without specific prior written permission.
                     43:  *
                     44:  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
                     45:  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
                     46:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
                     47:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
                     48:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
                     49:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
                     50:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
                     51:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
                     52:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
                     53:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
                     54:  * POSSIBILITY OF SUCH DAMAGE.
                     55:  */
                     56: /*-
                     57:  * Copyright (c) 1982, 1987, 1990 The Regents of the University of California.
                     58:  * All rights reserved.
                     59:  *
                     60:  * This code is derived from software contributed to Berkeley by
                     61:  * William Jolitz.
                     62:  *
                     63:  * Redistribution and use in source and binary forms, with or without
                     64:  * modification, are permitted provided that the following conditions
                     65:  * are met:
                     66:  * 1. Redistributions of source code must retain the above copyright
                     67:  *    notice, this list of conditions and the following disclaimer.
                     68:  * 2. Redistributions in binary form must reproduce the above copyright
                     69:  *    notice, this list of conditions and the following disclaimer in the
                     70:  *    documentation and/or other materials provided with the distribution.
                     71:  * 3. Neither the name of the University nor the names of its contributors
                     72:  *    may be used to endorse or promote products derived from this software
                     73:  *    without specific prior written permission.
                     74:  *
                     75:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     76:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     77:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     78:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     79:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     80:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     81:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     82:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     83:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     84:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     85:  * SUCH DAMAGE.
                     86:  *
                     87:  *     @(#)machdep.c   7.4 (Berkeley) 6/3/91
                     88:  */
                     89:
                     90: #include <sys/param.h>
                     91: #include <sys/systm.h>
                     92:
                     93: #include <sys/buf.h>
                     94: #include <sys/exec.h>
                     95: #include <sys/kernel.h>
                     96: #include <sys/malloc.h>
                     97: #include <sys/mount.h>
                     98: #include <sys/proc.h>
                     99: #include <sys/signalvar.h>
                    100: #include <sys/syscallargs.h>
                    101: #include <sys/user.h>
                    102: #include <sys/sched.h>
                    103: #include <sys/msg.h>
                    104: #include <sys/conf.h>
                    105: #include <sys/core.h>
                    106: #include <sys/kcore.h>
                    107: #include <sys/reboot.h>
                    108:
                    109: #include <uvm/uvm_extern.h>
                    110:
                    111: #include <dev/cons.h>
                    112:
                    113: #include <sh/cache.h>
                    114: #include <sh/clock.h>
                    115: #include <sh/locore.h>
                    116: #include <sh/mmu.h>
                    117: #include <sh/trap.h>
                    118: #include <sh/intr.h>
                    119: #include <sh/kcore.h>
                    120:
                    121: #ifndef BUFCACHEPERCENT
                    122: #define BUFCACHEPERCENT 5
                    123: #endif
                    124:
                    125: #ifdef  BUFPAGES
                    126: int    bufpages = BUFPAGES;
                    127: #else
                    128: int    bufpages = 0;
                    129: #endif
                    130: int    bufcachepercent = BUFCACHEPERCENT;
                    131:
                    132: /* Our exported CPU info; we can have only one. */
                    133: int cpu_arch;
                    134: int cpu_product;
                    135: char cpu_model[120];
                    136:
                    137: struct vm_map *exec_map;
                    138: struct vm_map *phys_map;
                    139:
                    140: int physmem;
                    141: struct user *proc0paddr;       /* init_main.c use this. */
                    142: struct pcb *curpcb;
                    143: struct md_upte *curupte;       /* SH3 wired u-area hack */
                    144:
                    145: #define        VBR     (u_int8_t *)SH3_PHYS_TO_P1SEG(IOM_RAM_BEGIN)
                    146: vaddr_t ram_start = SH3_PHYS_TO_P1SEG(IOM_RAM_BEGIN);
                    147: /* exception handler holder (sh/sh/vectors.S) */
                    148: extern char sh_vector_generic[], sh_vector_generic_end[];
                    149: extern char sh_vector_interrupt[], sh_vector_interrupt_end[];
                    150: #ifdef SH3
                    151: extern char sh3_vector_tlbmiss[], sh3_vector_tlbmiss_end[];
                    152: #endif
                    153: #ifdef SH4
                    154: extern char sh4_vector_tlbmiss[], sh4_vector_tlbmiss_end[];
                    155: #endif
                    156:
                    157: caddr_t allocsys(caddr_t);
                    158:
                    159: /*
                    160:  * These variables are needed by /sbin/savecore
                    161:  */
                    162: u_int32_t dumpmag = 0x8fca0101;        /* magic number */
                    163: u_int dumpsize;                        /* pages */
                    164: long dumplo;                   /* blocks */
                    165: cpu_kcore_hdr_t cpu_kcore_hdr;
                    166:
                    167: void
                    168: sh_cpu_init(int arch, int product)
                    169: {
                    170:        /* CPU type */
                    171:        cpu_arch = arch;
                    172:        cpu_product = product;
                    173:
                    174: #if defined(SH3) && defined(SH4)
                    175:        /* Set register addresses */
                    176:        sh_devreg_init();
                    177: #endif
                    178:        /* Cache access ops. */
                    179:        sh_cache_init();
                    180:
                    181:        /* MMU access ops. */
                    182:        sh_mmu_init();
                    183:
                    184:        /* Hardclock, RTC initialize. */
                    185:        machine_clock_init();
                    186:
                    187:        /* ICU initiailze. */
                    188:        intc_init();
                    189:
                    190:        /* Exception vector. */
                    191:        memcpy(VBR + 0x100, sh_vector_generic,
                    192:            sh_vector_generic_end - sh_vector_generic);
                    193: #ifdef SH3
                    194:        if (CPU_IS_SH3)
                    195:                memcpy(VBR + 0x400, sh3_vector_tlbmiss,
                    196:                    sh3_vector_tlbmiss_end - sh3_vector_tlbmiss);
                    197: #endif
                    198: #ifdef SH4
                    199:        if (CPU_IS_SH4)
                    200:                memcpy(VBR + 0x400, sh4_vector_tlbmiss,
                    201:                    sh4_vector_tlbmiss_end - sh4_vector_tlbmiss);
                    202: #endif
                    203:        memcpy(VBR + 0x600, sh_vector_interrupt,
                    204:            sh_vector_interrupt_end - sh_vector_interrupt);
                    205:
                    206:        if (!SH_HAS_UNIFIED_CACHE)
                    207:                sh_icache_sync_all();
                    208:
                    209:        __asm volatile("ldc %0, vbr" :: "r"(VBR));
                    210:
                    211:        /* kernel stack setup */
                    212:        __sh_switch_resume = CPU_IS_SH3 ? sh3_switch_resume : sh4_switch_resume;
                    213:
                    214:        /* Set page size (4KB) */
                    215:        uvm_setpagesize();
                    216: }
                    217:
                    218: /*
                    219:  * void sh_proc0_init(void):
                    220:  *     Setup proc0 u-area.
                    221:  */
                    222: void
                    223: sh_proc0_init()
                    224: {
                    225:        struct switchframe *sf;
                    226:        vaddr_t u;
                    227:
                    228:        /* Steal process0 u-area */
                    229:        u = uvm_pageboot_alloc(USPACE);
                    230:        memset((void *)u, 0, USPACE);
                    231:
                    232:        /* Setup proc0 */
                    233:        proc0paddr = (struct user *)u;
                    234:        proc0.p_addr = proc0paddr;
                    235:        /*
                    236:         * u-area map:
                    237:         * |user| .... | .................. |
                    238:         * | PAGE_SIZE | USPACE - PAGE_SIZE |
                    239:          *        frame top        stack top
                    240:         * current frame ... r6_bank
                    241:         * stack top     ... r7_bank
                    242:         * current stack ... r15
                    243:         */
                    244:        curpcb = proc0.p_md.md_pcb = &proc0.p_addr->u_pcb;
                    245:        curupte = proc0.p_md.md_upte;
                    246:
                    247:        sf = &curpcb->pcb_sf;
                    248:        sf->sf_r6_bank = u + PAGE_SIZE;
                    249:        sf->sf_r7_bank = sf->sf_r15     = u + USPACE;
                    250:        __asm volatile("ldc %0, r6_bank" :: "r"(sf->sf_r6_bank));
                    251:        __asm volatile("ldc %0, r7_bank" :: "r"(sf->sf_r7_bank));
                    252:
                    253:        proc0.p_md.md_regs = (struct trapframe *)sf->sf_r6_bank - 1;
                    254: #ifdef KSTACK_DEBUG
                    255:        memset((char *)(u + sizeof(struct user)), 0x5a,
                    256:            PAGE_SIZE - sizeof(struct user));
                    257:        memset((char *)(u + PAGE_SIZE), 0xa5, USPACE - PAGE_SIZE);
                    258: #endif /* KSTACK_DEBUG */
                    259: }
                    260:
                    261: void
                    262: sh_startup()
                    263: {
                    264:        vaddr_t minaddr, maxaddr;
                    265:        caddr_t sysbase;
                    266:        caddr_t size;
                    267:
                    268:        printf("%s", version);
                    269:        if (*cpu_model != '\0')
                    270:                printf("%s\n", cpu_model);
                    271: #ifdef DEBUG
                    272:        printf("general exception handler:\t%d byte\n",
                    273:            sh_vector_generic_end - sh_vector_generic);
                    274:        printf("TLB miss exception handler:\t%d byte\n",
                    275: #if defined(SH3) && defined(SH4)
                    276:            CPU_IS_SH3 ? sh3_vector_tlbmiss_end - sh3_vector_tlbmiss :
                    277:            sh4_vector_tlbmiss_end - sh4_vector_tlbmiss
                    278: #elif defined(SH3)
                    279:            sh3_vector_tlbmiss_end - sh3_vector_tlbmiss
                    280: #elif defined(SH4)
                    281:            sh4_vector_tlbmiss_end - sh4_vector_tlbmiss
                    282: #endif
                    283:            );
                    284:        printf("interrupt exception handler:\t%d byte\n",
                    285:            sh_vector_interrupt_end - sh_vector_interrupt);
                    286: #endif /* DEBUG */
                    287:
                    288:        printf("real mem = %u (%uK)\n", ctob(physmem), ctob(physmem) / 1024);
                    289:
                    290:        /*
                    291:         * Find out how much space we need, allocate it,
                    292:         * and then give everything true virtual addresses.
                    293:         */
                    294:        size = allocsys(NULL);
                    295:        sysbase = (caddr_t)uvm_km_zalloc(kernel_map, round_page((vaddr_t)size));
                    296:        if (sysbase == 0)
                    297:                panic("sh_startup: no room for system tables; %d required",
                    298:                    (u_int)size);
                    299:        if ((caddr_t)((allocsys(sysbase) - sysbase)) != size)
                    300:                panic("cpu_startup: system table size inconsistency");
                    301:
                    302:        /*
                    303:         * Determine how many buffers to allocate.
                    304:         * We allocate bufcachepercent% of memory for buffer space.
                    305:         */
                    306:        if (bufpages == 0)
                    307:                bufpages = physmem * bufcachepercent / 100;
                    308:
                    309:        /* Restrict to at most 25% filled kvm */
                    310:        if (bufpages >
                    311:            (VM_MAX_KERNEL_ADDRESS-VM_MIN_KERNEL_ADDRESS) / PAGE_SIZE / 4)
                    312:                bufpages = (VM_MAX_KERNEL_ADDRESS-VM_MIN_KERNEL_ADDRESS) /
                    313:                    PAGE_SIZE / 4;
                    314:
                    315:        /*
                    316:         * Allocate a submap for exec arguments.  This map effectively
                    317:         * limits the number of processes exec'ing at any time.
                    318:         */
                    319:        minaddr = vm_map_min(kernel_map);
                    320:        exec_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr,
                    321:            16 * NCARGS, VM_MAP_PAGEABLE, FALSE, NULL);
                    322:
                    323:        /*
                    324:         * Allocate a submap for physio
                    325:         */
                    326:        phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr,
                    327:            VM_PHYS_SIZE, 0, FALSE, NULL);
                    328:
                    329:        /*
                    330:         * Set up buffers, so they can be used to read disk labels.
                    331:         */
                    332:        bufinit();
                    333:
                    334:        printf("avail mem = %u (%uK)\n", ptoa(uvmexp.free),
                    335:            ptoa(uvmexp.free) / 1024);
                    336:
                    337:        if (boothowto & RB_CONFIG) {
                    338: #ifdef BOOT_CONFIG
                    339:                user_config();
                    340: #else
                    341:                printf("kernel does not support -c; continuing..\n");
                    342: #endif
                    343:        }
                    344: }
                    345:
                    346: /*
                    347:  * Allocate space for system data structures.  We are given
                    348:  * a starting virtual address and we return a final virtual
                    349:  * address; along the way we set each data structure pointer.
                    350:  *
                    351:  * We call allocsys() with 0 to find out how much space we want,
                    352:  * allocate that much and fill it with zeroes, and then call
                    353:  * allocsys() again with the correct base virtual address.
                    354:  */
                    355: caddr_t
                    356: allocsys(caddr_t v)
                    357: {
                    358: #define        valloc(name, type, num) v = (caddr_t)(((name) = (type *)v) + (num))
                    359:
                    360: #ifdef SYSVMSG
                    361:        valloc(msgpool, char, msginfo.msgmax);
                    362:        valloc(msgmaps, struct msgmap, msginfo.msgseg);
                    363:        valloc(msghdrs, struct msg, msginfo.msgtql);
                    364:        valloc(msqids, struct msqid_ds, msginfo.msgmni);
                    365: #endif
                    366:
                    367:        return v;
                    368: }
                    369:
                    370: void
                    371: dumpconf(void)
                    372: {
                    373:        cpu_kcore_hdr_t *h = &cpu_kcore_hdr;
                    374:        u_int dumpextra, totaldumpsize;         /* in disk blocks */
                    375:        u_int seg, nblks;
                    376:
                    377:        if (dumpdev == NODEV ||
                    378:            (nblks = (bdevsw[major(dumpdev)].d_psize)(dumpdev)) == 0)
                    379:                return;
                    380:        if (nblks <= ctod(1))
                    381:                return;
                    382:
                    383:        dumpsize = 0;
                    384:        for (seg = 0; seg < h->kcore_nsegs; seg++)
                    385:                dumpsize += atop(h->kcore_segs[seg].size);
                    386:        dumpextra = cpu_dumpsize();
                    387:
                    388:        /* Always skip the first block, in case there is a label there. */
                    389:        if (dumplo < btodb(1));
                    390:                dumplo = btodb(1);
                    391:
                    392:        /* Put dump at the end of the partition, and make it fit. */
                    393:        totaldumpsize = ctod(dumpsize) + dumpextra;
                    394:        if (totaldumpsize > nblks - dumplo) {
                    395:                totaldumpsize = dbtob(nblks - dumplo);
                    396:                dumpsize = dtoc(totaldumpsize - dumpextra);
                    397:        }
                    398:        if (dumplo < nblks - totaldumpsize)
                    399:                dumplo = nblks - totaldumpsize;
                    400: }
                    401:
                    402: void
                    403: dumpsys()
                    404: {
                    405:        cpu_kcore_hdr_t *h = &cpu_kcore_hdr;
                    406:        daddr64_t blkno;
                    407:        int (*dump)(dev_t, daddr64_t, caddr_t, size_t);
                    408:        u_int page = 0;
                    409:        paddr_t dumppa;
                    410:        u_int seg;
                    411:        int rc;
                    412:        extern int msgbufmapped;
                    413:
                    414:        /* Don't record dump messages in msgbuf. */
                    415:        msgbufmapped = 0;
                    416:
                    417:        /* Make sure dump settings are valid. */
                    418:        if (dumpdev == NODEV)
                    419:                return;
                    420:        if (dumpsize == 0) {
                    421:                dumpconf();
                    422:                if (dumpsize == 0)
                    423:                        return;
                    424:        }
                    425:        if (dumplo <= 0) {
                    426:                printf("\ndump to dev 0x%x not possible, not enough space\n",
                    427:                    dumpdev);
                    428:                return;
                    429:        }
                    430:
                    431:        dump = bdevsw[major(dumpdev)].d_dump;
                    432:        blkno = dumplo;
                    433:
                    434:        printf("\ndumping to dev 0x%x offset %ld\n", dumpdev, dumplo);
                    435:
                    436:        printf("dump ");
                    437:
                    438:        /* Write dump header */
                    439:        rc = cpu_dump(dump, &blkno);
                    440:        if (rc != 0)
                    441:                goto bad;
                    442:
                    443:        for (seg = 0; seg < h->kcore_nsegs; seg++) {
                    444:                u_int pagesleft;
                    445:
                    446:                pagesleft = atop(h->kcore_segs[seg].size);
                    447:                dumppa = (paddr_t)h->kcore_segs[seg].start;
                    448:
                    449:                while (pagesleft != 0) {
                    450:                        u_int npages;
                    451:
                    452: #define        NPGMB   atop(1024 * 1024)
                    453:                        if (page != 0 && (page % NPGMB) == 0)
                    454:                                printf("%u ", page / NPGMB);
                    455:
                    456:                        /* do not dump more than 1MB at once */
                    457:                        npages = min(pagesleft, NPGMB);
                    458: #undef NPGMB
                    459:                        npages = min(npages, dumpsize);
                    460:
                    461:                        rc = (*dump)(dumpdev, blkno,
                    462:                            (caddr_t)SH3_PHYS_TO_P2SEG(dumppa), ptoa(npages));
                    463:                        if (rc != 0)
                    464:                                goto bad;
                    465:
                    466:                        pagesleft -= npages;
                    467:                        dumppa += ptoa(npages);
                    468:                        page += npages;
                    469:                        dumpsize -= npages;
                    470:                        if (dumpsize == 0)
                    471:                                goto bad;       /* if truncated dump */
                    472:                        blkno += ctod(npages);
                    473:                }
                    474:        }
                    475: bad:
                    476:        switch (rc) {
                    477:        case 0:
                    478:                printf("succeeded\n");
                    479:                break;
                    480:        case ENXIO:
                    481:                printf("device bad\n");
                    482:                break;
                    483:        case EFAULT:
                    484:                printf("device not ready\n");
                    485:                break;
                    486:        case EINVAL:
                    487:                printf("area improper\n");
                    488:                break;
                    489:        case EIO:
                    490:                printf("I/O error\n");
                    491:                break;
                    492:        case EINTR:
                    493:                printf("aborted\n");
                    494:                break;
                    495:        default:
                    496:                printf("error %d\n", rc);
                    497:                break;
                    498:        }
                    499:
                    500:        /* make sure console can output our last message */
                    501:        delay(1 * 1000 * 1000);
                    502: }
                    503:
                    504: /*
                    505:  * Signal frame.
                    506:  */
                    507: struct sigframe {
                    508: #if 0 /* in registers on entry to signal trampoline */
                    509:        int             sf_signum;      /* r4 - "signum" argument for handler */
                    510:        siginfo_t       *sf_sip;        /* r5 - "sip" argument for handler */
                    511:        struct sigcontext *sf_ucp;      /* r6 - "ucp" argument for handler */
                    512: #endif
                    513:        struct sigcontext sf_uc;        /* actual context */
                    514:        siginfo_t       sf_si;
                    515: };
                    516:
                    517: /*
                    518:  * Send an interrupt to process.
                    519:  */
                    520: void
                    521: sendsig(sig_t catcher, int sig, int mask, u_long code, int type,
                    522:     union sigval val)
                    523: {
                    524:        struct proc *p = curproc;
                    525:        struct sigframe *fp, frame;
                    526:        struct trapframe *tf = p->p_md.md_regs;
                    527:        struct sigacts *ps = p->p_sigacts;
                    528:        siginfo_t *sip;
                    529:        int onstack;
                    530:
                    531:        onstack = ps->ps_sigstk.ss_flags & SS_ONSTACK;
                    532:        if ((ps->ps_flags & SAS_ALTSTACK) && onstack == 0 &&
                    533:            (ps->ps_sigonstack & sigmask(sig))) {
                    534:                fp = (struct sigframe *)((vaddr_t)ps->ps_sigstk.ss_sp +
                    535:                    ps->ps_sigstk.ss_size);
                    536:                ps->ps_sigstk.ss_flags |= SS_ONSTACK;
                    537:        } else
                    538:                fp = (void *)p->p_md.md_regs->tf_r15;
                    539:        --fp;
                    540:
                    541:
                    542:        bzero(&frame, sizeof(frame));
                    543:
                    544:        if (ps->ps_siginfo & sigmask(sig)) {
                    545:                initsiginfo(&frame.sf_si, sig, code, type, val);
                    546:                sip = &fp->sf_si;
                    547:        } else
                    548:                sip = NULL;
                    549:
                    550:        /* Save register context. */
                    551:        frame.sf_uc.sc_reg.r_spc = tf->tf_spc;
                    552:        frame.sf_uc.sc_reg.r_ssr = tf->tf_ssr;
                    553:        frame.sf_uc.sc_reg.r_pr = tf->tf_pr;
                    554:        frame.sf_uc.sc_reg.r_mach = tf->tf_mach;
                    555:        frame.sf_uc.sc_reg.r_macl = tf->tf_macl;
                    556:        frame.sf_uc.sc_reg.r_r15 = tf->tf_r15;
                    557:        frame.sf_uc.sc_reg.r_r14 = tf->tf_r14;
                    558:        frame.sf_uc.sc_reg.r_r13 = tf->tf_r13;
                    559:        frame.sf_uc.sc_reg.r_r12 = tf->tf_r12;
                    560:        frame.sf_uc.sc_reg.r_r11 = tf->tf_r11;
                    561:        frame.sf_uc.sc_reg.r_r10 = tf->tf_r10;
                    562:        frame.sf_uc.sc_reg.r_r9 = tf->tf_r9;
                    563:        frame.sf_uc.sc_reg.r_r8 = tf->tf_r8;
                    564:        frame.sf_uc.sc_reg.r_r7 = tf->tf_r7;
                    565:        frame.sf_uc.sc_reg.r_r6 = tf->tf_r6;
                    566:        frame.sf_uc.sc_reg.r_r5 = tf->tf_r5;
                    567:        frame.sf_uc.sc_reg.r_r4 = tf->tf_r4;
                    568:        frame.sf_uc.sc_reg.r_r3 = tf->tf_r3;
                    569:        frame.sf_uc.sc_reg.r_r2 = tf->tf_r2;
                    570:        frame.sf_uc.sc_reg.r_r1 = tf->tf_r1;
                    571:        frame.sf_uc.sc_reg.r_r0 = tf->tf_r0;
                    572: #ifdef SH4
                    573:        if (CPU_IS_SH4)
                    574:                fpu_save(&frame.sf_uc.sc_fpreg);
                    575: #endif
                    576:
                    577:        frame.sf_uc.sc_onstack = onstack;
                    578:        frame.sf_uc.sc_expevt = tf->tf_expevt;
                    579:        /* frame.sf_uc.sc_err = 0; */
                    580:        frame.sf_uc.sc_mask = mask;
                    581:
                    582:        if (copyout(&frame, fp, sizeof(frame)) != 0) {
                    583:                /*
                    584:                 * Process has trashed its stack; give it an illegal
                    585:                 * instruction to halt it in its tracks.
                    586:                 */
                    587:                sigexit(p, SIGILL);
                    588:                /* NOTREACHED */
                    589:        }
                    590:
                    591:        tf->tf_r4 = sig;                /* "signum" argument for handler */
                    592:        tf->tf_r5 = (int)sip;           /* "sip" argument for handler */
                    593:        tf->tf_r6 = (int)&fp->sf_uc;    /* "ucp" argument for handler */
                    594:        tf->tf_spc = (int)catcher;
                    595:        tf->tf_r15 = (int)fp;
                    596:        tf->tf_pr = (int)p->p_sigcode;
                    597: }
                    598:
                    599: /*
                    600:  * System call to cleanup state after a signal
                    601:  * has been taken.  Reset signal mask and
                    602:  * stack state from context left by sendsig (above).
                    603:  * Return to previous pc and psl as specified by
                    604:  * context left by sendsig. Check carefully to
                    605:  * make sure that the user has not modified the
                    606:  * psl to gain improper privileges or to cause
                    607:  * a machine fault.
                    608:  */
                    609: int
                    610: sys_sigreturn(struct proc *p, void *v, register_t *retval)
                    611: {
                    612:        struct sys_sigreturn_args /* {
                    613:                syscallarg(struct sigcontext *) sigcntxp;
                    614:        } */ *uap = v;
                    615:        struct sigcontext *scp, context;
                    616:        struct trapframe *tf;
                    617:        int error;
                    618:
                    619:        /*
                    620:         * The trampoline code hands us the context.
                    621:         * It is unsafe to keep track of it ourselves, in the event that a
                    622:         * program jumps out of a signal handler.
                    623:         */
                    624:        scp = SCARG(uap, sigcntxp);
                    625:        if ((error = copyin((caddr_t)scp, &context, sizeof(*scp))) != 0)
                    626:                return (error);
                    627:
                    628:        /* Restore signal context. */
                    629:        tf = p->p_md.md_regs;
                    630:
                    631:        /* Check for security violations. */
                    632:        if (((context.sc_reg.r_ssr ^ tf->tf_ssr) & PSL_USERSTATIC) != 0)
                    633:                return (EINVAL);
                    634:
                    635:        tf->tf_spc = context.sc_reg.r_spc;
                    636:        tf->tf_ssr = context.sc_reg.r_ssr;
                    637:        tf->tf_macl = context.sc_reg.r_macl;
                    638:        tf->tf_mach = context.sc_reg.r_mach;
                    639:        tf->tf_pr = context.sc_reg.r_pr;
                    640:        tf->tf_r13 = context.sc_reg.r_r13;
                    641:        tf->tf_r12 = context.sc_reg.r_r12;
                    642:        tf->tf_r11 = context.sc_reg.r_r11;
                    643:        tf->tf_r10 = context.sc_reg.r_r10;
                    644:        tf->tf_r9 = context.sc_reg.r_r9;
                    645:        tf->tf_r8 = context.sc_reg.r_r8;
                    646:        tf->tf_r7 = context.sc_reg.r_r7;
                    647:        tf->tf_r6 = context.sc_reg.r_r6;
                    648:        tf->tf_r5 = context.sc_reg.r_r5;
                    649:        tf->tf_r4 = context.sc_reg.r_r4;
                    650:        tf->tf_r3 = context.sc_reg.r_r3;
                    651:        tf->tf_r2 = context.sc_reg.r_r2;
                    652:        tf->tf_r1 = context.sc_reg.r_r1;
                    653:        tf->tf_r0 = context.sc_reg.r_r0;
                    654:        tf->tf_r15 = context.sc_reg.r_r15;
                    655:        tf->tf_r14 = context.sc_reg.r_r14;
                    656:
                    657: #ifdef SH4
                    658:        if (CPU_IS_SH4)
                    659:                fpu_restore(&context.sc_fpreg);
                    660: #endif
                    661:
                    662:        /* Restore signal stack. */
                    663:        if (context.sc_onstack)
                    664:                p->p_sigacts->ps_sigstk.ss_flags |= SS_ONSTACK;
                    665:        else
                    666:                p->p_sigacts->ps_sigstk.ss_flags &= ~SS_ONSTACK;
                    667:        /* Restore signal mask. */
                    668:        p->p_sigmask = context.sc_mask & ~sigcantmask;
                    669:
                    670:        return (EJUSTRETURN);
                    671: }
                    672:
                    673: /*
                    674:  * Clear registers on exec
                    675:  */
                    676: void
                    677: setregs(struct proc *p, struct exec_package *pack, u_long stack,
                    678:     register_t rval[2])
                    679: {
                    680:        struct trapframe *tf;
                    681:        struct pcb *pcb = p->p_md.md_pcb;
                    682:
                    683:        p->p_md.md_flags &= ~MDP_USEDFPU;
                    684:
                    685:        tf = p->p_md.md_regs;
                    686:
                    687:        tf->tf_r0 = 0;
                    688:        tf->tf_r1 = 0;
                    689:        tf->tf_r2 = 0;
                    690:        tf->tf_r3 = 0;
                    691:        copyin((caddr_t)stack, &tf->tf_r4, sizeof(register_t)); /* argc */
                    692:        tf->tf_r5 = stack + 4;                  /* argv */
                    693:        tf->tf_r6 = stack + 4 * tf->tf_r4 + 8;  /* envp */
                    694:        tf->tf_r7 = 0;
                    695:        tf->tf_r8 = 0;
                    696:        tf->tf_r9 = (int)PS_STRINGS;
                    697:        tf->tf_r10 = 0;
                    698:        tf->tf_r11 = 0;
                    699:        tf->tf_r12 = 0;
                    700:        tf->tf_r13 = 0;
                    701:        tf->tf_r14 = 0;
                    702:        tf->tf_spc = pack->ep_entry;
                    703:        tf->tf_ssr = PSL_USERSET;
                    704:        tf->tf_r15 = stack;
                    705:
                    706: #ifdef SH4
                    707:        if (CPU_IS_SH4) {
                    708:                /*
                    709:                 * Clear floating point registers.
                    710:                 */
                    711:                bzero(&pcb->pcb_fp, sizeof(pcb->pcb_fp));
                    712:                fpu_restore(&pcb->pcb_fp);
                    713:        }
                    714: #endif
                    715:
                    716:        rval[1] = 0;
                    717: }
                    718:
                    719: void
                    720: setrunqueue(struct proc *p)
                    721: {
                    722:        int whichq = p->p_priority / PPQ;
                    723:        struct prochd *q;
                    724:        struct proc *prev;
                    725:
                    726: #ifdef DIAGNOSTIC
                    727:        if (p->p_back != NULL || p->p_wchan != NULL || p->p_stat != SRUN)
                    728:                panic("setrunqueue");
                    729: #endif
                    730:        q = &qs[whichq];
                    731:        prev = q->ph_rlink;
                    732:        p->p_forw = (struct proc *)q;
                    733:        q->ph_rlink = p;
                    734:        prev->p_forw = p;
                    735:        p->p_back = prev;
                    736:        whichqs |= 1 << whichq;
                    737: }
                    738:
                    739: void
                    740: remrunqueue(struct proc *p)
                    741: {
                    742:        struct proc *prev, *next;
                    743:        int whichq = p->p_priority / PPQ;
                    744:
                    745: #ifdef DIAGNOSTIC
                    746:        if (((whichqs & (1 << whichq)) == 0))
                    747:                panic("remrunqueue: bit %d not set", whichq);
                    748: #endif
                    749:        prev = p->p_back;
                    750:        p->p_back = NULL;
                    751:        next = p->p_forw;
                    752:        prev->p_forw = next;
                    753:        next->p_back = prev;
                    754:        if (prev == next)
                    755:                whichqs &= ~(1 << whichq);
                    756: }
                    757:
                    758: /*
                    759:  * Jump to reset vector.
                    760:  */
                    761: void
                    762: cpu_reset()
                    763: {
                    764:        _cpu_exception_suspend();
                    765:        _reg_write_4(SH_(EXPEVT), EXPEVT_RESET_MANUAL);
                    766:
                    767: #ifndef __lint__
                    768:        goto *(void *)0xa0000000;
                    769: #endif
                    770:        /* NOTREACHED */
                    771: }

CVSweb