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

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

1.1       nbrk        1: /*     $OpenBSD: vm_machdep.c,v 1.9 2007/05/27 20:59:26 miod Exp $     */
                      2: /*     $NetBSD: vm_machdep.c,v 1.53 2006/08/31 16:49:21 matt 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) 2002 The NetBSD Foundation, Inc. All rights reserved.
                     22:  * Copyright (c) 1982, 1986 The Regents of the University of California.
                     23:  * All rights reserved.
                     24:  *
                     25:  * This code is derived from software contributed to Berkeley by
                     26:  * the Systems Programming Group of the University of Utah Computer
                     27:  * Science Department, and William Jolitz.
                     28:  *
                     29:  * Redistribution and use in source and binary forms, with or without
                     30:  * modification, are permitted provided that the following conditions
                     31:  * are met:
                     32:  * 1. Redistributions of source code must retain the above copyright
                     33:  *    notice, this list of conditions and the following disclaimer.
                     34:  * 2. Redistributions in binary form must reproduce the above copyright
                     35:  *    notice, this list of conditions and the following disclaimer in the
                     36:  *    documentation and/or other materials provided with the distribution.
                     37:  * 3. Neither the name of the University nor the names of its contributors
                     38:  *    may be used to endorse or promote products derived from this software
                     39:  *    without specific prior written permission.
                     40:  *
                     41:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     42:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     43:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     44:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     45:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     46:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     47:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     48:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     49:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     50:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     51:  * SUCH DAMAGE.
                     52:  *
                     53:  *     @(#)vm_machdep.c        7.3 (Berkeley) 5/13/91
                     54:  */
                     55: /*-
                     56:  * Copyright (c) 1995 Charles M. Hannum.  All rights reserved.
                     57:  * Copyright (c) 1989, 1990 William Jolitz
                     58:  * All rights reserved.
                     59:  *
                     60:  * This code is derived from software contributed to Berkeley by
                     61:  * the Systems Programming Group of the University of Utah Computer
                     62:  * Science Department, and William Jolitz.
                     63:  *
                     64:  * Redistribution and use in source and binary forms, with or without
                     65:  * modification, are permitted provided that the following conditions
                     66:  * are met:
                     67:  * 1. Redistributions of source code must retain the above copyright
                     68:  *    notice, this list of conditions and the following disclaimer.
                     69:  * 2. Redistributions in binary form must reproduce the above copyright
                     70:  *    notice, this list of conditions and the following disclaimer in the
                     71:  *    documentation and/or other materials provided with the distribution.
                     72:  * 3. All advertising materials mentioning features or use of this software
                     73:  *    must display the following acknowledgement:
                     74:  *     This product includes software developed by the University of
                     75:  *     California, Berkeley and its contributors.
                     76:  * 4. Neither the name of the University nor the names of its contributors
                     77:  *    may be used to endorse or promote products derived from this software
                     78:  *    without specific prior written permission.
                     79:  *
                     80:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     81:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     82:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     83:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     84:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     85:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     86:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     87:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     88:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     89:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     90:  * SUCH DAMAGE.
                     91:  *
                     92:  *     @(#)vm_machdep.c        7.3 (Berkeley) 5/13/91
                     93:  */
                     94:
                     95: /*
                     96:  *     Utah $Hdr: vm_machdep.c 1.16.1.1 89/06/23$
                     97:  */
                     98:
                     99: #include <sys/param.h>
                    100: #include <sys/systm.h>
                    101: #include <sys/proc.h>
                    102: #include <sys/malloc.h>
                    103: #include <sys/vnode.h>
                    104: #include <sys/buf.h>
                    105: #include <sys/user.h>
                    106: #include <sys/core.h>
                    107: #include <sys/exec.h>
                    108: #include <sys/ptrace.h>
                    109: #include <sys/signalvar.h>
                    110:
                    111: #include <uvm/uvm_extern.h>
                    112:
                    113: #include <sh/locore.h>
                    114: #include <sh/cpu.h>
                    115: #include <sh/reg.h>
                    116: #include <sh/mmu.h>
                    117: #include <sh/cache.h>
                    118:
                    119: extern void proc_trampoline(void);
                    120:
                    121: /*
                    122:  * Finish a fork operation, with process p2 nearly set up.
                    123:  * Copy and update the pcb and trap frame, making the child ready to run.
                    124:  *
                    125:  * Rig the child's kernel stack so that it will start out in
                    126:  * proc_trampoline() and call child_return() with p2 as an
                    127:  * argument. This causes the newly-created child process to go
                    128:  * directly to user level with an apparent return value of 0 from
                    129:  * fork(), while the parent process returns normally.
                    130:  *
                    131:  * p1 is the process being forked; if p1 == &proc0, we are creating
                    132:  * a kernel thread, and the return path and argument are specified with
                    133:  * `func' and `arg'.
                    134:  *
                    135:  * If an alternate user-level stack is requested (with non-zero values
                    136:  * in both the stack and stacksize args), set up the user stack pointer
                    137:  * accordingly.
                    138:  */
                    139: void
                    140: cpu_fork(struct proc *p1, struct proc *p2, void *stack, size_t stacksize,
                    141:     void (*func)(void *), void *arg)
                    142: {
                    143:        struct pcb *pcb;
                    144:        struct trapframe *tf;
                    145:        struct switchframe *sf;
                    146:        vaddr_t spbase, fptop;
                    147: #define        P1ADDR(x)       (SH3_PHYS_TO_P1SEG(*__pmap_kpte_lookup(x) & PG_PPN))
                    148:
                    149:        KDASSERT(p1 == curproc || p1 == &proc0);
                    150:
                    151:        bzero(&p2->p_md, sizeof(p2->p_md));
                    152:
                    153:        /* Copy flags */
                    154:        p2->p_md.md_flags = p1->p_md.md_flags;
                    155:
                    156:        pcb = NULL;             /* XXXGCC: -Wuninitialized */
                    157: #ifdef SH3
                    158:        /*
                    159:         * Convert frame pointer top to P1. because SH3 can't make
                    160:         * wired TLB entry, context store space accessing must not cause
                    161:         * exception. For SH3, we are 4K page, P3/P1 conversion don't
                    162:         * cause virtual-aliasing.
                    163:         */
                    164:        if (CPU_IS_SH3)
                    165:                pcb = (struct pcb *)P1ADDR((vaddr_t)&p2->p_addr->u_pcb);
                    166: #endif /* SH3 */
                    167: #ifdef SH4
                    168:        /* SH4 can make wired entry, no need to convert to P1. */
                    169:        if (CPU_IS_SH4)
                    170:                pcb = &p2->p_addr->u_pcb;
                    171: #endif /* SH4 */
                    172:
                    173:        p2->p_md.md_pcb = pcb;
                    174:        fptop = (vaddr_t)pcb + PAGE_SIZE;
                    175:
                    176:        /* set up the kernel stack pointer */
                    177:        spbase = (vaddr_t)p2->p_addr + PAGE_SIZE;
                    178: #ifdef P1_STACK
                    179:        /* Convert to P1 from P3 */
                    180:        /*
                    181:         * wbinv u-area to avoid cache-aliasing, since kernel stack
                    182:         * is accessed from P1 instead of P3.
                    183:         */
                    184:        if (SH_HAS_VIRTUAL_ALIAS)
                    185:                sh_dcache_wbinv_range((vaddr_t)p2->p_addr, USPACE);
                    186:        spbase = P1ADDR(spbase);
                    187: #else /* !P1_STACK */
                    188:        /* Prepare u-area PTEs */
                    189: #ifdef SH3
                    190:        if (CPU_IS_SH3)
                    191:                sh3_switch_setup(p2);
                    192: #endif
                    193: #ifdef SH4
                    194:        if (CPU_IS_SH4)
                    195:                sh4_switch_setup(p2);
                    196: #endif
                    197: #endif /* !P1_STACK */
                    198:
                    199: #ifdef KSTACK_DEBUG
                    200:        /* Fill magic number for tracking */
                    201:        memset((char *)fptop - PAGE_SIZE + sizeof(struct user), 0x5a,
                    202:            PAGE_SIZE - sizeof(struct user));
                    203:        memset((char *)spbase, 0xa5, (USPACE - PAGE_SIZE));
                    204:        memset(&pcb->pcb_sf, 0xb4, sizeof(struct switchframe));
                    205: #endif /* KSTACK_DEBUG */
                    206:
                    207:        /*
                    208:         * Copy the user context.
                    209:         */
                    210:        p2->p_md.md_regs = tf = (struct trapframe *)fptop - 1;
                    211:        memcpy(tf, p1->p_md.md_regs, sizeof(struct trapframe));
                    212:
                    213:        /*
                    214:         * If specified, give the child a different stack.
                    215:         */
                    216:        if (stack != NULL)
                    217:                tf->tf_r15 = (u_int)stack + stacksize;
                    218:
                    219:        /* Setup switch frame */
                    220:        sf = &pcb->pcb_sf;
                    221:        sf->sf_r11 = (int)arg;          /* proc_trampoline hook func's arg */
                    222:        sf->sf_r12 = (int)func;         /* proc_trampoline hook func */
                    223:        sf->sf_r15 = spbase + USPACE - PAGE_SIZE;/* current stack pointer */
                    224:        sf->sf_r7_bank = sf->sf_r15;    /* stack top */
                    225:        sf->sf_r6_bank = (vaddr_t)tf;   /* current frame pointer */
                    226:        /* when switch to me, jump to proc_trampoline */
                    227:        sf->sf_pr = (int)proc_trampoline;
                    228:        /*
                    229:         * Enable interrupt when switch frame is restored, since
                    230:         * kernel thread begin to run without restoring trapframe.
                    231:         */
                    232:        sf->sf_sr = PSL_MD;             /* kernel mode, interrupt enable */
                    233:
                    234: #ifdef SH4
                    235:        if (CPU_IS_SH4) {
                    236:                /*
                    237:                 * Propagate floating point registers to the new process
                    238:                 * (they are not in the trapframe).
                    239:                 */
                    240:                if (p1 == curproc)
                    241:                        fpu_save(&p1->p_md.md_pcb->pcb_fp);
                    242:                bcopy(&p1->p_md.md_pcb->pcb_fp, &pcb->pcb_fp,
                    243:                    sizeof(struct fpreg));
                    244:        }
                    245: #endif
                    246: }
                    247:
                    248: /*
                    249:  * Dump the machine specific segment at the start of a core dump.
                    250:  */
                    251: struct md_core {
                    252:        struct reg intreg;
                    253:        struct fpreg fpreg;
                    254: };
                    255:
                    256: int
                    257: cpu_coredump(struct proc *p, struct vnode *vp, struct ucred *cred,
                    258:     struct core *chdr)
                    259: {
                    260:        struct md_core md_core;
                    261:        struct coreseg cseg;
                    262:        int error;
                    263:
                    264:        CORE_SETMAGIC(*chdr, COREMAGIC, MID_MACHINE, 0);
                    265:        chdr->c_hdrsize = ALIGN(sizeof(*chdr));
                    266:        chdr->c_seghdrsize = ALIGN(sizeof(cseg));
                    267:        chdr->c_cpusize = sizeof(md_core);
                    268:
                    269:        /* Save integer registers. */
                    270:        error = process_read_regs(p, &md_core.intreg);
                    271:        if (error)
                    272:                return error;
                    273:
                    274: #ifdef SH4
                    275:        if (CPU_IS_SH4) {
                    276:                error = process_read_fpregs(p, &md_core.fpreg);
                    277:                if (error)
                    278:                        return error;
                    279:        }
                    280: #endif
                    281: #ifdef SH3
                    282:        if (CPU_IS_SH3)
                    283:                bzero(&md_core.fpreg, sizeof(md_core.fpreg));
                    284: #endif
                    285:
                    286:        CORE_SETMAGIC(cseg, CORESEGMAGIC, MID_MACHINE, CORE_CPU);
                    287:        cseg.c_addr = 0;
                    288:        cseg.c_size = chdr->c_cpusize;
                    289:
                    290:        error = vn_rdwr(UIO_WRITE, vp, (caddr_t)&cseg, chdr->c_seghdrsize,
                    291:            (off_t)chdr->c_hdrsize, UIO_SYSSPACE, IO_NODELOCKED | IO_UNIT, cred,
                    292:            NULL, p);
                    293:        if (error)
                    294:                return error;
                    295:
                    296:        error = vn_rdwr(UIO_WRITE, vp, (caddr_t)&md_core, sizeof(md_core),
                    297:            (off_t)(chdr->c_hdrsize + chdr->c_seghdrsize), UIO_SYSSPACE,
                    298:            IO_NODELOCKED | IO_UNIT, cred, NULL, p);
                    299:        if (error)
                    300:                return error;
                    301:
                    302:        chdr->c_nseg++;
                    303:        return 0;
                    304: }
                    305:
                    306: /*
                    307:  * Map an IO request into kernel virtual address space.
                    308:  * All requests are (re)mapped into kernel VA space via the phys_map
                    309:  * (a name with only slightly more meaning than "kernel_map")
                    310:  */
                    311:
                    312: void
                    313: vmapbuf(struct buf *bp, vsize_t len)
                    314: {
                    315:        vaddr_t faddr, taddr, off;
                    316:        paddr_t fpa;
                    317:        pmap_t kpmap, upmap;
                    318:
                    319:        if ((bp->b_flags & B_PHYS) == 0)
                    320:                panic("vmapbuf");
                    321:        bp->b_saveaddr = bp->b_data;
                    322:        faddr = trunc_page((vaddr_t)bp->b_data);
                    323:        off = (vaddr_t)bp->b_data - faddr;
                    324:        len = round_page(off + len);
                    325:        taddr = uvm_km_valloc_wait(phys_map, len);
                    326:        bp->b_data = (caddr_t)(taddr + off);
                    327:        /*
                    328:         * The region is locked, so we expect that pmap_pte() will return
                    329:         * non-NULL.
                    330:         * XXX: unwise to expect this in a multithreaded environment.
                    331:         * anything can happen to a pmap between the time we lock a
                    332:         * region, release the pmap lock, and then relock it for
                    333:         * the pmap_extract().
                    334:         *
                    335:         * no need to flush TLB since we expect nothing to be mapped
                    336:         * where we we just allocated (TLB will be flushed when our
                    337:         * mapping is removed).
                    338:         */
                    339:        upmap = vm_map_pmap(&bp->b_proc->p_vmspace->vm_map);
                    340:        kpmap = vm_map_pmap(phys_map);
                    341:        while (len) {
                    342:                pmap_extract(upmap, faddr, &fpa);
                    343:                pmap_enter(kpmap, taddr, fpa,
                    344:                    VM_PROT_READ | VM_PROT_WRITE, PMAP_WIRED);
                    345:                faddr += PAGE_SIZE;
                    346:                taddr += PAGE_SIZE;
                    347:                len -= PAGE_SIZE;
                    348:        }
                    349:        pmap_update(kpmap);
                    350: }
                    351:
                    352: /*
                    353:  * Free the io map PTEs associated with this IO operation.
                    354:  * We also invalidate the TLB entries and restore the original b_addr.
                    355:  */
                    356: void
                    357: vunmapbuf(struct buf *bp, vsize_t len)
                    358: {
                    359:        vaddr_t addr, off;
                    360:        pmap_t kpmap;
                    361:
                    362:        if ((bp->b_flags & B_PHYS) == 0)
                    363:                panic("vunmapbuf");
                    364:        addr = trunc_page((vaddr_t)bp->b_data);
                    365:        off = (vaddr_t)bp->b_data - addr;
                    366:        len = round_page(off + len);
                    367:        kpmap = vm_map_pmap(phys_map);
                    368:        pmap_remove(kpmap, addr, addr + len);
                    369:        pmap_update(kpmap);
                    370:        uvm_km_free_wakeup(phys_map, addr, len);
                    371:        bp->b_data = bp->b_saveaddr;
                    372:        bp->b_saveaddr = 0;
                    373: }

CVSweb