diff options
author | marcel <marcel@FreeBSD.org> | 2007-12-14 23:03:48 +0000 |
---|---|---|
committer | marcel <marcel@FreeBSD.org> | 2007-12-14 23:03:48 +0000 |
commit | e1d637468a8e50a52b36e23719afcb2d27cd3d05 (patch) | |
tree | f6158482f1dcb0dda5cbe1919374b2f89b1ca1a4 | |
parent | c8b672d408760215d85c007ea7936a5662824469 (diff) | |
download | FreeBSD-src-e1d637468a8e50a52b36e23719afcb2d27cd3d05.zip FreeBSD-src-e1d637468a8e50a52b36e23719afcb2d27cd3d05.tar.gz |
This file was repocopied to src/sys/powerpc/aim, where it will
live on -- an afterlife.
-rw-r--r-- | sys/powerpc/powerpc/clock.c | 318 | ||||
-rw-r--r-- | sys/powerpc/powerpc/copyinout.c | 356 | ||||
-rw-r--r-- | sys/powerpc/powerpc/interrupt.c | 101 | ||||
-rw-r--r-- | sys/powerpc/powerpc/locore.S | 208 | ||||
-rw-r--r-- | sys/powerpc/powerpc/machdep.c | 995 | ||||
-rw-r--r-- | sys/powerpc/powerpc/mmu_oea.c | 2544 | ||||
-rw-r--r-- | sys/powerpc/powerpc/nexus.c | 487 | ||||
-rw-r--r-- | sys/powerpc/powerpc/ofw_machdep.c | 436 | ||||
-rw-r--r-- | sys/powerpc/powerpc/ofwmagic.S | 75 | ||||
-rw-r--r-- | sys/powerpc/powerpc/swtch.S | 158 | ||||
-rw-r--r-- | sys/powerpc/powerpc/trap.c | 681 | ||||
-rw-r--r-- | sys/powerpc/powerpc/trap_subr.S | 540 | ||||
-rw-r--r-- | sys/powerpc/powerpc/uio_machdep.c | 124 | ||||
-rw-r--r-- | sys/powerpc/powerpc/uma_machdep.c | 91 | ||||
-rw-r--r-- | sys/powerpc/powerpc/vm_machdep.c | 369 |
15 files changed, 0 insertions, 7483 deletions
diff --git a/sys/powerpc/powerpc/clock.c b/sys/powerpc/powerpc/clock.c deleted file mode 100644 index 0c01cf0..0000000 --- a/sys/powerpc/powerpc/clock.c +++ /dev/null @@ -1,318 +0,0 @@ -/*- - * Copyright (C) 1995, 1996 Wolfgang Solfrank. - * Copyright (C) 1995, 1996 TooLs GmbH. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by TooLs GmbH. - * 4. The name of TooLs GmbH may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $NetBSD: clock.c,v 1.9 2000/01/19 02:52:19 msaitoh Exp $ - */ -/* - * Copyright (C) 2001 Benno Rice. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY Benno Rice ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/kernel.h> -#include <sys/sysctl.h> -#include <sys/bus.h> -#include <sys/clock.h> -#include <sys/timetc.h> -#include <sys/interrupt.h> - -#include <dev/ofw/openfirm.h> - -#include <machine/clock.h> -#include <machine/cpu.h> -#include <machine/intr.h> -#include <machine/md_var.h> - -/* - * Initially we assume a processor with a bus frequency of 12.5 MHz. - */ -u_int tickspending; -u_long ns_per_tick = 80; -static u_long ticks_per_sec = 12500000; -static long ticks_per_intr; -static volatile u_long lasttb; - -#define DIFF19041970 2082844800 - -static int clockinitted = 0; - -static timecounter_get_t decr_get_timecount; - -static struct timecounter decr_timecounter = { - decr_get_timecount, /* get_timecount */ - 0, /* no poll_pps */ - ~0u, /* counter_mask */ - 0, /* frequency */ - "decrementer" /* name */ -}; - -void -inittodr(time_t base) -{ - time_t deltat; - u_int rtc_time; - struct timespec ts; - phandle_t phandle; - ihandle_t ihandle; - char rtcpath[128]; - u_int rtcsecs; - - /* - * If we can't read from RTC, use the fs time. - */ - phandle = OF_finddevice("rtc"); - if (phandle != -1) { - OF_package_to_path(phandle, rtcpath, sizeof(rtcpath)); - ihandle = OF_open(rtcpath); - if (ihandle != -1) { - if (OF_call_method("read-rtc", ihandle, - 0, 1, &rtcsecs)) - printf("RTC call method error\n"); - else { - ts.tv_sec = rtcsecs - DIFF19041970; - ts.tv_nsec = 0; - tc_setclock(&ts); - return; - } - } - } - - { - ts.tv_sec = base; - ts.tv_nsec = 0; - tc_setclock(&ts); - return; - } - clockinitted = 1; - ts.tv_sec = rtc_time - DIFF19041970; - - deltat = ts.tv_sec - base; - if (deltat < 0) { - deltat = -deltat; - } - if (deltat < 2 * SECDAY) { - tc_setclock(&ts); - return; - } - - printf("WARNING: clock %s %d days", - ts.tv_sec < base ? "lost" : "gained", (int)(deltat / SECDAY)); - - printf(" -- CHECK AND RESET THE DATE!\n"); -} - -/* - * Similar to the above - */ -void -resettodr() -{ - -} - -void -decr_intr(struct trapframe *frame) -{ - u_long tb; - long tick; - int nticks; - - /* - * Check whether we are initialized. - */ - if (!ticks_per_intr) - return; - - /* - * Based on the actual time delay since the last decrementer reload, - * we arrange for earlier interrupt next time. - */ - __asm ("mftb %0; mfdec %1" : "=r"(tb), "=r"(tick)); - for (nticks = 0; tick < 0; nticks++) - tick += ticks_per_intr; - mtdec(tick); - /* - * lasttb is used during microtime. Set it to the virtual - * start of this tick interval. - */ - lasttb = tb + tick - ticks_per_intr; - - nticks += tickspending; - tickspending = 0; - - /* - * Reenable interrupts - */ -#if 0 - msr = mfmsr(); - mtmsr(msr | PSL_EE | PSL_RI); -#endif - /* - * Do standard timer interrupt stuff. - * Do softclock stuff only on the last iteration. - */ -#if 0 - while (--nticks > 0) { - hardclock(TRAPF_USERMODE(frame), TRAPF_PC(frame)); - } -#endif - hardclock(TRAPF_USERMODE(frame), TRAPF_PC(frame)); -} - -void -decr_init(void) -{ - int qhandle, phandle; - char name[32]; - unsigned int msr; - - phandle = 0; - - /* - * Get this info during autoconf? XXX - */ - for (qhandle = OF_peer(0); qhandle; qhandle = phandle) { - if (OF_getprop(qhandle, "device_type", name, sizeof name) >= 0 - && !strcmp(name, "cpu") - && OF_getprop(qhandle, "timebase-frequency", - &ticks_per_sec, sizeof ticks_per_sec) >= 0) { - /* - * Should check for correct CPU here? XXX - */ - msr = mfmsr(); - mtmsr(msr & ~(PSL_EE|PSL_RI)); - - ns_per_tick = 1000000000 / ticks_per_sec; - ticks_per_intr = ticks_per_sec / hz; - __asm __volatile ("mftb %0" : "=r"(lasttb)); - mtdec(ticks_per_intr); - - mtmsr(msr); - - break; - } - if ((phandle = OF_child(qhandle))) - continue; - while (qhandle) { - if ((phandle = OF_peer(qhandle))) - break; - qhandle = OF_parent(qhandle); - } - } - if (!phandle) - panic("no cpu node"); -} - -void -decr_tc_init(void) -{ - decr_timecounter.tc_frequency = ticks_per_sec; - tc_init(&decr_timecounter); -} - -static __inline u_quad_t -mftb(void) -{ - u_long scratch; - u_quad_t tb; - - __asm ("1: mftbu %0; mftb %0+1; mftbu %1; cmpw 0,%0,%1; bne 1b" - : "=r"(tb), "=r"(scratch)); - return tb; -} - -static unsigned -decr_get_timecount(struct timecounter *tc) -{ - return mftb(); -} - -/* - * Wait for about n microseconds (at least!). - */ -void -DELAY(int n) -{ - u_quad_t tb, ttb; - - tb = mftb(); - ttb = tb + (n * 1000 + ns_per_tick - 1) / ns_per_tick; - while (tb < ttb) - tb = mftb(); -} - -/* - * Nothing to do. - */ -void -cpu_startprofclock(void) -{ - - /* Do nothing */ -} - -void -cpu_stopprofclock(void) -{ -} - -/* - * XXX Needed by syscons - */ -int -sysbeep(int pitch, int period) -{ - - return (0); -} diff --git a/sys/powerpc/powerpc/copyinout.c b/sys/powerpc/powerpc/copyinout.c deleted file mode 100644 index 4e9f777..0000000 --- a/sys/powerpc/powerpc/copyinout.c +++ /dev/null @@ -1,356 +0,0 @@ -/*- - * Copyright (C) 2002 Benno Rice - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY Benno Rice ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ -/*- - * Copyright (C) 1993 Wolfgang Solfrank. - * Copyright (C) 1993 TooLs GmbH. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by TooLs GmbH. - * 4. The name of TooLs GmbH may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/proc.h> - -#include <vm/vm.h> -#include <vm/pmap.h> -#include <vm/vm_map.h> - -#include <machine/pcb.h> -#include <machine/sr.h> - -int setfault(faultbuf); /* defined in locore.S */ - -/* - * Makes sure that the right segment of userspace is mapped in. - */ -static __inline void -set_user_sr(register_t vsid) -{ - - isync(); - __asm __volatile ("mtsr %0,%1" :: "n"(USER_SR), "r"(vsid)); - isync(); -} - -int -copyout(const void *kaddr, void *udaddr, size_t len) -{ - struct thread *td; - pmap_t pm; - faultbuf env; - const char *kp; - char *up, *p; - size_t l; - - td = PCPU_GET(curthread); - pm = &td->td_proc->p_vmspace->vm_pmap; - - if (setfault(env)) { - td->td_pcb->pcb_onfault = NULL; - return (EFAULT); - } - - kp = kaddr; - up = udaddr; - - while (len > 0) { - p = (char *)USER_ADDR + ((u_int)up & ~SEGMENT_MASK); - - l = ((char *)USER_ADDR + SEGMENT_LENGTH) - p; - if (l > len) - l = len; - - set_user_sr(pm->pm_sr[(u_int)up >> ADDR_SR_SHFT]); - - bcopy(kp, p, l); - - up += l; - kp += l; - len -= l; - } - - td->td_pcb->pcb_onfault = NULL; - return (0); -} - -int -copyin(const void *udaddr, void *kaddr, size_t len) -{ - struct thread *td; - pmap_t pm; - faultbuf env; - const char *up; - char *kp, *p; - size_t l; - - td = PCPU_GET(curthread); - pm = &td->td_proc->p_vmspace->vm_pmap; - - if (setfault(env)) { - td->td_pcb->pcb_onfault = NULL; - return (EFAULT); - } - - kp = kaddr; - up = udaddr; - - while (len > 0) { - p = (char *)USER_ADDR + ((u_int)up & ~SEGMENT_MASK); - - l = ((char *)USER_ADDR + SEGMENT_LENGTH) - p; - if (l > len) - l = len; - - set_user_sr(pm->pm_sr[(u_int)up >> ADDR_SR_SHFT]); - - bcopy(p, kp, l); - - up += l; - kp += l; - len -= l; - } - - td->td_pcb->pcb_onfault = NULL; - return (0); -} - -int -copyinstr(const void *udaddr, void *kaddr, size_t len, size_t *done) -{ - struct thread *td; - pmap_t pm; - faultbuf env; - const char *up; - char *kp; - size_t l; - int rv, c; - - td = PCPU_GET(curthread); - pm = &td->td_proc->p_vmspace->vm_pmap; - - if (setfault(env)) { - td->td_pcb->pcb_onfault = NULL; - return (EFAULT); - } - - kp = kaddr; - up = udaddr; - - rv = ENAMETOOLONG; - - for (l = 0; len-- > 0; l++) { - if ((c = fubyte(up++)) < 0) { - rv = EFAULT; - break; - } - - if (!(*kp++ = c)) { - l++; - rv = 0; - break; - } - } - - if (done != NULL) { - *done = l; - } - - td->td_pcb->pcb_onfault = NULL; - return (rv); -} - -int -subyte(void *addr, int byte) -{ - struct thread *td; - pmap_t pm; - faultbuf env; - char *p; - - td = PCPU_GET(curthread); - pm = &td->td_proc->p_vmspace->vm_pmap; - p = (char *)((u_int)USER_ADDR + ((u_int)addr & ~SEGMENT_MASK)); - - if (setfault(env)) { - td->td_pcb->pcb_onfault = NULL; - return (-1); - } - - set_user_sr(pm->pm_sr[(u_int)addr >> ADDR_SR_SHFT]); - - *p = (char)byte; - - td->td_pcb->pcb_onfault = NULL; - return (0); -} - -int -suword(void *addr, long word) -{ - struct thread *td; - pmap_t pm; - faultbuf env; - long *p; - - td = PCPU_GET(curthread); - pm = &td->td_proc->p_vmspace->vm_pmap; - p = (long *)((u_int)USER_ADDR + ((u_int)addr & ~SEGMENT_MASK)); - - if (setfault(env)) { - td->td_pcb->pcb_onfault = NULL; - return (-1); - } - - set_user_sr(pm->pm_sr[(u_int)addr >> ADDR_SR_SHFT]); - - *p = word; - - td->td_pcb->pcb_onfault = NULL; - return (0); -} - -int -suword32(void *addr, int32_t word) -{ - return (suword(addr, (long)word)); -} - - -int -fubyte(const void *addr) -{ - struct thread *td; - pmap_t pm; - faultbuf env; - u_char *p; - int val; - - td = PCPU_GET(curthread); - pm = &td->td_proc->p_vmspace->vm_pmap; - p = (u_char *)((u_int)USER_ADDR + ((u_int)addr & ~SEGMENT_MASK)); - - if (setfault(env)) { - td->td_pcb->pcb_onfault = NULL; - return (-1); - } - - set_user_sr(pm->pm_sr[(u_int)addr >> ADDR_SR_SHFT]); - - val = *p; - - td->td_pcb->pcb_onfault = NULL; - return (val); -} - -long -fuword(const void *addr) -{ - struct thread *td; - pmap_t pm; - faultbuf env; - long *p, val; - - td = PCPU_GET(curthread); - pm = &td->td_proc->p_vmspace->vm_pmap; - p = (long *)((u_int)USER_ADDR + ((u_int)addr & ~SEGMENT_MASK)); - - if (setfault(env)) { - td->td_pcb->pcb_onfault = NULL; - return (-1); - } - - set_user_sr(pm->pm_sr[(u_int)addr >> ADDR_SR_SHFT]); - - val = *p; - - td->td_pcb->pcb_onfault = NULL; - return (val); -} - -int32_t -fuword32(const void *addr) -{ - return ((int32_t)fuword(addr)); -} - -uint32_t -casuword32(volatile uint32_t *base, uint32_t oldval, uint32_t newval) -{ - return (casuword((volatile u_long *)base, oldval, newval)); -} - -u_long -casuword(volatile u_long *addr, u_long old, u_long new) -{ - struct thread *td; - pmap_t pm; - faultbuf env; - u_long *p, val; - - td = PCPU_GET(curthread); - pm = &td->td_proc->p_vmspace->vm_pmap; - p = (u_long *)((u_int)USER_ADDR + ((u_int)addr & ~SEGMENT_MASK)); - - set_user_sr(pm->pm_sr[(u_int)addr >> ADDR_SR_SHFT]); - - if (setfault(env)) { - td->td_pcb->pcb_onfault = NULL; - return (-1); - } - - val = *p; - (void) atomic_cmpset_32((volatile uint32_t *)p, old, new); - - td->td_pcb->pcb_onfault = NULL; - - return (val); -} diff --git a/sys/powerpc/powerpc/interrupt.c b/sys/powerpc/powerpc/interrupt.c deleted file mode 100644 index ff77fc8..0000000 --- a/sys/powerpc/powerpc/interrupt.c +++ /dev/null @@ -1,101 +0,0 @@ -/*- - * Copyright 2002 by Peter Grehan. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED - * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $FreeBSD$ - */ - -/* - * Interrupts are dispatched to here from locore asm - */ - -#include <sys/cdefs.h> /* RCS ID & Copyright macro defns */ - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/bus.h> -#include <sys/interrupt.h> -#include <sys/kernel.h> -#include <sys/kthread.h> -#include <sys/ktr.h> -#include <sys/lock.h> -#include <sys/malloc.h> -#include <sys/mutex.h> -#include <sys/proc.h> -#include <sys/smp.h> -#include <sys/unistd.h> -#include <sys/vmmeter.h> - -#include <machine/cpu.h> -#include <machine/clock.h> -#include <machine/db_machdep.h> -#include <machine/fpu.h> -#include <machine/frame.h> -#include <machine/intr_machdep.h> -#include <machine/md_var.h> -#include <machine/pcb.h> -#include <machine/psl.h> -#include <machine/trap.h> -#include <machine/spr.h> -#include <machine/sr.h> - -#include "pic_if.h" - -/* - * A very short dispatch, to try and maximise assembler code use - * between all exception types. Maybe 'true' interrupts should go - * here, and the trap code can come in separately - */ -void -powerpc_interrupt(struct trapframe *framep) -{ - struct thread *td; - register_t ee; - - td = curthread; - - switch (framep->exc) { - case EXC_EXI: - atomic_add_int(&td->td_intr_nesting_level, 1); - PIC_DISPATCH(pic, framep); - atomic_subtract_int(&td->td_intr_nesting_level, 1); - break; - - case EXC_DECR: - atomic_add_int(&td->td_intr_nesting_level, 1); - decr_intr(framep); - atomic_subtract_int(&td->td_intr_nesting_level, 1); - break; - - default: - /* Re-enable interrupts if applicable. */ - ee = framep->srr1 & PSL_EE; - if (ee != 0) { - mtmsr(mfmsr() | ee); - isync(); - } - trap(framep); - } -} diff --git a/sys/powerpc/powerpc/locore.S b/sys/powerpc/powerpc/locore.S deleted file mode 100644 index 1a3c0bb..0000000 --- a/sys/powerpc/powerpc/locore.S +++ /dev/null @@ -1,208 +0,0 @@ -/* $FreeBSD$ */ -/* $NetBSD: locore.S,v 1.24 2000/05/31 05:09:17 thorpej Exp $ */ - -/*- - * Copyright (C) 2001 Benno Rice - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY Benno Rice ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/*- - * Copyright (C) 1995, 1996 Wolfgang Solfrank. - * Copyright (C) 1995, 1996 TooLs GmbH. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by TooLs GmbH. - * 4. The name of TooLs GmbH may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "assym.s" - -#include <sys/syscall.h> - -#include <machine/trap.h> -#include <machine/param.h> -#include <machine/sr.h> -#include <machine/spr.h> -#include <machine/psl.h> -#include <machine/asm.h> - -/* Locate the per-CPU data structure */ -#define GET_CPUINFO(r) \ - mfsprg0 r - -/* - * Globals - */ - .data -GLOBAL(tmpstk) - .space 8208 -GLOBAL(esym) - .long 0 /* end of symbol table */ - -GLOBAL(ofmsr) - .long 0, 0, 0, 0, 0 /* msr/sprg0-3 used in Open Firmware */ - -GLOBAL(powersave) - .long 0 - -#define INTSTK 16384 /* 16K interrupt stack */ -#define INTRCNT_COUNT 256 /* max(HROWPIC_IRQMAX,OPENPIC_IRQMAX) */ -GLOBAL(intrnames) - .space INTRCNT_COUNT * (MAXCOMLEN + 1) * 2 -GLOBAL(eintrnames) - .align 4 -GLOBAL(intrcnt) - .space INTRCNT_COUNT * 4 * 2 -GLOBAL(eintrcnt) - -/* - * File-scope for locore.S - */ -idle_u: - .long 0 /* fake uarea during idle after exit */ -openfirmware_entry: - .long 0 /* Open Firmware entry point */ -srsave: - .long 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 - -/* - * This symbol is here for the benefit of kvm_mkdb, and is supposed to - * mark the start of kernel text. - */ - .text - .globl kernel_text -kernel_text: - -/* - * Startup entry. Note, this must be the first thing in the text - * segment! - */ - .text - .globl __start -__start: -#ifdef FIRMWORKSBUGS - mfmsr 0 - andi. 0,0,PSL_IR|PSL_DR - beq 1f - - bl ofwr_init -1: -#endif - li 8,0 - li 9,0x100 - mtctr 9 -1: - dcbf 0,8 - icbi 0,8 - addi 8,8,0x20 - bdnz 1b - sync - isync - - /* Save the argument pointer and length */ - mr 20,6 - mr 21,7 - - lis 8,openfirmware_entry@ha - stw 5,openfirmware_entry@l(8) /* save client interface handler */ - mr 3,5 - - lis 1,tmpstk@ha - addi 1,1,tmpstk@l - addi 1,1,8192 - - mfmsr 0 - lis 9,ofmsr@ha - stwu 0,ofmsr@l(9) - - mfsprg0 0 /* save SPRG0-3 */ - stw 0,4(9) /* ofmsr[1] = sprg0 */ - mfsprg1 0 - stw 0,8(9) /* ofmsr[2] = sprg1 */ - mfsprg2 0 - stw 0,12(9) /* ofmsr[3] = sprg2 */ - mfsprg3 0 - stw 0,16(9) /* ofmsr[4] = sprg3 */ - - bl OF_init - - lis 4,end@ha - addi 4,4,end@l - mr 5,4 - - lis 3,kernel_text@ha - addi 3,3,kernel_text@l - - /* Restore the argument pointer and length */ - mr 6,20 - mr 7,21 - - bl powerpc_init - bl mi_startup - b OF_exit - -/* - * int setfault() - * - * Similar to setjmp to setup for handling faults on accesses to user memory. - * Any routine using this may only call bcopy, either the form below, - * or the (currently used) C code optimized, so it doesn't use any non-volatile - * registers. - */ - .globl setfault -setfault: - mflr 0 - mfcr 12 - mfsprg 4,0 - lwz 4,PC_CURTHREAD(4) - lwz 4,TD_PCB(4) - stw 3,PCB_ONFAULT(4) - stw 0,0(3) - stw 1,4(3) - stw 2,8(3) - stmw 12,12(3) - xor 3,3,3 - blr - -#include <powerpc/powerpc/trap_subr.S> diff --git a/sys/powerpc/powerpc/machdep.c b/sys/powerpc/powerpc/machdep.c deleted file mode 100644 index 7cea2c0..0000000 --- a/sys/powerpc/powerpc/machdep.c +++ /dev/null @@ -1,995 +0,0 @@ -/*- - * Copyright (C) 1995, 1996 Wolfgang Solfrank. - * Copyright (C) 1995, 1996 TooLs GmbH. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by TooLs GmbH. - * 4. The name of TooLs GmbH may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/*- - * Copyright (C) 2001 Benno Rice - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY Benno Rice ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * $NetBSD: machdep.c,v 1.74.2.1 2000/11/01 16:13:48 tv Exp $ - */ - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include "opt_compat.h" -#include "opt_ddb.h" -#include "opt_kstack_pages.h" -#include "opt_msgbuf.h" - -#include <sys/param.h> -#include <sys/proc.h> -#include <sys/systm.h> -#include <sys/bio.h> -#include <sys/buf.h> -#include <sys/bus.h> -#include <sys/cons.h> -#include <sys/cpu.h> -#include <sys/eventhandler.h> -#include <sys/exec.h> -#include <sys/imgact.h> -#include <sys/kdb.h> -#include <sys/kernel.h> -#include <sys/ktr.h> -#include <sys/linker.h> -#include <sys/lock.h> -#include <sys/malloc.h> -#include <sys/mbuf.h> -#include <sys/msgbuf.h> -#include <sys/mutex.h> -#include <sys/ptrace.h> -#include <sys/reboot.h> -#include <sys/signalvar.h> -#include <sys/sysctl.h> -#include <sys/sysent.h> -#include <sys/sysproto.h> -#include <sys/ucontext.h> -#include <sys/uio.h> -#include <sys/vmmeter.h> -#include <sys/vnode.h> - -#include <net/netisr.h> - -#include <vm/vm.h> -#include <vm/vm_extern.h> -#include <vm/vm_kern.h> -#include <vm/vm_page.h> -#include <vm/vm_map.h> -#include <vm/vm_object.h> -#include <vm/vm_pager.h> - -#include <machine/bat.h> -#include <machine/cpu.h> -#include <machine/elf.h> -#include <machine/fpu.h> -#include <machine/md_var.h> -#include <machine/metadata.h> -#include <machine/mmuvar.h> -#include <machine/pcb.h> -#include <machine/powerpc.h> -#include <machine/reg.h> -#include <machine/sigframe.h> -#include <machine/trap.h> -#include <machine/vmparam.h> - -#include <ddb/ddb.h> - -#include <dev/ofw/openfirm.h> - -#ifdef DDB -extern vm_offset_t ksym_start, ksym_end; -#endif - -int cold = 1; - -struct pcpu __pcpu[MAXCPU]; -struct trapframe frame0; - -vm_offset_t kstack0; -vm_offset_t kstack0_phys; - -char machine[] = "powerpc"; -SYSCTL_STRING(_hw, HW_MACHINE, machine, CTLFLAG_RD, machine, 0, ""); - -static int cacheline_size = CACHELINESIZE; -SYSCTL_INT(_machdep, CPU_CACHELINE, cacheline_size, - CTLFLAG_RD, &cacheline_size, 0, ""); - -static void cpu_startup(void *); -SYSINIT(cpu, SI_SUB_CPU, SI_ORDER_FIRST, cpu_startup, NULL) - -void powerpc_init(u_int, u_int, u_int, void *); - -int save_ofw_mapping(void); -int restore_ofw_mapping(void); - -void install_extint(void (*)(void)); - -int setfault(faultbuf); /* defined in locore.S */ - -static int grab_mcontext(struct thread *, mcontext_t *, int); - -void asm_panic(char *); - -long Maxmem = 0; -long realmem = 0; - -struct pmap ofw_pmap; -extern int ofmsr; - -struct bat battable[16]; - -struct kva_md_info kmi; - -void setPQL2(int *const size, int *const ways); - -void -setPQL2(int *const size, int *const ways) -{ - return; -} - -static void -powerpc_ofw_shutdown(void *junk, int howto) -{ - if (howto & RB_HALT) { - OF_halt(); - } - OF_reboot(); -} - -static void -cpu_startup(void *dummy) -{ - - /* - * Initialise the decrementer-based clock. - */ - decr_init(); - - /* - * Good {morning,afternoon,evening,night}. - */ - cpu_setup(PCPU_GET(cpuid)); - - /* startrtclock(); */ -#ifdef PERFMON - perfmon_init(); -#endif - printf("real memory = %ld (%ld MB)\n", ptoa(physmem), - ptoa(physmem) / 1048576); - realmem = physmem; - - /* - * Display any holes after the first chunk of extended memory. - */ - if (bootverbose) { - int indx; - - printf("Physical memory chunk(s):\n"); - for (indx = 0; phys_avail[indx + 1] != 0; indx += 2) { - int size1 = phys_avail[indx + 1] - phys_avail[indx]; - - printf("0x%08x - 0x%08x, %d bytes (%d pages)\n", - phys_avail[indx], phys_avail[indx + 1] - 1, size1, - size1 / PAGE_SIZE); - } - } - - vm_ksubmap_init(&kmi); - - printf("avail memory = %ld (%ld MB)\n", ptoa(cnt.v_free_count), - ptoa(cnt.v_free_count) / 1048576); - - /* - * Set up buffers, so they can be used to read disk labels. - */ - bufinit(); - vm_pager_bufferinit(); - - EVENTHANDLER_REGISTER(shutdown_final, powerpc_ofw_shutdown, 0, - SHUTDOWN_PRI_LAST); - -#ifdef SMP - /* - * OK, enough kmem_alloc/malloc state should be up, lets get on with it! - */ - mp_start(); /* fire up the secondaries */ - mp_announce(); -#endif /* SMP */ -} - -extern char kernel_text[], _end[]; - -extern void *trapcode, *trapsize; -extern void *alitrap, *alisize; -extern void *dsitrap, *dsisize; -extern void *decrint, *decrsize; -extern void *extint, *extsize; -extern void *dblow, *dbsize; -extern void *vectrap, *vectrapsize; - -void -powerpc_init(u_int startkernel, u_int endkernel, u_int basekernel, void *mdp) -{ - struct pcpu *pc; - vm_offset_t end, off; - void *kmdp; - char *env; - - end = 0; - kmdp = NULL; - - /* - * Parse metadata if present and fetch parameters. Must be done - * before console is inited so cninit gets the right value of - * boothowto. - */ - if (mdp != NULL) { - preload_metadata = mdp; - kmdp = preload_search_by_type("elf kernel"); - if (kmdp != NULL) { - boothowto = MD_FETCH(kmdp, MODINFOMD_HOWTO, int); - kern_envp = MD_FETCH(kmdp, MODINFOMD_ENVP, char *); - end = MD_FETCH(kmdp, MODINFOMD_KERNEND, vm_offset_t); -#ifdef DDB - ksym_start = MD_FETCH(kmdp, MODINFOMD_SSYM, uintptr_t); - ksym_end = MD_FETCH(kmdp, MODINFOMD_ESYM, uintptr_t); -#endif - } - } - - /* - * Init params/tunables that can be overridden by the loader - */ - init_param1(); - - /* - * Start initializing proc0 and thread0. - */ - proc_linkup0(&proc0, &thread0); - thread0.td_frame = &frame0; - - /* - * Set up per-cpu data. - */ - pc = &__pcpu[0]; - pcpu_init(pc, 0, sizeof(struct pcpu)); - pc->pc_curthread = &thread0; - pc->pc_curpcb = thread0.td_pcb; - pc->pc_cpuid = 0; - - __asm __volatile("mtsprg 0, %0" :: "r"(pc)); - - mutex_init(); - - /* - * Initialize the console before printing anything. - */ - cninit(); - - /* - * Complain if there is no metadata. - */ - if (mdp == NULL || kmdp == NULL) { - printf("powerpc_init: no loader metadata.\n"); - } - - kdb_init(); - - kobj_machdep_init(); - - /* - * XXX: Initialize the interrupt tables. - * Disable translation in case the vector area - * hasn't been mapped (G5) - */ - mtmsr(mfmsr() & ~(PSL_IR | PSL_DR)); - isync(); - bcopy(&trapcode, (void *)EXC_RST, (size_t)&trapsize); - bcopy(&trapcode, (void *)EXC_MCHK, (size_t)&trapsize); - bcopy(&dsitrap, (void *)EXC_DSI, (size_t)&dsisize); - bcopy(&trapcode, (void *)EXC_ISI, (size_t)&trapsize); - bcopy(&trapcode, (void *)EXC_EXI, (size_t)&trapsize); - bcopy(&alitrap, (void *)EXC_ALI, (size_t)&alisize); - bcopy(&trapcode, (void *)EXC_PGM, (size_t)&trapsize); - bcopy(&trapcode, (void *)EXC_FPU, (size_t)&trapsize); - bcopy(&trapcode, (void *)EXC_DECR, (size_t)&trapsize); - bcopy(&trapcode, (void *)EXC_SC, (size_t)&trapsize); - bcopy(&trapcode, (void *)EXC_TRC, (size_t)&trapsize); - bcopy(&trapcode, (void *)EXC_FPA, (size_t)&trapsize); - bcopy(&vectrap, (void *)EXC_VEC, (size_t)&vectrapsize); - bcopy(&trapcode, (void *)EXC_VECAST, (size_t)&trapsize); - bcopy(&trapcode, (void *)EXC_THRM, (size_t)&trapsize); - bcopy(&trapcode, (void *)EXC_BPT, (size_t)&trapsize); -#ifdef KDB - bcopy(&dblow, (void *)EXC_RST, (size_t)&dbsize); - bcopy(&dblow, (void *)EXC_MCHK, (size_t)&dbsize); - bcopy(&dblow, (void *)EXC_PGM, (size_t)&dbsize); - bcopy(&dblow, (void *)EXC_TRC, (size_t)&dbsize); - bcopy(&dblow, (void *)EXC_BPT, (size_t)&dbsize); -#endif - __syncicache(EXC_RSVD, EXC_LAST - EXC_RSVD); - - /* - * Make sure translation has been enabled - */ - mtmsr(mfmsr() | PSL_IR|PSL_DR|PSL_ME|PSL_RI); - isync(); - - /* - * Initialise virtual memory. - */ - pmap_mmu_install(MMU_TYPE_OEA, 0); /* XXX temporary */ - pmap_bootstrap(startkernel, endkernel); - - /* - * Initialize params/tunables that are derived from memsize - */ - init_param2(physmem); - - /* - * Grab booted kernel's name - */ - env = getenv("kernelname"); - if (env != NULL) { - strlcpy(kernelname, env, sizeof(kernelname)); - freeenv(env); - } - - /* - * Finish setting up thread0. - */ - thread0.td_kstack = kstack0; - thread0.td_pcb = (struct pcb *) - (thread0.td_kstack + KSTACK_PAGES * PAGE_SIZE) - 1; - - /* - * Map and initialise the message buffer. - */ - for (off = 0; off < round_page(MSGBUF_SIZE); off += PAGE_SIZE) - pmap_kenter((vm_offset_t)msgbufp + off, msgbuf_phys + off); - msgbufinit(msgbufp, MSGBUF_SIZE); - -#ifdef KDB - if (boothowto & RB_KDB) - kdb_enter("Boot flags requested debugger"); -#endif -} - -void -bzero(void *buf, size_t len) -{ - caddr_t p; - - p = buf; - - while (((vm_offset_t) p & (sizeof(u_long) - 1)) && len) { - *p++ = 0; - len--; - } - - while (len >= sizeof(u_long) * 8) { - *(u_long*) p = 0; - *((u_long*) p + 1) = 0; - *((u_long*) p + 2) = 0; - *((u_long*) p + 3) = 0; - len -= sizeof(u_long) * 8; - *((u_long*) p + 4) = 0; - *((u_long*) p + 5) = 0; - *((u_long*) p + 6) = 0; - *((u_long*) p + 7) = 0; - p += sizeof(u_long) * 8; - } - - while (len >= sizeof(u_long)) { - *(u_long*) p = 0; - len -= sizeof(u_long); - p += sizeof(u_long); - } - - while (len) { - *p++ = 0; - len--; - } -} - -void -sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask) -{ - struct trapframe *tf; - struct sigframe *sfp; - struct sigacts *psp; - struct sigframe sf; - struct thread *td; - struct proc *p; - int oonstack, rndfsize; - int sig; - int code; - - td = curthread; - p = td->td_proc; - PROC_LOCK_ASSERT(p, MA_OWNED); - sig = ksi->ksi_signo; - code = ksi->ksi_code; - psp = p->p_sigacts; - mtx_assert(&psp->ps_mtx, MA_OWNED); - tf = td->td_frame; - oonstack = sigonstack(tf->fixreg[1]); - - rndfsize = ((sizeof(sf) + 15) / 16) * 16; - - CTR4(KTR_SIG, "sendsig: td=%p (%s) catcher=%p sig=%d", td, p->p_comm, - catcher, sig); - - /* - * Save user context - */ - memset(&sf, 0, sizeof(sf)); - grab_mcontext(td, &sf.sf_uc.uc_mcontext, 0); - sf.sf_uc.uc_sigmask = *mask; - sf.sf_uc.uc_stack = td->td_sigstk; - sf.sf_uc.uc_stack.ss_flags = (td->td_pflags & TDP_ALTSTACK) - ? ((oonstack) ? SS_ONSTACK : 0) : SS_DISABLE; - - sf.sf_uc.uc_mcontext.mc_onstack = (oonstack) ? 1 : 0; - - /* - * Allocate and validate space for the signal handler context. - */ - if ((td->td_pflags & TDP_ALTSTACK) != 0 && !oonstack && - SIGISMEMBER(psp->ps_sigonstack, sig)) { - sfp = (struct sigframe *)(td->td_sigstk.ss_sp + - td->td_sigstk.ss_size - rndfsize); - } else { - sfp = (struct sigframe *)(tf->fixreg[1] - rndfsize); - } - - /* - * Translate the signal if appropriate (Linux emu ?) - */ - if (p->p_sysent->sv_sigtbl && sig <= p->p_sysent->sv_sigsize) - sig = p->p_sysent->sv_sigtbl[_SIG_IDX(sig)]; - - /* - * Save the floating-point state, if necessary, then copy it. - */ - /* XXX */ - - /* - * Set up the registers to return to sigcode. - * - * r1/sp - sigframe ptr - * lr - sig function, dispatched to by blrl in trampoline - * r3 - sig number - * r4 - SIGINFO ? &siginfo : exception code - * r5 - user context - * srr0 - trampoline function addr - */ - tf->lr = (register_t)catcher; - tf->fixreg[1] = (register_t)sfp; - tf->fixreg[FIRSTARG] = sig; - tf->fixreg[FIRSTARG+2] = (register_t)&sfp->sf_uc; - if (SIGISMEMBER(psp->ps_siginfo, sig)) { - /* - * Signal handler installed with SA_SIGINFO. - */ - tf->fixreg[FIRSTARG+1] = (register_t)&sfp->sf_si; - - /* - * Fill siginfo structure. - */ - sf.sf_si = ksi->ksi_info; - sf.sf_si.si_signo = sig; - sf.sf_si.si_addr = (void *) ((tf->exc == EXC_DSI) ? - tf->dar : tf->srr0); - } else { - /* Old FreeBSD-style arguments. */ - tf->fixreg[FIRSTARG+1] = code; - tf->fixreg[FIRSTARG+3] = (tf->exc == EXC_DSI) ? - tf->dar : tf->srr0; - } - mtx_unlock(&psp->ps_mtx); - PROC_UNLOCK(p); - - tf->srr0 = (register_t)(PS_STRINGS - *(p->p_sysent->sv_szsigcode)); - - /* - * copy the frame out to userland. - */ - if (copyout(&sf, sfp, sizeof(*sfp)) != 0) { - /* - * Process has trashed its stack. Kill it. - */ - CTR2(KTR_SIG, "sendsig: sigexit td=%p sfp=%p", td, sfp); - PROC_LOCK(p); - sigexit(td, SIGILL); - } - - CTR3(KTR_SIG, "sendsig: return td=%p pc=%#x sp=%#x", td, - tf->srr0, tf->fixreg[1]); - - PROC_LOCK(p); - mtx_lock(&psp->ps_mtx); -} - -int -sigreturn(struct thread *td, struct sigreturn_args *uap) -{ - struct proc *p; - ucontext_t uc; - int error; - - CTR2(KTR_SIG, "sigreturn: td=%p ucp=%p", td, uap->sigcntxp); - - if (copyin(uap->sigcntxp, &uc, sizeof(uc)) != 0) { - CTR1(KTR_SIG, "sigreturn: efault td=%p", td); - return (EFAULT); - } - - error = set_mcontext(td, &uc.uc_mcontext); - if (error != 0) - return (error); - - p = td->td_proc; - PROC_LOCK(p); - td->td_sigmask = uc.uc_sigmask; - SIG_CANTMASK(td->td_sigmask); - signotify(td); - PROC_UNLOCK(p); - - CTR3(KTR_SIG, "sigreturn: return td=%p pc=%#x sp=%#x", - td, uc.uc_mcontext.mc_srr0, uc.uc_mcontext.mc_gpr[1]); - - return (EJUSTRETURN); -} - -#ifdef COMPAT_FREEBSD4 -int -freebsd4_sigreturn(struct thread *td, struct freebsd4_sigreturn_args *uap) -{ - - return sigreturn(td, (struct sigreturn_args *)uap); -} -#endif - -/* - * Construct a PCB from a trapframe. This is called from kdb_trap() where - * we want to start a backtrace from the function that caused us to enter - * the debugger. We have the context in the trapframe, but base the trace - * on the PCB. The PCB doesn't have to be perfect, as long as it contains - * enough for a backtrace. - */ -void -makectx(struct trapframe *tf, struct pcb *pcb) -{ - - pcb->pcb_lr = tf->srr0; - pcb->pcb_sp = tf->fixreg[1]; -} - -/* - * get_mcontext/sendsig helper routine that doesn't touch the - * proc lock - */ -static int -grab_mcontext(struct thread *td, mcontext_t *mcp, int flags) -{ - struct pcb *pcb; - - pcb = td->td_pcb; - - memset(mcp, 0, sizeof(mcontext_t)); - - mcp->mc_vers = _MC_VERSION; - mcp->mc_flags = 0; - memcpy(&mcp->mc_frame, td->td_frame, sizeof(struct trapframe)); - if (flags & GET_MC_CLEAR_RET) { - mcp->mc_gpr[3] = 0; - mcp->mc_gpr[4] = 0; - } - - /* - * This assumes that floating-point context is *not* lazy, - * so if the thread has used FP there would have been a - * FP-unavailable exception that would have set things up - * correctly. - */ - if (pcb->pcb_flags & PCB_FPU) { - KASSERT(td == curthread, - ("get_mcontext: fp save not curthread")); - critical_enter(); - save_fpu(td); - critical_exit(); - mcp->mc_flags |= _MC_FP_VALID; - memcpy(&mcp->mc_fpscr, &pcb->pcb_fpu.fpscr, sizeof(double)); - memcpy(mcp->mc_fpreg, pcb->pcb_fpu.fpr, 32*sizeof(double)); - } - - /* XXX Altivec context ? */ - - mcp->mc_len = sizeof(*mcp); - - return (0); -} - -int -get_mcontext(struct thread *td, mcontext_t *mcp, int flags) -{ - int error; - - error = grab_mcontext(td, mcp, flags); - if (error == 0) { - PROC_LOCK(curthread->td_proc); - mcp->mc_onstack = sigonstack(td->td_frame->fixreg[1]); - PROC_UNLOCK(curthread->td_proc); - } - - return (error); -} - -int -set_mcontext(struct thread *td, const mcontext_t *mcp) -{ - struct pcb *pcb; - struct trapframe *tf; - - pcb = td->td_pcb; - tf = td->td_frame; - - if (mcp->mc_vers != _MC_VERSION || - mcp->mc_len != sizeof(*mcp)) - return (EINVAL); - - /* - * Don't let the user set privileged MSR bits - */ - if ((mcp->mc_srr1 & PSL_USERSTATIC) != (tf->srr1 & PSL_USERSTATIC)) { - return (EINVAL); - } - - memcpy(tf, mcp->mc_frame, sizeof(mcp->mc_frame)); - - if (mcp->mc_flags & _MC_FP_VALID) { - if ((pcb->pcb_flags & PCB_FPU) != PCB_FPU) { - critical_enter(); - enable_fpu(td); - critical_exit(); - } - memcpy(&pcb->pcb_fpu.fpscr, &mcp->mc_fpscr, sizeof(double)); - memcpy(pcb->pcb_fpu.fpr, mcp->mc_fpreg, 32*sizeof(double)); - } - - /* XXX Altivec context? */ - - return (0); -} - -void -cpu_boot(int howto) -{ -} - -void -cpu_initclocks(void) -{ - - decr_tc_init(); -} - -/* Get current clock frequency for the given cpu id. */ -int -cpu_est_clockrate(int cpu_id, uint64_t *rate) -{ - - return (ENXIO); -} - -/* - * Shutdown the CPU as much as possible. - */ -void -cpu_halt(void) -{ - - OF_exit(); -} - -void -cpu_idle(void) -{ - /* TODO: Insert code to halt (until next interrupt) */ - -#ifdef INVARIANTS - if ((mfmsr() & PSL_EE) != PSL_EE) { - struct thread *td = curthread; - printf("td msr %x\n", td->td_md.md_saved_msr); - panic("ints disabled in idleproc!"); - } -#endif -} - -/* - * Set set up registers on exec. - */ -void -exec_setregs(struct thread *td, u_long entry, u_long stack, u_long ps_strings) -{ - struct trapframe *tf; - struct ps_strings arginfo; - - tf = trapframe(td); - bzero(tf, sizeof *tf); - tf->fixreg[1] = -roundup(-stack + 8, 16); - - /* - * XXX Machine-independent code has already copied arguments and - * XXX environment to userland. Get them back here. - */ - (void)copyin((char *)PS_STRINGS, &arginfo, sizeof(arginfo)); - - /* - * Set up arguments for _start(): - * _start(argc, argv, envp, obj, cleanup, ps_strings); - * - * Notes: - * - obj and cleanup are the auxilliary and termination - * vectors. They are fixed up by ld.elf_so. - * - ps_strings is a NetBSD extention, and will be - * ignored by executables which are strictly - * compliant with the SVR4 ABI. - * - * XXX We have to set both regs and retval here due to different - * XXX calling convention in trap.c and init_main.c. - */ - /* - * XXX PG: these get overwritten in the syscall return code. - * execve() should return EJUSTRETURN, like it does on NetBSD. - * Emulate by setting the syscall return value cells. The - * registers still have to be set for init's fork trampoline. - */ - td->td_retval[0] = arginfo.ps_nargvstr; - td->td_retval[1] = (register_t)arginfo.ps_argvstr; - tf->fixreg[3] = arginfo.ps_nargvstr; - tf->fixreg[4] = (register_t)arginfo.ps_argvstr; - tf->fixreg[5] = (register_t)arginfo.ps_envstr; - tf->fixreg[6] = 0; /* auxillary vector */ - tf->fixreg[7] = 0; /* termination vector */ - tf->fixreg[8] = (register_t)PS_STRINGS; /* NetBSD extension */ - - tf->srr0 = entry; - tf->srr1 = PSL_MBO | PSL_USERSET | PSL_FE_DFLT; - td->td_pcb->pcb_flags = 0; -} - -int -fill_regs(struct thread *td, struct reg *regs) -{ - struct trapframe *tf; - - tf = td->td_frame; - memcpy(regs, tf, sizeof(struct reg)); - - return (0); -} - -int -fill_dbregs(struct thread *td, struct dbreg *dbregs) -{ - /* No debug registers on PowerPC */ - return (ENOSYS); -} - -int -fill_fpregs(struct thread *td, struct fpreg *fpregs) -{ - struct pcb *pcb; - - pcb = td->td_pcb; - - if ((pcb->pcb_flags & PCB_FPU) == 0) - memset(fpregs, 0, sizeof(struct fpreg)); - else - memcpy(fpregs, &pcb->pcb_fpu, sizeof(struct fpreg)); - - return (0); -} - -int -set_regs(struct thread *td, struct reg *regs) -{ - struct trapframe *tf; - - tf = td->td_frame; - memcpy(tf, regs, sizeof(struct reg)); - - return (0); -} - -int -set_dbregs(struct thread *td, struct dbreg *dbregs) -{ - /* No debug registers on PowerPC */ - return (ENOSYS); -} - -int -set_fpregs(struct thread *td, struct fpreg *fpregs) -{ - struct pcb *pcb; - - pcb = td->td_pcb; - if ((pcb->pcb_flags & PCB_FPU) == 0) - enable_fpu(td); - memcpy(&pcb->pcb_fpu, fpregs, sizeof(struct fpreg)); - - return (0); -} - -int -ptrace_set_pc(struct thread *td, unsigned long addr) -{ - struct trapframe *tf; - - tf = td->td_frame; - tf->srr0 = (register_t)addr; - - return (0); -} - -int -ptrace_single_step(struct thread *td) -{ - struct trapframe *tf; - - tf = td->td_frame; - tf->srr1 |= PSL_SE; - - return (0); -} - -int -ptrace_clear_single_step(struct thread *td) -{ - struct trapframe *tf; - - tf = td->td_frame; - tf->srr1 &= ~PSL_SE; - - return (0); -} - -/* - * Initialise a struct pcpu. - */ -void -cpu_pcpu_init(struct pcpu *pcpu, int cpuid, size_t sz) -{ - -} - -void -spinlock_enter(void) -{ - struct thread *td; - - td = curthread; - if (td->td_md.md_spinlock_count == 0) - td->td_md.md_saved_msr = intr_disable(); - td->td_md.md_spinlock_count++; - critical_enter(); -} - -void -spinlock_exit(void) -{ - struct thread *td; - - td = curthread; - critical_exit(); - td->td_md.md_spinlock_count--; - if (td->td_md.md_spinlock_count == 0) - intr_restore(td->td_md.md_saved_msr); -} - -/* - * kcopy(const void *src, void *dst, size_t len); - * - * Copy len bytes from src to dst, aborting if we encounter a fatal - * page fault. - * - * kcopy() _must_ save and restore the old fault handler since it is - * called by uiomove(), which may be in the path of servicing a non-fatal - * page fault. - */ -int -kcopy(const void *src, void *dst, size_t len) -{ - struct thread *td; - faultbuf env, *oldfault; - int rv; - - td = PCPU_GET(curthread); - oldfault = td->td_pcb->pcb_onfault; - if ((rv = setfault(env)) != 0) { - td->td_pcb->pcb_onfault = oldfault; - return rv; - } - - memcpy(dst, src, len); - - td->td_pcb->pcb_onfault = oldfault; - return (0); -} - -void -asm_panic(char *pstr) -{ - panic(pstr); -} - -int db_trap_glue(struct trapframe *); /* Called from trap_subr.S */ - -int -db_trap_glue(struct trapframe *frame) -{ - if (!(frame->srr1 & PSL_PR) - && (frame->exc == EXC_TRC || frame->exc == EXC_RUNMODETRC - || (frame->exc == EXC_PGM - && (frame->srr1 & 0x20000)) - || frame->exc == EXC_BPT - || frame->exc == EXC_DSI)) { - int type = frame->exc; - if (type == EXC_PGM && (frame->srr1 & 0x20000)) { - type = T_BREAKPOINT; - } - return (kdb_trap(type, 0, frame)); - } - - return (0); -} diff --git a/sys/powerpc/powerpc/mmu_oea.c b/sys/powerpc/powerpc/mmu_oea.c deleted file mode 100644 index db2c3bb..0000000 --- a/sys/powerpc/powerpc/mmu_oea.c +++ /dev/null @@ -1,2544 +0,0 @@ -/*- - * Copyright (c) 2001 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Matt Thomas <matt@3am-software.com> of Allegro Networks, Inc. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the NetBSD - * Foundation, Inc. and its contributors. - * 4. Neither the name of The NetBSD Foundation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ -/*- - * Copyright (C) 1995, 1996 Wolfgang Solfrank. - * Copyright (C) 1995, 1996 TooLs GmbH. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by TooLs GmbH. - * 4. The name of TooLs GmbH may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $NetBSD: pmap.c,v 1.28 2000/03/26 20:42:36 kleink Exp $ - */ -/*- - * Copyright (C) 2001 Benno Rice. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY Benno Rice ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -/* - * Manages physical address maps. - * - * In addition to hardware address maps, this module is called upon to - * provide software-use-only maps which may or may not be stored in the - * same form as hardware maps. These pseudo-maps are used to store - * intermediate results from copy operations to and from address spaces. - * - * Since the information managed by this module is also stored by the - * logical address mapping module, this module may throw away valid virtual - * to physical mappings at almost any time. However, invalidations of - * mappings must be done as requested. - * - * In order to cope with hardware architectures which make virtual to - * physical map invalidates expensive, this module may delay invalidate - * reduced protection operations until such time as they are actually - * necessary. This module is given full information as to which processors - * are currently using which maps, and to when physical maps must be made - * correct. - */ - -#include "opt_kstack_pages.h" - -#include <sys/param.h> -#include <sys/kernel.h> -#include <sys/ktr.h> -#include <sys/lock.h> -#include <sys/msgbuf.h> -#include <sys/mutex.h> -#include <sys/proc.h> -#include <sys/sysctl.h> -#include <sys/systm.h> -#include <sys/vmmeter.h> - -#include <dev/ofw/openfirm.h> - -#include <vm/vm.h> -#include <vm/vm_param.h> -#include <vm/vm_kern.h> -#include <vm/vm_page.h> -#include <vm/vm_map.h> -#include <vm/vm_object.h> -#include <vm/vm_extern.h> -#include <vm/vm_pageout.h> -#include <vm/vm_pager.h> -#include <vm/uma.h> - -#include <machine/cpu.h> -#include <machine/powerpc.h> -#include <machine/bat.h> -#include <machine/frame.h> -#include <machine/md_var.h> -#include <machine/psl.h> -#include <machine/pte.h> -#include <machine/sr.h> -#include <machine/mmuvar.h> - -#include "mmu_if.h" - -#define MOEA_DEBUG - -#define TODO panic("%s: not implemented", __func__); - -#define TLBIE(va) __asm __volatile("tlbie %0" :: "r"(va)) -#define TLBSYNC() __asm __volatile("tlbsync"); -#define SYNC() __asm __volatile("sync"); -#define EIEIO() __asm __volatile("eieio"); - -#define VSID_MAKE(sr, hash) ((sr) | (((hash) & 0xfffff) << 4)) -#define VSID_TO_SR(vsid) ((vsid) & 0xf) -#define VSID_TO_HASH(vsid) (((vsid) >> 4) & 0xfffff) - -#define PVO_PTEGIDX_MASK 0x007 /* which PTEG slot */ -#define PVO_PTEGIDX_VALID 0x008 /* slot is valid */ -#define PVO_WIRED 0x010 /* PVO entry is wired */ -#define PVO_MANAGED 0x020 /* PVO entry is managed */ -#define PVO_EXECUTABLE 0x040 /* PVO entry is executable */ -#define PVO_BOOTSTRAP 0x080 /* PVO entry allocated during - bootstrap */ -#define PVO_FAKE 0x100 /* fictitious phys page */ -#define PVO_VADDR(pvo) ((pvo)->pvo_vaddr & ~ADDR_POFF) -#define PVO_ISEXECUTABLE(pvo) ((pvo)->pvo_vaddr & PVO_EXECUTABLE) -#define PVO_ISFAKE(pvo) ((pvo)->pvo_vaddr & PVO_FAKE) -#define PVO_PTEGIDX_GET(pvo) ((pvo)->pvo_vaddr & PVO_PTEGIDX_MASK) -#define PVO_PTEGIDX_ISSET(pvo) ((pvo)->pvo_vaddr & PVO_PTEGIDX_VALID) -#define PVO_PTEGIDX_CLR(pvo) \ - ((void)((pvo)->pvo_vaddr &= ~(PVO_PTEGIDX_VALID|PVO_PTEGIDX_MASK))) -#define PVO_PTEGIDX_SET(pvo, i) \ - ((void)((pvo)->pvo_vaddr |= (i)|PVO_PTEGIDX_VALID)) - -#define MOEA_PVO_CHECK(pvo) - -struct ofw_map { - vm_offset_t om_va; - vm_size_t om_len; - vm_offset_t om_pa; - u_int om_mode; -}; - -/* - * Map of physical memory regions. - */ -static struct mem_region *regions; -static struct mem_region *pregions; -u_int phys_avail_count; -int regions_sz, pregions_sz; -static struct ofw_map *translations; - -extern struct pmap ofw_pmap; - - - -/* - * Lock for the pteg and pvo tables. - */ -struct mtx moea_table_mutex; - -/* - * PTEG data. - */ -static struct pteg *moea_pteg_table; -u_int moea_pteg_count; -u_int moea_pteg_mask; - -/* - * PVO data. - */ -struct pvo_head *moea_pvo_table; /* pvo entries by pteg index */ -struct pvo_head moea_pvo_kunmanaged = - LIST_HEAD_INITIALIZER(moea_pvo_kunmanaged); /* list of unmanaged pages */ -struct pvo_head moea_pvo_unmanaged = - LIST_HEAD_INITIALIZER(moea_pvo_unmanaged); /* list of unmanaged pages */ - -uma_zone_t moea_upvo_zone; /* zone for pvo entries for unmanaged pages */ -uma_zone_t moea_mpvo_zone; /* zone for pvo entries for managed pages */ - -#define BPVO_POOL_SIZE 32768 -static struct pvo_entry *moea_bpvo_pool; -static int moea_bpvo_pool_index = 0; - -#define VSID_NBPW (sizeof(u_int32_t) * 8) -static u_int moea_vsid_bitmap[NPMAPS / VSID_NBPW]; - -static boolean_t moea_initialized = FALSE; - -/* - * Statistics. - */ -u_int moea_pte_valid = 0; -u_int moea_pte_overflow = 0; -u_int moea_pte_replacements = 0; -u_int moea_pvo_entries = 0; -u_int moea_pvo_enter_calls = 0; -u_int moea_pvo_remove_calls = 0; -u_int moea_pte_spills = 0; -SYSCTL_INT(_machdep, OID_AUTO, moea_pte_valid, CTLFLAG_RD, &moea_pte_valid, - 0, ""); -SYSCTL_INT(_machdep, OID_AUTO, moea_pte_overflow, CTLFLAG_RD, - &moea_pte_overflow, 0, ""); -SYSCTL_INT(_machdep, OID_AUTO, moea_pte_replacements, CTLFLAG_RD, - &moea_pte_replacements, 0, ""); -SYSCTL_INT(_machdep, OID_AUTO, moea_pvo_entries, CTLFLAG_RD, &moea_pvo_entries, - 0, ""); -SYSCTL_INT(_machdep, OID_AUTO, moea_pvo_enter_calls, CTLFLAG_RD, - &moea_pvo_enter_calls, 0, ""); -SYSCTL_INT(_machdep, OID_AUTO, moea_pvo_remove_calls, CTLFLAG_RD, - &moea_pvo_remove_calls, 0, ""); -SYSCTL_INT(_machdep, OID_AUTO, moea_pte_spills, CTLFLAG_RD, - &moea_pte_spills, 0, ""); - -struct pvo_entry *moea_pvo_zeropage; -struct mtx moea_pvo_zeropage_mtx; - -vm_offset_t moea_rkva_start = VM_MIN_KERNEL_ADDRESS; -u_int moea_rkva_count = 4; - -/* - * Allocate physical memory for use in moea_bootstrap. - */ -static vm_offset_t moea_bootstrap_alloc(vm_size_t, u_int); - -/* - * PTE calls. - */ -static int moea_pte_insert(u_int, struct pte *); - -/* - * PVO calls. - */ -static int moea_pvo_enter(pmap_t, uma_zone_t, struct pvo_head *, - vm_offset_t, vm_offset_t, u_int, int); -static void moea_pvo_remove(struct pvo_entry *, int); -static struct pvo_entry *moea_pvo_find_va(pmap_t, vm_offset_t, int *); -static struct pte *moea_pvo_to_pte(const struct pvo_entry *, int); - -/* - * Utility routines. - */ -static void moea_enter_locked(pmap_t, vm_offset_t, vm_page_t, - vm_prot_t, boolean_t); -static struct pvo_entry *moea_rkva_alloc(mmu_t); -static void moea_pa_map(struct pvo_entry *, vm_offset_t, - struct pte *, int *); -static void moea_pa_unmap(struct pvo_entry *, struct pte *, int *); -static void moea_syncicache(vm_offset_t, vm_size_t); -static boolean_t moea_query_bit(vm_page_t, int); -static u_int moea_clear_bit(vm_page_t, int, int *); -static void moea_kremove(mmu_t, vm_offset_t); -static void tlbia(void); -int moea_pte_spill(vm_offset_t); - -/* - * Kernel MMU interface - */ -void moea_change_wiring(mmu_t, pmap_t, vm_offset_t, boolean_t); -void moea_clear_modify(mmu_t, vm_page_t); -void moea_clear_reference(mmu_t, vm_page_t); -void moea_copy_page(mmu_t, vm_page_t, vm_page_t); -void moea_enter(mmu_t, pmap_t, vm_offset_t, vm_page_t, vm_prot_t, boolean_t); -void moea_enter_object(mmu_t, pmap_t, vm_offset_t, vm_offset_t, vm_page_t, - vm_prot_t); -void moea_enter_quick(mmu_t, pmap_t, vm_offset_t, vm_page_t, vm_prot_t); -vm_paddr_t moea_extract(mmu_t, pmap_t, vm_offset_t); -vm_page_t moea_extract_and_hold(mmu_t, pmap_t, vm_offset_t, vm_prot_t); -void moea_init(mmu_t); -boolean_t moea_is_modified(mmu_t, vm_page_t); -boolean_t moea_ts_referenced(mmu_t, vm_page_t); -vm_offset_t moea_map(mmu_t, vm_offset_t *, vm_offset_t, vm_offset_t, int); -boolean_t moea_page_exists_quick(mmu_t, pmap_t, vm_page_t); -int moea_page_wired_mappings(mmu_t, vm_page_t); -void moea_pinit(mmu_t, pmap_t); -void moea_pinit0(mmu_t, pmap_t); -void moea_protect(mmu_t, pmap_t, vm_offset_t, vm_offset_t, vm_prot_t); -void moea_qenter(mmu_t, vm_offset_t, vm_page_t *, int); -void moea_qremove(mmu_t, vm_offset_t, int); -void moea_release(mmu_t, pmap_t); -void moea_remove(mmu_t, pmap_t, vm_offset_t, vm_offset_t); -void moea_remove_all(mmu_t, vm_page_t); -void moea_remove_write(mmu_t, vm_page_t); -void moea_zero_page(mmu_t, vm_page_t); -void moea_zero_page_area(mmu_t, vm_page_t, int, int); -void moea_zero_page_idle(mmu_t, vm_page_t); -void moea_activate(mmu_t, struct thread *); -void moea_deactivate(mmu_t, struct thread *); -void moea_bootstrap(mmu_t, vm_offset_t, vm_offset_t); -void *moea_mapdev(mmu_t, vm_offset_t, vm_size_t); -void moea_unmapdev(mmu_t, vm_offset_t, vm_size_t); -vm_offset_t moea_kextract(mmu_t, vm_offset_t); -void moea_kenter(mmu_t, vm_offset_t, vm_offset_t); -boolean_t moea_dev_direct_mapped(mmu_t, vm_offset_t, vm_size_t); -boolean_t moea_page_executable(mmu_t, vm_page_t); - -static mmu_method_t moea_methods[] = { - MMUMETHOD(mmu_change_wiring, moea_change_wiring), - MMUMETHOD(mmu_clear_modify, moea_clear_modify), - MMUMETHOD(mmu_clear_reference, moea_clear_reference), - MMUMETHOD(mmu_copy_page, moea_copy_page), - MMUMETHOD(mmu_enter, moea_enter), - MMUMETHOD(mmu_enter_object, moea_enter_object), - MMUMETHOD(mmu_enter_quick, moea_enter_quick), - MMUMETHOD(mmu_extract, moea_extract), - MMUMETHOD(mmu_extract_and_hold, moea_extract_and_hold), - MMUMETHOD(mmu_init, moea_init), - MMUMETHOD(mmu_is_modified, moea_is_modified), - MMUMETHOD(mmu_ts_referenced, moea_ts_referenced), - MMUMETHOD(mmu_map, moea_map), - MMUMETHOD(mmu_page_exists_quick,moea_page_exists_quick), - MMUMETHOD(mmu_page_wired_mappings,moea_page_wired_mappings), - MMUMETHOD(mmu_pinit, moea_pinit), - MMUMETHOD(mmu_pinit0, moea_pinit0), - MMUMETHOD(mmu_protect, moea_protect), - MMUMETHOD(mmu_qenter, moea_qenter), - MMUMETHOD(mmu_qremove, moea_qremove), - MMUMETHOD(mmu_release, moea_release), - MMUMETHOD(mmu_remove, moea_remove), - MMUMETHOD(mmu_remove_all, moea_remove_all), - MMUMETHOD(mmu_remove_write, moea_remove_write), - MMUMETHOD(mmu_zero_page, moea_zero_page), - MMUMETHOD(mmu_zero_page_area, moea_zero_page_area), - MMUMETHOD(mmu_zero_page_idle, moea_zero_page_idle), - MMUMETHOD(mmu_activate, moea_activate), - MMUMETHOD(mmu_deactivate, moea_deactivate), - - /* Internal interfaces */ - MMUMETHOD(mmu_bootstrap, moea_bootstrap), - MMUMETHOD(mmu_mapdev, moea_mapdev), - MMUMETHOD(mmu_unmapdev, moea_unmapdev), - MMUMETHOD(mmu_kextract, moea_kextract), - MMUMETHOD(mmu_kenter, moea_kenter), - MMUMETHOD(mmu_dev_direct_mapped,moea_dev_direct_mapped), - MMUMETHOD(mmu_page_executable, moea_page_executable), - - { 0, 0 } -}; - -static mmu_def_t oea_mmu = { - MMU_TYPE_OEA, - moea_methods, - 0 -}; -MMU_DEF(oea_mmu); - - -static __inline int -va_to_sr(u_int *sr, vm_offset_t va) -{ - return (sr[(uintptr_t)va >> ADDR_SR_SHFT]); -} - -static __inline u_int -va_to_pteg(u_int sr, vm_offset_t addr) -{ - u_int hash; - - hash = (sr & SR_VSID_MASK) ^ (((u_int)addr & ADDR_PIDX) >> - ADDR_PIDX_SHFT); - return (hash & moea_pteg_mask); -} - -static __inline struct pvo_head * -pa_to_pvoh(vm_offset_t pa, vm_page_t *pg_p) -{ - struct vm_page *pg; - - pg = PHYS_TO_VM_PAGE(pa); - - if (pg_p != NULL) - *pg_p = pg; - - if (pg == NULL) - return (&moea_pvo_unmanaged); - - return (&pg->md.mdpg_pvoh); -} - -static __inline struct pvo_head * -vm_page_to_pvoh(vm_page_t m) -{ - - return (&m->md.mdpg_pvoh); -} - -static __inline void -moea_attr_clear(vm_page_t m, int ptebit) -{ - - mtx_assert(&vm_page_queue_mtx, MA_OWNED); - m->md.mdpg_attrs &= ~ptebit; -} - -static __inline int -moea_attr_fetch(vm_page_t m) -{ - - return (m->md.mdpg_attrs); -} - -static __inline void -moea_attr_save(vm_page_t m, int ptebit) -{ - - mtx_assert(&vm_page_queue_mtx, MA_OWNED); - m->md.mdpg_attrs |= ptebit; -} - -static __inline int -moea_pte_compare(const struct pte *pt, const struct pte *pvo_pt) -{ - if (pt->pte_hi == pvo_pt->pte_hi) - return (1); - - return (0); -} - -static __inline int -moea_pte_match(struct pte *pt, u_int sr, vm_offset_t va, int which) -{ - return (pt->pte_hi & ~PTE_VALID) == - (((sr & SR_VSID_MASK) << PTE_VSID_SHFT) | - ((va >> ADDR_API_SHFT) & PTE_API) | which); -} - -static __inline void -moea_pte_create(struct pte *pt, u_int sr, vm_offset_t va, u_int pte_lo) -{ - - mtx_assert(&moea_table_mutex, MA_OWNED); - - /* - * Construct a PTE. Default to IMB initially. Valid bit only gets - * set when the real pte is set in memory. - * - * Note: Don't set the valid bit for correct operation of tlb update. - */ - pt->pte_hi = ((sr & SR_VSID_MASK) << PTE_VSID_SHFT) | - (((va & ADDR_PIDX) >> ADDR_API_SHFT) & PTE_API); - pt->pte_lo = pte_lo; -} - -static __inline void -moea_pte_synch(struct pte *pt, struct pte *pvo_pt) -{ - - mtx_assert(&moea_table_mutex, MA_OWNED); - pvo_pt->pte_lo |= pt->pte_lo & (PTE_REF | PTE_CHG); -} - -static __inline void -moea_pte_clear(struct pte *pt, vm_offset_t va, int ptebit) -{ - - mtx_assert(&moea_table_mutex, MA_OWNED); - - /* - * As shown in Section 7.6.3.2.3 - */ - pt->pte_lo &= ~ptebit; - TLBIE(va); - EIEIO(); - TLBSYNC(); - SYNC(); -} - -static __inline void -moea_pte_set(struct pte *pt, struct pte *pvo_pt) -{ - - mtx_assert(&moea_table_mutex, MA_OWNED); - pvo_pt->pte_hi |= PTE_VALID; - - /* - * Update the PTE as defined in section 7.6.3.1. - * Note that the REF/CHG bits are from pvo_pt and thus should havce - * been saved so this routine can restore them (if desired). - */ - pt->pte_lo = pvo_pt->pte_lo; - EIEIO(); - pt->pte_hi = pvo_pt->pte_hi; - SYNC(); - moea_pte_valid++; -} - -static __inline void -moea_pte_unset(struct pte *pt, struct pte *pvo_pt, vm_offset_t va) -{ - - mtx_assert(&moea_table_mutex, MA_OWNED); - pvo_pt->pte_hi &= ~PTE_VALID; - - /* - * Force the reg & chg bits back into the PTEs. - */ - SYNC(); - - /* - * Invalidate the pte. - */ - pt->pte_hi &= ~PTE_VALID; - - SYNC(); - TLBIE(va); - EIEIO(); - TLBSYNC(); - SYNC(); - - /* - * Save the reg & chg bits. - */ - moea_pte_synch(pt, pvo_pt); - moea_pte_valid--; -} - -static __inline void -moea_pte_change(struct pte *pt, struct pte *pvo_pt, vm_offset_t va) -{ - - /* - * Invalidate the PTE - */ - moea_pte_unset(pt, pvo_pt, va); - moea_pte_set(pt, pvo_pt); -} - -/* - * Quick sort callout for comparing memory regions. - */ -static int mr_cmp(const void *a, const void *b); -static int om_cmp(const void *a, const void *b); - -static int -mr_cmp(const void *a, const void *b) -{ - const struct mem_region *regiona; - const struct mem_region *regionb; - - regiona = a; - regionb = b; - if (regiona->mr_start < regionb->mr_start) - return (-1); - else if (regiona->mr_start > regionb->mr_start) - return (1); - else - return (0); -} - -static int -om_cmp(const void *a, const void *b) -{ - const struct ofw_map *mapa; - const struct ofw_map *mapb; - - mapa = a; - mapb = b; - if (mapa->om_pa < mapb->om_pa) - return (-1); - else if (mapa->om_pa > mapb->om_pa) - return (1); - else - return (0); -} - -void -moea_bootstrap(mmu_t mmup, vm_offset_t kernelstart, vm_offset_t kernelend) -{ - ihandle_t mmui; - phandle_t chosen, mmu; - int sz; - int i, j; - int ofw_mappings; - vm_size_t size, physsz, hwphyssz; - vm_offset_t pa, va, off; - u_int batl, batu; - - /* - * Set up BAT0 to map the lowest 256 MB area - */ - battable[0x0].batl = BATL(0x00000000, BAT_M, BAT_PP_RW); - battable[0x0].batu = BATU(0x00000000, BAT_BL_256M, BAT_Vs); - - /* - * Map PCI memory space. - */ - battable[0x8].batl = BATL(0x80000000, BAT_I|BAT_G, BAT_PP_RW); - battable[0x8].batu = BATU(0x80000000, BAT_BL_256M, BAT_Vs); - - battable[0x9].batl = BATL(0x90000000, BAT_I|BAT_G, BAT_PP_RW); - battable[0x9].batu = BATU(0x90000000, BAT_BL_256M, BAT_Vs); - - battable[0xa].batl = BATL(0xa0000000, BAT_I|BAT_G, BAT_PP_RW); - battable[0xa].batu = BATU(0xa0000000, BAT_BL_256M, BAT_Vs); - - battable[0xb].batl = BATL(0xb0000000, BAT_I|BAT_G, BAT_PP_RW); - battable[0xb].batu = BATU(0xb0000000, BAT_BL_256M, BAT_Vs); - - /* - * Map obio devices. - */ - battable[0xf].batl = BATL(0xf0000000, BAT_I|BAT_G, BAT_PP_RW); - battable[0xf].batu = BATU(0xf0000000, BAT_BL_256M, BAT_Vs); - - /* - * Use an IBAT and a DBAT to map the bottom segment of memory - * where we are. - */ - batu = BATU(0x00000000, BAT_BL_256M, BAT_Vs); - batl = BATL(0x00000000, BAT_M, BAT_PP_RW); - __asm (".balign 32; \n" - "mtibatu 0,%0; mtibatl 0,%1; isync; \n" - "mtdbatu 0,%0; mtdbatl 0,%1; isync" - :: "r"(batu), "r"(batl)); - -#if 0 - /* map frame buffer */ - batu = BATU(0x90000000, BAT_BL_256M, BAT_Vs); - batl = BATL(0x90000000, BAT_I|BAT_G, BAT_PP_RW); - __asm ("mtdbatu 1,%0; mtdbatl 1,%1; isync" - :: "r"(batu), "r"(batl)); -#endif - -#if 1 - /* map pci space */ - batu = BATU(0x80000000, BAT_BL_256M, BAT_Vs); - batl = BATL(0x80000000, BAT_I|BAT_G, BAT_PP_RW); - __asm ("mtdbatu 1,%0; mtdbatl 1,%1; isync" - :: "r"(batu), "r"(batl)); -#endif - - /* - * Set the start and end of kva. - */ - virtual_avail = VM_MIN_KERNEL_ADDRESS; - virtual_end = VM_MAX_KERNEL_ADDRESS; - - mem_regions(&pregions, &pregions_sz, ®ions, ®ions_sz); - CTR0(KTR_PMAP, "moea_bootstrap: physical memory"); - - qsort(pregions, pregions_sz, sizeof(*pregions), mr_cmp); - for (i = 0; i < pregions_sz; i++) { - vm_offset_t pa; - vm_offset_t end; - - CTR3(KTR_PMAP, "physregion: %#x - %#x (%#x)", - pregions[i].mr_start, - pregions[i].mr_start + pregions[i].mr_size, - pregions[i].mr_size); - /* - * Install entries into the BAT table to allow all - * of physmem to be convered by on-demand BAT entries. - * The loop will sometimes set the same battable element - * twice, but that's fine since they won't be used for - * a while yet. - */ - pa = pregions[i].mr_start & 0xf0000000; - end = pregions[i].mr_start + pregions[i].mr_size; - do { - u_int n = pa >> ADDR_SR_SHFT; - - battable[n].batl = BATL(pa, BAT_M, BAT_PP_RW); - battable[n].batu = BATU(pa, BAT_BL_256M, BAT_Vs); - pa += SEGMENT_LENGTH; - } while (pa < end); - } - - if (sizeof(phys_avail)/sizeof(phys_avail[0]) < regions_sz) - panic("moea_bootstrap: phys_avail too small"); - qsort(regions, regions_sz, sizeof(*regions), mr_cmp); - phys_avail_count = 0; - physsz = 0; - hwphyssz = 0; - TUNABLE_ULONG_FETCH("hw.physmem", (u_long *) &hwphyssz); - for (i = 0, j = 0; i < regions_sz; i++, j += 2) { - CTR3(KTR_PMAP, "region: %#x - %#x (%#x)", regions[i].mr_start, - regions[i].mr_start + regions[i].mr_size, - regions[i].mr_size); - if (hwphyssz != 0 && - (physsz + regions[i].mr_size) >= hwphyssz) { - if (physsz < hwphyssz) { - phys_avail[j] = regions[i].mr_start; - phys_avail[j + 1] = regions[i].mr_start + - hwphyssz - physsz; - physsz = hwphyssz; - phys_avail_count++; - } - break; - } - phys_avail[j] = regions[i].mr_start; - phys_avail[j + 1] = regions[i].mr_start + regions[i].mr_size; - phys_avail_count++; - physsz += regions[i].mr_size; - } - physmem = btoc(physsz); - - /* - * Allocate PTEG table. - */ -#ifdef PTEGCOUNT - moea_pteg_count = PTEGCOUNT; -#else - moea_pteg_count = 0x1000; - - while (moea_pteg_count < physmem) - moea_pteg_count <<= 1; - - moea_pteg_count >>= 1; -#endif /* PTEGCOUNT */ - - size = moea_pteg_count * sizeof(struct pteg); - CTR2(KTR_PMAP, "moea_bootstrap: %d PTEGs, %d bytes", moea_pteg_count, - size); - moea_pteg_table = (struct pteg *)moea_bootstrap_alloc(size, size); - CTR1(KTR_PMAP, "moea_bootstrap: PTEG table at %p", moea_pteg_table); - bzero((void *)moea_pteg_table, moea_pteg_count * sizeof(struct pteg)); - moea_pteg_mask = moea_pteg_count - 1; - - /* - * Allocate pv/overflow lists. - */ - size = sizeof(struct pvo_head) * moea_pteg_count; - moea_pvo_table = (struct pvo_head *)moea_bootstrap_alloc(size, - PAGE_SIZE); - CTR1(KTR_PMAP, "moea_bootstrap: PVO table at %p", moea_pvo_table); - for (i = 0; i < moea_pteg_count; i++) - LIST_INIT(&moea_pvo_table[i]); - - /* - * Initialize the lock that synchronizes access to the pteg and pvo - * tables. - */ - mtx_init(&moea_table_mutex, "pmap table", NULL, MTX_DEF | - MTX_RECURSE); - - /* - * Allocate the message buffer. - */ - msgbuf_phys = moea_bootstrap_alloc(MSGBUF_SIZE, 0); - - /* - * Initialise the unmanaged pvo pool. - */ - moea_bpvo_pool = (struct pvo_entry *)moea_bootstrap_alloc( - BPVO_POOL_SIZE*sizeof(struct pvo_entry), 0); - moea_bpvo_pool_index = 0; - - /* - * Make sure kernel vsid is allocated as well as VSID 0. - */ - moea_vsid_bitmap[(KERNEL_VSIDBITS & (NPMAPS - 1)) / VSID_NBPW] - |= 1 << (KERNEL_VSIDBITS % VSID_NBPW); - moea_vsid_bitmap[0] |= 1; - - /* - * Set up the Open Firmware pmap and add it's mappings. - */ - moea_pinit(mmup, &ofw_pmap); - ofw_pmap.pm_sr[KERNEL_SR] = KERNEL_SEGMENT; - ofw_pmap.pm_sr[KERNEL2_SR] = KERNEL2_SEGMENT; - if ((chosen = OF_finddevice("/chosen")) == -1) - panic("moea_bootstrap: can't find /chosen"); - OF_getprop(chosen, "mmu", &mmui, 4); - if ((mmu = OF_instance_to_package(mmui)) == -1) - panic("moea_bootstrap: can't get mmu package"); - if ((sz = OF_getproplen(mmu, "translations")) == -1) - panic("moea_bootstrap: can't get ofw translation count"); - translations = NULL; - for (i = 0; phys_avail[i] != 0; i += 2) { - if (phys_avail[i + 1] >= sz) { - translations = (struct ofw_map *)phys_avail[i]; - break; - } - } - if (translations == NULL) - panic("moea_bootstrap: no space to copy translations"); - bzero(translations, sz); - if (OF_getprop(mmu, "translations", translations, sz) == -1) - panic("moea_bootstrap: can't get ofw translations"); - CTR0(KTR_PMAP, "moea_bootstrap: translations"); - sz /= sizeof(*translations); - qsort(translations, sz, sizeof (*translations), om_cmp); - for (i = 0, ofw_mappings = 0; i < sz; i++) { - CTR3(KTR_PMAP, "translation: pa=%#x va=%#x len=%#x", - translations[i].om_pa, translations[i].om_va, - translations[i].om_len); - - /* - * If the mapping is 1:1, let the RAM and device on-demand - * BAT tables take care of the translation. - */ - if (translations[i].om_va == translations[i].om_pa) - continue; - - /* Enter the pages */ - for (off = 0; off < translations[i].om_len; off += PAGE_SIZE) { - struct vm_page m; - - m.phys_addr = translations[i].om_pa + off; - PMAP_LOCK(&ofw_pmap); - moea_enter_locked(&ofw_pmap, - translations[i].om_va + off, &m, - VM_PROT_ALL, 1); - PMAP_UNLOCK(&ofw_pmap); - ofw_mappings++; - } - } -#ifdef SMP - TLBSYNC(); -#endif - - /* - * Initialize the kernel pmap (which is statically allocated). - */ - PMAP_LOCK_INIT(kernel_pmap); - for (i = 0; i < 16; i++) { - kernel_pmap->pm_sr[i] = EMPTY_SEGMENT; - } - kernel_pmap->pm_sr[KERNEL_SR] = KERNEL_SEGMENT; - kernel_pmap->pm_sr[KERNEL2_SR] = KERNEL2_SEGMENT; - kernel_pmap->pm_active = ~0; - - /* - * Allocate a kernel stack with a guard page for thread0 and map it - * into the kernel page map. - */ - pa = moea_bootstrap_alloc(KSTACK_PAGES * PAGE_SIZE, 0); - kstack0_phys = pa; - kstack0 = virtual_avail + (KSTACK_GUARD_PAGES * PAGE_SIZE); - CTR2(KTR_PMAP, "moea_bootstrap: kstack0 at %#x (%#x)", kstack0_phys, - kstack0); - virtual_avail += (KSTACK_PAGES + KSTACK_GUARD_PAGES) * PAGE_SIZE; - for (i = 0; i < KSTACK_PAGES; i++) { - pa = kstack0_phys + i * PAGE_SIZE; - va = kstack0 + i * PAGE_SIZE; - moea_kenter(mmup, va, pa); - TLBIE(va); - } - - /* - * Calculate the last available physical address. - */ - for (i = 0; phys_avail[i + 2] != 0; i += 2) - ; - Maxmem = powerpc_btop(phys_avail[i + 1]); - - /* - * Allocate virtual address space for the message buffer. - */ - msgbufp = (struct msgbuf *)virtual_avail; - virtual_avail += round_page(MSGBUF_SIZE); - - /* - * Initialize hardware. - */ - for (i = 0; i < 16; i++) { - mtsrin(i << ADDR_SR_SHFT, EMPTY_SEGMENT); - } - __asm __volatile ("mtsr %0,%1" - :: "n"(KERNEL_SR), "r"(KERNEL_SEGMENT)); - __asm __volatile ("mtsr %0,%1" - :: "n"(KERNEL2_SR), "r"(KERNEL2_SEGMENT)); - __asm __volatile ("sync; mtsdr1 %0; isync" - :: "r"((u_int)moea_pteg_table | (moea_pteg_mask >> 10))); - tlbia(); - - pmap_bootstrapped++; -} - -/* - * Activate a user pmap. The pmap must be activated before it's address - * space can be accessed in any way. - */ -void -moea_activate(mmu_t mmu, struct thread *td) -{ - pmap_t pm, pmr; - - /* - * Load all the data we need up front to encourage the compiler to - * not issue any loads while we have interrupts disabled below. - */ - pm = &td->td_proc->p_vmspace->vm_pmap; - - if ((pmr = (pmap_t)moea_kextract(mmu, (vm_offset_t)pm)) == NULL) - pmr = pm; - - pm->pm_active |= PCPU_GET(cpumask); - PCPU_SET(curpmap, pmr); -} - -void -moea_deactivate(mmu_t mmu, struct thread *td) -{ - pmap_t pm; - - pm = &td->td_proc->p_vmspace->vm_pmap; - pm->pm_active &= ~(PCPU_GET(cpumask)); - PCPU_SET(curpmap, NULL); -} - -void -moea_change_wiring(mmu_t mmu, pmap_t pm, vm_offset_t va, boolean_t wired) -{ - struct pvo_entry *pvo; - - PMAP_LOCK(pm); - pvo = moea_pvo_find_va(pm, va & ~ADDR_POFF, NULL); - - if (pvo != NULL) { - if (wired) { - if ((pvo->pvo_vaddr & PVO_WIRED) == 0) - pm->pm_stats.wired_count++; - pvo->pvo_vaddr |= PVO_WIRED; - } else { - if ((pvo->pvo_vaddr & PVO_WIRED) != 0) - pm->pm_stats.wired_count--; - pvo->pvo_vaddr &= ~PVO_WIRED; - } - } - PMAP_UNLOCK(pm); -} - -void -moea_copy_page(mmu_t mmu, vm_page_t msrc, vm_page_t mdst) -{ - vm_offset_t dst; - vm_offset_t src; - - dst = VM_PAGE_TO_PHYS(mdst); - src = VM_PAGE_TO_PHYS(msrc); - - kcopy((void *)src, (void *)dst, PAGE_SIZE); -} - -/* - * Zero a page of physical memory by temporarily mapping it into the tlb. - */ -void -moea_zero_page(mmu_t mmu, vm_page_t m) -{ - vm_offset_t pa = VM_PAGE_TO_PHYS(m); - caddr_t va; - - if (pa < SEGMENT_LENGTH) { - va = (caddr_t) pa; - } else if (moea_initialized) { - if (moea_pvo_zeropage == NULL) { - moea_pvo_zeropage = moea_rkva_alloc(mmu); - mtx_init(&moea_pvo_zeropage_mtx, "pvo zero page", - NULL, MTX_DEF); - } - mtx_lock(&moea_pvo_zeropage_mtx); - moea_pa_map(moea_pvo_zeropage, pa, NULL, NULL); - va = (caddr_t)PVO_VADDR(moea_pvo_zeropage); - } else { - panic("moea_zero_page: can't zero pa %#x", pa); - } - - bzero(va, PAGE_SIZE); - - if (pa >= SEGMENT_LENGTH) { - moea_pa_unmap(moea_pvo_zeropage, NULL, NULL); - mtx_unlock(&moea_pvo_zeropage_mtx); - } -} - -void -moea_zero_page_area(mmu_t mmu, vm_page_t m, int off, int size) -{ - vm_offset_t pa = VM_PAGE_TO_PHYS(m); - caddr_t va; - - if (pa < SEGMENT_LENGTH) { - va = (caddr_t) pa; - } else if (moea_initialized) { - if (moea_pvo_zeropage == NULL) { - moea_pvo_zeropage = moea_rkva_alloc(mmu); - mtx_init(&moea_pvo_zeropage_mtx, "pvo zero page", - NULL, MTX_DEF); - } - mtx_lock(&moea_pvo_zeropage_mtx); - moea_pa_map(moea_pvo_zeropage, pa, NULL, NULL); - va = (caddr_t)PVO_VADDR(moea_pvo_zeropage); - } else { - panic("moea_zero_page: can't zero pa %#x", pa); - } - - bzero(va + off, size); - - if (pa >= SEGMENT_LENGTH) { - moea_pa_unmap(moea_pvo_zeropage, NULL, NULL); - mtx_unlock(&moea_pvo_zeropage_mtx); - } -} - -void -moea_zero_page_idle(mmu_t mmu, vm_page_t m) -{ - - moea_zero_page(mmu, m); -} - -/* - * Map the given physical page at the specified virtual address in the - * target pmap with the protection requested. If specified the page - * will be wired down. - */ -void -moea_enter(mmu_t mmu, pmap_t pmap, vm_offset_t va, vm_page_t m, vm_prot_t prot, - boolean_t wired) -{ - - vm_page_lock_queues(); - PMAP_LOCK(pmap); - moea_enter_locked(pmap, va, m, prot, wired); - vm_page_unlock_queues(); - PMAP_UNLOCK(pmap); -} - -/* - * Map the given physical page at the specified virtual address in the - * target pmap with the protection requested. If specified the page - * will be wired down. - * - * The page queues and pmap must be locked. - */ -static void -moea_enter_locked(pmap_t pmap, vm_offset_t va, vm_page_t m, vm_prot_t prot, - boolean_t wired) -{ - struct pvo_head *pvo_head; - uma_zone_t zone; - vm_page_t pg; - u_int pte_lo, pvo_flags, was_exec, i; - int error; - - if (!moea_initialized) { - pvo_head = &moea_pvo_kunmanaged; - zone = moea_upvo_zone; - pvo_flags = 0; - pg = NULL; - was_exec = PTE_EXEC; - } else { - pvo_head = vm_page_to_pvoh(m); - pg = m; - zone = moea_mpvo_zone; - pvo_flags = PVO_MANAGED; - was_exec = 0; - } - if (pmap_bootstrapped) - mtx_assert(&vm_page_queue_mtx, MA_OWNED); - PMAP_LOCK_ASSERT(pmap, MA_OWNED); - - /* XXX change the pvo head for fake pages */ - if ((m->flags & PG_FICTITIOUS) == PG_FICTITIOUS) - pvo_head = &moea_pvo_kunmanaged; - - /* - * If this is a managed page, and it's the first reference to the page, - * clear the execness of the page. Otherwise fetch the execness. - */ - if ((pg != NULL) && ((m->flags & PG_FICTITIOUS) == 0)) { - if (LIST_EMPTY(pvo_head)) { - moea_attr_clear(pg, PTE_EXEC); - } else { - was_exec = moea_attr_fetch(pg) & PTE_EXEC; - } - } - - /* - * Assume the page is cache inhibited and access is guarded unless - * it's in our available memory array. - */ - pte_lo = PTE_I | PTE_G; - for (i = 0; i < pregions_sz; i++) { - if ((VM_PAGE_TO_PHYS(m) >= pregions[i].mr_start) && - (VM_PAGE_TO_PHYS(m) < - (pregions[i].mr_start + pregions[i].mr_size))) { - pte_lo &= ~(PTE_I | PTE_G); - break; - } - } - - if (prot & VM_PROT_WRITE) { - pte_lo |= PTE_BW; - if (pmap_bootstrapped) - vm_page_flag_set(m, PG_WRITEABLE); - } else - pte_lo |= PTE_BR; - - if (prot & VM_PROT_EXECUTE) - pvo_flags |= PVO_EXECUTABLE; - - if (wired) - pvo_flags |= PVO_WIRED; - - if ((m->flags & PG_FICTITIOUS) != 0) - pvo_flags |= PVO_FAKE; - - error = moea_pvo_enter(pmap, zone, pvo_head, va, VM_PAGE_TO_PHYS(m), - pte_lo, pvo_flags); - - /* - * Flush the real page from the instruction cache if this page is - * mapped executable and cacheable and was not previously mapped (or - * was not mapped executable). - */ - if (error == 0 && (pvo_flags & PVO_EXECUTABLE) && - (pte_lo & PTE_I) == 0 && was_exec == 0) { - /* - * Flush the real memory from the cache. - */ - moea_syncicache(VM_PAGE_TO_PHYS(m), PAGE_SIZE); - if (pg != NULL) - moea_attr_save(pg, PTE_EXEC); - } - - /* XXX syncicache always until problems are sorted */ - moea_syncicache(VM_PAGE_TO_PHYS(m), PAGE_SIZE); -} - -/* - * Maps a sequence of resident pages belonging to the same object. - * The sequence begins with the given page m_start. This page is - * mapped at the given virtual address start. Each subsequent page is - * mapped at a virtual address that is offset from start by the same - * amount as the page is offset from m_start within the object. The - * last page in the sequence is the page with the largest offset from - * m_start that can be mapped at a virtual address less than the given - * virtual address end. Not every virtual page between start and end - * is mapped; only those for which a resident page exists with the - * corresponding offset from m_start are mapped. - */ -void -moea_enter_object(mmu_t mmu, pmap_t pm, vm_offset_t start, vm_offset_t end, - vm_page_t m_start, vm_prot_t prot) -{ - vm_page_t m; - vm_pindex_t diff, psize; - - psize = atop(end - start); - m = m_start; - PMAP_LOCK(pm); - while (m != NULL && (diff = m->pindex - m_start->pindex) < psize) { - moea_enter_locked(pm, start + ptoa(diff), m, prot & - (VM_PROT_READ | VM_PROT_EXECUTE), FALSE); - m = TAILQ_NEXT(m, listq); - } - PMAP_UNLOCK(pm); -} - -void -moea_enter_quick(mmu_t mmu, pmap_t pm, vm_offset_t va, vm_page_t m, - vm_prot_t prot) -{ - - PMAP_LOCK(pm); - moea_enter_locked(pm, va, m, prot & (VM_PROT_READ | VM_PROT_EXECUTE), - FALSE); - PMAP_UNLOCK(pm); - -} - -vm_paddr_t -moea_extract(mmu_t mmu, pmap_t pm, vm_offset_t va) -{ - struct pvo_entry *pvo; - vm_paddr_t pa; - - PMAP_LOCK(pm); - pvo = moea_pvo_find_va(pm, va & ~ADDR_POFF, NULL); - if (pvo == NULL) - pa = 0; - else - pa = (pvo->pvo_pte.pte_lo & PTE_RPGN) | (va & ADDR_POFF); - PMAP_UNLOCK(pm); - return (pa); -} - -/* - * Atomically extract and hold the physical page with the given - * pmap and virtual address pair if that mapping permits the given - * protection. - */ -vm_page_t -moea_extract_and_hold(mmu_t mmu, pmap_t pmap, vm_offset_t va, vm_prot_t prot) -{ - struct pvo_entry *pvo; - vm_page_t m; - - m = NULL; - vm_page_lock_queues(); - PMAP_LOCK(pmap); - pvo = moea_pvo_find_va(pmap, va & ~ADDR_POFF, NULL); - if (pvo != NULL && (pvo->pvo_pte.pte_hi & PTE_VALID) && - ((pvo->pvo_pte.pte_lo & PTE_PP) == PTE_RW || - (prot & VM_PROT_WRITE) == 0)) { - m = PHYS_TO_VM_PAGE(pvo->pvo_pte.pte_lo & PTE_RPGN); - vm_page_hold(m); - } - vm_page_unlock_queues(); - PMAP_UNLOCK(pmap); - return (m); -} - -void -moea_init(mmu_t mmu) -{ - - CTR0(KTR_PMAP, "moea_init"); - - moea_upvo_zone = uma_zcreate("UPVO entry", sizeof (struct pvo_entry), - NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, - UMA_ZONE_VM | UMA_ZONE_NOFREE); - moea_mpvo_zone = uma_zcreate("MPVO entry", sizeof(struct pvo_entry), - NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, - UMA_ZONE_VM | UMA_ZONE_NOFREE); - moea_initialized = TRUE; -} - -boolean_t -moea_is_modified(mmu_t mmu, vm_page_t m) -{ - - if ((m->flags & (PG_FICTITIOUS |PG_UNMANAGED)) != 0) - return (FALSE); - - return (moea_query_bit(m, PTE_CHG)); -} - -void -moea_clear_reference(mmu_t mmu, vm_page_t m) -{ - - if ((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) != 0) - return; - moea_clear_bit(m, PTE_REF, NULL); -} - -void -moea_clear_modify(mmu_t mmu, vm_page_t m) -{ - - if ((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) != 0) - return; - moea_clear_bit(m, PTE_CHG, NULL); -} - -/* - * Clear the write and modified bits in each of the given page's mappings. - */ -void -moea_remove_write(mmu_t mmu, vm_page_t m) -{ - struct pvo_entry *pvo; - struct pte *pt; - pmap_t pmap; - u_int lo; - - mtx_assert(&vm_page_queue_mtx, MA_OWNED); - if ((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) != 0 || - (m->flags & PG_WRITEABLE) == 0) - return; - lo = moea_attr_fetch(m); - SYNC(); - LIST_FOREACH(pvo, vm_page_to_pvoh(m), pvo_vlink) { - pmap = pvo->pvo_pmap; - PMAP_LOCK(pmap); - if ((pvo->pvo_pte.pte_lo & PTE_PP) != PTE_BR) { - pt = moea_pvo_to_pte(pvo, -1); - pvo->pvo_pte.pte_lo &= ~PTE_PP; - pvo->pvo_pte.pte_lo |= PTE_BR; - if (pt != NULL) { - moea_pte_synch(pt, &pvo->pvo_pte); - lo |= pvo->pvo_pte.pte_lo; - pvo->pvo_pte.pte_lo &= ~PTE_CHG; - moea_pte_change(pt, &pvo->pvo_pte, - pvo->pvo_vaddr); - mtx_unlock(&moea_table_mutex); - } - } - PMAP_UNLOCK(pmap); - } - if ((lo & PTE_CHG) != 0) { - moea_attr_clear(m, PTE_CHG); - vm_page_dirty(m); - } - vm_page_flag_clear(m, PG_WRITEABLE); -} - -/* - * moea_ts_referenced: - * - * Return a count of reference bits for a page, clearing those bits. - * It is not necessary for every reference bit to be cleared, but it - * is necessary that 0 only be returned when there are truly no - * reference bits set. - * - * XXX: The exact number of bits to check and clear is a matter that - * should be tested and standardized at some point in the future for - * optimal aging of shared pages. - */ -boolean_t -moea_ts_referenced(mmu_t mmu, vm_page_t m) -{ - int count; - - if ((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) != 0) - return (0); - - count = moea_clear_bit(m, PTE_REF, NULL); - - return (count); -} - -/* - * Map a wired page into kernel virtual address space. - */ -void -moea_kenter(mmu_t mmu, vm_offset_t va, vm_offset_t pa) -{ - u_int pte_lo; - int error; - int i; - -#if 0 - if (va < VM_MIN_KERNEL_ADDRESS) - panic("moea_kenter: attempt to enter non-kernel address %#x", - va); -#endif - - pte_lo = PTE_I | PTE_G; - for (i = 0; i < pregions_sz; i++) { - if ((pa >= pregions[i].mr_start) && - (pa < (pregions[i].mr_start + pregions[i].mr_size))) { - pte_lo &= ~(PTE_I | PTE_G); - break; - } - } - - PMAP_LOCK(kernel_pmap); - error = moea_pvo_enter(kernel_pmap, moea_upvo_zone, - &moea_pvo_kunmanaged, va, pa, pte_lo, PVO_WIRED); - - if (error != 0 && error != ENOENT) - panic("moea_kenter: failed to enter va %#x pa %#x: %d", va, - pa, error); - - /* - * Flush the real memory from the instruction cache. - */ - if ((pte_lo & (PTE_I | PTE_G)) == 0) { - moea_syncicache(pa, PAGE_SIZE); - } - PMAP_UNLOCK(kernel_pmap); -} - -/* - * Extract the physical page address associated with the given kernel virtual - * address. - */ -vm_offset_t -moea_kextract(mmu_t mmu, vm_offset_t va) -{ - struct pvo_entry *pvo; - vm_paddr_t pa; - -#ifdef UMA_MD_SMALL_ALLOC - /* - * Allow direct mappings - */ - if (va < VM_MIN_KERNEL_ADDRESS) { - return (va); - } -#endif - - PMAP_LOCK(kernel_pmap); - pvo = moea_pvo_find_va(kernel_pmap, va & ~ADDR_POFF, NULL); - KASSERT(pvo != NULL, ("moea_kextract: no addr found")); - pa = (pvo->pvo_pte.pte_lo & PTE_RPGN) | (va & ADDR_POFF); - PMAP_UNLOCK(kernel_pmap); - return (pa); -} - -/* - * Remove a wired page from kernel virtual address space. - */ -void -moea_kremove(mmu_t mmu, vm_offset_t va) -{ - - moea_remove(mmu, kernel_pmap, va, va + PAGE_SIZE); -} - -/* - * Map a range of physical addresses into kernel virtual address space. - * - * The value passed in *virt is a suggested virtual address for the mapping. - * Architectures which can support a direct-mapped physical to virtual region - * can return the appropriate address within that region, leaving '*virt' - * unchanged. We cannot and therefore do not; *virt is updated with the - * first usable address after the mapped region. - */ -vm_offset_t -moea_map(mmu_t mmu, vm_offset_t *virt, vm_offset_t pa_start, - vm_offset_t pa_end, int prot) -{ - vm_offset_t sva, va; - - sva = *virt; - va = sva; - for (; pa_start < pa_end; pa_start += PAGE_SIZE, va += PAGE_SIZE) - moea_kenter(mmu, va, pa_start); - *virt = va; - return (sva); -} - -/* - * Returns true if the pmap's pv is one of the first - * 16 pvs linked to from this page. This count may - * be changed upwards or downwards in the future; it - * is only necessary that true be returned for a small - * subset of pmaps for proper page aging. - */ -boolean_t -moea_page_exists_quick(mmu_t mmu, pmap_t pmap, vm_page_t m) -{ - int loops; - struct pvo_entry *pvo; - - if (!moea_initialized || (m->flags & PG_FICTITIOUS)) - return FALSE; - - loops = 0; - LIST_FOREACH(pvo, vm_page_to_pvoh(m), pvo_vlink) { - if (pvo->pvo_pmap == pmap) - return (TRUE); - if (++loops >= 16) - break; - } - - return (FALSE); -} - -/* - * Return the number of managed mappings to the given physical page - * that are wired. - */ -int -moea_page_wired_mappings(mmu_t mmu, vm_page_t m) -{ - struct pvo_entry *pvo; - int count; - - count = 0; - if (!moea_initialized || (m->flags & PG_FICTITIOUS) != 0) - return (count); - mtx_assert(&vm_page_queue_mtx, MA_OWNED); - LIST_FOREACH(pvo, vm_page_to_pvoh(m), pvo_vlink) - if ((pvo->pvo_vaddr & PVO_WIRED) != 0) - count++; - return (count); -} - -static u_int moea_vsidcontext; - -void -moea_pinit(mmu_t mmu, pmap_t pmap) -{ - int i, mask; - u_int entropy; - - KASSERT((int)pmap < VM_MIN_KERNEL_ADDRESS, ("moea_pinit: virt pmap")); - PMAP_LOCK_INIT(pmap); - - entropy = 0; - __asm __volatile("mftb %0" : "=r"(entropy)); - - /* - * Allocate some segment registers for this pmap. - */ - for (i = 0; i < NPMAPS; i += VSID_NBPW) { - u_int hash, n; - - /* - * Create a new value by mutiplying by a prime and adding in - * entropy from the timebase register. This is to make the - * VSID more random so that the PT hash function collides - * less often. (Note that the prime casues gcc to do shifts - * instead of a multiply.) - */ - moea_vsidcontext = (moea_vsidcontext * 0x1105) + entropy; - hash = moea_vsidcontext & (NPMAPS - 1); - if (hash == 0) /* 0 is special, avoid it */ - continue; - n = hash >> 5; - mask = 1 << (hash & (VSID_NBPW - 1)); - hash = (moea_vsidcontext & 0xfffff); - if (moea_vsid_bitmap[n] & mask) { /* collision? */ - /* anything free in this bucket? */ - if (moea_vsid_bitmap[n] == 0xffffffff) { - entropy = (moea_vsidcontext >> 20); - continue; - } - i = ffs(~moea_vsid_bitmap[i]) - 1; - mask = 1 << i; - hash &= 0xfffff & ~(VSID_NBPW - 1); - hash |= i; - } - moea_vsid_bitmap[n] |= mask; - for (i = 0; i < 16; i++) - pmap->pm_sr[i] = VSID_MAKE(i, hash); - return; - } - - panic("moea_pinit: out of segments"); -} - -/* - * Initialize the pmap associated with process 0. - */ -void -moea_pinit0(mmu_t mmu, pmap_t pm) -{ - - moea_pinit(mmu, pm); - bzero(&pm->pm_stats, sizeof(pm->pm_stats)); -} - -/* - * Set the physical protection on the specified range of this map as requested. - */ -void -moea_protect(mmu_t mmu, pmap_t pm, vm_offset_t sva, vm_offset_t eva, - vm_prot_t prot) -{ - struct pvo_entry *pvo; - struct pte *pt; - int pteidx; - - CTR4(KTR_PMAP, "moea_protect: pm=%p sva=%#x eva=%#x prot=%#x", pm, sva, - eva, prot); - - - KASSERT(pm == &curproc->p_vmspace->vm_pmap || pm == kernel_pmap, - ("moea_protect: non current pmap")); - - if ((prot & VM_PROT_READ) == VM_PROT_NONE) { - moea_remove(mmu, pm, sva, eva); - return; - } - - vm_page_lock_queues(); - PMAP_LOCK(pm); - for (; sva < eva; sva += PAGE_SIZE) { - pvo = moea_pvo_find_va(pm, sva, &pteidx); - if (pvo == NULL) - continue; - - if ((prot & VM_PROT_EXECUTE) == 0) - pvo->pvo_vaddr &= ~PVO_EXECUTABLE; - - /* - * Grab the PTE pointer before we diddle with the cached PTE - * copy. - */ - pt = moea_pvo_to_pte(pvo, pteidx); - /* - * Change the protection of the page. - */ - pvo->pvo_pte.pte_lo &= ~PTE_PP; - pvo->pvo_pte.pte_lo |= PTE_BR; - - /* - * If the PVO is in the page table, update that pte as well. - */ - if (pt != NULL) { - moea_pte_change(pt, &pvo->pvo_pte, pvo->pvo_vaddr); - mtx_unlock(&moea_table_mutex); - } - } - vm_page_unlock_queues(); - PMAP_UNLOCK(pm); -} - -/* - * Map a list of wired pages into kernel virtual address space. This is - * intended for temporary mappings which do not need page modification or - * references recorded. Existing mappings in the region are overwritten. - */ -void -moea_qenter(mmu_t mmu, vm_offset_t sva, vm_page_t *m, int count) -{ - vm_offset_t va; - - va = sva; - while (count-- > 0) { - moea_kenter(mmu, va, VM_PAGE_TO_PHYS(*m)); - va += PAGE_SIZE; - m++; - } -} - -/* - * Remove page mappings from kernel virtual address space. Intended for - * temporary mappings entered by moea_qenter. - */ -void -moea_qremove(mmu_t mmu, vm_offset_t sva, int count) -{ - vm_offset_t va; - - va = sva; - while (count-- > 0) { - moea_kremove(mmu, va); - va += PAGE_SIZE; - } -} - -void -moea_release(mmu_t mmu, pmap_t pmap) -{ - int idx, mask; - - /* - * Free segment register's VSID - */ - if (pmap->pm_sr[0] == 0) - panic("moea_release"); - - idx = VSID_TO_HASH(pmap->pm_sr[0]) & (NPMAPS-1); - mask = 1 << (idx % VSID_NBPW); - idx /= VSID_NBPW; - moea_vsid_bitmap[idx] &= ~mask; - PMAP_LOCK_DESTROY(pmap); -} - -/* - * Remove the given range of addresses from the specified map. - */ -void -moea_remove(mmu_t mmu, pmap_t pm, vm_offset_t sva, vm_offset_t eva) -{ - struct pvo_entry *pvo; - int pteidx; - - vm_page_lock_queues(); - PMAP_LOCK(pm); - for (; sva < eva; sva += PAGE_SIZE) { - pvo = moea_pvo_find_va(pm, sva, &pteidx); - if (pvo != NULL) { - moea_pvo_remove(pvo, pteidx); - } - } - PMAP_UNLOCK(pm); - vm_page_unlock_queues(); -} - -/* - * Remove physical page from all pmaps in which it resides. moea_pvo_remove() - * will reflect changes in pte's back to the vm_page. - */ -void -moea_remove_all(mmu_t mmu, vm_page_t m) -{ - struct pvo_head *pvo_head; - struct pvo_entry *pvo, *next_pvo; - pmap_t pmap; - - mtx_assert(&vm_page_queue_mtx, MA_OWNED); - - pvo_head = vm_page_to_pvoh(m); - for (pvo = LIST_FIRST(pvo_head); pvo != NULL; pvo = next_pvo) { - next_pvo = LIST_NEXT(pvo, pvo_vlink); - - MOEA_PVO_CHECK(pvo); /* sanity check */ - pmap = pvo->pvo_pmap; - PMAP_LOCK(pmap); - moea_pvo_remove(pvo, -1); - PMAP_UNLOCK(pmap); - } - vm_page_flag_clear(m, PG_WRITEABLE); -} - -/* - * Allocate a physical page of memory directly from the phys_avail map. - * Can only be called from moea_bootstrap before avail start and end are - * calculated. - */ -static vm_offset_t -moea_bootstrap_alloc(vm_size_t size, u_int align) -{ - vm_offset_t s, e; - int i, j; - - size = round_page(size); - for (i = 0; phys_avail[i + 1] != 0; i += 2) { - if (align != 0) - s = (phys_avail[i] + align - 1) & ~(align - 1); - else - s = phys_avail[i]; - e = s + size; - - if (s < phys_avail[i] || e > phys_avail[i + 1]) - continue; - - if (s == phys_avail[i]) { - phys_avail[i] += size; - } else if (e == phys_avail[i + 1]) { - phys_avail[i + 1] -= size; - } else { - for (j = phys_avail_count * 2; j > i; j -= 2) { - phys_avail[j] = phys_avail[j - 2]; - phys_avail[j + 1] = phys_avail[j - 1]; - } - - phys_avail[i + 3] = phys_avail[i + 1]; - phys_avail[i + 1] = s; - phys_avail[i + 2] = e; - phys_avail_count++; - } - - return (s); - } - panic("moea_bootstrap_alloc: could not allocate memory"); -} - -/* - * Return an unmapped pvo for a kernel virtual address. - * Used by pmap functions that operate on physical pages. - */ -static struct pvo_entry * -moea_rkva_alloc(mmu_t mmu) -{ - struct pvo_entry *pvo; - struct pte *pt; - vm_offset_t kva; - int pteidx; - - if (moea_rkva_count == 0) - panic("moea_rkva_alloc: no more reserved KVAs"); - - kva = moea_rkva_start + (PAGE_SIZE * --moea_rkva_count); - moea_kenter(mmu, kva, 0); - - pvo = moea_pvo_find_va(kernel_pmap, kva, &pteidx); - - if (pvo == NULL) - panic("moea_kva_alloc: moea_pvo_find_va failed"); - - pt = moea_pvo_to_pte(pvo, pteidx); - - if (pt == NULL) - panic("moea_kva_alloc: moea_pvo_to_pte failed"); - - moea_pte_unset(pt, &pvo->pvo_pte, pvo->pvo_vaddr); - mtx_unlock(&moea_table_mutex); - PVO_PTEGIDX_CLR(pvo); - - moea_pte_overflow++; - - return (pvo); -} - -static void -moea_pa_map(struct pvo_entry *pvo, vm_offset_t pa, struct pte *saved_pt, - int *depth_p) -{ - struct pte *pt; - - /* - * If this pvo already has a valid pte, we need to save it so it can - * be restored later. We then just reload the new PTE over the old - * slot. - */ - if (saved_pt != NULL) { - pt = moea_pvo_to_pte(pvo, -1); - - if (pt != NULL) { - moea_pte_unset(pt, &pvo->pvo_pte, pvo->pvo_vaddr); - mtx_unlock(&moea_table_mutex); - PVO_PTEGIDX_CLR(pvo); - moea_pte_overflow++; - } - - *saved_pt = pvo->pvo_pte; - - pvo->pvo_pte.pte_lo &= ~PTE_RPGN; - } - - pvo->pvo_pte.pte_lo |= pa; - - if (!moea_pte_spill(pvo->pvo_vaddr)) - panic("moea_pa_map: could not spill pvo %p", pvo); - - if (depth_p != NULL) - (*depth_p)++; -} - -static void -moea_pa_unmap(struct pvo_entry *pvo, struct pte *saved_pt, int *depth_p) -{ - struct pte *pt; - - pt = moea_pvo_to_pte(pvo, -1); - - if (pt != NULL) { - moea_pte_unset(pt, &pvo->pvo_pte, pvo->pvo_vaddr); - mtx_unlock(&moea_table_mutex); - PVO_PTEGIDX_CLR(pvo); - moea_pte_overflow++; - } - - pvo->pvo_pte.pte_lo &= ~PTE_RPGN; - - /* - * If there is a saved PTE and it's valid, restore it and return. - */ - if (saved_pt != NULL && (saved_pt->pte_lo & PTE_RPGN) != 0) { - if (depth_p != NULL && --(*depth_p) == 0) - panic("moea_pa_unmap: restoring but depth == 0"); - - pvo->pvo_pte = *saved_pt; - - if (!moea_pte_spill(pvo->pvo_vaddr)) - panic("moea_pa_unmap: could not spill pvo %p", pvo); - } -} - -static void -moea_syncicache(vm_offset_t pa, vm_size_t len) -{ - __syncicache((void *)pa, len); -} - -static void -tlbia(void) -{ - caddr_t i; - - SYNC(); - for (i = 0; i < (caddr_t)0x00040000; i += 0x00001000) { - TLBIE(i); - EIEIO(); - } - TLBSYNC(); - SYNC(); -} - -static int -moea_pvo_enter(pmap_t pm, uma_zone_t zone, struct pvo_head *pvo_head, - vm_offset_t va, vm_offset_t pa, u_int pte_lo, int flags) -{ - struct pvo_entry *pvo; - u_int sr; - int first; - u_int ptegidx; - int i; - int bootstrap; - - moea_pvo_enter_calls++; - first = 0; - bootstrap = 0; - - /* - * Compute the PTE Group index. - */ - va &= ~ADDR_POFF; - sr = va_to_sr(pm->pm_sr, va); - ptegidx = va_to_pteg(sr, va); - - /* - * Remove any existing mapping for this page. Reuse the pvo entry if - * there is a mapping. - */ - mtx_lock(&moea_table_mutex); - LIST_FOREACH(pvo, &moea_pvo_table[ptegidx], pvo_olink) { - if (pvo->pvo_pmap == pm && PVO_VADDR(pvo) == va) { - if ((pvo->pvo_pte.pte_lo & PTE_RPGN) == pa && - (pvo->pvo_pte.pte_lo & PTE_PP) == - (pte_lo & PTE_PP)) { - mtx_unlock(&moea_table_mutex); - return (0); - } - moea_pvo_remove(pvo, -1); - break; - } - } - - /* - * If we aren't overwriting a mapping, try to allocate. - */ - if (moea_initialized) { - pvo = uma_zalloc(zone, M_NOWAIT); - } else { - if (moea_bpvo_pool_index >= BPVO_POOL_SIZE) { - panic("moea_enter: bpvo pool exhausted, %d, %d, %d", - moea_bpvo_pool_index, BPVO_POOL_SIZE, - BPVO_POOL_SIZE * sizeof(struct pvo_entry)); - } - pvo = &moea_bpvo_pool[moea_bpvo_pool_index]; - moea_bpvo_pool_index++; - bootstrap = 1; - } - - if (pvo == NULL) { - mtx_unlock(&moea_table_mutex); - return (ENOMEM); - } - - moea_pvo_entries++; - pvo->pvo_vaddr = va; - pvo->pvo_pmap = pm; - LIST_INSERT_HEAD(&moea_pvo_table[ptegidx], pvo, pvo_olink); - pvo->pvo_vaddr &= ~ADDR_POFF; - if (flags & VM_PROT_EXECUTE) - pvo->pvo_vaddr |= PVO_EXECUTABLE; - if (flags & PVO_WIRED) - pvo->pvo_vaddr |= PVO_WIRED; - if (pvo_head != &moea_pvo_kunmanaged) - pvo->pvo_vaddr |= PVO_MANAGED; - if (bootstrap) - pvo->pvo_vaddr |= PVO_BOOTSTRAP; - if (flags & PVO_FAKE) - pvo->pvo_vaddr |= PVO_FAKE; - - moea_pte_create(&pvo->pvo_pte, sr, va, pa | pte_lo); - - /* - * Remember if the list was empty and therefore will be the first - * item. - */ - if (LIST_FIRST(pvo_head) == NULL) - first = 1; - LIST_INSERT_HEAD(pvo_head, pvo, pvo_vlink); - - if (pvo->pvo_pte.pte_lo & PVO_WIRED) - pm->pm_stats.wired_count++; - pm->pm_stats.resident_count++; - - /* - * We hope this succeeds but it isn't required. - */ - i = moea_pte_insert(ptegidx, &pvo->pvo_pte); - if (i >= 0) { - PVO_PTEGIDX_SET(pvo, i); - } else { - panic("moea_pvo_enter: overflow"); - moea_pte_overflow++; - } - mtx_unlock(&moea_table_mutex); - - return (first ? ENOENT : 0); -} - -static void -moea_pvo_remove(struct pvo_entry *pvo, int pteidx) -{ - struct pte *pt; - - /* - * If there is an active pte entry, we need to deactivate it (and - * save the ref & cfg bits). - */ - pt = moea_pvo_to_pte(pvo, pteidx); - if (pt != NULL) { - moea_pte_unset(pt, &pvo->pvo_pte, pvo->pvo_vaddr); - mtx_unlock(&moea_table_mutex); - PVO_PTEGIDX_CLR(pvo); - } else { - moea_pte_overflow--; - } - - /* - * Update our statistics. - */ - pvo->pvo_pmap->pm_stats.resident_count--; - if (pvo->pvo_pte.pte_lo & PVO_WIRED) - pvo->pvo_pmap->pm_stats.wired_count--; - - /* - * Save the REF/CHG bits into their cache if the page is managed. - */ - if ((pvo->pvo_vaddr & (PVO_MANAGED|PVO_FAKE)) == PVO_MANAGED) { - struct vm_page *pg; - - pg = PHYS_TO_VM_PAGE(pvo->pvo_pte.pte_lo & PTE_RPGN); - if (pg != NULL) { - moea_attr_save(pg, pvo->pvo_pte.pte_lo & - (PTE_REF | PTE_CHG)); - } - } - - /* - * Remove this PVO from the PV list. - */ - LIST_REMOVE(pvo, pvo_vlink); - - /* - * Remove this from the overflow list and return it to the pool - * if we aren't going to reuse it. - */ - LIST_REMOVE(pvo, pvo_olink); - if (!(pvo->pvo_vaddr & PVO_BOOTSTRAP)) - uma_zfree(pvo->pvo_vaddr & PVO_MANAGED ? moea_mpvo_zone : - moea_upvo_zone, pvo); - moea_pvo_entries--; - moea_pvo_remove_calls++; -} - -static __inline int -moea_pvo_pte_index(const struct pvo_entry *pvo, int ptegidx) -{ - int pteidx; - - /* - * We can find the actual pte entry without searching by grabbing - * the PTEG index from 3 unused bits in pte_lo[11:9] and by - * noticing the HID bit. - */ - pteidx = ptegidx * 8 + PVO_PTEGIDX_GET(pvo); - if (pvo->pvo_pte.pte_hi & PTE_HID) - pteidx ^= moea_pteg_mask * 8; - - return (pteidx); -} - -static struct pvo_entry * -moea_pvo_find_va(pmap_t pm, vm_offset_t va, int *pteidx_p) -{ - struct pvo_entry *pvo; - int ptegidx; - u_int sr; - - va &= ~ADDR_POFF; - sr = va_to_sr(pm->pm_sr, va); - ptegidx = va_to_pteg(sr, va); - - mtx_lock(&moea_table_mutex); - LIST_FOREACH(pvo, &moea_pvo_table[ptegidx], pvo_olink) { - if (pvo->pvo_pmap == pm && PVO_VADDR(pvo) == va) { - if (pteidx_p) - *pteidx_p = moea_pvo_pte_index(pvo, ptegidx); - break; - } - } - mtx_unlock(&moea_table_mutex); - - return (pvo); -} - -static struct pte * -moea_pvo_to_pte(const struct pvo_entry *pvo, int pteidx) -{ - struct pte *pt; - - /* - * If we haven't been supplied the ptegidx, calculate it. - */ - if (pteidx == -1) { - int ptegidx; - u_int sr; - - sr = va_to_sr(pvo->pvo_pmap->pm_sr, pvo->pvo_vaddr); - ptegidx = va_to_pteg(sr, pvo->pvo_vaddr); - pteidx = moea_pvo_pte_index(pvo, ptegidx); - } - - pt = &moea_pteg_table[pteidx >> 3].pt[pteidx & 7]; - mtx_lock(&moea_table_mutex); - - if ((pvo->pvo_pte.pte_hi & PTE_VALID) && !PVO_PTEGIDX_ISSET(pvo)) { - panic("moea_pvo_to_pte: pvo %p has valid pte in pvo but no " - "valid pte index", pvo); - } - - if ((pvo->pvo_pte.pte_hi & PTE_VALID) == 0 && PVO_PTEGIDX_ISSET(pvo)) { - panic("moea_pvo_to_pte: pvo %p has valid pte index in pvo " - "pvo but no valid pte", pvo); - } - - if ((pt->pte_hi ^ (pvo->pvo_pte.pte_hi & ~PTE_VALID)) == PTE_VALID) { - if ((pvo->pvo_pte.pte_hi & PTE_VALID) == 0) { - panic("moea_pvo_to_pte: pvo %p has valid pte in " - "moea_pteg_table %p but invalid in pvo", pvo, pt); - } - - if (((pt->pte_lo ^ pvo->pvo_pte.pte_lo) & ~(PTE_CHG|PTE_REF)) - != 0) { - panic("moea_pvo_to_pte: pvo %p pte does not match " - "pte %p in moea_pteg_table", pvo, pt); - } - - mtx_assert(&moea_table_mutex, MA_OWNED); - return (pt); - } - - if (pvo->pvo_pte.pte_hi & PTE_VALID) { - panic("moea_pvo_to_pte: pvo %p has invalid pte %p in " - "moea_pteg_table but valid in pvo", pvo, pt); - } - - mtx_unlock(&moea_table_mutex); - return (NULL); -} - -/* - * XXX: THIS STUFF SHOULD BE IN pte.c? - */ -int -moea_pte_spill(vm_offset_t addr) -{ - struct pvo_entry *source_pvo, *victim_pvo; - struct pvo_entry *pvo; - int ptegidx, i, j; - u_int sr; - struct pteg *pteg; - struct pte *pt; - - moea_pte_spills++; - - sr = mfsrin(addr); - ptegidx = va_to_pteg(sr, addr); - - /* - * Have to substitute some entry. Use the primary hash for this. - * Use low bits of timebase as random generator. - */ - pteg = &moea_pteg_table[ptegidx]; - mtx_lock(&moea_table_mutex); - __asm __volatile("mftb %0" : "=r"(i)); - i &= 7; - pt = &pteg->pt[i]; - - source_pvo = NULL; - victim_pvo = NULL; - LIST_FOREACH(pvo, &moea_pvo_table[ptegidx], pvo_olink) { - /* - * We need to find a pvo entry for this address. - */ - MOEA_PVO_CHECK(pvo); - if (source_pvo == NULL && - moea_pte_match(&pvo->pvo_pte, sr, addr, - pvo->pvo_pte.pte_hi & PTE_HID)) { - /* - * Now found an entry to be spilled into the pteg. - * The PTE is now valid, so we know it's active. - */ - j = moea_pte_insert(ptegidx, &pvo->pvo_pte); - - if (j >= 0) { - PVO_PTEGIDX_SET(pvo, j); - moea_pte_overflow--; - MOEA_PVO_CHECK(pvo); - mtx_unlock(&moea_table_mutex); - return (1); - } - - source_pvo = pvo; - - if (victim_pvo != NULL) - break; - } - - /* - * We also need the pvo entry of the victim we are replacing - * so save the R & C bits of the PTE. - */ - if ((pt->pte_hi & PTE_HID) == 0 && victim_pvo == NULL && - moea_pte_compare(pt, &pvo->pvo_pte)) { - victim_pvo = pvo; - if (source_pvo != NULL) - break; - } - } - - if (source_pvo == NULL) { - mtx_unlock(&moea_table_mutex); - return (0); - } - - if (victim_pvo == NULL) { - if ((pt->pte_hi & PTE_HID) == 0) - panic("moea_pte_spill: victim p-pte (%p) has no pvo" - "entry", pt); - - /* - * If this is a secondary PTE, we need to search it's primary - * pvo bucket for the matching PVO. - */ - LIST_FOREACH(pvo, &moea_pvo_table[ptegidx ^ moea_pteg_mask], - pvo_olink) { - MOEA_PVO_CHECK(pvo); - /* - * We also need the pvo entry of the victim we are - * replacing so save the R & C bits of the PTE. - */ - if (moea_pte_compare(pt, &pvo->pvo_pte)) { - victim_pvo = pvo; - break; - } - } - - if (victim_pvo == NULL) - panic("moea_pte_spill: victim s-pte (%p) has no pvo" - "entry", pt); - } - - /* - * We are invalidating the TLB entry for the EA we are replacing even - * though it's valid. If we don't, we lose any ref/chg bit changes - * contained in the TLB entry. - */ - source_pvo->pvo_pte.pte_hi &= ~PTE_HID; - - moea_pte_unset(pt, &victim_pvo->pvo_pte, victim_pvo->pvo_vaddr); - moea_pte_set(pt, &source_pvo->pvo_pte); - - PVO_PTEGIDX_CLR(victim_pvo); - PVO_PTEGIDX_SET(source_pvo, i); - moea_pte_replacements++; - - MOEA_PVO_CHECK(victim_pvo); - MOEA_PVO_CHECK(source_pvo); - - mtx_unlock(&moea_table_mutex); - return (1); -} - -static int -moea_pte_insert(u_int ptegidx, struct pte *pvo_pt) -{ - struct pte *pt; - int i; - - mtx_assert(&moea_table_mutex, MA_OWNED); - - /* - * First try primary hash. - */ - for (pt = moea_pteg_table[ptegidx].pt, i = 0; i < 8; i++, pt++) { - if ((pt->pte_hi & PTE_VALID) == 0) { - pvo_pt->pte_hi &= ~PTE_HID; - moea_pte_set(pt, pvo_pt); - return (i); - } - } - - /* - * Now try secondary hash. - */ - ptegidx ^= moea_pteg_mask; - - for (pt = moea_pteg_table[ptegidx].pt, i = 0; i < 8; i++, pt++) { - if ((pt->pte_hi & PTE_VALID) == 0) { - pvo_pt->pte_hi |= PTE_HID; - moea_pte_set(pt, pvo_pt); - return (i); - } - } - - panic("moea_pte_insert: overflow"); - return (-1); -} - -static boolean_t -moea_query_bit(vm_page_t m, int ptebit) -{ - struct pvo_entry *pvo; - struct pte *pt; - -#if 0 - if (moea_attr_fetch(m) & ptebit) - return (TRUE); -#endif - - LIST_FOREACH(pvo, vm_page_to_pvoh(m), pvo_vlink) { - MOEA_PVO_CHECK(pvo); /* sanity check */ - - /* - * See if we saved the bit off. If so, cache it and return - * success. - */ - if (pvo->pvo_pte.pte_lo & ptebit) { - moea_attr_save(m, ptebit); - MOEA_PVO_CHECK(pvo); /* sanity check */ - return (TRUE); - } - } - - /* - * No luck, now go through the hard part of looking at the PTEs - * themselves. Sync so that any pending REF/CHG bits are flushed to - * the PTEs. - */ - SYNC(); - LIST_FOREACH(pvo, vm_page_to_pvoh(m), pvo_vlink) { - MOEA_PVO_CHECK(pvo); /* sanity check */ - - /* - * See if this pvo has a valid PTE. if so, fetch the - * REF/CHG bits from the valid PTE. If the appropriate - * ptebit is set, cache it and return success. - */ - pt = moea_pvo_to_pte(pvo, -1); - if (pt != NULL) { - moea_pte_synch(pt, &pvo->pvo_pte); - mtx_unlock(&moea_table_mutex); - if (pvo->pvo_pte.pte_lo & ptebit) { - moea_attr_save(m, ptebit); - MOEA_PVO_CHECK(pvo); /* sanity check */ - return (TRUE); - } - } - } - - return (FALSE); -} - -static u_int -moea_clear_bit(vm_page_t m, int ptebit, int *origbit) -{ - u_int count; - struct pvo_entry *pvo; - struct pte *pt; - int rv; - - /* - * Clear the cached value. - */ - rv = moea_attr_fetch(m); - moea_attr_clear(m, ptebit); - - /* - * Sync so that any pending REF/CHG bits are flushed to the PTEs (so - * we can reset the right ones). note that since the pvo entries and - * list heads are accessed via BAT0 and are never placed in the page - * table, we don't have to worry about further accesses setting the - * REF/CHG bits. - */ - SYNC(); - - /* - * For each pvo entry, clear the pvo's ptebit. If this pvo has a - * valid pte clear the ptebit from the valid pte. - */ - count = 0; - LIST_FOREACH(pvo, vm_page_to_pvoh(m), pvo_vlink) { - MOEA_PVO_CHECK(pvo); /* sanity check */ - pt = moea_pvo_to_pte(pvo, -1); - if (pt != NULL) { - moea_pte_synch(pt, &pvo->pvo_pte); - if (pvo->pvo_pte.pte_lo & ptebit) { - count++; - moea_pte_clear(pt, PVO_VADDR(pvo), ptebit); - } - mtx_unlock(&moea_table_mutex); - } - rv |= pvo->pvo_pte.pte_lo; - pvo->pvo_pte.pte_lo &= ~ptebit; - MOEA_PVO_CHECK(pvo); /* sanity check */ - } - - if (origbit != NULL) { - *origbit = rv; - } - - return (count); -} - -/* - * Return true if the physical range is encompassed by the battable[idx] - */ -static int -moea_bat_mapped(int idx, vm_offset_t pa, vm_size_t size) -{ - u_int prot; - u_int32_t start; - u_int32_t end; - u_int32_t bat_ble; - - /* - * Return immediately if not a valid mapping - */ - if (!battable[idx].batu & BAT_Vs) - return (EINVAL); - - /* - * The BAT entry must be cache-inhibited, guarded, and r/w - * so it can function as an i/o page - */ - prot = battable[idx].batl & (BAT_I|BAT_G|BAT_PP_RW); - if (prot != (BAT_I|BAT_G|BAT_PP_RW)) - return (EPERM); - - /* - * The address should be within the BAT range. Assume that the - * start address in the BAT has the correct alignment (thus - * not requiring masking) - */ - start = battable[idx].batl & BAT_PBS; - bat_ble = (battable[idx].batu & ~(BAT_EBS)) | 0x03; - end = start | (bat_ble << 15) | 0x7fff; - - if ((pa < start) || ((pa + size) > end)) - return (ERANGE); - - return (0); -} - -boolean_t -moea_dev_direct_mapped(mmu_t mmu, vm_offset_t pa, vm_size_t size) -{ - int i; - - /* - * This currently does not work for entries that - * overlap 256M BAT segments. - */ - - for(i = 0; i < 16; i++) - if (moea_bat_mapped(i, pa, size) == 0) - return (0); - - return (EFAULT); -} - -boolean_t -moea_page_executable(mmu_t mmu, vm_page_t pg) -{ - return ((moea_attr_fetch(pg) & PTE_EXEC) == PTE_EXEC); -} - -/* - * Map a set of physical memory pages into the kernel virtual - * address space. Return a pointer to where it is mapped. This - * routine is intended to be used for mapping device memory, - * NOT real memory. - */ -void * -moea_mapdev(mmu_t mmu, vm_offset_t pa, vm_size_t size) -{ - vm_offset_t va, tmpva, ppa, offset; - int i; - - ppa = trunc_page(pa); - offset = pa & PAGE_MASK; - size = roundup(offset + size, PAGE_SIZE); - - GIANT_REQUIRED; - - /* - * If the physical address lies within a valid BAT table entry, - * return the 1:1 mapping. This currently doesn't work - * for regions that overlap 256M BAT segments. - */ - for (i = 0; i < 16; i++) { - if (moea_bat_mapped(i, pa, size) == 0) - return ((void *) pa); - } - - va = kmem_alloc_nofault(kernel_map, size); - if (!va) - panic("moea_mapdev: Couldn't alloc kernel virtual memory"); - - for (tmpva = va; size > 0;) { - moea_kenter(mmu, tmpva, ppa); - TLBIE(tmpva); /* XXX or should it be invalidate-all ? */ - size -= PAGE_SIZE; - tmpva += PAGE_SIZE; - ppa += PAGE_SIZE; - } - - return ((void *)(va + offset)); -} - -void -moea_unmapdev(mmu_t mmu, vm_offset_t va, vm_size_t size) -{ - vm_offset_t base, offset; - - /* - * If this is outside kernel virtual space, then it's a - * battable entry and doesn't require unmapping - */ - if ((va >= VM_MIN_KERNEL_ADDRESS) && (va <= VM_MAX_KERNEL_ADDRESS)) { - base = trunc_page(va); - offset = va & PAGE_MASK; - size = roundup(offset + size, PAGE_SIZE); - kmem_free(kernel_map, base, size); - } -} diff --git a/sys/powerpc/powerpc/nexus.c b/sys/powerpc/powerpc/nexus.c deleted file mode 100644 index e31ef61..0000000 --- a/sys/powerpc/powerpc/nexus.c +++ /dev/null @@ -1,487 +0,0 @@ -/*- - * Copyright 1998 Massachusetts Institute of Technology - * - * Permission to use, copy, modify, and distribute this software and - * its documentation for any purpose and without fee is hereby - * granted, provided that both the above copyright notice and this - * permission notice appear in all copies, that both the above - * copyright notice and this permission notice appear in all - * supporting documentation, and that the name of M.I.T. not be used - * in advertising or publicity pertaining to distribution of the - * software without specific, written prior permission. M.I.T. makes - * no representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied - * warranty. - * - * THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''. M.I.T. DISCLAIMS - * ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT - * SHALL M.I.T. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ -/*- - * Copyright 2001 by Thomas Moestl <tmm@FreeBSD.org>. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * from: FreeBSD: src/sys/i386/i386/nexus.c,v 1.43 2001/02/09 - * - * $FreeBSD$ - */ -#include "opt_psim.h" - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/module.h> -#include <sys/bus.h> -#include <sys/cons.h> -#include <sys/kernel.h> -#include <sys/malloc.h> - -#include <dev/ofw/openfirm.h> - -#include <machine/bus.h> -#include <machine/frame.h> -#include <machine/intr_machdep.h> -#include <machine/nexusvar.h> -#include <machine/resource.h> - -#include <sys/rman.h> - -#include "ofw_bus_if.h" -#include "pic_if.h" - -/* - * The nexus (which is a pseudo-bus actually) iterates over the nodes that - * exist in Open Firmware and adds them as devices to this bus so that drivers - * can be attached to them. - * - * Maybe this code should get into dev/ofw to some extent, as some of it should - * work for all Open Firmware based machines... - */ - -static MALLOC_DEFINE(M_NEXUS, "nexus", "nexus device information"); - -struct nexus_devinfo { - phandle_t ndi_node; - /* Some common properties. */ - const char *ndi_name; - const char *ndi_device_type; - const char *ndi_compatible; -}; - -struct nexus_softc { - struct rman sc_rman; -}; - -/* - * Device interface - */ -static int nexus_probe(device_t); -static void nexus_probe_nomatch(device_t, device_t); - -/* - * Bus interface - */ -static device_t nexus_add_child(device_t, int, const char *, int); -static int nexus_read_ivar(device_t, device_t, int, uintptr_t *); -static int nexus_write_ivar(device_t, device_t, int, uintptr_t); -static int nexus_setup_intr(device_t, device_t, struct resource *, int, - driver_filter_t *, driver_intr_t *, void *, void **); -static int nexus_teardown_intr(device_t, device_t, struct resource *, - void *); -static struct resource *nexus_alloc_resource(device_t, device_t, int, int *, - u_long, u_long, u_long, u_int); -static int nexus_activate_resource(device_t, device_t, int, int, - struct resource *); -static int nexus_deactivate_resource(device_t, device_t, int, int, - struct resource *); -static int nexus_release_resource(device_t, device_t, int, int, - struct resource *); - -static phandle_t nexus_ofw_get_node(device_t, device_t); -static const char *nexus_ofw_get_name(device_t, device_t); -static const char *nexus_ofw_get_type(device_t, device_t); -static const char *nexus_ofw_get_compat(device_t, device_t); - -/* - * Local routines - */ -static device_t nexus_device_from_node(device_t, phandle_t); - -static device_method_t nexus_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, nexus_probe), - DEVMETHOD(device_attach, bus_generic_attach), - DEVMETHOD(device_detach, bus_generic_detach), - DEVMETHOD(device_shutdown, bus_generic_shutdown), - DEVMETHOD(device_suspend, bus_generic_suspend), - DEVMETHOD(device_resume, bus_generic_resume), - - /* Bus interface. Resource management is business of the children... */ - DEVMETHOD(bus_add_child, nexus_add_child), - DEVMETHOD(bus_print_child, bus_generic_print_child), - DEVMETHOD(bus_probe_nomatch, nexus_probe_nomatch), - DEVMETHOD(bus_read_ivar, nexus_read_ivar), - DEVMETHOD(bus_write_ivar, nexus_write_ivar), - DEVMETHOD(bus_setup_intr, nexus_setup_intr), - DEVMETHOD(bus_teardown_intr, nexus_teardown_intr), - DEVMETHOD(bus_alloc_resource, nexus_alloc_resource), - DEVMETHOD(bus_activate_resource, nexus_activate_resource), - DEVMETHOD(bus_deactivate_resource, nexus_deactivate_resource), - DEVMETHOD(bus_release_resource, nexus_release_resource), - - /* OFW bus interface */ - DEVMETHOD(ofw_bus_get_node, nexus_ofw_get_node), - DEVMETHOD(ofw_bus_get_name, nexus_ofw_get_name), - DEVMETHOD(ofw_bus_get_type, nexus_ofw_get_type), - DEVMETHOD(ofw_bus_get_compat, nexus_ofw_get_compat), - - { 0, 0 } -}; - -static driver_t nexus_driver = { - "nexus", - nexus_methods, - sizeof(struct nexus_softc), -}; - -static devclass_t nexus_devclass; - -DRIVER_MODULE(nexus, root, nexus_driver, nexus_devclass, 0, 0); - -static int -nexus_probe(device_t dev) -{ - phandle_t root; - phandle_t child; - struct nexus_softc *sc; - u_long start, end; - - if ((root = OF_peer(0)) == -1) - panic("nexus_probe: OF_peer failed."); - - sc = device_get_softc(dev); - - start = 0; - end = INTR_VECTORS - 1; - - sc->sc_rman.rm_start = start; - sc->sc_rman.rm_end = end; - sc->sc_rman.rm_type = RMAN_ARRAY; - sc->sc_rman.rm_descr = "Interrupt request lines"; - if (rman_init(&sc->sc_rman) || - rman_manage_region(&sc->sc_rman, start, end)) - panic("nexus_probe IRQ rman"); - - /* - * Allow devices to identify - */ - bus_generic_probe(dev); - - /* - * Now walk the OFW tree to locate top-level devices - */ - for (child = OF_child(root); child != 0; child = OF_peer(child)) { - if (child == -1) - panic("nexus_probe(): OF_child failed."); - (void)nexus_device_from_node(dev, child); - - } - device_set_desc(dev, "Open Firmware Nexus device"); - return (0); -} - -static void -nexus_probe_nomatch(device_t dev, device_t child) -{ - char *name, *type; - - if (BUS_READ_IVAR(dev, child, NEXUS_IVAR_NAME, - (uintptr_t *)&name) != 0 || - BUS_READ_IVAR(dev, child, NEXUS_IVAR_DEVICE_TYPE, - (uintptr_t *)&type) != 0) - return; - - if (type == NULL) - type = "(unknown)"; - - if (bootverbose) - device_printf(dev, "<%s>, type %s (no driver attached)\n", - name, type); -} - -static device_t -nexus_add_child(device_t dev, int order, const char *name, int unit) -{ - device_t child; - struct nexus_devinfo *dinfo; - - child = device_add_child_ordered(dev, order, name, unit); - if (child == NULL) - return (NULL); - - dinfo = malloc(sizeof(struct nexus_devinfo), M_NEXUS, M_NOWAIT|M_ZERO); - if (dinfo == NULL) - return (NULL); - - dinfo->ndi_node = -1; - dinfo->ndi_name = name; - device_set_ivars(child, dinfo); - - return (child); -} - - -static int -nexus_read_ivar(device_t dev, device_t child, int which, uintptr_t *result) -{ - struct nexus_devinfo *dinfo; - - if ((dinfo = device_get_ivars(child)) == 0) - return (ENOENT); - switch (which) { - case NEXUS_IVAR_NODE: - *result = dinfo->ndi_node; - break; - case NEXUS_IVAR_NAME: - *result = (uintptr_t)dinfo->ndi_name; - break; - case NEXUS_IVAR_DEVICE_TYPE: - *result = (uintptr_t)dinfo->ndi_device_type; - break; - case NEXUS_IVAR_COMPATIBLE: - *result = (uintptr_t)dinfo->ndi_compatible; - break; - default: - return (ENOENT); - } - return 0; -} - -static int -nexus_write_ivar(device_t dev, device_t child, int which, uintptr_t value) -{ - struct nexus_devinfo *dinfo; - - if ((dinfo = device_get_ivars(child)) == 0) - return (ENOENT); - - switch (which) { - case NEXUS_IVAR_NAME: - return (EINVAL); - - /* Identified devices may want to set these */ - case NEXUS_IVAR_NODE: - dinfo->ndi_node = (phandle_t)value; - break; - - case NEXUS_IVAR_DEVICE_TYPE: - dinfo->ndi_device_type = (char *)value; - break; - - default: - return (ENOENT); - } - return 0; -} - -static int -nexus_setup_intr(device_t dev, device_t child, struct resource *res, int flags, - driver_filter_t *filter, driver_intr_t *ihand, void *arg, void **cookiep) -{ - driver_t *driver; - int error; - - /* somebody tried to setup an irq that failed to allocate! */ - if (res == NULL) - panic("nexus_setup_intr: NULL irq resource!"); - - *cookiep = 0; - if ((rman_get_flags(res) & RF_SHAREABLE) == 0) - flags |= INTR_EXCL; - - driver = device_get_driver(child); - - /* - * We depend here on rman_activate_resource() being idempotent. - */ - error = rman_activate_resource(res); - if (error) - return (error); - - error = powerpc_setup_intr(device_get_nameunit(child), - rman_get_start(res), filter, ihand, arg, flags, cookiep); - - return (error); -} - -static int -nexus_teardown_intr(device_t dev, device_t child, struct resource *res, - void *cookie) -{ - - return (powerpc_teardown_intr(cookie)); -} - -/* - * Allocate resources at the behest of a child. This only handles interrupts, - * since I/O resources are handled by child busses. - */ -static struct resource * -nexus_alloc_resource(device_t bus, device_t child, int type, int *rid, - u_long start, u_long end, u_long count, u_int flags) -{ - struct nexus_softc *sc; - struct resource *rv; - - if (type != SYS_RES_IRQ) { - device_printf(bus, "unknown resource request from %s\n", - device_get_nameunit(child)); - return (NULL); - } - - if (count == 0 || start + count - 1 != end) { - device_printf(bus, "invalid IRQ allocation from %s\n", - device_get_nameunit(child)); - return (NULL); - } - - sc = device_get_softc(bus); - - rv = rman_reserve_resource(&sc->sc_rman, start, end, count, - flags, child); - if (rv == NULL) { - device_printf(bus, "IRQ allocation failed for %s\n", - device_get_nameunit(child)); - } else - rman_set_rid(rv, *rid); - - return (rv); -} - -static int -nexus_activate_resource(device_t bus, device_t child, int type, int rid, - struct resource *res) -{ - - /* Not much to be done yet... */ - return (rman_activate_resource(res)); -} - -static int -nexus_deactivate_resource(device_t bus, device_t child, int type, int rid, - struct resource *res) -{ - - /* Not much to be done yet... */ - return (rman_deactivate_resource(res)); -} - -static int -nexus_release_resource(device_t bus, device_t child, int type, int rid, - struct resource *res) -{ - - if (type != SYS_RES_IRQ) { - device_printf(bus, "unknown resource request from %s\n", - device_get_nameunit(child)); - return (EINVAL); - } - - return (rman_release_resource(res)); -} - -static device_t -nexus_device_from_node(device_t parent, phandle_t node) -{ - device_t cdev; - struct nexus_devinfo *dinfo; - char *name, *type, *compatible; - - OF_getprop_alloc(node, "name", 1, (void **)&name); - OF_getprop_alloc(node, "device_type", 1, (void **)&type); - OF_getprop_alloc(node, "compatible", 1, (void **)&compatible); - cdev = device_add_child(parent, NULL, -1); - if (cdev != NULL) { - dinfo = malloc(sizeof(*dinfo), M_NEXUS, M_WAITOK); - dinfo->ndi_node = node; - dinfo->ndi_name = name; - dinfo->ndi_device_type = type; - dinfo->ndi_compatible = compatible; - device_set_ivars(cdev, dinfo); - } else - free(name, M_OFWPROP); - - return (cdev); -} - -static const char * -nexus_ofw_get_name(device_t bus, device_t dev) -{ - struct nexus_devinfo *dinfo; - - if ((dinfo = device_get_ivars(dev)) == NULL) - return (NULL); - - return (dinfo->ndi_name); -} - -static phandle_t -nexus_ofw_get_node(device_t bus, device_t dev) -{ - struct nexus_devinfo *dinfo; - - if ((dinfo = device_get_ivars(dev)) == NULL) - return (0); - - return (dinfo->ndi_node); -} - -static const char * -nexus_ofw_get_type(device_t bus, device_t dev) -{ - struct nexus_devinfo *dinfo; - - if ((dinfo = device_get_ivars(dev)) == NULL) - return (NULL); - - return (dinfo->ndi_device_type); -} - -static const char * -nexus_ofw_get_compat(device_t bus, device_t dev) -{ - struct nexus_devinfo *dinfo; - - if ((dinfo = device_get_ivars(dev)) == NULL) - return (NULL); - - return (dinfo->ndi_compatible); -} diff --git a/sys/powerpc/powerpc/ofw_machdep.c b/sys/powerpc/powerpc/ofw_machdep.c deleted file mode 100644 index d63236f..0000000 --- a/sys/powerpc/powerpc/ofw_machdep.c +++ /dev/null @@ -1,436 +0,0 @@ -/*- - * Copyright (C) 1996 Wolfgang Solfrank. - * Copyright (C) 1996 TooLs GmbH. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by TooLs GmbH. - * 4. The name of TooLs GmbH may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $NetBSD: ofw_machdep.c,v 1.5 2000/05/23 13:25:43 tsubai Exp $ - */ - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <sys/param.h> -#include <sys/bus.h> -#include <sys/systm.h> -#include <sys/conf.h> -#include <sys/disk.h> -#include <sys/fcntl.h> -#include <sys/malloc.h> -#include <sys/stat.h> - -#include <net/ethernet.h> - -#include <dev/ofw/openfirm.h> -#include <dev/ofw/ofw_pci.h> - -#include <vm/vm.h> -#include <vm/vm_param.h> -#include <vm/vm_page.h> - -#include <machine/bus.h> -#include <machine/md_var.h> -#include <machine/powerpc.h> -#include <machine/ofw_machdep.h> -#include <powerpc/ofw/ofw_pci.h> - -#define OFMEM_REGIONS 32 -static struct mem_region OFmem[OFMEM_REGIONS + 1], OFavail[OFMEM_REGIONS + 3]; -static struct mem_region OFfree[OFMEM_REGIONS + 3]; - -extern register_t ofmsr[5]; -extern struct pcpu __pcpu[MAXCPU]; -extern struct pmap ofw_pmap; -static int (*ofwcall)(void *); - -/* - * Saved SPRG0-3 from OpenFirmware. Will be restored prior to the callback. - */ -register_t ofw_sprg0_save; - -static __inline void -ofw_sprg_prepare(void) -{ - /* - * Assume that interrupt are disabled at this point, or - * SPRG1-3 could be trashed - */ - __asm __volatile("mfsprg0 %0\n\t" - "mtsprg0 %1\n\t" - "mtsprg1 %2\n\t" - "mtsprg2 %3\n\t" - "mtsprg3 %4\n\t" - : "=&r"(ofw_sprg0_save) - : "r"(ofmsr[1]), - "r"(ofmsr[2]), - "r"(ofmsr[3]), - "r"(ofmsr[4])); -} - -static __inline void -ofw_sprg_restore(void) -{ - /* - * Note that SPRG1-3 contents are irrelevant. They are scratch - * registers used in the early portion of trap handling when - * interrupts are disabled. - * - * PCPU data cannot be used until this routine is called ! - */ - __asm __volatile("mtsprg0 %0" :: "r"(ofw_sprg0_save)); -} - -/* - * Memory region utilities: determine if two regions overlap, - * and merge two overlapping regions into one - */ -static int -memr_overlap(struct mem_region *r1, struct mem_region *r2) -{ - if ((r1->mr_start + r1->mr_size) < r2->mr_start || - (r2->mr_start + r2->mr_size) < r1->mr_start) - return (FALSE); - - return (TRUE); -} - -static void -memr_merge(struct mem_region *from, struct mem_region *to) -{ - int end; - end = imax(to->mr_start + to->mr_size, from->mr_start + from->mr_size); - to->mr_start = imin(from->mr_start, to->mr_start); - to->mr_size = end - to->mr_start; -} - -/* - * This is called during powerpc_init, before the system is really initialized. - * It shall provide the total and the available regions of RAM. - * Both lists must have a zero-size entry as terminator. - * The available regions need not take the kernel into account, but needs - * to provide space for two additional entry beyond the terminating one. - */ -void -mem_regions(struct mem_region **memp, int *memsz, - struct mem_region **availp, int *availsz) -{ - int phandle; - int asz, msz, fsz; - int i, j; - int still_merging; - - /* - * Get memory. - */ - if ((phandle = OF_finddevice("/memory")) == -1 - || (msz = OF_getprop(phandle, "reg", - OFmem, sizeof OFmem[0] * OFMEM_REGIONS)) - <= 0 - || (asz = OF_getprop(phandle, "available", - OFavail, sizeof OFavail[0] * OFMEM_REGIONS)) - <= 0) - panic("no memory?"); - *memp = OFmem; - *memsz = msz / sizeof(struct mem_region); - - /* - * OFavail may have overlapping regions - collapse these - * and copy out remaining regions to OFfree - */ - asz /= sizeof(struct mem_region); - do { - still_merging = FALSE; - for (i = 0; i < asz; i++) { - if (OFavail[i].mr_size == 0) - continue; - for (j = i+1; j < asz; j++) { - if (OFavail[j].mr_size == 0) - continue; - if (memr_overlap(&OFavail[j], &OFavail[i])) { - memr_merge(&OFavail[j], &OFavail[i]); - /* mark inactive */ - OFavail[j].mr_size = 0; - still_merging = TRUE; - } - } - } - } while (still_merging == TRUE); - - /* evict inactive ranges */ - for (i = 0, fsz = 0; i < asz; i++) { - if (OFavail[i].mr_size != 0) { - OFfree[fsz] = OFavail[i]; - fsz++; - } - } - - *availp = OFfree; - *availsz = fsz; -} - -void -set_openfirm_callback(int (*openfirm)(void *)) -{ - - ofwcall = openfirm; -} - -int -openfirmware(void *args) -{ - long oldmsr; - int result; - u_int srsave[16]; - u_int i; - - __asm __volatile( "\t" - "sync\n\t" - "mfmsr %0\n\t" - "mtmsr %1\n\t" - "isync\n" - : "=r" (oldmsr) - : "r" (ofmsr[0]) - ); - - ofw_sprg_prepare(); - - if (pmap_bootstrapped) { - /* - * Swap the kernel's address space with Open Firmware's - */ - for (i = 0; i < 16; i++) { - srsave[i] = mfsrin(i << ADDR_SR_SHFT); - mtsrin(i << ADDR_SR_SHFT, ofw_pmap.pm_sr[i]); - } - - /* - * Clear battable[] translations - */ - __asm __volatile("mtdbatu 2, %0\n" - "mtdbatu 3, %0" : : "r" (0)); - isync(); - } - - result = ofwcall(args); - - if (pmap_bootstrapped) { - /* - * Restore the kernel's addr space. The isync() doesn;t - * work outside the loop unless mtsrin() is open-coded - * in an asm statement :( - */ - for (i = 0; i < 16; i++) { - mtsrin(i << ADDR_SR_SHFT, srsave[i]); - isync(); - } - } - - ofw_sprg_restore(); - - __asm( "\t" - "mtmsr %0\n\t" - "isync\n" - : : "r" (oldmsr) - ); - - return (result); -} - -void -OF_halt() -{ - int retval; /* dummy, this may not be needed */ - - OF_interpret("shut-down", 1, &retval); - for (;;); /* just in case */ -} - -void -OF_reboot() -{ - int retval; /* dummy, this may not be needed */ - - OF_interpret("reset-all", 1, &retval); - for (;;); /* just in case */ -} - -void -OF_getetheraddr(device_t dev, u_char *addr) -{ - phandle_t node; - - node = ofw_pci_find_node(dev); - OF_getprop(node, "local-mac-address", addr, ETHER_ADDR_LEN); -} - -/* - * Return a bus handle and bus tag that corresponds to the register - * numbered regno for the device referenced by the package handle - * dev. This function is intended to be used by console drivers in - * early boot only. It works by mapping the address of the device's - * register in the address space of its parent and recursively walk - * the device tree upward this way. - */ -static void -OF_get_addr_props(phandle_t node, uint32_t *addrp, uint32_t *sizep, int *pcip) -{ - char name[16]; - uint32_t addr, size; - int pci, res; - - res = OF_getprop(node, "#address-cells", &addr, sizeof(addr)); - if (res == -1) - addr = 2; - res = OF_getprop(node, "#size-cells", &size, sizeof(size)); - if (res == -1) - size = 1; - pci = 0; - if (addr == 3 && size == 2) { - res = OF_getprop(node, "name", name, sizeof(name)); - if (res != -1) { - name[sizeof(name) - 1] = '\0'; - pci = (strcmp(name, "pci") == 0) ? 1 : 0; - } - } - if (addrp != NULL) - *addrp = addr; - if (sizep != NULL) - *sizep = size; - if (pcip != NULL) - *pcip = pci; -} - -int -OF_decode_addr(phandle_t dev, int regno, bus_space_tag_t *tag, - bus_space_handle_t *handle) -{ - uint32_t cell[32]; - bus_addr_t addr, raddr, baddr; - bus_size_t size, rsize; - uint32_t c, nbridge, naddr, nsize; - phandle_t bridge, parent; - u_int spc, rspc; - int pci, pcib, res; - - /* Sanity checking. */ - if (dev == 0) - return (EINVAL); - bridge = OF_parent(dev); - if (bridge == 0) - return (EINVAL); - if (regno < 0) - return (EINVAL); - if (tag == NULL || handle == NULL) - return (EINVAL); - - /* Get the requested register. */ - OF_get_addr_props(bridge, &naddr, &nsize, &pci); - res = OF_getprop(dev, (pci) ? "assigned-addresses" : "reg", - cell, sizeof(cell)); - if (res == -1) - return (ENXIO); - if (res % sizeof(cell[0])) - return (ENXIO); - res /= sizeof(cell[0]); - regno *= naddr + nsize; - if (regno + naddr + nsize > res) - return (EINVAL); - spc = (pci) ? cell[regno] & OFW_PCI_PHYS_HI_SPACEMASK : ~0; - addr = 0; - for (c = 0; c < naddr; c++) - addr = ((uint64_t)addr << 32) | cell[regno++]; - size = 0; - for (c = 0; c < nsize; c++) - size = ((uint64_t)size << 32) | cell[regno++]; - - /* - * Map the address range in the bridge's decoding window as given - * by the "ranges" property. If a node doesn't have such property - * then no mapping is done. - */ - parent = OF_parent(bridge); - while (parent != 0) { - OF_get_addr_props(parent, &nbridge, NULL, &pcib); - res = OF_getprop(bridge, "ranges", cell, sizeof(cell)); - if (res == -1) - goto next; - if (res % sizeof(cell[0])) - return (ENXIO); - res /= sizeof(cell[0]); - regno = 0; - while (regno < res) { - rspc = (pci) - ? cell[regno] & OFW_PCI_PHYS_HI_SPACEMASK - : ~0; - if (rspc != spc) { - regno += naddr + nbridge + nsize; - continue; - } - raddr = 0; - for (c = 0; c < naddr; c++) - raddr = ((uint64_t)raddr << 32) | cell[regno++]; - rspc = (pcib) - ? cell[regno] & OFW_PCI_PHYS_HI_SPACEMASK - : ~0; - baddr = 0; - for (c = 0; c < nbridge; c++) - baddr = ((uint64_t)baddr << 32) | cell[regno++]; - rsize = 0; - for (c = 0; c < nsize; c++) - rsize = ((uint64_t)rsize << 32) | cell[regno++]; - if (addr < raddr || addr >= raddr + rsize) - continue; - addr = addr - raddr + baddr; - if (rspc != ~0) - spc = rspc; - } - - next: - bridge = parent; - parent = OF_parent(bridge); - OF_get_addr_props(bridge, &naddr, &nsize, &pci); - } - - /* Default to memory mapped I/O. */ - *tag = PPC_BUS_SPACE_MEM; - if (spc == OFW_PCI_PHYS_HI_SPACE_IO) - *tag = PPC_BUS_SPACE_IO; - return (bus_space_map(*tag, addr, size, 0, handle)); -} - -int -mem_valid(vm_offset_t addr, int len) -{ - int i; - - for (i = 0; i < OFMEM_REGIONS; i++) - if ((addr >= OFmem[i].mr_start) - && (addr + len < OFmem[i].mr_start + OFmem[i].mr_size)) - return (0); - - return (EFAULT); -} diff --git a/sys/powerpc/powerpc/ofwmagic.S b/sys/powerpc/powerpc/ofwmagic.S deleted file mode 100644 index 55af6d2..0000000 --- a/sys/powerpc/powerpc/ofwmagic.S +++ /dev/null @@ -1,75 +0,0 @@ -/* $FreeBSD$ */ -/* $NetBSD: ofwmagic.S,v 1.2 1997/10/09 08:38:18 jtc Exp $ */ - -/*- - * Copyright (c) 1997 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Jason R. Thorpe. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the NetBSD - * Foundation, Inc. and its contributors. - * 4. Neither the name of The NetBSD Foundation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * Magic note section used by Open Firmware. - */ - - .section ".note" - - /*# note header */ - - /*# length of name */ - .long 8 - - /*# note descriptor size */ - .long 20 - - /*# note type (IEEE 1275) */ - .long 0x1275 - - /*# name of owner */ - .asciz "PowerPC" - .balign 4 - - - /*# note descriptor */ - - /*# real mode (-1) or virtual mode (0) */ - .long 0 - - /*# real-base */ - .long -1 - /*# real-size */ - .long -1 - - /*# virt-base */ - .long -1 - /*# virt-size */ - .long -1 diff --git a/sys/powerpc/powerpc/swtch.S b/sys/powerpc/powerpc/swtch.S deleted file mode 100644 index 1a09d87..0000000 --- a/sys/powerpc/powerpc/swtch.S +++ /dev/null @@ -1,158 +0,0 @@ -/* $FreeBSD$ */ -/* $NetBSD: locore.S,v 1.24 2000/05/31 05:09:17 thorpej Exp $ */ - -/*- - * Copyright (C) 2001 Benno Rice - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY Benno Rice ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ -/*- - * Copyright (C) 1995, 1996 Wolfgang Solfrank. - * Copyright (C) 1995, 1996 TooLs GmbH. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by TooLs GmbH. - * 4. The name of TooLs GmbH may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "assym.s" - -#include <sys/syscall.h> - -#include <machine/trap.h> -#include <machine/param.h> -#include <machine/sr.h> -#include <machine/psl.h> -#include <machine/asm.h> - -/* - * void cpu_switch(struct thread *old, - * struct thread *new, - * struct mutex *mtx); - * - * Switch to a new thread saving the current state in the old thread. - */ -ENTRY(cpu_switch) - stw %r5,TD_LOCK(%r3) /* ULE: update old thread's lock */ - /* XXX needs to change for MP */ - - lwz %r5,TD_PCB(%r3) /* Get the old thread's PCB ptr */ - mr %r12,%r2 - stmw %r12,PCB_CONTEXT(%r5) /* Save the non-volatile GP regs. - These can now be used for scratch */ - - mfcr %r16 /* Save the condition register */ - stw %r16,PCB_CR(%r5) - mflr %r16 /* Save the link register */ - stw %r16,PCB_LR(%r5) - mfsr %r16,USER_SR /* Save USER_SR for copyin/out */ - isync - stw %r16,PCB_USR(%r5) - stw %r1,PCB_SP(%r5) /* Save the stack pointer */ - - mr %r14,%r3 /* Copy the old thread ptr... */ - mr %r15,%r4 /* and the new thread ptr in scratch */ - - lwz %r6,PCB_FLAGS(%r5) /* Save FPU context if needed */ - andi. %r6, %r6, PCB_FPU - beq .L1 - bl save_fpu - mr %r3,%r14 /* restore old thread ptr */ -.L1: - bl pmap_deactivate /* Deactivate the current pmap */ - - mr %r3,%r15 /* Get new thread ptr */ - bl pmap_activate /* Activate the new address space */ - - mfsprg %r7,0 /* Get the pcpu pointer */ - stw %r15,PC_CURTHREAD(%r7) /* Store new current thread */ - lwz %r17,TD_PCB(%r15) /* Store new current PCB */ - stw %r17,PC_CURPCB(%r7) - - lwz %r6, PCB_FLAGS(%r17) /* Restore FPU context if needed */ - andi. %r6, %r6, PCB_FPU - beq .L2 - mr %r3,%r15 /* Pass curthread to enable_fpu */ - bl enable_fpu - - /* thread to restore is in r3 */ -.L2: - mr %r3,%r17 /* Recover PCB ptr */ - lmw %r12,PCB_CONTEXT(%r3) /* Load the non-volatile GP regs */ - mr %r2,%r12 - lwz %r5,PCB_CR(%r3) /* Load the condition register */ - mtcr %r5 - lwz %r5,PCB_LR(%r3) /* Load the link register */ - mtlr %r5 - lwz %r5,PCB_USR(%r3) /* Load the USER_SR segment reg */ - mtsr USER_SR,%r5 - isync - lwz %r1,PCB_SP(%r3) /* Load the stack pointer */ - blr - -/* - * savectx(pcb) - * Update pcb, saving current processor state - */ -ENTRY(savectx) - mr %r12,%r2 - stmw %r12,PCB_CONTEXT(%r3) /* Save the non-volatile GP regs */ - mfcr %r4 /* Save the condition register */ - stw %r4,PCB_CONTEXT(%r3) - blr - -/* - * fork_trampoline() - * Set up the return from cpu_fork() - */ -ENTRY(fork_trampoline) - lwz %r3,CF_FUNC(%r1) - lwz %r4,CF_ARG0(%r1) - lwz %r5,CF_ARG1(%r1) - bl fork_exit - addi %r1,%r1,CF_SIZE-FSP /* Allow 8 bytes in front of - trapframe to simulate FRAME_SETUP - does when allocating space for - a frame pointer/saved LR */ - b trapexit diff --git a/sys/powerpc/powerpc/trap.c b/sys/powerpc/powerpc/trap.c deleted file mode 100644 index b691a65..0000000 --- a/sys/powerpc/powerpc/trap.c +++ /dev/null @@ -1,681 +0,0 @@ -/*- - * Copyright (C) 1995, 1996 Wolfgang Solfrank. - * Copyright (C) 1995, 1996 TooLs GmbH. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by TooLs GmbH. - * 4. The name of TooLs GmbH may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $NetBSD: trap.c,v 1.58 2002/03/04 04:07:35 dbj Exp $ - */ - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include "opt_ktrace.h" - -#include <sys/param.h> -#include <sys/kdb.h> -#include <sys/proc.h> -#include <sys/ktr.h> -#include <sys/lock.h> -#include <sys/mutex.h> -#include <sys/pioctl.h> -#include <sys/ptrace.h> -#include <sys/reboot.h> -#include <sys/syscall.h> -#include <sys/sysent.h> -#include <sys/systm.h> -#include <sys/uio.h> -#include <sys/signalvar.h> -#ifdef KTRACE -#include <sys/ktrace.h> -#endif -#include <sys/vmmeter.h> - -#include <security/audit/audit.h> - -#include <vm/vm.h> -#include <vm/pmap.h> -#include <vm/vm_extern.h> -#include <vm/vm_param.h> -#include <vm/vm_kern.h> -#include <vm/vm_map.h> -#include <vm/vm_page.h> - -#include <machine/cpu.h> -#include <machine/db_machdep.h> -#include <machine/fpu.h> -#include <machine/frame.h> -#include <machine/pcb.h> -#include <machine/pmap.h> -#include <machine/psl.h> -#include <machine/trap.h> -#include <machine/spr.h> -#include <machine/sr.h> - -static void trap_fatal(struct trapframe *frame); -static void printtrap(u_int vector, struct trapframe *frame, int isfatal, - int user); -static int trap_pfault(struct trapframe *frame, int user); -static int fix_unaligned(struct thread *td, struct trapframe *frame); -static int handle_onfault(struct trapframe *frame); -static void syscall(struct trapframe *frame); - -static __inline void setusr(u_int); - -int setfault(faultbuf); /* defined in locore.S */ - -/* Why are these not defined in a header? */ -int badaddr(void *, size_t); -int badaddr_read(void *, size_t, int *); - -extern char *syscallnames[]; - -struct powerpc_exception { - u_int vector; - char *name; -}; - -static struct powerpc_exception powerpc_exceptions[] = { - { 0x0100, "system reset" }, - { 0x0200, "machine check" }, - { 0x0300, "data storage interrupt" }, - { 0x0400, "instruction storage interrupt" }, - { 0x0500, "external interrupt" }, - { 0x0600, "alignment" }, - { 0x0700, "program" }, - { 0x0800, "floating-point unavailable" }, - { 0x0900, "decrementer" }, - { 0x0c00, "system call" }, - { 0x0d00, "trace" }, - { 0x0e00, "floating-point assist" }, - { 0x0f00, "performance monitoring" }, - { 0x0f20, "altivec unavailable" }, - { 0x1000, "instruction tlb miss" }, - { 0x1100, "data load tlb miss" }, - { 0x1200, "data store tlb miss" }, - { 0x1300, "instruction breakpoint" }, - { 0x1400, "system management" }, - { 0x1600, "altivec assist" }, - { 0x1700, "thermal management" }, - { 0x2000, "run mode/trace" }, - { 0x3000, NULL } -}; - -static const char * -trapname(u_int vector) -{ - struct powerpc_exception *pe; - - for (pe = powerpc_exceptions; pe->vector != 0x3000; pe++) { - if (pe->vector == vector) - return (pe->name); - } - - return ("unknown"); -} - -void -trap(struct trapframe *frame) -{ - struct thread *td; - struct proc *p; - int sig, type, user; - u_int ucode; - ksiginfo_t ksi; - - PCPU_INC(cnt.v_trap); - - td = PCPU_GET(curthread); - p = td->td_proc; - - type = ucode = frame->exc; - sig = 0; - user = frame->srr1 & PSL_PR; - - CTR3(KTR_TRAP, "trap: %s type=%s (%s)", td->td_name, - trapname(type), user ? "user" : "kernel"); - - if (user) { - td->td_pticks = 0; - td->td_frame = frame; - if (td->td_ucred != p->p_ucred) - cred_update_thread(td); - - /* User Mode Traps */ - switch (type) { - case EXC_RUNMODETRC: - case EXC_TRC: - frame->srr1 &= ~PSL_SE; - sig = SIGTRAP; - break; - - case EXC_DSI: - case EXC_ISI: - sig = trap_pfault(frame, 1); - break; - - case EXC_SC: - syscall(frame); - break; - - case EXC_FPU: - KASSERT((td->td_pcb->pcb_flags & PCB_FPU) != PCB_FPU, - ("FPU already enabled for thread")); - enable_fpu(td); - break; - -#ifdef ALTIVEC - case EXC_VEC: - if ((vecthread = PCPU_GET(vecthread)) != NULL) { - KASSERT(vecthread != td, - ("altivec already enabled")); - save_vec(vecthread); - } - PCPU_SET(vecthread, td); - td->td_pcb->pcb_veccpu = PCPU_GET(cpuid); - enable_vec(td); - frame->srr1 |= PSL_VEC; - break; -#else - case EXC_VEC: - case EXC_VECAST: - sig = SIGILL; - break; -#endif /* ALTIVEC */ - - case EXC_ALI: - if (fix_unaligned(td, frame) != 0) - sig = SIGBUS; - else - frame->srr0 += 4; - break; - - case EXC_PGM: - /* XXX temporarily */ - /* XXX: Magic Number? */ - if (frame->srr1 & 0x0002000) - sig = SIGTRAP; - else - sig = SIGILL; - break; - - default: - trap_fatal(frame); - } - } else { - /* Kernel Mode Traps */ - - KASSERT(cold || td->td_ucred != NULL, - ("kernel trap doesn't have ucred")); - switch (type) { - case EXC_DSI: - if (trap_pfault(frame, 0) == 0) - return; - break; - case EXC_MCHK: - if (handle_onfault(frame)) - return; - break; - default: - break; - } - trap_fatal(frame); - } - -#ifdef ALTIVEC - if (td != PCPU_GET(vecthread) || - td->td_pcb->pcb_veccpu != PCPU_GET(cpuid)) - frame->srr1 &= ~PSL_VEC; -#endif /* ALTIVEC */ - - if (sig != 0) { - if (p->p_sysent->sv_transtrap != NULL) - sig = (p->p_sysent->sv_transtrap)(sig, type); - ksiginfo_init_trap(&ksi); - ksi.ksi_signo = sig; - ksi.ksi_code = (int) ucode; /* XXX, not POSIX */ - /* ksi.ksi_addr = ? */ - ksi.ksi_trapno = type; - trapsignal(td, &ksi); - } - - userret(td, frame); - mtx_assert(&Giant, MA_NOTOWNED); -} - -static void -trap_fatal(struct trapframe *frame) -{ - - printtrap(frame->exc, frame, 1, (frame->srr1 & PSL_PR)); -#ifdef KDB - if ((debugger_on_panic || kdb_active) && - kdb_trap(frame->exc, 0, frame)) - return; -#endif - panic("%s trap", trapname(frame->exc)); -} - -static void -printtrap(u_int vector, struct trapframe *frame, int isfatal, int user) -{ - - printf("\n"); - printf("%s %s trap:\n", isfatal ? "fatal" : "handled", - user ? "user" : "kernel"); - printf("\n"); - printf(" exception = 0x%x (%s)\n", vector >> 8, - trapname(vector)); - switch (vector) { - case EXC_DSI: - printf(" virtual address = 0x%x\n", frame->dar); - break; - case EXC_ISI: - printf(" virtual address = 0x%x\n", frame->srr0); - break; - } - printf(" srr0 = 0x%x\n", frame->srr0); - printf(" srr1 = 0x%x\n", frame->srr1); - printf(" curthread = %p\n", curthread); - if (curthread != NULL) - printf(" pid = %d, comm = %s\n", - curthread->td_proc->p_pid, curthread->td_name); - printf("\n"); -} - -/* - * Handles a fatal fault when we have onfault state to recover. Returns - * non-zero if there was onfault recovery state available. - */ -static int -handle_onfault(struct trapframe *frame) -{ - struct thread *td; - faultbuf *fb; - - td = curthread; - fb = td->td_pcb->pcb_onfault; - if (fb != NULL) { - frame->srr0 = (*fb)[0]; - frame->fixreg[1] = (*fb)[1]; - frame->fixreg[2] = (*fb)[2]; - frame->fixreg[3] = 1; - frame->cr = (*fb)[3]; - bcopy(&(*fb)[4], &frame->fixreg[13], - 19 * sizeof(register_t)); - return (1); - } - return (0); -} - -void -syscall(struct trapframe *frame) -{ - caddr_t params; - struct sysent *callp; - struct thread *td; - struct proc *p; - int error, n; - size_t narg; - register_t args[10]; - u_int code; - - td = PCPU_GET(curthread); - p = td->td_proc; - - PCPU_INC(cnt.v_syscall); - -#ifdef KSE - if (p->p_flag & P_SA) - thread_user_enter(td); -#endif - - code = frame->fixreg[0]; - params = (caddr_t)(frame->fixreg + FIRSTARG); - n = NARGREG; - - if (p->p_sysent->sv_prepsyscall) { - /* - * The prep code is MP aware. - */ - (*p->p_sysent->sv_prepsyscall)(frame, args, &code, ¶ms); - } else if (code == SYS_syscall) { - /* - * code is first argument, - * followed by actual args. - */ - code = *(u_int *) params; - params += sizeof(register_t); - n -= 1; - } else if (code == SYS___syscall) { - /* - * Like syscall, but code is a quad, - * so as to maintain quad alignment - * for the rest of the args. - */ - params += sizeof(register_t); - code = *(u_int *) params; - params += sizeof(register_t); - n -= 2; - } - - if (p->p_sysent->sv_mask) - code &= p->p_sysent->sv_mask; - - if (code >= p->p_sysent->sv_size) - callp = &p->p_sysent->sv_table[0]; - else - callp = &p->p_sysent->sv_table[code]; - - narg = callp->sy_narg; - - if (narg > n) { - bcopy(params, args, n * sizeof(register_t)); - error = copyin(MOREARGS(frame->fixreg[1]), args + n, - (narg - n) * sizeof(register_t)); - params = (caddr_t)args; - } else - error = 0; - - CTR5(KTR_SYSC, "syscall: p=%s %s(%x %x %x)", td->td_name, - syscallnames[code], - frame->fixreg[FIRSTARG], - frame->fixreg[FIRSTARG+1], - frame->fixreg[FIRSTARG+2]); - -#ifdef KTRACE - if (KTRPOINT(td, KTR_SYSCALL)) - ktrsyscall(code, narg, (register_t *)params); -#endif - - td->td_syscalls++; - - if (error == 0) { - td->td_retval[0] = 0; - td->td_retval[1] = frame->fixreg[FIRSTARG + 1]; - - STOPEVENT(p, S_SCE, narg); - - PTRACESTOP_SC(p, td, S_PT_SCE); - - AUDIT_SYSCALL_ENTER(code, td); - error = (*callp->sy_call)(td, params); - AUDIT_SYSCALL_EXIT(error, td); - - CTR3(KTR_SYSC, "syscall: p=%s %s ret=%x", td->td_name, - syscallnames[code], td->td_retval[0]); - } - switch (error) { - case 0: - if (frame->fixreg[0] == SYS___syscall && - code != SYS_freebsd6_lseek && code != SYS_lseek) { - /* - * 64-bit return, 32-bit syscall. Fixup byte order - */ - frame->fixreg[FIRSTARG] = 0; - frame->fixreg[FIRSTARG + 1] = td->td_retval[0]; - } else { - frame->fixreg[FIRSTARG] = td->td_retval[0]; - frame->fixreg[FIRSTARG + 1] = td->td_retval[1]; - } - /* XXX: Magic number */ - frame->cr &= ~0x10000000; - break; - case ERESTART: - /* - * Set user's pc back to redo the system call. - */ - frame->srr0 -= 4; - break; - case EJUSTRETURN: - /* nothing to do */ - break; - default: - if (p->p_sysent->sv_errsize) { - if (error >= p->p_sysent->sv_errsize) - error = -1; /* XXX */ - else - error = p->p_sysent->sv_errtbl[error]; - } - frame->fixreg[FIRSTARG] = error; - /* XXX: Magic number: Carry Flag Equivalent? */ - frame->cr |= 0x10000000; - break; - } - - /* - * Check for misbehavior. - */ - WITNESS_WARN(WARN_PANIC, NULL, "System call %s returning", - (code >= 0 && code < SYS_MAXSYSCALL) ? syscallnames[code] : "???"); - KASSERT(td->td_critnest == 0, - ("System call %s returning in a critical section", - (code >= 0 && code < SYS_MAXSYSCALL) ? syscallnames[code] : "???")); - KASSERT(td->td_locks == 0, - ("System call %s returning with %d locks held", - (code >= 0 && code < SYS_MAXSYSCALL) ? syscallnames[code] : "???", - td->td_locks)); - -#ifdef KTRACE - if (KTRPOINT(td, KTR_SYSRET)) - ktrsysret(code, error, td->td_retval[0]); -#endif - - /* - * Does the comment in the i386 code about errno apply here? - */ - STOPEVENT(p, S_SCX, code); - - PTRACESTOP_SC(p, td, S_PT_SCX); -} - -static int -trap_pfault(struct trapframe *frame, int user) -{ - vm_offset_t eva, va; - struct thread *td; - struct proc *p; - vm_map_t map; - vm_prot_t ftype; - int rv; - u_int user_sr; - - td = curthread; - p = td->td_proc; - if (frame->exc == EXC_ISI) { - eva = frame->srr0; - ftype = VM_PROT_READ | VM_PROT_EXECUTE; - } else { - eva = frame->dar; - if (frame->dsisr & DSISR_STORE) - ftype = VM_PROT_WRITE; - else - ftype = VM_PROT_READ; - } - - if (user) { - map = &p->p_vmspace->vm_map; - } else { - if ((eva >> ADDR_SR_SHFT) == USER_SR) { - if (p->p_vmspace == NULL) - return (SIGSEGV); - - __asm ("mfsr %0, %1" - : "=r"(user_sr) - : "K"(USER_SR)); - eva &= ADDR_PIDX | ADDR_POFF; - eva |= user_sr << ADDR_SR_SHFT; - map = &p->p_vmspace->vm_map; - } else { - map = kernel_map; - } - } - va = trunc_page(eva); - - if (map != kernel_map) { - /* - * Keep swapout from messing with us during this - * critical time. - */ - PROC_LOCK(p); - ++p->p_lock; - PROC_UNLOCK(p); - - /* Fault in the user page: */ - rv = vm_fault(map, va, ftype, - (ftype & VM_PROT_WRITE) ? VM_FAULT_DIRTY - : VM_FAULT_NORMAL); - - PROC_LOCK(p); - --p->p_lock; - PROC_UNLOCK(p); - } else { - /* - * Don't have to worry about process locking or stacks in the - * kernel. - */ - rv = vm_fault(map, va, ftype, VM_FAULT_NORMAL); - } - - if (rv == KERN_SUCCESS) - return (0); - - if (!user && handle_onfault(frame)) - return (0); - - return (SIGSEGV); -} - -static __inline void -setusr(u_int content) -{ - __asm __volatile ("isync; mtsr %0,%1; isync" - :: "n"(USER_SR), "r"(content)); -} - -int -badaddr(void *addr, size_t size) -{ - return (badaddr_read(addr, size, NULL)); -} - -int -badaddr_read(void *addr, size_t size, int *rptr) -{ - struct thread *td; - faultbuf env; - int x; - - /* Get rid of any stale machine checks that have been waiting. */ - __asm __volatile ("sync; isync"); - - td = PCPU_GET(curthread); - - if (setfault(env)) { - td->td_pcb->pcb_onfault = 0; - __asm __volatile ("sync"); - return 1; - } - - __asm __volatile ("sync"); - - switch (size) { - case 1: - x = *(volatile int8_t *)addr; - break; - case 2: - x = *(volatile int16_t *)addr; - break; - case 4: - x = *(volatile int32_t *)addr; - break; - default: - panic("badaddr: invalid size (%d)", size); - } - - /* Make sure we took the machine check, if we caused one. */ - __asm __volatile ("sync; isync"); - - td->td_pcb->pcb_onfault = 0; - __asm __volatile ("sync"); /* To be sure. */ - - /* Use the value to avoid reorder. */ - if (rptr) - *rptr = x; - - return (0); -} - -/* - * For now, this only deals with the particular unaligned access case - * that gcc tends to generate. Eventually it should handle all of the - * possibilities that can happen on a 32-bit PowerPC in big-endian mode. - */ - -static int -fix_unaligned(struct thread *td, struct trapframe *frame) -{ - struct thread *fputhread; - int indicator, reg; - double *fpr; - - indicator = EXC_ALI_OPCODE_INDICATOR(frame->dsisr); - - switch (indicator) { - case EXC_ALI_LFD: - case EXC_ALI_STFD: - reg = EXC_ALI_RST(frame->dsisr); - fpr = &td->td_pcb->pcb_fpu.fpr[reg]; - fputhread = PCPU_GET(fputhread); - - /* Juggle the FPU to ensure that we've initialized - * the FPRs, and that their current state is in - * the PCB. - */ - if (fputhread != td) { - if (fputhread) - save_fpu(fputhread); - enable_fpu(td); - } - save_fpu(td); - - if (indicator == EXC_ALI_LFD) { - if (copyin((void *)frame->dar, fpr, - sizeof(double)) != 0) - return -1; - enable_fpu(td); - } else { - if (copyout(fpr, (void *)frame->dar, - sizeof(double)) != 0) - return -1; - } - return 0; - break; - } - - return -1; -} diff --git a/sys/powerpc/powerpc/trap_subr.S b/sys/powerpc/powerpc/trap_subr.S deleted file mode 100644 index 06ed891..0000000 --- a/sys/powerpc/powerpc/trap_subr.S +++ /dev/null @@ -1,540 +0,0 @@ -/* $FreeBSD$ */ -/* $NetBSD: trap_subr.S,v 1.20 2002/04/22 23:20:08 kleink Exp $ */ - -/*- - * Copyright (C) 1995, 1996 Wolfgang Solfrank. - * Copyright (C) 1995, 1996 TooLs GmbH. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by TooLs GmbH. - * 4. The name of TooLs GmbH may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * NOTICE: This is not a standalone file. to use it, #include it in - * your port's locore.S, like so: - * - * #include <powerpc/powerpc/trap_subr.S> - */ - -/* - * Save/restore segment registers - */ -#define RESTORE_SRS(pmap,sr) mtsr 0,sr; \ - lwz sr,1*4(pmap); mtsr 1,sr; \ - lwz sr,2*4(pmap); mtsr 2,sr; \ - lwz sr,3*4(pmap); mtsr 3,sr; \ - lwz sr,4*4(pmap); mtsr 4,sr; \ - lwz sr,5*4(pmap); mtsr 5,sr; \ - lwz sr,6*4(pmap); mtsr 6,sr; \ - lwz sr,7*4(pmap); mtsr 7,sr; \ - lwz sr,8*4(pmap); mtsr 8,sr; \ - lwz sr,9*4(pmap); mtsr 9,sr; \ - lwz sr,10*4(pmap); mtsr 10,sr; \ - lwz sr,11*4(pmap); mtsr 11,sr; \ - lwz sr,12*4(pmap); mtsr 12,sr; \ - lwz sr,13*4(pmap); mtsr 13,sr; \ - lwz sr,14*4(pmap); mtsr 14,sr; \ - lwz sr,15*4(pmap); mtsr 15,sr; isync; - -/* - * User SRs are loaded through a pointer to the current pmap. - */ -#define RESTORE_USER_SRS(pmap,sr) \ - GET_CPUINFO(pmap); \ - lwz pmap,PC_CURPMAP(pmap); \ - lwzu sr,PM_SR(pmap); \ - RESTORE_SRS(pmap,sr) - -/* - * Kernel SRs are loaded directly from kernel_pmap_ - */ -#define RESTORE_KERN_SRS(pmap,sr) \ - lis pmap,CNAME(kernel_pmap_store)@ha; \ - lwzu sr,CNAME(kernel_pmap_store)+PM_SR@l(pmap); \ - RESTORE_SRS(pmap,sr) - -/* - * FRAME_SETUP assumes: - * SPRG1 SP (1) - * savearea r28-r31,DAR,DSISR (DAR & DSISR only for DSI traps) - * r28 LR - * r29 CR - * r30 scratch - * r31 scratch - * r1 kernel stack - * LR trap type (from calling address, mask with 0xff00) - * SRR0/1 as at start of trap - */ -#define FRAME_SETUP(savearea) \ -/* Have to enable translation to allow access of kernel stack: */ \ - GET_CPUINFO(%r31); \ - mfsrr0 %r30; \ - stw %r30,(savearea+CPUSAVE_SRR0)(%r31); /* save SRR0 */ \ - mfsrr1 %r30; \ - stw %r30,(savearea+CPUSAVE_SRR1)(%r31); /* save SRR1 */ \ - mfmsr %r30; \ - ori %r30,%r30,(PSL_DR|PSL_IR|PSL_RI)@l; /* relocation on */ \ - mtmsr %r30; /* stack can now be accessed */ \ - isync; \ - mfsprg1 %r31; /* get saved SP */ \ - stwu %r31,-FRAMELEN(%r1); /* save it in the callframe */ \ - stw %r0, FRAME_0+8(%r1); /* save r0 in the trapframe */ \ - stw %r31,FRAME_1+8(%r1); /* save SP " " */ \ - stw %r2, FRAME_2+8(%r1); /* save r2 " " */ \ - stw %r28,FRAME_LR+8(%r1); /* save LR " " */ \ - stw %r29,FRAME_CR+8(%r1); /* save CR " " */ \ - GET_CPUINFO(%r2); \ - lwz %r28,(savearea+CPUSAVE_R28)(%r2); /* get saved r28 */ \ - lwz %r29,(savearea+CPUSAVE_R29)(%r2); /* get saved r29 */ \ - lwz %r30,(savearea+CPUSAVE_R30)(%r2); /* get saved r30 */ \ - lwz %r31,(savearea+CPUSAVE_R31)(%r2); /* get saved r31 */ \ - stw %r3, FRAME_3+8(%r1); /* save r3-r31 */ \ - stw %r4, FRAME_4+8(%r1); \ - stw %r5, FRAME_5+8(%r1); \ - stw %r6, FRAME_6+8(%r1); \ - stw %r7, FRAME_7+8(%r1); \ - stw %r8, FRAME_8+8(%r1); \ - stw %r9, FRAME_9+8(%r1); \ - stw %r10, FRAME_10+8(%r1); \ - stw %r11, FRAME_11+8(%r1); \ - stw %r12, FRAME_12+8(%r1); \ - stw %r13, FRAME_13+8(%r1); \ - stw %r14, FRAME_14+8(%r1); \ - stw %r15, FRAME_15+8(%r1); \ - stw %r16, FRAME_16+8(%r1); \ - stw %r17, FRAME_17+8(%r1); \ - stw %r18, FRAME_18+8(%r1); \ - stw %r19, FRAME_19+8(%r1); \ - stw %r20, FRAME_20+8(%r1); \ - stw %r21, FRAME_21+8(%r1); \ - stw %r22, FRAME_22+8(%r1); \ - stw %r23, FRAME_23+8(%r1); \ - stw %r24, FRAME_24+8(%r1); \ - stw %r25, FRAME_25+8(%r1); \ - stw %r26, FRAME_26+8(%r1); \ - stw %r27, FRAME_27+8(%r1); \ - stw %r28, FRAME_28+8(%r1); \ - stw %r29, FRAME_29+8(%r1); \ - stw %r30, FRAME_30+8(%r1); \ - stw %r31, FRAME_31+8(%r1); \ - lwz %r28,(savearea+CPUSAVE_DAR)(%r2); /* saved DAR */ \ - lwz %r29,(savearea+CPUSAVE_DSISR)(%r2);/* saved DSISR */ \ - lwz %r30,(savearea+CPUSAVE_SRR0)(%r2); /* saved SRR0 */ \ - lwz %r31,(savearea+CPUSAVE_SRR1)(%r2); /* saved SRR1 */ \ - mfxer %r3; \ - mfctr %r4; \ - mflr %r5; \ - andi. %r5,%r5,0xff00; /* convert LR to exc # */ \ - stw %r3, FRAME_XER+8(1); /* save xer/ctr/exc */ \ - stw %r4, FRAME_CTR+8(1); \ - stw %r5, FRAME_EXC+8(1); \ - stw %r28,FRAME_DAR+8(1); \ - stw %r29,FRAME_DSISR+8(1); /* save dsisr/srr0/srr1 */ \ - stw %r30,FRAME_SRR0+8(1); \ - stw %r31,FRAME_SRR1+8(1) - -#define FRAME_LEAVE(savearea) \ -/* Now restore regs: */ \ - lwz %r2,FRAME_SRR0+8(%r1); \ - lwz %r3,FRAME_SRR1+8(%r1); \ - lwz %r4,FRAME_CTR+8(%r1); \ - lwz %r5,FRAME_XER+8(%r1); \ - lwz %r6,FRAME_LR+8(%r1); \ - GET_CPUINFO(%r7); \ - stw %r2,(savearea+CPUSAVE_SRR0)(%r7); /* save SRR0 */ \ - stw %r3,(savearea+CPUSAVE_SRR1)(%r7); /* save SRR1 */ \ - lwz %r7,FRAME_CR+8(%r1); \ - mtctr %r4; \ - mtxer %r5; \ - mtlr %r6; \ - mtsprg1 %r7; /* save cr */ \ - lwz %r31,FRAME_31+8(%r1); /* restore r0-31 */ \ - lwz %r30,FRAME_30+8(%r1); \ - lwz %r29,FRAME_29+8(%r1); \ - lwz %r28,FRAME_28+8(%r1); \ - lwz %r27,FRAME_27+8(%r1); \ - lwz %r26,FRAME_26+8(%r1); \ - lwz %r25,FRAME_25+8(%r1); \ - lwz %r24,FRAME_24+8(%r1); \ - lwz %r23,FRAME_23+8(%r1); \ - lwz %r22,FRAME_22+8(%r1); \ - lwz %r21,FRAME_21+8(%r1); \ - lwz %r20,FRAME_20+8(%r1); \ - lwz %r19,FRAME_19+8(%r1); \ - lwz %r18,FRAME_18+8(%r1); \ - lwz %r17,FRAME_17+8(%r1); \ - lwz %r16,FRAME_16+8(%r1); \ - lwz %r15,FRAME_15+8(%r1); \ - lwz %r14,FRAME_14+8(%r1); \ - lwz %r13,FRAME_13+8(%r1); \ - lwz %r12,FRAME_12+8(%r1); \ - lwz %r11,FRAME_11+8(%r1); \ - lwz %r10,FRAME_10+8(%r1); \ - lwz %r9, FRAME_9+8(%r1); \ - lwz %r8, FRAME_8+8(%r1); \ - lwz %r7, FRAME_7+8(%r1); \ - lwz %r6, FRAME_6+8(%r1); \ - lwz %r5, FRAME_5+8(%r1); \ - lwz %r4, FRAME_4+8(%r1); \ - lwz %r3, FRAME_3+8(%r1); \ - lwz %r2, FRAME_2+8(%r1); \ - lwz %r0, FRAME_0+8(%r1); \ - lwz %r1, FRAME_1+8(%r1); \ -/* Can't touch %r1 from here on */ \ - mtsprg2 %r2; /* save r2 & r3 */ \ - mtsprg3 %r3; \ -/* Disable translation, machine check and recoverability: */ \ - mfmsr %r2; \ - andi. %r2,%r2,~(PSL_DR|PSL_IR|PSL_EE|PSL_ME|PSL_RI)@l; \ - mtmsr %r2; \ - isync; \ -/* Decide whether we return to user mode: */ \ - GET_CPUINFO(%r2); \ - lwz %r3,(savearea+CPUSAVE_SRR1)(%r2); \ - mtcr %r3; \ - bf 17,1f; /* branch if PSL_PR is false */ \ -/* Restore user SRs */ \ - RESTORE_USER_SRS(%r2,%r3); \ -1: mfsprg1 %r2; /* restore cr */ \ - mtcr %r2; \ - GET_CPUINFO(%r2); \ - lwz %r3,(savearea+CPUSAVE_SRR0)(%r2); /* restore srr0 */ \ - mtsrr0 %r3; \ - lwz %r3,(savearea+CPUSAVE_SRR1)(%r2); /* restore srr1 */ \ - mtsrr1 %r3; \ - mfsprg2 %r2; /* restore r2 & r3 */ \ - mfsprg3 %r3 - -#ifdef KDB -/* - * Define the kdb debugger stack - */ - .data -GLOBAL(dbstk) - .space INTSTK+8 /* kdb stack */ -#endif - -/* - * This code gets copied to all the trap vectors - * (except ISI/DSI, ALI, and the interrupts) - */ - .text - .globl CNAME(trapcode),CNAME(trapsize) -CNAME(trapcode): - mtsprg1 %r1 /* save SP */ - GET_CPUINFO(%r1) - stw %r28,(PC_TEMPSAVE+CPUSAVE_R28)(%r1) /* free r28-r31 */ - stw %r29,(PC_TEMPSAVE+CPUSAVE_R29)(%r1) - stw %r30,(PC_TEMPSAVE+CPUSAVE_R30)(%r1) - stw %r31,(PC_TEMPSAVE+CPUSAVE_R31)(%r1) - mfsprg1 %r1 /* restore SP, in case of branch */ - mflr %r28 /* save LR */ - mfcr %r29 /* save CR */ -/* Test whether we already had PR set */ - mfsrr1 %r31 - mtcr %r31 - bla s_trap /* LR & 0xff00 is exception # */ -CNAME(trapsize) = .-CNAME(trapcode) - -/* - * For ALI: has to save DSISR and DAR - */ - .globl CNAME(alitrap),CNAME(alisize) -CNAME(alitrap): - mtsprg1 %r1 /* save SP */ - GET_CPUINFO(%r1) - stw %r28,(PC_TEMPSAVE+CPUSAVE_R28)(%r1) /* free r28-r31 */ - stw %r29,(PC_TEMPSAVE+CPUSAVE_R29)(%r1) - stw %r30,(PC_TEMPSAVE+CPUSAVE_R30)(%r1) - stw %r31,(PC_TEMPSAVE+CPUSAVE_R31)(%r1) - mfdar %r30 - mfdsisr %r31 - stw %r30,(PC_TEMPSAVE+CPUSAVE_DAR)(%r1) - stw %r31,(PC_TEMPSAVE+CPUSAVE_DSISR)(%r1) - mfsprg1 %r1 /* restore SP, in case of branch */ - mflr %r28 /* save LR */ - mfcr %r29 /* save CR */ -/* Test whether we already had PR set */ - mfsrr1 %r31 - mtcr %r31 - bla s_trap /* LR & 0xff00 is exception # */ -CNAME(alisize) = .-CNAME(alitrap) - -/* - * Similar to the above for DSI - * Has to handle BAT spills - * and standard pagetable spills - */ - .globl CNAME(dsitrap),CNAME(dsisize) -CNAME(dsitrap): - mtsprg1 %r1 /* save SP */ - GET_CPUINFO(%r1) - stw %r28,(PC_DISISAVE+CPUSAVE_R28)(%r1) /* free r28-r31 */ - stw %r29,(PC_DISISAVE+CPUSAVE_R29)(%r1) - stw %r30,(PC_DISISAVE+CPUSAVE_R30)(%r1) - stw %r31,(PC_DISISAVE+CPUSAVE_R31)(%r1) - mfsprg1 %r1 /* restore SP */ - mfcr %r29 /* save CR */ - mfxer %r30 /* save XER */ - mtsprg2 %r30 /* in SPRG2 */ - mfsrr1 %r31 /* test kernel mode */ - mtcr %r31 - bt 17,1f /* branch if PSL_PR is set */ - mfdar %r31 /* get fault address */ - rlwinm %r31,%r31,7,25,28 /* get segment * 8 */ - - /* get batu */ - addis %r31,%r31,CNAME(battable)@ha - lwz %r30,CNAME(battable)@l(31) - mtcr %r30 - bf 30,1f /* branch if supervisor valid is - false */ - /* get batl */ - lwz %r31,CNAME(battable)+4@l(31) -/* We randomly use the highest two bat registers here */ - mftb %r28 - andi. %r28,%r28,1 - bne 2f - mtdbatu 2,%r30 - mtdbatl 2,%r31 - b 3f -2: - mtdbatu 3,%r30 - mtdbatl 3,%r31 -3: - mfsprg2 %r30 /* restore XER */ - mtxer %r30 - mtcr %r29 /* restore CR */ - mtsprg1 %r1 - GET_CPUINFO(%r1) - lwz %r28,(PC_DISISAVE+CPUSAVE_R28)(%r1) /* restore r28-r31 */ - lwz %r29,(PC_DISISAVE+CPUSAVE_R29)(%r1) - lwz %r30,(PC_DISISAVE+CPUSAVE_R30)(%r1) - lwz %r31,(PC_DISISAVE+CPUSAVE_R31)(%r1) - mfsprg1 %r1 - rfi /* return to trapped code */ -1: - mflr %r28 /* save LR (SP already saved) */ - bla disitrap -CNAME(dsisize) = .-CNAME(dsitrap) - -/* - * Preamble code for DSI/ISI traps - */ -disitrap: - GET_CPUINFO(%r1) - lwz %r30,(PC_DISISAVE+CPUSAVE_R28)(%r1) - stw %r30,(PC_TEMPSAVE+CPUSAVE_R28)(%r1) - lwz %r31,(PC_DISISAVE+CPUSAVE_R29)(%r1) - stw %r31,(PC_TEMPSAVE+CPUSAVE_R29)(%r1) - lwz %r30,(PC_DISISAVE+CPUSAVE_R30)(%r1) - stw %r30,(PC_TEMPSAVE+CPUSAVE_R30)(%r1) - lwz %r31,(PC_DISISAVE+CPUSAVE_R31)(%r1) - stw %r31,(PC_TEMPSAVE+CPUSAVE_R31)(%r1) - mfdar %r30 - mfdsisr %r31 - stw %r30,(PC_TEMPSAVE+CPUSAVE_DAR)(%r1) - stw %r31,(PC_TEMPSAVE+CPUSAVE_DSISR)(%r1) - -#ifdef KDB - /* Try and detect a kernel stack overflow */ - mfsrr1 %r31 - mtcr %r31 - bt 17,realtrap /* branch is user mode */ - mfsprg1 %r31 /* get old SP */ - sub. %r30,%r31,%r30 /* SP - DAR */ - bge 1f - neg %r30,%r30 /* modulo value */ -1: cmplwi %cr0,%r30,4096 /* is DAR within a page of SP? */ - bge %cr0,realtrap /* no, too far away. */ - - /* Now convert this DSI into a DDB trap. */ - GET_CPUINFO(%r1) - lwz %r30,(PC_TEMPSAVE+CPUSAVE_DAR)(%r1) /* get DAR */ - stw %r30,(PC_DBSAVE +CPUSAVE_DAR)(%r1) /* save DAR */ - lwz %r30,(PC_TEMPSAVE+CPUSAVE_DSISR)(%r1) /* get DSISR */ - lwz %r30,(PC_DBSAVE +CPUSAVE_DSISR)(%r1) /* save DSISR */ - lwz %r30,(PC_DISISAVE+CPUSAVE_R28)(%r1) /* get r28 */ - stw %r30,(PC_DBSAVE +CPUSAVE_R28)(%r1) /* save r28 */ - lwz %r31,(PC_DISISAVE+CPUSAVE_R29)(%r1) /* get r29 */ - stw %r31,(PC_DBSAVE +CPUSAVE_R29)(%r1) /* save r29 */ - lwz %r30,(PC_DISISAVE+CPUSAVE_R30)(%r1) /* get r30 */ - stw %r30,(PC_DBSAVE +CPUSAVE_R30)(%r1) /* save r30 */ - lwz %r31,(PC_DISISAVE+CPUSAVE_R31)(%r1) /* get r31 */ - stw %r31,(PC_DBSAVE +CPUSAVE_R31)(%r1) /* save r31 */ - lis %r1,dbstk+INTSTK@ha /* get new SP */ - addi %r1,%r1,dbstk+INTSTK@l - b dbtrap -#endif - - /* XXX need stack probe here */ -realtrap: -/* Test whether we already had PR set */ - mfsrr1 %r1 - mtcr %r1 - mfsprg1 %r1 /* restore SP (might have been - overwritten) */ -s_trap: - bf 17,k_trap /* branch if PSL_PR is false */ - GET_CPUINFO(%r1) -u_trap: - lwz %r1,PC_CURPCB(%r1) - RESTORE_KERN_SRS(%r30,%r31) /* enable kernel mapping */ - -/* - * Now the common trap catching code. - */ -k_trap: - FRAME_SETUP(PC_TEMPSAVE) -/* Call C interrupt dispatcher: */ -trapagain: - addi %r3,%r1,8 - bl CNAME(powerpc_interrupt) - .globl CNAME(trapexit) /* backtrace code sentinel */ -CNAME(trapexit): - -/* Disable interrupts: */ - mfmsr %r3 - andi. %r3,%r3,~PSL_EE@l - mtmsr %r3 -/* Test AST pending: */ - lwz %r5,FRAME_SRR1+8(%r1) - mtcr %r5 - bf 17,1f /* branch if PSL_PR is false */ - - GET_CPUINFO(%r3) /* get per-CPU pointer */ - lwz %r4, PC_CURTHREAD(%r3) /* deref to get curthread */ - lwz %r4, TD_FLAGS(%r4) /* get thread flags value */ - lis %r5, (TDF_ASTPENDING|TDF_NEEDRESCHED)@h - ori %r5,%r5, (TDF_ASTPENDING|TDF_NEEDRESCHED)@l - and. %r4,%r4,%r5 - beq 1f - mfmsr %r3 /* re-enable interrupts */ - ori %r3,%r3,PSL_EE@l - mtmsr %r3 - isync - addi %r3,%r1,8 - bl CNAME(ast) - .globl CNAME(asttrapexit) /* backtrace code sentinel #2 */ -CNAME(asttrapexit): - b trapexit /* test ast ret value ? */ -1: - FRAME_LEAVE(PC_TEMPSAVE) - rfi - -/* - * Temporary: vector-unavailable traps are directed to vector-assist traps - */ - .globl CNAME(vectrap),CNAME(vectrapsize) -CNAME(vectrap): - ba EXC_VECAST -CNAME(vectrapsize) = .-CNAME(vectrap) - -#if defined(KDB) -/* - * Deliberate entry to dbtrap - */ - .globl CNAME(ppc_db_trap) -CNAME(ppc_db_trap): - mtsprg1 %r1 - mfmsr %r3 - mtsrr1 %r3 - andi. %r3,%r3,~(PSL_EE|PSL_ME)@l - mtmsr %r3 /* disable interrupts */ - isync - GET_CPUINFO(%r3) - stw %r28,(PC_DBSAVE+CPUSAVE_R28)(%r3) - stw %r29,(PC_DBSAVE+CPUSAVE_R29)(%r3) - stw %r30,(PC_DBSAVE+CPUSAVE_R30)(%r3) - stw %r31,(PC_DBSAVE+CPUSAVE_R31)(%r3) - mflr %r28 - li %r29,EXC_BPT - mtlr %r29 - mfcr %r29 - mtsrr0 %r28 - -/* - * Now the kdb trap catching code. - */ -dbtrap: - FRAME_SETUP(PC_DBSAVE) -/* Call C trap code: */ - addi %r3,%r1,8 - bl CNAME(db_trap_glue) - or. %r3,%r3,%r3 - bne dbleave -/* This wasn't for KDB, so switch to real trap: */ - lwz %r3,FRAME_EXC+8(%r1) /* save exception */ - GET_CPUINFO(%r4) - stw %r3,(PC_DBSAVE+CPUSAVE_R31)(%r4) - FRAME_LEAVE(PC_DBSAVE) - mtsprg1 %r1 /* prepare for entrance to realtrap */ - GET_CPUINFO(%r1) - stw %r28,(PC_TEMPSAVE+CPUSAVE_R28)(%r1) - stw %r29,(PC_TEMPSAVE+CPUSAVE_R29)(%r1) - stw %r30,(PC_TEMPSAVE+CPUSAVE_R30)(%r1) - stw %r31,(PC_TEMPSAVE+CPUSAVE_R31)(%r1) - mflr %r28 - mfcr %r29 - lwz %r31,(PC_DBSAVE+CPUSAVE_R31)(%r1) - mtlr %r31 - mfsprg1 %r1 - b realtrap -dbleave: - FRAME_LEAVE(PC_DBSAVE) - rfi - -/* - * In case of KDB we want a separate trap catcher for it - */ - .globl CNAME(dblow),CNAME(dbsize) -CNAME(dblow): - mtsprg1 %r1 /* save SP */ - mtsprg2 %r29 /* save r29 */ - mfcr %r29 /* save CR in r29 */ - mfsrr1 %r1 - mtcr %r1 - GET_CPUINFO(%r1) - bf 17,1f /* branch if privileged */ - stw %r28,(PC_TEMPSAVE+CPUSAVE_R28)(%r1) /* free r28 */ - mfsprg2 %r28 /* r29 holds cr ... */ - stw %r28,(PC_TEMPSAVE+CPUSAVE_R29)(%r1) /* free r29 */ - stw %r30,(PC_TEMPSAVE+CPUSAVE_R30)(%r1) /* free r30 */ - stw %r31,(PC_TEMPSAVE+CPUSAVE_R31)(%r1) /* free r31 */ - mflr %r28 /* save LR */ - bla u_trap -1: - stw %r28,(PC_DBSAVE+CPUSAVE_R28)(%r1) /* free r28 */ - mfsprg2 %r28 /* r29 holds cr... */ - stw %r28,(PC_DBSAVE+CPUSAVE_R29)(%r1) /* free r29 */ - stw %r30,(PC_DBSAVE+CPUSAVE_R30)(%r1) /* free r30 */ - stw %r31,(PC_DBSAVE+CPUSAVE_R31)(%r1) /* free r31 */ - mflr %r28 /* save LR */ - lis %r1,dbstk+INTSTK@ha /* get new SP */ - addi %r1,%r1,dbstk+INTSTK@l - bla dbtrap -CNAME(dbsize) = .-CNAME(dblow) -#endif /* KDB */ diff --git a/sys/powerpc/powerpc/uio_machdep.c b/sys/powerpc/powerpc/uio_machdep.c deleted file mode 100644 index 070ad98..0000000 --- a/sys/powerpc/powerpc/uio_machdep.c +++ /dev/null @@ -1,124 +0,0 @@ -/*- - * Copyright (c) 2004 Alan L. Cox <alc@cs.rice.edu> - * Copyright (c) 1982, 1986, 1991, 1993 - * The Regents of the University of California. All rights reserved. - * (c) UNIX System Laboratories, Inc. - * All or some portions of this file are derived from material licensed - * to the University of California by American Telephone and Telegraph - * Co. or Unix System Laboratories, Inc. and are reproduced herein with - * the permission of UNIX System Laboratories, Inc. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)kern_subr.c 8.3 (Berkeley) 1/21/94 - */ - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <sys/param.h> -#include <sys/kernel.h> -#include <sys/lock.h> -#include <sys/mutex.h> -#include <sys/proc.h> -#include <sys/systm.h> -#include <sys/uio.h> - -#include <vm/vm.h> -#include <vm/vm_page.h> - -#include <machine/md_var.h> -#include <machine/vmparam.h> - -/* - * Implement uiomove(9) from physical memory using the direct map to - * avoid the creation and destruction of ephemeral mappings. - */ -int -uiomove_fromphys(vm_page_t ma[], vm_offset_t offset, int n, struct uio *uio) -{ - struct thread *td = curthread; - struct iovec *iov; - void *cp; - vm_offset_t page_offset; - size_t cnt; - int error = 0; - int save = 0; - - KASSERT(uio->uio_rw == UIO_READ || uio->uio_rw == UIO_WRITE, - ("uiomove_fromphys: mode")); - KASSERT(uio->uio_segflg != UIO_USERSPACE || uio->uio_td == curthread, - ("uiomove_fromphys proc")); - save = td->td_pflags & TDP_DEADLKTREAT; - td->td_pflags |= TDP_DEADLKTREAT; - while (n > 0 && uio->uio_resid) { - iov = uio->uio_iov; - cnt = iov->iov_len; - if (cnt == 0) { - uio->uio_iov++; - uio->uio_iovcnt--; - continue; - } - if (cnt > n) - cnt = n; - page_offset = offset & PAGE_MASK; - cnt = min(cnt, PAGE_SIZE - page_offset); - cp = (char *)VM_PAGE_TO_PHYS(ma[offset >> PAGE_SHIFT]) + - page_offset; - switch (uio->uio_segflg) { - case UIO_USERSPACE: - if (ticks - PCPU_GET(switchticks) >= hogticks) - uio_yield(); - if (uio->uio_rw == UIO_READ) - error = copyout(cp, iov->iov_base, cnt); - else - error = copyin(iov->iov_base, cp, cnt); - if (error) - goto out; - if (uio->uio_rw == UIO_WRITE && - pmap_page_executable(ma[offset >> PAGE_SHIFT])) - __syncicache(cp, cnt); - break; - case UIO_SYSSPACE: - if (uio->uio_rw == UIO_READ) - bcopy(cp, iov->iov_base, cnt); - else - bcopy(iov->iov_base, cp, cnt); - break; - case UIO_NOCOPY: - break; - } - iov->iov_base = (char *)iov->iov_base + cnt; - iov->iov_len -= cnt; - uio->uio_resid -= cnt; - uio->uio_offset += cnt; - offset += cnt; - n -= cnt; - } -out: - if (save == 0) - td->td_pflags &= ~TDP_DEADLKTREAT; - return (error); -} diff --git a/sys/powerpc/powerpc/uma_machdep.c b/sys/powerpc/powerpc/uma_machdep.c deleted file mode 100644 index 89d092a..0000000 --- a/sys/powerpc/powerpc/uma_machdep.c +++ /dev/null @@ -1,91 +0,0 @@ -/*- - * Copyright (c) 2003 The FreeBSD Project - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <sys/param.h> -#include <sys/kernel.h> -#include <sys/lock.h> -#include <sys/mutex.h> -#include <sys/systm.h> -#include <sys/sysctl.h> -#include <vm/vm.h> -#include <vm/vm_page.h> -#include <vm/vm_pageout.h> -#include <vm/uma.h> -#include <vm/uma_int.h> -#include <machine/vmparam.h> - -static int hw_uma_mdpages; -SYSCTL_INT(_hw, OID_AUTO, uma_mdpages, CTLFLAG_RD, &hw_uma_mdpages, 0, - "UMA MD pages in use"); - -void * -uma_small_alloc(uma_zone_t zone, int bytes, u_int8_t *flags, int wait) -{ - static vm_pindex_t color; - void *va; - vm_page_t m; - int pflags; - - *flags = UMA_SLAB_PRIV; - if ((wait & (M_NOWAIT|M_USE_RESERVE)) == M_NOWAIT) - pflags = VM_ALLOC_INTERRUPT | VM_ALLOC_WIRED; - else - pflags = VM_ALLOC_SYSTEM | VM_ALLOC_WIRED; - if (wait & M_ZERO) - pflags |= VM_ALLOC_ZERO; - - for (;;) { - m = vm_page_alloc(NULL, color++, pflags | VM_ALLOC_NOOBJ); - if (m == NULL) { - if (wait & M_NOWAIT) - return (NULL); - VM_WAIT; - } else - break; - } - - va = (void *) VM_PAGE_TO_PHYS(m); - if ((wait & M_ZERO) && (m->flags & PG_ZERO) == 0) - bzero(va, PAGE_SIZE); - atomic_add_int(&hw_uma_mdpages, 1); - - return (va); -} - -void -uma_small_free(void *mem, int size, u_int8_t flags) -{ - vm_page_t m; - - m = PHYS_TO_VM_PAGE((u_int32_t)mem); - m->wire_count--; - vm_page_free(m); - atomic_subtract_int(&cnt.v_wire_count, 1); - atomic_subtract_int(&hw_uma_mdpages, 1); -} diff --git a/sys/powerpc/powerpc/vm_machdep.c b/sys/powerpc/powerpc/vm_machdep.c deleted file mode 100644 index ce8416a..0000000 --- a/sys/powerpc/powerpc/vm_machdep.c +++ /dev/null @@ -1,369 +0,0 @@ -/*- - * Copyright (c) 1982, 1986 The Regents of the University of California. - * Copyright (c) 1989, 1990 William Jolitz - * Copyright (c) 1994 John Dyson - * All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * the Systems Programming Group of the University of Utah Computer - * Science Department, and William Jolitz. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * from: @(#)vm_machdep.c 7.3 (Berkeley) 5/13/91 - * Utah $Hdr: vm_machdep.c 1.16.1.1 89/06/23$ - * $FreeBSD$ - */ -/*- - * Copyright (c) 1994, 1995, 1996 Carnegie-Mellon University. - * All rights reserved. - * - * Author: Chris G. Demetriou - * - * Permission to use, copy, modify and distribute this software and - * its documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation. - * - * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" - * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND - * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. - * - * Carnegie Mellon requests users of this software to return to - * - * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU - * School of Computer Science - * Carnegie Mellon University - * Pittsburgh PA 15213-3890 - * - * any improvements or extensions that they make and grant Carnegie the - * rights to redistribute these changes. - */ - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/proc.h> -#include <sys/malloc.h> -#include <sys/bio.h> -#include <sys/buf.h> -#include <sys/ktr.h> -#include <sys/lock.h> -#include <sys/mutex.h> -#include <sys/vnode.h> -#include <sys/vmmeter.h> -#include <sys/kernel.h> -#include <sys/mbuf.h> -#include <sys/sf_buf.h> -#include <sys/sysctl.h> -#include <sys/unistd.h> - -#include <machine/cpu.h> -#include <machine/fpu.h> -#include <machine/frame.h> -#include <machine/md_var.h> -#include <machine/pcb.h> -#include <machine/powerpc.h> - -#include <dev/ofw/openfirm.h> - -#include <vm/vm.h> -#include <vm/vm_param.h> -#include <vm/vm_kern.h> -#include <vm/vm_page.h> -#include <vm/vm_map.h> -#include <vm/vm_extern.h> - -/* - * Finish a fork operation, with process p2 nearly set up. - * Copy and update the pcb, set up the stack so that the child - * ready to run and return to user mode. - */ -void -cpu_fork(struct thread *td1, struct proc *p2, struct thread *td2, int flags) -{ - struct proc *p1; - struct trapframe *tf; - struct callframe *cf; - struct pcb *pcb; - - KASSERT(td1 == curthread || td1 == &thread0, - ("cpu_fork: p1 not curproc and not proc0")); - CTR3(KTR_PROC, "cpu_fork: called td1=%08x p2=%08x flags=%x", (u_int)td1, (u_int)p2, flags); - - if ((flags & RFPROC) == 0) - return; - - p1 = td1->td_proc; - - pcb = (struct pcb *)((td2->td_kstack + - td2->td_kstack_pages * PAGE_SIZE - sizeof(struct pcb)) & ~0x2fU); - td2->td_pcb = pcb; - - /* Copy the pcb */ - bcopy(td1->td_pcb, pcb, sizeof(struct pcb)); - - /* - * Create a fresh stack for the new process. - * Copy the trap frame for the return to user mode as if from a - * syscall. This copies most of the user mode register values. - */ - tf = (struct trapframe *)pcb - 1; - bcopy(td1->td_frame, tf, sizeof(*tf)); - - /* Set up trap frame. */ - tf->fixreg[FIRSTARG] = 0; - tf->fixreg[FIRSTARG + 1] = 0; - tf->cr &= ~0x10000000; - - td2->td_frame = tf; - - cf = (struct callframe *)tf - 1; - memset(cf, 0, sizeof(struct callframe)); - cf->cf_func = (register_t)fork_return; - cf->cf_arg0 = (register_t)td2; - cf->cf_arg1 = (register_t)tf; - - pcb->pcb_sp = (register_t)cf; - pcb->pcb_lr = (register_t)fork_trampoline; - pcb->pcb_usr = kernel_pmap->pm_sr[USER_SR]; - - /* Setup to release spin count in fork_exit(). */ - td2->td_md.md_spinlock_count = 1; - td2->td_md.md_saved_msr = PSL_KERNSET; - - /* - * Now cpu_switch() can schedule the new process. - */ -} - -/* - * Intercept the return address from a freshly forked process that has NOT - * been scheduled yet. - * - * This is needed to make kernel threads stay in kernel mode. - */ -void -cpu_set_fork_handler(td, func, arg) - struct thread *td; - void (*func)(void *); - void *arg; -{ - struct callframe *cf; - - CTR3(KTR_PROC, "cpu_set_fork_handler: called with td=%08x func=%08x arg=%08x", - (u_int)td, (u_int)func, (u_int)arg); - - cf = (struct callframe *)td->td_pcb->pcb_sp; - - cf->cf_func = (register_t)func; - cf->cf_arg0 = (register_t)arg; -} - -void -cpu_exit(td) - register struct thread *td; -{ -} - -/* Temporary helper */ -void -cpu_throw(struct thread *old, struct thread *new) -{ - - cpu_switch(old, new, old->td_lock); - panic("cpu_throw() didn't"); -} - -/* - * Reset back to firmware. - */ -void -cpu_reset() -{ - OF_reboot(); -} - -/* - * Allocate an sf_buf for the given vm_page. On this machine, however, there - * is no sf_buf object. Instead, an opaque pointer to the given vm_page is - * returned. - */ -struct sf_buf * -sf_buf_alloc(struct vm_page *m, int pri) -{ - - return ((struct sf_buf *)m); -} - -/* - * Free the sf_buf. In fact, do nothing because there are no resources - * associated with the sf_buf. - */ -void -sf_buf_free(struct sf_buf *sf) -{ -} - -/* - * Software interrupt handler for queued VM system processing. - */ -void -swi_vm(void *dummy) -{ -#if 0 /* XXX: Don't have busdma stuff yet */ - if (busdma_swi_pending != 0) - busdma_swi(); -#endif -} - -/* - * Tell whether this address is in some physical memory region. - * Currently used by the kernel coredump code in order to avoid - * dumping the ``ISA memory hole'' which could cause indefinite hangs, - * or other unpredictable behaviour. - */ - - -int -is_physical_memory(addr) - vm_offset_t addr; -{ - /* - * stuff other tests for known memory-mapped devices (PCI?) - * here - */ - - return 1; -} - -/* - * KSE functions - */ -void -cpu_thread_exit(struct thread *td) -{ -} - -void -cpu_thread_clean(struct thread *td) -{ -} - -void -cpu_thread_alloc(struct thread *td) -{ - struct pcb *pcb; - - pcb = (struct pcb *)((td->td_kstack + td->td_kstack_pages * PAGE_SIZE - - sizeof(struct pcb)) & ~0x2fU); - td->td_pcb = pcb; - td->td_frame = (struct trapframe *)pcb - 1; -} - -void -cpu_thread_free(struct thread *td) -{ -} - -void -cpu_thread_swapin(struct thread *td) -{ -} - -void -cpu_thread_swapout(struct thread *td) -{ -} - -void -cpu_set_upcall(struct thread *td, struct thread *td0) -{ - struct pcb *pcb2; - struct trapframe *tf; - struct callframe *cf; - - pcb2 = td->td_pcb; - - /* Copy the upcall pcb */ - bcopy(td0->td_pcb, pcb2, sizeof(*pcb2)); - - /* Create a stack for the new thread */ - tf = td->td_frame; - bcopy(td0->td_frame, tf, sizeof(struct trapframe)); - tf->fixreg[FIRSTARG] = 0; - tf->fixreg[FIRSTARG + 1] = 0; - tf->cr &= ~0x10000000; - - /* Set registers for trampoline to user mode. */ - cf = (struct callframe *)tf - 1; - memset(cf, 0, sizeof(struct callframe)); - cf->cf_func = (register_t)fork_return; - cf->cf_arg0 = (register_t)td; - cf->cf_arg1 = (register_t)tf; - - pcb2->pcb_sp = (register_t)cf; - pcb2->pcb_lr = (register_t)fork_trampoline; - pcb2->pcb_usr = kernel_pmap->pm_sr[USER_SR]; - - /* Setup to release spin count in fork_exit(). */ - td->td_md.md_spinlock_count = 1; - td->td_md.md_saved_msr = PSL_KERNSET; -} - -void -cpu_set_upcall_kse(struct thread *td, void (*entry)(void *), void *arg, - stack_t *stack) -{ - struct trapframe *tf; - uint32_t sp; - - tf = td->td_frame; - /* align stack and alloc space for frame ptr and saved LR */ - sp = ((uint32_t)stack->ss_sp + stack->ss_size - - 2*sizeof(u_int32_t)) & ~0x1f; - bzero(tf, sizeof(struct trapframe)); - - tf->fixreg[1] = (register_t)sp; - tf->fixreg[3] = (register_t)arg; - tf->srr0 = (register_t)entry; - tf->srr1 = PSL_MBO | PSL_USERSET | PSL_FE_DFLT; - td->td_pcb->pcb_flags = 0; - - td->td_retval[0] = (register_t)entry; - td->td_retval[1] = 0; -} - -int -cpu_set_user_tls(struct thread *td, void *tls_base) -{ - - td->td_frame->fixreg[2] = (register_t)tls_base + 0x7008; - return (0); -} |