diff options
Diffstat (limited to 'sys/arch/solbourne')
74 files changed, 0 insertions, 11311 deletions
diff --git a/sys/arch/solbourne/Makefile b/sys/arch/solbourne/Makefile deleted file mode 100644 index d6e52d62bdc..00000000000 --- a/sys/arch/solbourne/Makefile +++ /dev/null @@ -1,45 +0,0 @@ -# $OpenBSD: Makefile,v 1.8 2013/12/08 14:46:39 espie Exp $ - -S= ${.CURDIR}/../.. -KFILE= GENERIC -.if exists(conf/GENERIC.MP) -KFILE= GENERIC.MP -.endif -TDIRS= ${_arch} include -TAGS= ${.CURDIR}/tags - -NOPROG= -NOMAN= -NOOBJ= -SUBDIR= - -# config the fattest kernel we can find into a temporary dir -# to create a Makefile. Then use make to pull some variables -# out and push them into the sub-shell to expand the paths, -# and finally run ctags. -tags:: - TDIR=`mktemp -d /tmp/_tagXXXXXXXXXX` || exit 1; \ - eval "S=${S}" && \ - config -s ${S} -b $${TDIR} ${.CURDIR}/conf/${KFILE} && \ - eval "_arch=\"`make -V _arch -f $${TDIR}/Makefile`\"" && \ - eval "_mach=\"`make -V _mach -f $${TDIR}/Makefile`\"" && \ - eval "_machdir=\$S/arch/$${_mach}" && \ - eval "_archdir=\$S/arch/$${_arch}" && \ - eval "HFILES=\"`find $S \( -path $S/'arch' -o -path $S/stand -o -path $S/lib/libsa -o -path $S'/lib/libkern/arch' \) -prune -o -name '*.h'; find $${_machdir} $${_archdir} $S/lib/libkern/arch/$${_mach} \( -name boot -o -name stand \) -prune -o -name '*.h'`\"" && \ - eval "SFILES=\"`make -V SFILES -f $${TDIR}/Makefile`\"" && \ - eval "CFILES=\"`make -V CFILES -f $${TDIR}/Makefile`\"" && \ - eval "AFILES=\"`make -V AFILES -f $${TDIR}/Makefile`\"" && \ - ctags -wd -f ${TAGS} $${CFILES} $${HFILES} && \ - egrep "^[_A-Z]*ENTRY[_A-Z]*\(.*\)" $${SFILES} $${AFILES} | \ - sed "s;\\([^:]*\\):\\([^(]*\\)(\\([^, )]*\\)\\(.*\\);\\3 \\1 /^\\2(\\3\\4$$/;" \ - >> ${TAGS} && \ - sort -o ${TAGS} ${TAGS} && \ - rm -rf $${TDIR} - -links: - -for i in conf ${TDIRS}; do \ - (cd $$i && rm -f tags; ln -s tags tags); done - -obj: _SUBDIRUSE - -.include <bsd.prog.mk> diff --git a/sys/arch/solbourne/compile/.cvsignore b/sys/arch/solbourne/compile/.cvsignore deleted file mode 100644 index b72af3039e6..00000000000 --- a/sys/arch/solbourne/compile/.cvsignore +++ /dev/null @@ -1,2 +0,0 @@ -GENERIC -RAMDISK diff --git a/sys/arch/solbourne/conf/GENERIC b/sys/arch/solbourne/conf/GENERIC deleted file mode 100644 index 358de46af88..00000000000 --- a/sys/arch/solbourne/conf/GENERIC +++ /dev/null @@ -1,38 +0,0 @@ -# $OpenBSD: GENERIC,v 1.3 2005/04/30 00:49:36 deraadt Exp $ -# -# For further information on compiling OpenBSD kernels, see the config(8) -# man page. -# -# For further information on hardware support for this architecture, see -# the intro(4) man page. For further information about kernel options -# for this architecture, see the options(4) man page. For an explanation -# of each device driver in this file see the section 4 man page for the -# device. - -machine solbourne sparc -include "../../../conf/GENERIC" -maxusers 32 # estimated number of users - -option SOLBOURNE # necessary for proper config(8) operation - -# Generic swap; second partition of root disk or network. -config bsd swap generic - -# Main bus and CPU .. all systems. -mainbus0 at root -cpu0 at mainbus0 -obio0 at mainbus0 - -# Oki MSM62X42BRS TODclock -tod0 at obio0 - -# Zilog 8530 serial chips. Each has two-channels. -# zs0 is ttya and ttyb. zs1 is the keyboard and mouse. -zs0 at obio0 -zs1 at obio0 - -zstty* at zs? -zsclock0 at zs1 - -# On-board Ethernet -le0 at obio0 diff --git a/sys/arch/solbourne/conf/Makefile.solbourne b/sys/arch/solbourne/conf/Makefile.solbourne deleted file mode 100644 index 1607941a4bc..00000000000 --- a/sys/arch/solbourne/conf/Makefile.solbourne +++ /dev/null @@ -1,168 +0,0 @@ -# $OpenBSD: Makefile.solbourne,v 1.47 2015/01/13 01:12:50 deraadt Exp $ - -# For instructions on building kernels consult the config(8) and options(4) -# manual pages. -# -# N.B.: NO DEPENDENCIES ON FOLLOWING FLAGS ARE VISIBLE TO MAKEFILE -# IF YOU CHANGE THE DEFINITION OF ANY OF THESE RECOMPILE EVERYTHING -# DEBUG is set to -g by config if debugging is requested (config -g). -# PROF is set to -pg by config if profiling is requested (config -p). - -.include <bsd.own.mk> - -SIZE?= size -STRIP?= strip - -# source tree is located via $S relative to the compilation directory -.ifndef S -S!= cd ../../../..; pwd -.endif - -_machdir?= $S/arch/${_mach} -_archdir?= $S/arch/${_arch} - -INCLUDES= -nostdinc -I$S -I. -I$S/arch -CPPFLAGS= ${INCLUDES} ${IDENT} ${PARAM} -D_KERNEL -D__${_mach}__ -MD -MP -CWARNFLAGS= -Werror -Wall -Wimplicit-function-declaration \ - -Wno-main -Wno-uninitialized \ - -Wframe-larger-than=2047 - -CMACHFLAGS= -mno-fpu -CMACHFLAGS+= -fno-builtin-printf -fno-builtin-snprintf \ - -fno-builtin-vsnprintf -fno-builtin-log \ - -fno-builtin-log2 -fno-builtin-malloc ${NOPIE_FLAGS} -.if ${IDENT:M-DNO_PROPOLICE} -CMACHFLAGS+= -fno-stack-protector -.endif - -COPTS?= -O2 -CFLAGS= ${DEBUG} ${CWARNFLAGS} ${CMACHFLAGS} ${COPTS} ${PIPE} -AFLAGS= -D_LOCORE -x assembler-with-cpp ${CWARNFLAGS} ${CMACHFLAGS} -LDSCRIPT= ${_machdir}/conf/ld.script -LINKFLAGS= -N -e start -T ${LDSCRIPT} -Ttext FD084000 --warn-common -nopie - -.if ${IDENT:M-DDDB_STRUCT} -DB_STRUCTINFO= db_structinfo.h -.else -DB_STRUCTINFO= -.endif - -HOSTCC?= ${CC} -HOSTED_CPPFLAGS=${CPPFLAGS:S/^-nostdinc$//} -HOSTED_CFLAGS= ${CFLAGS} -HOSTED_C= ${HOSTCC} ${HOSTED_CFLAGS} ${HOSTED_CPPFLAGS} -c $< - -NORMAL_C_NOP= ${CC} ${CFLAGS} ${CPPFLAGS} -c $< -NORMAL_C= ${CC} ${CFLAGS} ${CPPFLAGS} ${PROF} -c $< -NORMAL_S= ${CC} ${AFLAGS} ${CPPFLAGS} -c $< - -%OBJS - -%CFILES - -%SFILES - -# load lines for config "xxx" will be emitted as: -# xxx: ${SYSTEM_DEP} swapxxx.o -# ${SYSTEM_LD_HEAD} -# ${SYSTEM_LD} swapxxx.o -# ${SYSTEM_LD_TAIL} -SYSTEM_HEAD= locore.o param.o ioconf.o -SYSTEM_OBJ= ${SYSTEM_HEAD} ${OBJS} -SYSTEM_DEP= Makefile ${SYSTEM_OBJ} ${LDSCRIPT} -SYSTEM_LD_HEAD= @rm -f $@ -SYSTEM_LD= @echo ${LD} ${LINKFLAGS} -o $@ '$${SYSTEM_HEAD} vers.o $${OBJS}'; \ - ${LD} ${LINKFLAGS} -o $@ ${SYSTEM_HEAD} vers.o ${OBJS} -SYSTEM_LD_TAIL= @${SIZE} $@; chmod 755 $@ - -DEBUG?= -.if ${DEBUG} == "-g" -LINKFLAGS+= -X -STRIPFLAGS= -g -x -SYSTEM_LD_TAIL+=; \ - echo mv $@ $@.gdb; rm -f $@.gdb; mv $@ $@.gdb; \ - echo ${STRIP} ${STRIPFLAGS} -o $@ $@.gdb; \ - ${STRIP} ${STRIPFLAGS} -o $@ $@.gdb -.else -LINKFLAGS+= -S -x -.endif - -%LOAD - -# cc's -MD puts the source and output paths in the dependency file; -# since those are temp files here we need to fix it up. It also -# puts the file in /tmp, so we use -MF to put it in the current -# directory as assym.P and then generate assym.d from it with a -# good target name -assym.h: $S/kern/genassym.sh Makefile \ - ${_archdir}/${_arch}/genassym.cf ${_machdir}/${_mach}/genassym.cf - cat ${_archdir}/${_arch}/genassym.cf ${_machdir}/${_mach}/genassym.cf | \ - sh $S/kern/genassym.sh ${CC} ${CFLAGS} ${CPPFLAGS} -MF assym.P > assym.h.tmp - sed '1s/.*/assym.h: \\/' assym.P > assym.d - sort -u assym.h.tmp > assym.h - -param.c: $S/conf/param.c - rm -f param.c - cp $S/conf/param.c . - -param.o: param.c Makefile - ${NORMAL_C} - -mcount.o: $S/lib/libkern/mcount.c Makefile - ${NORMAL_C_NOP} - -ioconf.o: ioconf.c - ${NORMAL_C} - -vers.o: ${SYSTEM_DEP} ${SYSTEM_SWAP_DEP} - sh $S/conf/newvers.sh - ${CC} ${CFLAGS} ${CPPFLAGS} ${PROF} -c vers.c - -clean:: - rm -f eddep *bsd *bsd.gdb tags *.[dio] [a-z]*.s \ - [Ee]rrs linterrs assym.h ${DB_STRUCTINFO} - -lint: - @lint -hbxncez -Dvolatile= ${CPPFLAGS} -UKGDB \ - ${CFILES} ioconf.c param.c | \ - grep -v 'static function .* unused' - -depend: - @touch $@ - -tags: - @echo "see $S/kern/Makefile for tags" - -db_structinfo.h: $S/ddb/db_structinfo.c $S/ddb/parse_structinfo.pl - ${CC} ${CFLAGS} ${CPPFLAGS} -MT $@ -gstabs -c $S/ddb/db_structinfo.c - objdump -g db_structinfo.o | perl $S/ddb/parse_structinfo.pl > $@ - rm -f db_structinfo.o - -locore.o: ${_machdir}/${_mach}/locore.s assym.h - -# The install target can be redefined by putting a -# install-kernel-${MACHINE_NAME} target into /etc/mk.conf -MACHINE_NAME!= uname -n -install: install-kernel-${MACHINE_NAME} -.if !target(install-kernel-${MACHINE_NAME}}) -install-kernel-${MACHINE_NAME}: - cmp -s bsd /bsd || ln -f /bsd /obsd - cp bsd /nbsd - mv /nbsd /bsd -.endif - -# pull in the dependency information -.if !empty(DB_STRUCTINFO) && !exists(${DB_STRUCTINFO}) - ${SYSTEM_OBJ}: ${DB_STRUCTINFO} -.endif -.ifnmake clean -. for o in ${SYSTEM_OBJ} assym.h ${DB_STRUCTINFO} -. if exists(${o:R}.d) -. include "${o:R}.d" -. elif exists($o) - .PHONY: $o -. endif -. endfor -.endif - -%RULES diff --git a/sys/arch/solbourne/conf/files.solbourne b/sys/arch/solbourne/conf/files.solbourne deleted file mode 100644 index c6e3b04bea0..00000000000 --- a/sys/arch/solbourne/conf/files.solbourne +++ /dev/null @@ -1,33 +0,0 @@ -# $OpenBSD: files.solbourne,v 1.2 2006/06/19 15:13:35 deraadt Exp $ - -# Kernel configuration rules for OpenBSD/solbourne. -# Most device definitions and files rules are imported from -# sys/arch/sparc/conf/files.sparc and are not repeated here. -# Hence, this file only lists solbourne-specific changes from -# the sparc port. - -maxpartitions 16 - -maxusers 2 8 64 - -# obio on solbourne is just an administrative wrapper on which -# all on-board devices attach. -file arch/solbourne/dev/obio.c obio - -# OKI TODclock chip -device tod -attach tod at obio -file arch/solbourne/dev/tod.c tod - -# Z8530 clock hijack -device zsclock -attach zsclock at zs -file arch/solbourne/dev/zsclock.c zsclock - -file arch/solbourne/solbourne/autoconf.c -file arch/solbourne/solbourne/clock.c -file arch/solbourne/solbourne/machdep.c -file arch/solbourne/solbourne/mem.c -file arch/solbourne/solbourne/pmap.c -file arch/solbourne/solbourne/prom_machdep.c -file arch/solbourne/solbourne/trap.c diff --git a/sys/arch/solbourne/conf/ld.script b/sys/arch/solbourne/conf/ld.script deleted file mode 100644 index 7ba21f5dd27..00000000000 --- a/sys/arch/solbourne/conf/ld.script +++ /dev/null @@ -1,53 +0,0 @@ -/* $OpenBSD: ld.script,v 1.2 2007/04/12 18:36:15 miod Exp $ */ -/* - * Copyright (c) 2005, Miodrag Vallat - * - * 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. - */ - -OUTPUT_FORMAT("a.out-sparc-netbsd") -OUTPUT_ARCH(sparc) -ENTRY(start) -SECTIONS -{ - .text : - { - *(.text) - . = ALIGN(0x2000); - PROVIDE(etext = ABSOLUTE(.)); - } - .data : - { - *(.rodata) - *(.data) - PROVIDE(edata = ABSOLUTE(.)); - } - .bss : - { - *(.bss) - } - PROVIDE(end = ABSOLUTE(.)); - /DISCARD/ : - { - *(.comment) - } -} diff --git a/sys/arch/solbourne/dev/obio.c b/sys/arch/solbourne/dev/obio.c deleted file mode 100644 index 99f1ce5d906..00000000000 --- a/sys/arch/solbourne/dev/obio.c +++ /dev/null @@ -1,142 +0,0 @@ -/* $OpenBSD: obio.c,v 1.1 2005/04/20 01:00:16 miod Exp $ */ -/* OpenBSD: obio.c,v 1.16 2004/09/29 07:35:11 miod Exp */ - -/* - * Copyright (c) 1993, 1994 Theo de Raadt - * Copyright (c) 1995, 1997 Paul Kranenburg - * 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. - */ - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/device.h> - -#include <machine/autoconf.h> -#include <machine/cpu.h> -#include <machine/idt.h> - -/* autoconfiguration driver */ -static int obiomatch(struct device *, void *, void *); -static void obioattach(struct device *, struct device *, void *); - -int obioprint(void *, const char *); -int obio_scan(struct device *, void *, void *); - -struct cfattach obio_ca = { - sizeof(struct device), obiomatch, obioattach -}; - -struct cfdriver obio_cd = { - NULL, "obio", DV_DULL -}; - -/* - * A list of the on-board devices in the IDT systems. This is better than - * having people playing with locators in their kernel configuration - * files, and necessary because the device tree built by the PROM does not - * list all on-board devices (audio and floppy are missing). - */ -const struct { - char *devname; - paddr_t address; - int intr; -} obio_devices[] = { - { "tod", TODCLOCK_BASE, -1 }, - { "nvram", NVRAM_BASE, -1 }, - { "zs", ZS0_BASE, 12 }, - { "zs", ZS1_BASE, 12 }, - { "fdc", FDC_BASE, 11 }, - { "audioamd", AUDIO_BASE, 13 }, - { "wdsc", SE_BASE + 0x20, 4 }, - { "le", SE_BASE + 0x30, 6 }, - { NULL, 0 } -}; - -int -obiomatch(parent, vcf, aux) - struct device *parent; - void *vcf, *aux; -{ - register struct cfdata *cf = vcf; - register struct confargs *ca = aux; - register struct romaux *ra = &ca->ca_ra; - - return (strcmp(cf->cf_driver->cd_name, ra->ra_name) == 0); -} - -int -obioprint(args, obio) - void *args; - const char *obio; -{ - register struct confargs *ca = args; - - if (ca->ca_ra.ra_name == NULL) - ca->ca_ra.ra_name = "<unknown>"; - - if (obio) - printf("%s at %s", ca->ca_ra.ra_name, obio); - - printf(" addr %p", ca->ca_ra.ra_paddr); - - return (UNCONF); -} - -void -obioattach(parent, self, args) - struct device *parent, *self; - void *args; -{ - struct confargs *ca = args; - struct confargs oca; - int i; - - if (self->dv_unit > 0) { - printf(" unsupported\n"); - return; - } - printf("\n"); - - for (i = 0; obio_devices[i].devname != NULL; i++) { - /* fake a rom_reg */ - bzero(&oca, sizeof oca); - oca.ca_ra.ra_paddr = (caddr_t)obio_devices[i].address; - oca.ca_ra.ra_vaddr = NULL; - oca.ca_ra.ra_len = 0; - oca.ca_ra.ra_nreg = 1; - oca.ca_ra.ra_iospace = 0; - oca.ca_ra.ra_intr[0].int_pri = obio_devices[i].intr; - oca.ca_ra.ra_intr[0].int_vec = -1; - oca.ca_ra.ra_nintr = oca.ca_ra.ra_intr[0].int_pri < 0 ? 0 : 1; - oca.ca_ra.ra_name = obio_devices[i].devname; - if (ca->ca_ra.ra_bp != NULL) - oca.ca_ra.ra_bp = ca->ca_ra.ra_bp + 1; - else - oca.ca_ra.ra_bp = NULL; - oca.ca_bustype = BUS_OBIO; - - config_found(self, &oca, obioprint); - } -} diff --git a/sys/arch/solbourne/dev/tod.c b/sys/arch/solbourne/dev/tod.c deleted file mode 100644 index 86f8503bb51..00000000000 --- a/sys/arch/solbourne/dev/tod.c +++ /dev/null @@ -1,236 +0,0 @@ -/* $OpenBSD: tod.c,v 1.1 2005/04/20 01:00:16 miod Exp $ */ -/* - * Copyright (c) 2005, Miodrag Vallat - * - * 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. - */ - -/* - * TODclock driver. We only use it to know the current time during boot, - * as we do not get interrupts from it. - * - * The clock in the IDT machines is the Oki MSM62X42BRS. - * - * A datasheet for this chip is available from: - * http://www.datasheetarchive.com/datasheet/pdf/19/196099.html - */ - -#include <sys/param.h> -#include <sys/kernel.h> -#include <sys/device.h> -#include <sys/systm.h> - -#include <machine/autoconf.h> -#include <machine/cpu.h> - -#include <solbourne/dev/todreg.h> -#include <dev/clock_subr.h> - -#include <machine/idt.h> -#include <machine/kap.h> - -int todmatch(struct device *, void *, void *); -void todattach(struct device *, struct device *, void *); - -struct cfattach tod_ca = { - sizeof(struct device), todmatch, todattach -}; - -struct cfdriver tod_cd = { - NULL, "tod", DV_DULL -}; - -volatile u_char *tod_regs; - -u_char msm_read(u_int); -void msm_write(u_int, u_char); - -int -todmatch(parent, vcf, aux) - struct device *parent; - void *vcf, *aux; -{ - struct confargs *ca = aux; - - return (strcmp(tod_cd.cd_name, ca->ca_ra.ra_name) == 0); -} - -void -todattach(parent, self, aux) - struct device *parent, *self; - void *aux; -{ - printf(": OKI MSM62X42BRS\n"); - - /* the register are already mapped 1:1 by pmap_bootstrap() */ - tod_regs = (volatile u_char *)TODCLOCK_BASE; -} - -/* - * Read or write a register of the Oki clock. - * - * The clock registers are not directly accessible (while control registers - * are). We need to freeze them first. To do so, we set the hold bit in - * D, and if the busy bit clears, we are free to proceed. If the busy bit - * is still set, we need to clear the hold bit and retry. - */ -u_char -msm_read(u_int regno) -{ - u_char d, r; - - /* no need to do the hold dance for control registers */ - if (regno >= MSM_D) - return (tod_regs[regno] & 0x0f); - - d = tod_regs[MSM_D] & 0x0f & ~MSM_D_HOLD; - for (;;) { - tod_regs[MSM_D] = d | MSM_D_HOLD; - if (!ISSET(tod_regs[MSM_D], MSM_D_BUSY)) - break; - tod_regs[MSM_D] = d; - } - - r = tod_regs[regno] & 0x0f; - tod_regs[MSM_D] = d; - - return (r); -} - -void -msm_write(u_int regno, u_char value) -{ - u_char d; - - /* no need to do the hold dance for control registers */ - if (regno >= MSM_D) { - tod_regs[regno] = value; - return; - } - - d = tod_regs[MSM_D] & 0x0f & ~MSM_D_HOLD; - for (;;) { - tod_regs[MSM_D] = d | MSM_D_HOLD; - if (!ISSET(tod_regs[MSM_D], MSM_D_BUSY)) - break; - tod_regs[MSM_D] = d; - } - - tod_regs[regno] = value; - tod_regs[MSM_D] = d; -} - -void -inittodr(base) - time_t base; -{ - struct clock_ymdhms dt; - - dt.dt_sec = msm_read(MSM_SEC_UNITS) + 10 * msm_read(MSM_SEC_TENS); - dt.dt_min = msm_read(MSM_MIN_UNITS) + 10 * msm_read(MSM_MIN_TENS); -#if 0 - dt.dt_hour = msm_read(MSM_HOUR_UNITS) + 10 * msm_read(MSM_HOUR_TENS); -#else - dt.dt_hour = msm_read(MSM_HOUR_TENS); - if (dt.dt_hour & MSM_HOUR_PM) - dt.dt_hour = 12 + 10 * (dt.dt_hour & ~MSM_HOUR_TENS); - else - dt.dt_hour *= 10; - dt.dt_hour += msm_read(MSM_HOUR_UNITS); -#endif - dt.dt_day = msm_read(MSM_DAY_UNITS) + 10 * msm_read(MSM_DAY_TENS); - dt.dt_mon = msm_read(MSM_MONTH_UNITS) + 10 * msm_read(MSM_MONTH_TENS); - dt.dt_year = msm_read(MSM_YEAR_UNITS) + 10 * msm_read(MSM_YEAR_TENS); - dt.dt_year += CLOCK_YEAR_BASE; - /* dt_wday left uninitialized */ - - time.tv_sec = clock_ymdhms_to_secs(&dt); - - if (time.tv_sec == 0) { - /* - * Believe the time in the file system for lack of - * anything better, resetting the clock. - */ - if (base < 35 * SECYR) {/* this port did not exist until 2005 */ - /* - * If base is 0, assume filesystem time is just unknown - * in stead of preposterous. Don't bark. - */ - if (base != 0) - printf("WARNING: preposterous time in file system\n"); - /* not going to use it anyway, if the chip is readable */ - time.tv_sec = 35 * SECYR + 90 * SECDAY + SECDAY / 2; - } else { - printf("WARNING: bad date in battery clock"); - time.tv_sec = base; - resettodr(); - } - } else { - int deltat = time.tv_sec - base; - - if (deltat < 0) - deltat = -deltat; - if (deltat < 2 * SECDAY) - return; - -#ifndef SMALL_KERNEL - printf("WARNING: clock %s %d days", - time.tv_sec < base ? "lost" : "gained", deltat / SECDAY); -#endif - } - printf(" -- CHECK AND RESET THE DATE!\n"); -} - -void -resettodr() -{ - struct clock_ymdhms dt; - - if (time.tv_sec == 0 || tod_regs == NULL) - return; - - clock_secs_to_ymdhms(time.tv_sec, &dt); - - /* - * Since we don't know if the clock is in AM/PM or 24 hour mode, - * we need to reset it and force one mode. Being an evil european - * person, I'll force 24 hour mode, of course. - */ - msm_write(MSM_F, MSM_F_RESET | MSM_F_24HR); - msm_write(MSM_F, MSM_F_STOP); /* leave reset mode, but stop clock */ - - dt.dt_year -= CLOCK_YEAR_BASE; - msm_write(MSM_YEAR_TENS, dt.dt_year / 10); - msm_write(MSM_YEAR_UNITS, dt.dt_year % 10); - msm_write(MSM_MONTH_TENS, dt.dt_mon / 10); - msm_write(MSM_MONTH_UNITS, dt.dt_mon % 10); - msm_write(MSM_DAY_TENS, dt.dt_day / 10); - msm_write(MSM_DAY_UNITS, dt.dt_day % 10); - msm_write(MSM_HOUR_TENS, dt.dt_hour / 10); - msm_write(MSM_HOUR_UNITS, dt.dt_hour % 10); - msm_write(MSM_MIN_TENS, dt.dt_min / 10); - msm_write(MSM_MIN_UNITS, dt.dt_min % 10); - msm_write(MSM_SEC_TENS, dt.dt_sec / 10); - msm_write(MSM_SEC_UNITS, dt.dt_sec % 10); - - msm_write(MSM_F, 0); /* restart clock */ -} diff --git a/sys/arch/solbourne/dev/todreg.h b/sys/arch/solbourne/dev/todreg.h deleted file mode 100644 index 540fdf2f06f..00000000000 --- a/sys/arch/solbourne/dev/todreg.h +++ /dev/null @@ -1,72 +0,0 @@ -/* $OpenBSD: todreg.h,v 1.1 2005/04/20 01:00:16 miod Exp $ */ -/* - * Copyright (c) 2005, Miodrag Vallat - * - * 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. - */ - -/* - * Oki MSM62X42BRS registers. - * - * A datasheet for this chip is available from: - * http://www.datasheetarchive.com/datasheet/pdf/19/196099.html - */ - -#define MSM_REG(x) ((x) << 3) - -#define MSM_SEC_UNITS MSM_REG(0) /* seconds, low digit */ -#define MSM_SEC_TENS MSM_REG(1) /* seconds, high digit */ -#define MSM_MIN_UNITS MSM_REG(2) /* minutes, low digit */ -#define MSM_MIN_TENS MSM_REG(3) /* minutes, high digit */ -#define MSM_HOUR_UNITS MSM_REG(4) /* hours, low digit */ -#define MSM_HOUR_TENS MSM_REG(5) /* hours, high digit */ -#define MSM_HOUR_PM 0x04 /* PM bit if PM mode */ -#define MSM_DAY_UNITS MSM_REG(6) /* day, low digit */ -#define MSM_DAY_TENS MSM_REG(7) /* day, high digit */ -#define MSM_MONTH_UNITS MSM_REG(8) /* month, low digit */ -#define MSM_MONTH_TENS MSM_REG(9) /* month, high digit */ -#define MSM_YEAR_UNITS MSM_REG(10) /* year, low digit */ -#define MSM_YEAR_TENS MSM_REG(11) /* year, high digit */ -#define CLOCK_YEAR_BASE 1968 -#define MSM_DOW MSM_REG(12) /* day of week, 0 = sunday */ - -#define MSM_D MSM_REG(13) /* control register D */ -#define MSM_D_HOLD 0x01 /* hold clock for access */ -#define MSM_D_BUSY 0x02 /* clock is busy */ -#define MSM_D_INTR 0x04 /* interrupt pending */ -#define MSM_D_30 0x08 /* 30 seconds adjustment */ - -#define MSM_E MSM_REG(14) /* control register E */ -#define MSM_E_MASK 0x01 /* output mask (set to disable) */ -#define MSM_E_INTR 0x02 /* output interrupts (1) or pulse (0) */ -#define MSM_E_PERIOD 0x04 /* interrupt (or pulse) period - needs - to be written twice! (2 bits) */ -#define MSM_PERIOD_64HZ 0x00 -#define MSM_PERIOD_1HZ 0x01 -#define MSM_PERIOD_1MIN 0x10 -#define MSM_PERIOD_1HOUR 0x11 - -#define MSM_F MSM_REG(15) /* control register F */ -#define MSM_F_RESET 0x01 /* reset clock */ -#define MSM_F_STOP 0x02 /* stop clock */ -#define MSM_F_24HR 0x04 /* 24 hour mode (valid on reset only) */ -#define MSM_F_TEST 0x08 /* assert test signal */ diff --git a/sys/arch/solbourne/dev/zsclock.c b/sys/arch/solbourne/dev/zsclock.c deleted file mode 100644 index 4b0c19557a0..00000000000 --- a/sys/arch/solbourne/dev/zsclock.c +++ /dev/null @@ -1,192 +0,0 @@ -/* $OpenBSD: zsclock.c,v 1.4 2014/11/18 20:51:01 krw Exp $ */ -/* $NetBSD: clock.c,v 1.11 1995/05/16 07:30:46 phil Exp $ */ - -/*- - * Copyright (c) 1990 The Regents of the University of California. - * All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * William Jolitz and Don Ahn. - * - * 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. - * - * @(#)clock.c 7.2 (Berkeley) 5/12/91 - * - */ - -/* - * Primitive clock interrupt routines. - * - * Improved by Phil Budne ... 10/17/94. - * Pulled over code from i386/isa/clock.c (Matthias Pfaller 12/03/94). - */ - -#include <sys/param.h> -#include <sys/time.h> -#include <sys/kernel.h> -#include <sys/systm.h> -#include <sys/proc.h> -#include <sys/device.h> -#include <sys/conf.h> -#include <sys/ioctl.h> - -#include <dev/ic/z8530reg.h> -#include <machine/z8530var.h> - -#include <machine/autoconf.h> -#include <machine/cpu.h> - -/* - * Zilog Z8530 Dual UART driver (clock interface) - */ - -/* Clock state. */ -struct zsclock_softc { - struct device zsc_dev; - struct zs_chanstate *zsc_cs; -}; - -int zsclock_match(struct device *, void *, void *); -void zsclock_attach(struct device *, struct device *, void *); - -struct cfattach zsclock_ca = { - sizeof(struct zsclock_softc), zsclock_match, zsclock_attach -}; - -struct cfdriver zsclock_cd = { - NULL, "zsclock", DV_DULL -}; - -void zsclock_stint(struct zs_chanstate *, int); - -struct zsops zsops_clock = { - NULL, - zsclock_stint, - NULL, - NULL -}; - -static int zsclock_attached; - -/* - * clock_match: how is this zs channel configured? - */ -int -zsclock_match(struct device *parent, void *match, void *aux) -{ - struct cfdata *cf = match; - struct zsc_attach_args *args = aux; - - /* only attach one instance */ - if (zsclock_attached) - return (0); - - /* make sure we'll win a probe over zstty or zskbd */ - if (cf->cf_loc[ZSCCF_CHANNEL] == args->channel) - return (2 + 2); - - if (cf->cf_loc[ZSCCF_CHANNEL] == ZSCCF_CHANNEL_DEFAULT) - return (2 + 1); - - return (0); -} - -/* - * The Solbourne IDT systems provide a 4.9152 MHz clock to the ZS chips. - */ -#define PCLK (9600 * 512) /* PCLK pin input clock rate */ - -void -zsclock_attach(struct device *parent, struct device *self, void *aux) -{ - struct zsc_softc *zsc = (void *)parent; - struct zsclock_softc *sc = (void *)self; - struct zsc_attach_args *args = aux; - struct zs_chanstate *cs; - int channel; - int reset, s, tconst; - - channel = args->channel; - - cs = &zsc->zsc_cs[channel]; - cs->cs_private = zsc; - cs->cs_ops = &zsops_clock; - - sc->zsc_cs = cs; - - printf("\n"); - - hz = 100; - tconst = ((PCLK / 2) / hz) - 2; - - s = splclock(); - - reset = (channel == 0) ? ZSWR9_A_RESET : ZSWR9_B_RESET; - zs_write_reg(cs, 9, reset); - - cs->cs_preg[1] = 0; - cs->cs_preg[3] = ZSWR3_RX_8 | ZSWR3_RX_ENABLE; - cs->cs_preg[4] = ZSWR4_CLK_X1 | ZSWR4_ONESB | ZSWR4_PARENB; - cs->cs_preg[5] = ZSWR5_TX_8 | ZSWR5_TX_ENABLE; - cs->cs_preg[9] = ZSWR9_MASTER_IE; - cs->cs_preg[10] = 0; - cs->cs_preg[11] = ZSWR11_RXCLK_RTXC | ZSWR11_TXCLK_RTXC | - ZSWR11_TRXC_OUT_ENA | ZSWR11_TRXC_BAUD; - cs->cs_preg[12] = tconst; - cs->cs_preg[13] = tconst >> 8; - cs->cs_preg[14] = ZSWR14_BAUD_FROM_PCLK | ZSWR14_BAUD_ENA; - cs->cs_preg[15] = ZSWR15_ZERO_COUNT_IE; - - zs_loadchannelregs(cs); - - splx(s); - - /* enable interrupts */ - cs->cs_preg[1] |= ZSWR1_SIE; - zs_write_reg(cs, 1, cs->cs_preg[1]); - - zsclock_attached = 1; -} - -void -zsclock_stint(struct zs_chanstate *cs, int force) -{ - u_char rr0; - - rr0 = zs_read_csr(cs); - cs->cs_rr0 = rr0; - - /* - * Retrigger the interrupt as a soft interrupt, because we need - * a trap frame for hardclock(). - */ - ienab_bis(IE_L10); - - zs_write_csr(cs, ZSWR0_RESET_STATUS); -} diff --git a/sys/arch/solbourne/include/_float.h b/sys/arch/solbourne/include/_float.h deleted file mode 100644 index fc0d5fae677..00000000000 --- a/sys/arch/solbourne/include/_float.h +++ /dev/null @@ -1,3 +0,0 @@ -/* $OpenBSD: _float.h,v 1.1 2012/06/26 16:12:45 deraadt Exp $ */ - -#include <sparc/_float.h> diff --git a/sys/arch/solbourne/include/_types.h b/sys/arch/solbourne/include/_types.h deleted file mode 100644 index 8fb97f7b1e0..00000000000 --- a/sys/arch/solbourne/include/_types.h +++ /dev/null @@ -1,3 +0,0 @@ -/* $OpenBSD: _types.h,v 1.2 2013/03/21 02:10:37 deraadt Exp $ */ - -#include <sparc/_types.h> diff --git a/sys/arch/solbourne/include/asm.h b/sys/arch/solbourne/include/asm.h deleted file mode 100644 index 4f19a2ca879..00000000000 --- a/sys/arch/solbourne/include/asm.h +++ /dev/null @@ -1,3 +0,0 @@ -/* $OpenBSD: asm.h,v 1.1 2005/04/19 21:30:17 miod Exp $ */ -/* public domain */ -#include <sparc/asm.h> diff --git a/sys/arch/solbourne/include/atomic.h b/sys/arch/solbourne/include/atomic.h deleted file mode 100644 index 255818f8e0c..00000000000 --- a/sys/arch/solbourne/include/atomic.h +++ /dev/null @@ -1,10 +0,0 @@ -/* $OpenBSD: atomic.h,v 1.3 2011/03/23 16:54:37 pirofti Exp $ */ - -/* Public Domain */ - -#ifndef _MACHINE_ATOMIC_H_ -#define _MACHINE_ATOMIC_H_ - -#include <sparc/atomic.h> - -#endif /* _MACHINE_ATOMIC_H_ */ diff --git a/sys/arch/solbourne/include/autoconf.h b/sys/arch/solbourne/include/autoconf.h deleted file mode 100644 index 286c94b4d1a..00000000000 --- a/sys/arch/solbourne/include/autoconf.h +++ /dev/null @@ -1,3 +0,0 @@ -/* $OpenBSD: autoconf.h,v 1.2 2013/03/21 02:10:37 deraadt Exp $ */ - -#include <sparc/autoconf.h> diff --git a/sys/arch/solbourne/include/bppioctl.h b/sys/arch/solbourne/include/bppioctl.h deleted file mode 100644 index e7825b78a65..00000000000 --- a/sys/arch/solbourne/include/bppioctl.h +++ /dev/null @@ -1,3 +0,0 @@ -/* $OpenBSD: bppioctl.h,v 1.2 2013/03/21 02:10:37 deraadt Exp $ */ - -#include <sparc/bppioctl.h> diff --git a/sys/arch/solbourne/include/bsd_openprom.h b/sys/arch/solbourne/include/bsd_openprom.h deleted file mode 100644 index aa37b7e5b20..00000000000 --- a/sys/arch/solbourne/include/bsd_openprom.h +++ /dev/null @@ -1,3 +0,0 @@ -/* $OpenBSD: bsd_openprom.h,v 1.2 2013/03/21 02:10:37 deraadt Exp $ */ - -#include <sparc/bsd_openprom.h> diff --git a/sys/arch/solbourne/include/bus.h b/sys/arch/solbourne/include/bus.h deleted file mode 100644 index c4ba781eab0..00000000000 --- a/sys/arch/solbourne/include/bus.h +++ /dev/null @@ -1,3 +0,0 @@ -/* $OpenBSD: bus.h,v 1.2 2013/03/21 02:10:37 deraadt Exp $ */ - -#include <sparc/bus.h> diff --git a/sys/arch/solbourne/include/cdefs.h b/sys/arch/solbourne/include/cdefs.h deleted file mode 100644 index 1910212e0d8..00000000000 --- a/sys/arch/solbourne/include/cdefs.h +++ /dev/null @@ -1,3 +0,0 @@ -/* $OpenBSD: cdefs.h,v 1.3 2013/03/21 02:10:37 deraadt Exp $ */ - -#include <sparc/cdefs.h> diff --git a/sys/arch/solbourne/include/conf.h b/sys/arch/solbourne/include/conf.h deleted file mode 100644 index 2b6350ef997..00000000000 --- a/sys/arch/solbourne/include/conf.h +++ /dev/null @@ -1,3 +0,0 @@ -/* $OpenBSD: conf.h,v 1.2 2013/03/21 02:10:37 deraadt Exp $ */ - -#include <sparc/conf.h> diff --git a/sys/arch/solbourne/include/cpu.h b/sys/arch/solbourne/include/cpu.h deleted file mode 100644 index 1f3a883f177..00000000000 --- a/sys/arch/solbourne/include/cpu.h +++ /dev/null @@ -1,3 +0,0 @@ -/* $OpenBSD: cpu.h,v 1.2 2013/03/21 02:10:37 deraadt Exp $ */ - -#include <sparc/cpu.h> diff --git a/sys/arch/solbourne/include/ctlreg.h b/sys/arch/solbourne/include/ctlreg.h deleted file mode 100644 index 7eea08a1a49..00000000000 --- a/sys/arch/solbourne/include/ctlreg.h +++ /dev/null @@ -1,3 +0,0 @@ -/* $OpenBSD: ctlreg.h,v 1.2 2013/03/21 02:10:37 deraadt Exp $ */ - -#include <sparc/ctlreg.h> diff --git a/sys/arch/solbourne/include/db_machdep.h b/sys/arch/solbourne/include/db_machdep.h deleted file mode 100644 index 18625753f3e..00000000000 --- a/sys/arch/solbourne/include/db_machdep.h +++ /dev/null @@ -1,3 +0,0 @@ -/* $OpenBSD: db_machdep.h,v 1.2 2013/03/21 02:10:37 deraadt Exp $ */ - -#include <sparc/db_machdep.h> diff --git a/sys/arch/solbourne/include/disklabel.h b/sys/arch/solbourne/include/disklabel.h deleted file mode 100644 index b666b70a0d2..00000000000 --- a/sys/arch/solbourne/include/disklabel.h +++ /dev/null @@ -1,3 +0,0 @@ -/* $OpenBSD: disklabel.h,v 1.3 2013/03/21 02:10:37 deraadt Exp $ */ - -#include <sparc/disklabel.h> diff --git a/sys/arch/solbourne/include/eeprom.h b/sys/arch/solbourne/include/eeprom.h deleted file mode 100644 index a34c175d266..00000000000 --- a/sys/arch/solbourne/include/eeprom.h +++ /dev/null @@ -1,3 +0,0 @@ -/* $OpenBSD: eeprom.h,v 1.2 2013/03/21 02:10:37 deraadt Exp $ */ - -#include <sparc/eeprom.h> diff --git a/sys/arch/solbourne/include/endian.h b/sys/arch/solbourne/include/endian.h deleted file mode 100644 index d0b2d04fc3a..00000000000 --- a/sys/arch/solbourne/include/endian.h +++ /dev/null @@ -1,3 +0,0 @@ -/* $OpenBSD: endian.h,v 1.2 2013/03/21 02:10:37 deraadt Exp $ */ - -#include <sparc/endian.h> diff --git a/sys/arch/solbourne/include/exec.h b/sys/arch/solbourne/include/exec.h deleted file mode 100644 index db385fc4f92..00000000000 --- a/sys/arch/solbourne/include/exec.h +++ /dev/null @@ -1,3 +0,0 @@ -/* $OpenBSD: exec.h,v 1.2 2013/03/21 02:10:37 deraadt Exp $ */ - -#include <sparc/exec.h> diff --git a/sys/arch/solbourne/include/fbvar.h b/sys/arch/solbourne/include/fbvar.h deleted file mode 100644 index 688e40a6ffb..00000000000 --- a/sys/arch/solbourne/include/fbvar.h +++ /dev/null @@ -1,3 +0,0 @@ -/* $OpenBSD: fbvar.h,v 1.2 2013/03/21 02:10:37 deraadt Exp $ */ - -#include <sparc/fbvar.h> diff --git a/sys/arch/solbourne/include/fenv.h b/sys/arch/solbourne/include/fenv.h deleted file mode 100644 index 37ae677c085..00000000000 --- a/sys/arch/solbourne/include/fenv.h +++ /dev/null @@ -1,3 +0,0 @@ -/* $OpenBSD: fenv.h,v 1.2 2013/06/01 21:20:54 jasper Exp $ */ -/* public domain */ -#include <sparc/fenv.h> diff --git a/sys/arch/solbourne/include/frame.h b/sys/arch/solbourne/include/frame.h deleted file mode 100644 index 7fbd9b2430b..00000000000 --- a/sys/arch/solbourne/include/frame.h +++ /dev/null @@ -1,3 +0,0 @@ -/* $OpenBSD: frame.h,v 1.2 2013/03/21 02:10:37 deraadt Exp $ */ - -#include <sparc/frame.h> diff --git a/sys/arch/solbourne/include/fsr.h b/sys/arch/solbourne/include/fsr.h deleted file mode 100644 index 42028d94dd2..00000000000 --- a/sys/arch/solbourne/include/fsr.h +++ /dev/null @@ -1,3 +0,0 @@ -/* $OpenBSD: fsr.h,v 1.2 2013/03/21 02:10:37 deraadt Exp $ */ - -#include <sparc/fsr.h> diff --git a/sys/arch/solbourne/include/idprom.h b/sys/arch/solbourne/include/idprom.h deleted file mode 100644 index a9bb99fd509..00000000000 --- a/sys/arch/solbourne/include/idprom.h +++ /dev/null @@ -1,3 +0,0 @@ -/* $OpenBSD: idprom.h,v 1.2 2013/03/21 02:10:37 deraadt Exp $ */ - -#include <sparc/idprom.h> diff --git a/sys/arch/solbourne/include/idt.h b/sys/arch/solbourne/include/idt.h deleted file mode 100644 index 6357ca91c8a..00000000000 --- a/sys/arch/solbourne/include/idt.h +++ /dev/null @@ -1,189 +0,0 @@ -/* $OpenBSD: idt.h,v 1.3 2013/03/21 02:10:37 deraadt Exp $ */ - -/* - * Copyright (c) 2005, Miodrag Vallat - * - * 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. - */ - -#ifndef _MACHINE_IDT_H_ -#define _MACHINE_IDT_H_ - -/* - * Definitions for the core chips found on the IDT motherboard. - * - * All addresses are physical. - */ - -/* - * iGLU: GLUE Logic - */ - -#define GLU_BASE 0x60000000 - -/* profiling timer (level 14) */ -#define GLU_L14_DIVISOR 0x60000000 -#define GLU_L14_RESOLUTION (256 / 5) /* in microseconds */ -#define GLU_L14_ENABLE 0x60000008 -#define GLU_L14_IACK 0x6000000c - -/* scheduling timer (level 10) */ -#define GLU_L10_IACK 0x60000800 - -/* board status register */ -#define GLU_BSR 0x60001800 -#define GBSR_LED_MASK 0x07 -#define GBSR_LED_OFF 00 -#define GBSR_LED_AMBER 02 -#define GBSR_LED_AMBER_BLINK 03 -#define GBSR_LED_GREEN 04 -#define GBSR_LED_GREEN_BLINK 05 -#define GBSR_LED_BOTH_BLINK 07 -#define GBSR_DIAG 0x08 -#define GBSR_WARM 0x10 -#define GBSR_NMI 0x20 - -/* board diagnostic register */ -#define GLU_DIAG 0x60001808 -#define GD_EXTRA_MEMORY 0x10 -#define GD_36MHZ 0x20 -#define GD_L2_CACHE 0x40 - -/* interrupt control register */ -#define GLU_ICR 0x60002000 -#define GICR_DISPATCH_MASK 0x0000000f /* post a software interrupt */ -#define GICR_DISABLE_ALL 0x00000010 - -/* programmable interrupt levels for sbus and onboard audio */ -#define GLU_SBUS1 0x60002008 -#define GLU_SBUS2 0x60002010 -#define GLU_SBUS3 0x60002018 -#define GLU_SBUS4 0x60002020 -#define GLU_SBUS5 0x60002028 -#define GLU_SBUS6 0x60002030 -#define GLU_SBUS7 0x60002038 -#define GLU_AUDIO 0x60002040 - -/* reset register */ -#define GLU_RESET 0x60002800 - -/* programmable base for on-board i/o devices */ -#define GLU_IOBASE 0x60003800 - -/* - * iMC: Memory Controller - */ - -#define MC_BASE 0x70000000 - -#define MC0_MCR 0x70000001 -#define MC1_MCR 0x71000001 /* may be missing */ -#define MCR_BANK1_AVAIL 0x08 -#define MCR_BANK0_AVAIL 0x04 -#define MCR_BANK1_32M 0x02 -#define MCR_BANK0_32M 0x01 - -/* - * iCU: DMA and Interrupt Controller - */ - -#define ICU_BASE 0x50000000 - -/* interrupt status register */ -#define ICU_ISR 0x50000000 -#define ISR_S0_DMA_SECC 0x00000001 -#define ISR_S0_DMA_MECC 0x00000002 -#define ISR_S0_DMA_SERR 0x00000004 -#define ISR_S1_DMA_SECC 0x00000008 -#define ISR_S1_DMA_MECC 0x00000010 -#define ISR_S1_DMA_SERR 0x00000020 -#define ISR_S2_DMA_SECC 0x00000040 -#define ISR_S2_DMA_MECC 0x00000080 -#define ISR_S2_DMA_SERR 0x00000100 -#define ISR_EN_DMA_SECC 0x00000200 -#define ISR_EN_DMA_MECC 0x00000400 -#define ISR_EN_DMA_SERR 0x00000800 -#define ISR_SCSI_DMA_SECC 0x00001000 -#define ISR_SCSI_DMA_MECC 0x00002000 -#define ISR_SCSI_DMA_SERR 0x00004000 -#define ISR_RIO_NMI_ENABLE 0x00008000 -#define ISR_DMA_NMI_ENABLE 0x00010000 -#define ISR_ICU_INT_ENABLE 0x00020000 -#define ISR_SECC_COUNT 0x003c0000 -#define ISR_SECC_OVERFLOW 0x00400000 -#define ISR_MEMDEC_MISS 0x00800000 -#define ISR_XLAT_INVALID 0x01000000 -#define ISR_WIN_MISS 0x02000000 -#define ISR_FAULT 0x04000000 -#define ISR_S0_RIO_ERR 0x08000000 -#define ISR_S1_RIO_ERR 0x10000000 -#define ISR_S2_RIO_ERR 0x20000000 -#define ISR_EN_RIO_ERR 0x40000000 -#define ISR_RIO_RETRY_TMO 0x80000000 - -#define ISR_BITS "\020" \ - "\01S0_SECC\02S0_MECC\03S0_SERR\04S1_SECC\05S1_MECC\06S1_SERR" \ - "\07S2_SECC\10S2_MECC\11S2_SERR\12EN_SECC\13EN_MECC\14EN_SERR" \ - "\15SCSI_SECC\16SCSSI_MECC\17SCSI_SERR\20RIO_NMIE\21DMA_NMIE\22ICU_IE" \ - "\27SECC_OVERFLOW\30MEMDEC_MISS\31XLAT_INVALID\32WIN_MISS\33FAULT" \ - "\34S0_RIO\35S1_RIO\36S2_RIO\37RIO_TMO" - -#define ICU_TIR 0x50000008 - -#define ICU_TER 0x5000000c -#define TER_S0 0x00000002 -#define TER_S1 0x00000004 -#define TER_S2 0x00000008 -#define TER_ETHERNET 0x00000010 -#define TER_SCSI 0x00000020 -#define TER_IO_DISABLE 0x00000040 -#define TER_W_COMP_DIS 0x00000080 - -#define ICU_TWR 0x50000010 - -#define ICU_TRR 0x50000014 - -#define ICU_CONF 0x50000018 -#define CONF_ECC_ENABLE 0x00000004 -#define CONF_NO_EXTRA_MEMORY 0x00000008 -#define CONF_SBUS_25MHZ 0x00000020 -#define CONF_SLOW_DMA_WRITE 0x00000080 -#define CONF_SLOW_DMA_READ 0x00000100 -#define CONF_ICACHE_DISABLE 0x00000400 - -/* - * Onboard devices - */ - -#define SE_BASE 0x40000000 /* scsi and ethernet */ -#define NVRAM_BASE 0x80000000 -#define ZS1_BASE 0x80004000 -#define ZS0_BASE 0x80008000 -#define FDC_BASE 0x8000c000 -#define AUDIO_BASE 0x80010000 -#define TODCLOCK_BASE 0x80014000 - -/* we map the following range 1:1 in kernel space */ -#define OBIO_PA_START 0x80000000 -#define OBIO_PA_END 0x80018000 - -#endif /* _MACHINE_IDT_H_ */ diff --git a/sys/arch/solbourne/include/ieee.h b/sys/arch/solbourne/include/ieee.h deleted file mode 100644 index 736dd276afd..00000000000 --- a/sys/arch/solbourne/include/ieee.h +++ /dev/null @@ -1,3 +0,0 @@ -/* $OpenBSD: ieee.h,v 1.2 2013/03/21 02:10:37 deraadt Exp $ */ - -#include <sparc/ieee.h> diff --git a/sys/arch/solbourne/include/ieeefp.h b/sys/arch/solbourne/include/ieeefp.h deleted file mode 100644 index a0473c94dfe..00000000000 --- a/sys/arch/solbourne/include/ieeefp.h +++ /dev/null @@ -1,3 +0,0 @@ -/* $OpenBSD: ieeefp.h,v 1.2 2013/03/21 02:10:37 deraadt Exp $ */ - -#include <sparc/ieeefp.h> diff --git a/sys/arch/solbourne/include/instr.h b/sys/arch/solbourne/include/instr.h deleted file mode 100644 index 4c32a7f6309..00000000000 --- a/sys/arch/solbourne/include/instr.h +++ /dev/null @@ -1,3 +0,0 @@ -/* $OpenBSD: instr.h,v 1.2 2013/03/21 02:10:37 deraadt Exp $ */ - -#include <sparc/instr.h> diff --git a/sys/arch/solbourne/include/ioctl_fd.h b/sys/arch/solbourne/include/ioctl_fd.h deleted file mode 100644 index 278e061b9c6..00000000000 --- a/sys/arch/solbourne/include/ioctl_fd.h +++ /dev/null @@ -1,3 +0,0 @@ -/* $OpenBSD: ioctl_fd.h,v 1.2 2013/03/21 02:10:37 deraadt Exp $ */ - -#include <sparc/ioctl_fd.h> diff --git a/sys/arch/solbourne/include/kap.h b/sys/arch/solbourne/include/kap.h deleted file mode 100644 index c5a163a14ce..00000000000 --- a/sys/arch/solbourne/include/kap.h +++ /dev/null @@ -1,173 +0,0 @@ -/* $OpenBSD: kap.h,v 1.4 2013/03/21 02:10:37 deraadt Exp $ */ - -/* - * Copyright (c) 2005, Miodrag Vallat - * - * 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. - */ - -#ifndef _MACHINE_KAP_H_ -#define _MACHINE_KAP_H_ - -/* - * KAP specific control registers - */ - -#ifdef _KERNEL - -/* TLB handling - write only */ -#define ASI_GTLB_RANDOM 0xc0 /* random TLB drop-in */ -#define ASI_GTLB_DROPIN 0xc1 /* TLB drop-in */ -#define ASI_GTLB_INVAL_ENTRY 0xc2 /* invalidate entry */ -#define ASI_GTLB_INVAL_PID 0xc3 /* invalidate PID */ -#define ASI_GTLB_INVALIDATE 0xc4 /* invalidate entire TLB */ -#define ASI_ITLB_DROPIN 0xc8 /* iTLB drop-in */ - -/* TLB position addressing */ -#define TLB_SLOT(x) ((x) << 3) -#define TLB_INCR (1 << 3) -#define GTLB_SLOTS (128 + 8) /* XXX unsure */ -#define ITLB_SLOTS 8 /* XXX unsure */ - -/* data cache handling - read only except ASI_DCACHE_RW */ -#define ASI_DCACHE_FLUSH 0xd0 /* flush dcache block */ -#define ASI_DCACHE_LOOKUP 0xd1 /* check for dcache hit */ -#define ASI_DCACHE_RW 0xd2 /* read/write dcache */ -#define ASI_DCACHE_INVAL 0xd3 /* invalidate dcache */ - -/* cache line addressing (for D flushes) */ -#define DCACHE_LINE(x) ((x) << 2) -#define DCACHE_INCR (1 << 2) -#define DCACHE_LINES 256 - -/* bus access - read/write */ -#define ASI_PHYS_IO 0xd4 /* not cached */ -#define ASI_PHYS_CACHED 0xd5 /* cached */ -#define ASI_PHYS_NBW 0xd6 /* non byte writeable shared */ -#define ASI_PHYS_BW 0xd7 /* byte writeable shared */ - -/* inst cache handling - read only except ASI_ICACHE_RW */ -#define ASI_ICACHE_LOOKUP 0xd9 /* check for icache hit */ -#define ASI_ICACHE_RW 0xda /* read/write icache */ -#define ASI_ICACHE_INVAL 0xdb /* invalidate icache */ - -/* MMU registers */ -#define ASI_MMCR 0xe0 /* control register, rw */ -#define ASI_PDBR 0xe1 /* page directory base address, rw */ -#define ASI_FVAR 0xe2 /* fault va, rw */ -#define ASI_PDER 0xe3 /* page directory entry pointer, ro */ -#define ASI_PTOR 0xe4 /* page table offset, ro */ -#define ASI_FPAR 0xe5 /* fault pa, rw */ -#define ASI_FPSR 0xe6 /* fault ASI, rw */ -#define ASI_PIID 0xe7 /* process ID invalidation, rw */ -#define ASI_PID 0xe8 /* process ID, rw */ -#define ASI_BCR 0xe9 /* bus control, rw */ -#define ASI_FCR 0xea /* fault cause, rw */ -#define ASI_PTW0 0xeb /* translation window #0, rw */ -#define ASI_PTW1 0xec /* translation window #0, rw */ -#define ASI_PTW2 0xed /* translation window #0, rw */ - -/* Hardware watchdog */ -#define ASI_WAR0 0xee /* watchpoint address 0, rw */ -#define ASI_WAR1 0xef /* watchpoint address 1, rw */ -#define ASI_WCR 0xf0 /* watchpoint control register, rw */ - -/* MMCR fields */ -#define MMCR_ENABLE 0x00000001 /* MMU enable */ -#define MMCR_MATCH_PTW 0x00000002 /* lookup matches PTW */ -#define MMCR_MATCH_ITLB 0x00000004 /* lookup matches ITLB */ -#define MMCR_MATCH_GTLB 0x00000008 /* lookup matches GTLB */ -#define MMCR_ISET0 0x00000080 /* icache set 0 */ -#define MMCR_ISET1 0x00000100 /* icache set 1 */ -#define MMCR_ISET2 0x00000200 /* icache set 2 */ -#define MMCR_DSET0 0x00000400 /* dcache set 0 */ -#define MMCR_DSET1 0x00000800 /* dcache set 1 */ - -/* BCR fields */ -#define BCR_FAULT_SYNDROME 0x000000ff /* ECC syndrome byte */ -#define BCR_ECC 0x00000100 /* ECC enable */ -#define BCR_FAULT_DISABLE 0x00000200 /* disable ECC faults */ - -/* FCR fields */ -#define FCR_PROTMASK 0x0000000f -#define FCR_V 0x00000001 /* page not valid */ -#define FCR_RO 0x00000002 /* write access on read only */ -#define FCR_S 0x00000004 /* user access on sup. only */ -#define FCR_EXTERNAL 0x00000100 /* external fault */ -#define FCR_ECC_SINGLE 0x00000200 /* single bit ECC */ -#define FCR_ECC_MULTIPLE 0x00000400 /* multiple bit ECC */ - -#define FCR_BITS "\020\01V\02RO\03S\011EXTERNAL\012ECCS\013ECCM" - -/* PTW fields */ -#define PTW_V 0x00000001 /* valid */ -#define PTW_RO 0x00000002 /* read only */ -#define PTW_RW 0x00000000 -#define PTW_S 0x00000004 /* supervisor only */ -#define PTW_CACHEABLE 0x00000008 -#define PTW_BYTE_SHARED 0x00000010 -#define PTW_SHARED 0x00000018 -#define PTW_MASK_MASK 0x0000ff00 /* window address mask */ -#define PTW_MASK_SHIFT 8 -#define PTW_PA_MASK 0x00ff0000 /* physical window */ -#define PTW_PA_SHIFT 16 -#define PTW_VA_MASK 0xff000000 /* virtual window */ -#define PTW_VA_SHIFT 24 - -#define PTW_WINDOW_SIZE 0x01000000 -#define PTW_WINDOW_MASK 0xff000000 -#define PTW_WINDOW_SHIFT 24 - -#define PTW_TEMPLATE(va,pa,size) \ - (((va) << PTW_VA_SHIFT) | ((pa) << PTW_PA_SHIFT) | \ - (((~((size) - 1) >> 24) << PTW_MASK_SHIFT) & PTW_MASK_MASK)) - -/* - * Initial virtual memory settings - */ - -#define ROM_WINDOW 0x00 -#define PTW0_BASE (vaddr_t)(ROM_WINDOW << PTW_WINDOW_SHIFT) -#define PHYSMEM_WINDOW 0xf0 -#define PHYSMEM_BASE (vaddr_t)(PHYSMEM_WINDOW << PTW_WINDOW_SHIFT) -#define PTW1_WINDOW 0xfd -#define PTW1_BASE (vaddr_t)(PTW1_WINDOW << PTW_WINDOW_SHIFT) -#define PTW2_WINDOW 0xfe -#define PTW2_BASE (vaddr_t)(PTW2_WINDOW << PTW_WINDOW_SHIFT) -#define PTW0_DEFAULT \ - PTW_TEMPLATE(ROM_WINDOW, ROM_WINDOW, 0x10000000) | PTW_S | PTW_V -#define PTW1_DEFAULT PTW_CACHEABLE | \ - PTW_TEMPLATE(PTW1_WINDOW, PHYSMEM_WINDOW, 0x01000000) | PTW_S | PTW_V -#define PTW2_DEFAULT PTW_SHARED | \ - PTW_TEMPLATE(PTW2_WINDOW, PHYSMEM_WINDOW, 0x01000000) | PTW_S | PTW_V - -#define PTW0_TO_PHYS(va) (paddr_t)(va) -#define PTW1_TO_PHYS(va) (paddr_t)((va) - PTW1_BASE + PHYSMEM_BASE) -#define PTW2_TO_PHYS(va) (paddr_t)((va) - PTW2_BASE + PHYSMEM_BASE) - -#define PHYS_TO_PTW0(pa) (vaddr_t)(pa) -#define PHYS_TO_PTW1(pa) (vaddr_t)((pa) - PHYSMEM_BASE + PTW1_BASE) -#define PHYS_TO_PTW2(pa) (vaddr_t)((pa) - PHYSMEM_BASE + PTW2_BASE) - -#endif /* _KERNEL */ - -#endif /* _MACHINE_KAP_H_ */ diff --git a/sys/arch/solbourne/include/kcore.h b/sys/arch/solbourne/include/kcore.h deleted file mode 100644 index c1787372375..00000000000 --- a/sys/arch/solbourne/include/kcore.h +++ /dev/null @@ -1,3 +0,0 @@ -/* $OpenBSD: kcore.h,v 1.2 2013/03/21 02:10:37 deraadt Exp $ */ - -#include <sparc/kcore.h> diff --git a/sys/arch/solbourne/include/limits.h b/sys/arch/solbourne/include/limits.h deleted file mode 100644 index 07bc416ec8a..00000000000 --- a/sys/arch/solbourne/include/limits.h +++ /dev/null @@ -1,3 +0,0 @@ -/* $OpenBSD: limits.h,v 1.2 2013/03/21 02:10:37 deraadt Exp $ */ - -#include <sparc/limits.h> diff --git a/sys/arch/solbourne/include/lock.h b/sys/arch/solbourne/include/lock.h deleted file mode 100644 index 08003af08ac..00000000000 --- a/sys/arch/solbourne/include/lock.h +++ /dev/null @@ -1,3 +0,0 @@ -/* $OpenBSD: lock.h,v 1.2 2013/03/21 02:10:37 deraadt Exp $ */ - -#include <sparc/lock.h> diff --git a/sys/arch/solbourne/include/mutex.h b/sys/arch/solbourne/include/mutex.h deleted file mode 100644 index 38a96b5bec6..00000000000 --- a/sys/arch/solbourne/include/mutex.h +++ /dev/null @@ -1,3 +0,0 @@ -/* $OpenBSD: mutex.h,v 1.2 2013/03/21 02:10:37 deraadt Exp $ */ - -#include <sparc/mutex.h> diff --git a/sys/arch/solbourne/include/oldmon.h b/sys/arch/solbourne/include/oldmon.h deleted file mode 100644 index b5b02c4c59e..00000000000 --- a/sys/arch/solbourne/include/oldmon.h +++ /dev/null @@ -1,3 +0,0 @@ -/* $OpenBSD: oldmon.h,v 1.2 2013/03/21 02:10:37 deraadt Exp $ */ - -#include <sparc/oldmon.h> diff --git a/sys/arch/solbourne/include/openpromio.h b/sys/arch/solbourne/include/openpromio.h deleted file mode 100644 index b5cdb8e126e..00000000000 --- a/sys/arch/solbourne/include/openpromio.h +++ /dev/null @@ -1,3 +0,0 @@ -/* $OpenBSD: openpromio.h,v 1.2 2013/03/21 02:10:37 deraadt Exp $ */ - -#include <sparc/openpromio.h> diff --git a/sys/arch/solbourne/include/param.h b/sys/arch/solbourne/include/param.h deleted file mode 100644 index 6e04748c643..00000000000 --- a/sys/arch/solbourne/include/param.h +++ /dev/null @@ -1,132 +0,0 @@ -/* $OpenBSD: param.h,v 1.14 2013/11/20 23:57:07 miod Exp $ */ - -/* - * Copyright (c) 1992, 1993 - * The Regents of the University of California. All rights reserved. - * - * This software was developed by the Computer Systems Engineering group - * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and - * contributed to Berkeley. - * - * 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, Lawrence Berkeley Laboratory. - * - * 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. 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. - */ - -#ifndef _MACHINE_PARAM_H_ -#define _MACHINE_PARAM_H_ - -#ifdef _KERNEL /* XXX */ -#ifndef _LOCORE /* XXX */ -#include <machine/cpu.h> /* XXX */ -#endif /* XXX */ -#endif /* XXX */ - -#define _MACHINE solbourne -#define MACHINE "solbourne" -#define _MACHINE_ARCH sparc -#define MACHINE_ARCH "sparc" -#define MID_MACHINE MID_SPARC - -#define SUN4_PGSHIFT 13 /* for a sun4 machine */ -#define SUN4CM_PGSHIFT 12 /* for a sun4c or sun4m machine */ -#define PAGE_SHIFT SUN4_PGSHIFT -#define PAGE_SIZE (1 << PAGE_SHIFT) -#define PAGE_MASK (PAGE_SIZE - 1) - -#define KERNBASE 0xfd080000 - -#ifdef _KERNEL - -#define KERNTEXTOFF 0xfd084000 /* start of kernel text */ -#define MSGBUF_PA PTW1_TO_PHYS(KERNBASE) /* msgbuf physical address */ - -#define NBPG PAGE_SIZE /* bytes/page */ -#define PGSHIFT PAGE_SHIFT /* LOG2(PAGE_SIZE) */ -#define PGOFSET PAGE_MASK /* byte offset into page */ - -#define UPAGES 1 -#define USPACE 8192 /* total size of u-area */ -#define USPACE_ALIGN 0 /* u-area alignment 0-none */ - -#define NMBCLUSTERS 2048 /* map size, max cluster allocation */ - -#define MSGBUFSIZE (1 * PAGE_SIZE) /* larger than on sparc! */ - -/* - * Maximum size of the kernel malloc arena in PAGE_SIZE-sized - * logical pages. - */ -#define NKMEMPAGES_MAX_DEFAULT ((64 * 1024 * 1024) >> PAGE_SHIFT) - -/* - * dvmamap manages a range of DVMA addresses intended to create double - * mappings of physical memory. In a way, `dvmamap' is a submap of the - * VM map `phys_map'. The difference is the use of the `extent' - * routines to manage page allocation, allowing DVMA addresses to be - * allocated and freed from within interrupt routines. - * - * Note that `phys_map' can still be used to allocate memory-backed pages - * in DVMA space. - */ -#ifndef _LOCORE -extern vaddr_t dvma_base; -extern vaddr_t dvma_end; -extern struct extent *dvmamap_extent; - -extern caddr_t kdvma_mapin(caddr_t, int, int); -extern caddr_t dvma_malloc_space(size_t, void *, int, int); -extern void dvma_free(caddr_t, size_t, void *); -#define dvma_malloc(len,kaddr,flags) dvma_malloc_space(len,kaddr,flags,0) - -extern void delay(unsigned int); -#define DELAY(n) delay(n) - -extern int cputyp; - -#endif /* _LOCORE */ - -/* - * Values for the cputyp variable. - */ -#define CPU_KAP 5 - -/* - * Shorthand CPU-type macros. - * Let compiler optimize away code conditional on constants. - */ -#define CPU_ISSUN4M (0) -#define CPU_ISSUN4C (0) -#define CPU_ISSUN4 (0) -#define CPU_ISSUN4OR4C (0) -#define CPU_ISSUN4COR4M (0) -#define CPU_ISKAP (1) - -#endif /* _KERNEL */ - -#endif /* _MACHINE_PARAM_H_ */ diff --git a/sys/arch/solbourne/include/pcb.h b/sys/arch/solbourne/include/pcb.h deleted file mode 100644 index ac6f06d160b..00000000000 --- a/sys/arch/solbourne/include/pcb.h +++ /dev/null @@ -1,3 +0,0 @@ -/* $OpenBSD: pcb.h,v 1.2 2013/03/21 02:10:37 deraadt Exp $ */ - -#include <sparc/pcb.h> diff --git a/sys/arch/solbourne/include/pmap.h b/sys/arch/solbourne/include/pmap.h deleted file mode 100644 index fc2ea553806..00000000000 --- a/sys/arch/solbourne/include/pmap.h +++ /dev/null @@ -1,112 +0,0 @@ -/* $OpenBSD: pmap.h,v 1.10 2015/02/15 21:34:33 miod Exp $ */ - -/* - * Copyright (c) 2005, Miodrag Vallat - * - * 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. - */ - -#ifndef _MACHINE_PMAP_H_ -#define _MACHINE_PMAP_H_ - -#include <machine/pte.h> - -/* - * PMAP structure - */ -struct pmap { - pd_entry_t *pm_segtab; /* first level table */ - paddr_t pm_psegtab; /* pa of above */ - - int pm_refcount; /* reference count */ - struct pmap_statistics pm_stats; /* pmap statistics */ -}; - -typedef struct pmap *pmap_t; - -/* - * Extra constants passed in the low bits of pa in pmap_enter() to - * request specific memory attributes. - */ - -#define PMAP_NC 1 -#define PMAP_OBIO PMAP_NC -#define PMAP_BWS 2 - -/* - * Macro to pass iospace bits in the low bits of pa in pmap_enter(). - * Provided for source code compatibility - we don't need such bits. - */ - -#define PMAP_IOENC(x) 0 - -#ifdef _KERNEL - -extern struct pmap kernel_pmap_store; - -#define kvm_recache(addr, npages) kvm_setcache(addr, npages, 1) -#define kvm_uncache(addr, npages) kvm_setcache(addr, npages, 0) -#define pmap_copy(a,b,c,d,e) do { /* nothing */ } while (0) -#define pmap_deactivate(p) do { /* nothing */ } while (0) -#define pmap_kernel() (&kernel_pmap_store) -#define pmap_resident_count(p) ((p)->pm_stats.resident_count) -#define pmap_update(p) do { /* nothing */ } while (0) -#define pmap_wired_count(p) ((p)->pm_stats.wired_count) -#define pmap_remove_holes(vm) do { /* nothing */ } while (0) - -#define PMAP_PREFER(fo, ap) pmap_prefer((fo), (ap)) - -struct proc; -void kvm_setcache(caddr_t, int, int); -void switchexit(struct proc *); /* locore.s */ -void pmap_bootstrap(size_t); -void pmap_cache_enable(void); -void pmap_changeprot(pmap_t, vaddr_t, vm_prot_t, int); -vaddr_t pmap_map(vaddr_t, paddr_t, paddr_t, int); -int pmap_pa_exists(paddr_t); -vaddr_t pmap_prefer(vaddr_t, vaddr_t); -void pmap_release(pmap_t); -void pmap_redzone(void); -void pmap_virtual_space(vaddr_t *, vaddr_t *); -void pmap_writetext(unsigned char *, int); - -#endif /* _KERNEL */ - -struct pvlist { - struct pvlist *pv_next; /* next pvlist, if any */ - struct pmap *pv_pmap; /* pmap of this va */ - vaddr_t pv_va; /* virtual address */ - int pv_flags; /* flags (below) */ -}; - -struct vm_page_md { - struct pvlist pv_head; -}; - -#define VM_MDPAGE_INIT(pg) do { \ - (pg)->mdpage.pv_head.pv_next = NULL; \ - (pg)->mdpage.pv_head.pv_pmap = NULL; \ - (pg)->mdpage.pv_head.pv_va = 0; \ - (pg)->mdpage.pv_head.pv_flags = 0; \ -} while (0) - -#endif /* _MACHINE_PMAP_H_ */ diff --git a/sys/arch/solbourne/include/proc.h b/sys/arch/solbourne/include/proc.h deleted file mode 100644 index 71d1af6ec43..00000000000 --- a/sys/arch/solbourne/include/proc.h +++ /dev/null @@ -1,3 +0,0 @@ -/* $OpenBSD: proc.h,v 1.2 2013/03/21 02:10:37 deraadt Exp $ */ - -#include <sparc/proc.h> diff --git a/sys/arch/solbourne/include/profile.h b/sys/arch/solbourne/include/profile.h deleted file mode 100644 index 9ecd98bc6fb..00000000000 --- a/sys/arch/solbourne/include/profile.h +++ /dev/null @@ -1,3 +0,0 @@ -/* $OpenBSD: profile.h,v 1.2 2013/03/21 02:10:37 deraadt Exp $ */ - -#include <sparc/profile.h> diff --git a/sys/arch/solbourne/include/prom.h b/sys/arch/solbourne/include/prom.h deleted file mode 100644 index 1034ee72189..00000000000 --- a/sys/arch/solbourne/include/prom.h +++ /dev/null @@ -1,109 +0,0 @@ -/* $OpenBSD: prom.h,v 1.3 2013/03/21 02:10:37 deraadt Exp $ */ - -/* - * Copyright (c) 2005, Miodrag Vallat - * - * 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. - */ - -#ifndef _MACHINE_PROM_H_ -#define _MACHINE_PROM_H_ - -/* - * The following describes the PROM communication structure, - * which appears at the beginning of physical memory. - */ - -#define PROM_CODE_PA 0x00000000 -#define PROM_CODE_VA PTW0_BASE -#define PROM_DATA_PA PHYSMEM_BASE -#define PROM_DATA_VA PTW1_BASE - -struct sb_prom { - int sp_interface; /* interface version */ - int (*sp_interp)(const char *); /* prom commands */ - char sp_version[128]; /* prom version */ - int (*sp_eval)(const char *); /* forth commands */ - int sp_ramdisk; /* ramdisk size if any in MB */ - int sp_promend; /* first available va */ - int sp_memsize; /* memory size in pages... */ - int sp_memsize_mb; /* ...and in MB */ - int sp_reserve_start; /* reserved area (in pages) */ - int sp_reserve_len; /* and length (in pages) */ - vaddr_t sp_msgbufp; /* PROM msgbuf pointer */ - int sp_sash_usrtrap; - int sp_rootnode; - int sp_validregs; /* nonzero if registers... */ - int sp_regs[100]; /* ...array is valid */ - int sp_revision; /* prom revision */ -}; - -#define PROM_INTERFACE 4 - -/* - * Reset strings - */ - -#define PROM_RESET_COLD "cold" -#define PROM_RESET_WARM "warm" -#define PROM_RESET_HALT "halt" - -/* - * Environment variables (all upper-case) - */ - -#define ENV_ETHERADDR "ENETADDR" -#define ENV_INPUTDEVICE "INPUT-DEVICE" -#define ENV_MODEL "MODEL" -#define ENV_OUTPUTDEVICE "OUTPUT-DEVICE" -#define ENV_TTYA "TTYA_MODE" -#define ENV_TTYB "TTYB_MODE" - -/* - * Node structures - */ - -struct prom_node { - int pn_sibling; - int pn_child; - vaddr_t pn_props; - char *pn_name; -}; - -struct prom_prop { - struct prom_prop *pp_next; - size_t pp_size; - char pp_data[0]; -}; - -/* - * System model - */ - -extern int sysmodel; - -#define SYS_S4000 0xf4 -#define SYS_S4100 0xf5 - -const char *prom_getenv(const char *); - -#endif /* _MACHINE_PROM_H_ */ diff --git a/sys/arch/solbourne/include/psl.h b/sys/arch/solbourne/include/psl.h deleted file mode 100644 index 7845f667a58..00000000000 --- a/sys/arch/solbourne/include/psl.h +++ /dev/null @@ -1,3 +0,0 @@ -/* $OpenBSD: psl.h,v 1.2 2013/03/21 02:10:37 deraadt Exp $ */ - -#include <sparc/psl.h> diff --git a/sys/arch/solbourne/include/pte.h b/sys/arch/solbourne/include/pte.h deleted file mode 100644 index 8b6f295d29b..00000000000 --- a/sys/arch/solbourne/include/pte.h +++ /dev/null @@ -1,95 +0,0 @@ -/* $OpenBSD: pte.h,v 1.2 2013/03/21 02:10:37 deraadt Exp $ */ - -/* - * Copyright (c) 2005, Miodrag Vallat - * - * 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. - */ - -/* - * KAP page table entries. - * - * Ref/Mod bits are handled in software. - */ - -/* - * First-level : Page Directory Tables (topmost 9 bits of a va) - * - * Page directory entries contain both the pa and the va of the page - * tables they point to. - */ - -#define PDT_INDEX_SIZE 9 -#define PDT_INDEX_SHIFT 23 -#define PDT_INDEX_MASK 0xff800000 - -/* - * Second-level: Page Table Entries (middle 10 bits of a va) - */ - -#define PT_INDEX_SIZE 10 -#define PT_INDEX_SHIFT 13 -#define PT_INDEX_MASK 0x007fe000 - -#define PG_V 0x00000001 -#define PG_NV 0x00000000 -#define PG_RO 0x00000002 /* read only */ -#define PG_RW 0x00000000 -#define PG_PROT (PG_RO | PG_S) -#define PG_S 0x00000004 /* supervisor only */ -#define PG_MA 0x00000018 /* memory attributes mask */ -#define PG_G 0x00000020 /* global */ -/* software bits from now on... */ -#define PG_W 0x00000040 /* wired */ -#define PG_M 0x00000080 /* modified */ -#define PG_U 0x00000100 /* referenced */ - /* 0x00001e00 unused */ -#define PG_FRAME 0xffffe000 /* PFN mask */ - -/* memory attributes */ -#define PG_IO 0x00000000 /* not cached */ -#define PG_CACHE 0x00000008 /* cached */ -#define PG_BYTE_SHARED 0x00000010 /* byte-writeable shared */ -#define PG_SHARED 0x00000018 /* non byte-writeable shared */ - -/* - * Page directory constants - */ - -#define PDT_SIZE 4096 /* size of a page directory table */ -#define PT_SIZE 4096 /* size of a page table */ - -#define NBR_PDE (PDT_SIZE / 8) -#define NBR_PTE (PT_SIZE / 4) - -#define NBSEG (1 << PDT_INDEX_SHIFT) - -#if !defined(_LOCORE) - -typedef u_int32_t pt_entry_t; - -typedef struct { - u_int32_t pde_pa; - pt_entry_t* pde_va; -} pd_entry_t; - -#endif diff --git a/sys/arch/solbourne/include/ptrace.h b/sys/arch/solbourne/include/ptrace.h deleted file mode 100644 index 7421f6aa4d9..00000000000 --- a/sys/arch/solbourne/include/ptrace.h +++ /dev/null @@ -1,3 +0,0 @@ -/* $OpenBSD: ptrace.h,v 1.2 2013/03/21 02:10:37 deraadt Exp $ */ - -#include <sparc/ptrace.h> diff --git a/sys/arch/solbourne/include/reg.h b/sys/arch/solbourne/include/reg.h deleted file mode 100644 index c964a71a080..00000000000 --- a/sys/arch/solbourne/include/reg.h +++ /dev/null @@ -1,3 +0,0 @@ -/* $OpenBSD: reg.h,v 1.2 2013/03/21 02:10:37 deraadt Exp $ */ - -#include <sparc/reg.h> diff --git a/sys/arch/solbourne/include/reloc.h b/sys/arch/solbourne/include/reloc.h deleted file mode 100644 index 2fbeec8d2b5..00000000000 --- a/sys/arch/solbourne/include/reloc.h +++ /dev/null @@ -1,3 +0,0 @@ -/* $OpenBSD: reloc.h,v 1.2 2013/03/21 02:10:37 deraadt Exp $ */ - -#include <sparc/reloc.h> diff --git a/sys/arch/solbourne/include/setjmp.h b/sys/arch/solbourne/include/setjmp.h deleted file mode 100644 index 8ab5e73206e..00000000000 --- a/sys/arch/solbourne/include/setjmp.h +++ /dev/null @@ -1,3 +0,0 @@ -/* $OpenBSD: setjmp.h,v 1.2 2013/03/21 02:10:37 deraadt Exp $ */ - -#include <sparc/setjmp.h> diff --git a/sys/arch/solbourne/include/signal.h b/sys/arch/solbourne/include/signal.h deleted file mode 100644 index ebcbd63a212..00000000000 --- a/sys/arch/solbourne/include/signal.h +++ /dev/null @@ -1,3 +0,0 @@ -/* $OpenBSD: signal.h,v 1.2 2013/03/21 02:10:37 deraadt Exp $ */ - -#include <sparc/signal.h> diff --git a/sys/arch/solbourne/include/spinlock.h b/sys/arch/solbourne/include/spinlock.h deleted file mode 100644 index c9739a45ea9..00000000000 --- a/sys/arch/solbourne/include/spinlock.h +++ /dev/null @@ -1,3 +0,0 @@ -/* $OpenBSD: spinlock.h,v 1.2 2013/03/21 02:10:37 deraadt Exp $ */ - -#include <sparc/spinlock.h> diff --git a/sys/arch/solbourne/include/stdarg.h b/sys/arch/solbourne/include/stdarg.h deleted file mode 100644 index 78485966c67..00000000000 --- a/sys/arch/solbourne/include/stdarg.h +++ /dev/null @@ -1,3 +0,0 @@ -/* $OpenBSD: stdarg.h,v 1.2 2013/03/21 02:10:37 deraadt Exp $ */ - -#include <sparc/stdarg.h> diff --git a/sys/arch/solbourne/include/sun_disklabel.h b/sys/arch/solbourne/include/sun_disklabel.h deleted file mode 100644 index 34cf78dc129..00000000000 --- a/sys/arch/solbourne/include/sun_disklabel.h +++ /dev/null @@ -1,3 +0,0 @@ -/* $OpenBSD: sun_disklabel.h,v 1.2 2013/03/21 02:10:37 deraadt Exp $ */ - -#include <sparc/sun_disklabel.h> diff --git a/sys/arch/solbourne/include/tcb.h b/sys/arch/solbourne/include/tcb.h deleted file mode 100644 index d85400bb72c..00000000000 --- a/sys/arch/solbourne/include/tcb.h +++ /dev/null @@ -1,3 +0,0 @@ -/* $OpenBSD: tcb.h,v 1.2 2013/06/01 21:20:54 jasper Exp $ */ -/* public domain */ -#include <sparc/tcb.h> diff --git a/sys/arch/solbourne/include/trap.h b/sys/arch/solbourne/include/trap.h deleted file mode 100644 index 2bb2f5e6fe2..00000000000 --- a/sys/arch/solbourne/include/trap.h +++ /dev/null @@ -1,3 +0,0 @@ -/* $OpenBSD: trap.h,v 1.2 2013/03/21 02:10:37 deraadt Exp $ */ - -#include <sparc/trap.h> diff --git a/sys/arch/solbourne/include/varargs.h b/sys/arch/solbourne/include/varargs.h deleted file mode 100644 index a072f898879..00000000000 --- a/sys/arch/solbourne/include/varargs.h +++ /dev/null @@ -1,3 +0,0 @@ -/* $OpenBSD: varargs.h,v 1.2 2013/03/21 02:10:37 deraadt Exp $ */ - -#include <sparc/varargs.h> diff --git a/sys/arch/solbourne/include/vmparam.h b/sys/arch/solbourne/include/vmparam.h deleted file mode 100644 index db2e0d866ee..00000000000 --- a/sys/arch/solbourne/include/vmparam.h +++ /dev/null @@ -1,27 +0,0 @@ -/* $OpenBSD: vmparam.h,v 1.4 2013/03/21 02:10:37 deraadt Exp $ */ -/* public domain */ - -#ifndef _MACHINE_VMPARAM_H_ -#define _MACHINE_VMPARAM_H_ - -#include <sparc/vmparam.h> - -/* - * User/kernel map constants. We slightly differ from sparc here. - */ -#undef VM_MIN_KERNEL_ADDRESS -#define VM_MIN_KERNEL_ADDRESS ((vaddr_t)0xf8000000) -#undef VM_MAX_KERNEL_ADDRESS -#define VM_MAX_KERNEL_ADDRESS ((vaddr_t)0xfd000000) - -#undef IOSPACE_BASE -#define IOSPACE_BASE ((vaddr_t)0xff000000) -#undef IOSPACE_LEN -#define IOSPACE_LEN 0x00f00000 /* 15 MB of iospace */ - -#undef VM_PHYSSEG_MAX -#define VM_PHYSSEG_MAX 2 -#undef VM_PHYSSEG_STRAT -#define VM_PHYSSEG_STRAT VM_PSTRAT_BIGFIRST - -#endif /* _MACHINE_VMPARAM_H_ */ diff --git a/sys/arch/solbourne/include/z8530var.h b/sys/arch/solbourne/include/z8530var.h deleted file mode 100644 index e760841ca6c..00000000000 --- a/sys/arch/solbourne/include/z8530var.h +++ /dev/null @@ -1,3 +0,0 @@ -/* $OpenBSD: z8530var.h,v 1.2 2013/03/21 02:10:37 deraadt Exp $ */ - -#include <sparc/z8530var.h> diff --git a/sys/arch/solbourne/solbourne/autoconf.c b/sys/arch/solbourne/solbourne/autoconf.c deleted file mode 100644 index cd0d7035ae3..00000000000 --- a/sys/arch/solbourne/solbourne/autoconf.c +++ /dev/null @@ -1,603 +0,0 @@ -/* $OpenBSD: autoconf.c,v 1.12 2010/11/18 21:13:19 miod Exp $ */ -/* OpenBSD: autoconf.c,v 1.64 2005/03/23 17:10:24 miod Exp */ - -/* - * Copyright (c) 1996 - * The President and Fellows of Harvard College. All rights reserved. - * Copyright (c) 1992, 1993 - * The Regents of the University of California. All rights reserved. - * - * This software was developed by the Computer Systems Engineering group - * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and - * contributed to Berkeley. - * - * All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Harvard University. - * This product includes software developed by the University of - * California, Lawrence Berkeley Laboratory. - * - * 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. 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. - * - * @(#)autoconf.c 8.4 (Berkeley) 10/1/93 - */ - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/buf.h> -#include <sys/disklabel.h> -#include <sys/device.h> -#include <sys/disk.h> -#include <sys/conf.h> -#include <sys/reboot.h> -#include <sys/socket.h> -#include <sys/malloc.h> -#include <sys/queue.h> - -#include <net/if.h> - -#include <dev/cons.h> - -#include <uvm/uvm_extern.h> - -#include <machine/autoconf.h> -#include <machine/bsd_openprom.h> -#include <machine/cpu.h> -#include <machine/ctlreg.h> -#include <machine/pmap.h> -#include <sparc/sparc/asm.h> -#include <sparc/sparc/cpuvar.h> -#include <sparc/sparc/timerreg.h> - -#ifdef DDB -#include <machine/db_machdep.h> -#include <ddb/db_sym.h> -#include <ddb/db_extern.h> -#endif - -#include <machine/idt.h> -#include <machine/kap.h> -#include <machine/prom.h> - -/* - * The following several variables are related to - * the configuration process, and are used in initializing - * the machine. - */ -int fbnode; /* node ID of ROM's console frame buffer */ - -#ifdef KGDB -extern int kgdb_debug_panic; -#endif - -static int mbprint(void *, const char *); -void sync_crash(void); -int mainbus_match(struct device *, void *, void *); -static void mainbus_attach(struct device *, struct device *, void *); - -struct bootpath bootpath[8]; -int nbootpath; -static void bootpath_build(void); -char mainbus_model[30]; - -u_int prom_argc; -char **prom_argv; -char **prom_environ; -vaddr_t prom_data; - -/* - * locore.s code calls bootstrap() just before calling main(), after double - * mapping the kernel to high memory and setting up the trap base register. - * We must finish mapping the kernel properly and glean any bootstrap info. - */ -void -bootstrap() -{ - char **old_argv, **old_environ; - u_int i, nenv; - size_t asize; - char *dst; - - bzero(&cpuinfo, sizeof(struct cpu_softc)); - cpuinfo.master = 1; - getcpuinfo(&cpuinfo, 0); - - /* - * Compute how much memory is used by the PROM arguments. - */ - asize = prom_argc * sizeof(const char *); - for (i = 0; i < prom_argc; i++) - asize += 1 + strlen(prom_argv[i]); - asize = roundup(asize, 4); - - for (nenv = 0; prom_environ[nenv] != NULL; nenv++) - asize += 1 + strlen(prom_environ[i]); - asize = roundup(asize, 4); - asize += (1 + nenv) * sizeof(const char *); - - /* - * Setup the initial mappings. - */ - pmap_bootstrap(asize); - - /* - * Now that we have allocated memory for the commandline arguments - * and the environment, save them. - */ - old_argv = prom_argv; - prom_argv = (char **)prom_data; - dst = (char *)(prom_data + prom_argc * sizeof(char *)); - for (i = 0; i < prom_argc; i++) { - prom_argv[i] = dst; - asize = 1 + strlen(old_argv[i]); - bcopy(old_argv[i], dst, asize); - dst += asize; - } - old_environ = prom_environ; - prom_environ = (char **)roundup((vaddr_t)dst, 4); - dst = (char *)((vaddr_t)prom_environ + (1 + nenv) * sizeof(char *)); - for (i = 0; i < nenv; i++) { - prom_environ[i] = dst; - asize = 1 + strlen(old_environ[i]); - bcopy(old_environ[i], dst, asize); - dst += asize; - } - prom_environ[nenv] = NULL; - - /* Moved zs_kgdb_init() to zs.c:consinit() */ -#ifdef DDB - db_machine_init(); - ddb_init(); -#endif -} - -/* - * bootpath_build: build a bootpath. Used when booting a generic - * kernel to find our root device. Newer proms give us a bootpath, - * for older proms we have to create one. An element in a bootpath - * has 4 fields: name (device name), val[0], val[1], and val[2]. Note that: - * Interpretation of val[] is device-dependent. Some examples: - * - * if (val[0] == -1) { - * val[1] is a unit number (happens most often with old proms) - * } else { - * [sbus device] val[0] is a sbus slot, and val[1] is an sbus offset - * [scsi disk] val[0] is target, val[1] is lun, val[2] is partition - * [scsi tape] val[0] is target, val[1] is lun, val[2] is file # - * } - * - */ - -static void -bootpath_build() -{ - u_int i; - char *cp; - -/* XXX needs a rewrite for S4000 - we do not need to do things that way */ - - bzero(bootpath, sizeof(bootpath)); - - /* - * The boot path is contained in argv[0] only. - * It has the form: - * [subdevice.]device([[ctrl],[unit],[partition]])[/]path - */ - - printf("bootpath: %s\n", prom_argv[0]); - - /* - * Remaining arguments are interpreted as options, with or without - * leading dashes. - */ - for (i = 1; i < prom_argc; i++) { - for (cp = prom_argv[i]; *cp != '\0'; cp++) - switch (*cp) { - case 'a': - boothowto |= RB_ASKNAME; - break; - - case 'c': - boothowto |= RB_CONFIG; - break; - -#ifdef DDB - case 'd': - Debugger(); - break; -#endif - - case 's': - boothowto |= RB_SINGLE; - break; - } - } -} - -/* - * save or read a bootpath pointer from the boothpath store. - * - * XXX. required because of SCSI... we don't have control over the "sd" - * device, so we can't set boot device there. we patch in with - * device_register(), and use this to recover the bootpath. - */ - -struct bootpath * -bootpath_store(storep, bp) - int storep; - struct bootpath *bp; -{ - static struct bootpath *save; - struct bootpath *retval; - - retval = save; - if (storep) - save = bp; - - return (retval); -} - -/* - * Determine mass storage and memory configuration for a machine. - * We get the PROM's root device and make sure we understand it, then - * attach it as `mainbus0'. We also set up to handle the PROM `sync' - * command. - */ -void -cpu_configure() -{ - struct confargs oca; - register int node = 0; - register char *cp; - int s; - extern struct user *proc0paddr; - - /* build the bootpath */ - bootpath_build(); - - if (boothowto & RB_CONFIG) { -#ifdef BOOT_CONFIG - user_config(); -#else - printf("kernel does not support -c; continuing..\n"); -#endif - } - - node = findroot(); - - oca.ca_ra.ra_node = node; - oca.ca_ra.ra_name = cp = "mainbus"; - if (config_rootfound(cp, (void *)&oca) == NULL) - panic("mainbus not configured"); - - /* Enable device interrupts */ - sta(GLU_ICR, ASI_PHYS_IO, - ((lda(GLU_ICR, ASI_PHYS_IO) >> 24) & ~GICR_DISABLE_ALL) << 24); - (void)spl0(); - - cold = 0; - - /* - * Re-zero proc0's user area, to nullify the effect of the - * stack running into it during auto-configuration. - * XXX - should fix stack usage. - */ - s = splhigh(); - bzero(proc0paddr, sizeof(struct user)); - - pmap_redzone(); - splx(s); -} - -void -diskconf(void) -{ - struct bootpath *bp; - struct device *bootdv; - int bootpart; - - /* - * Configure swap area and related system - * parameter based on device(s) used. - */ - bp = nbootpath == 0 ? NULL : &bootpath[nbootpath-1]; - bootdv = (bp == NULL) ? NULL : bp->dev; - bootpart = (bp == NULL) ? 0 : bp->val[2]; - - setroot(bootdv, bootpart, RB_USERREQ | RB_HALT); - dumpconf(); -} - -/* - * Console `sync' command. SunOS just does a `panic: zero' so I guess - * no one really wants anything fancy... - */ -void -sync_crash() -{ - - panic("PROM sync command"); -} - -char * -clockfreq(freq) - register int freq; -{ - register char *p; - static char buf[10]; - - freq /= 1000; - snprintf(buf, sizeof buf, "%d", freq / 1000); - freq %= 1000; - if (freq) { - freq += 1000; /* now in 1000..1999 */ - p = buf + strlen(buf); - snprintf(p, buf + sizeof buf - p, "%d", freq); - *p = '.'; /* now buf = %d.%3d */ - } - return (buf); -} - -/* ARGSUSED */ -static int -mbprint(aux, name) - void *aux; - const char *name; -{ - register struct confargs *ca = aux; - - if (name) - printf("%s at %s", ca->ca_ra.ra_name, name); - if (ca->ca_ra.ra_paddr) - printf(" %saddr 0x%x", ca->ca_ra.ra_iospace ? "io" : "", - (int)ca->ca_ra.ra_paddr); - return (UNCONF); -} - -/* - * Given a `first child' node number, locate the node with the given name. - * Return the node number, or 0 if not found. - */ -int -findnode(first, name) - int first; - register const char *name; -{ - register int node; - - for (node = first; node; node = nextsibling(node)) - if (strcmp(getpropstring(node, "name"), name) == 0) - return (node); - return (0); -} - -int -mainbus_match(parent, self, aux) - struct device *parent; - void *self; - void *aux; -{ - struct cfdata *cf = self; - register struct confargs *ca = aux; - register struct romaux *ra = &ca->ca_ra; - - return (strcmp(cf->cf_driver->cd_name, ra->ra_name) == 0); -} - -/* - * Attach the mainbus. - * - * Our main job is to attach the CPU (the root node we got in cpu_configure()) - * and iterate down the list of `mainbus devices' (children of that node). - * We also record the `node id' of the default frame buffer, if any. - */ -static void -mainbus_attach(parent, dev, aux) - struct device *parent, *dev; - void *aux; -{ - struct confargs oca; - struct confargs *ca = aux; - int node0; - const char *model; - - node0 = ca->ca_ra.ra_node; /* i.e., the root node */ - - model = getpropstring(node0, "model"); - if (model == NULL) - model = sysmodel == SYS_S4000 ? "S4000" : "S4100"; - strlcpy(mainbus_model, model, sizeof mainbus_model); - printf(": %s\n", mainbus_model); - - /* - * Locate and configure the ``early'' devices. These must be - * configured before we can do the rest. For instance, the - * EEPROM contains the Ethernet address for the LANCE chip. - * If the device cannot be located or configured, panic. - */ - - /* Configure the CPU. */ - bzero(&oca, sizeof(oca)); - oca.ca_bustype = BUS_MAIN; - oca.ca_ra.ra_node = node0; - oca.ca_ra.ra_name = "cpu"; - (void)config_found(dev, (void *)&oca, mbprint); - - /* - * XXX we don't support frame buffers, yet - */ - fbnode = 0; - - bzero(&oca, sizeof(oca)); - oca.ca_bustype = BUS_MAIN; - oca.ca_ra.ra_node = node0; - oca.ca_ra.ra_name = "obio"; - (void)config_found(dev, (void *)&oca, mbprint); -} - -struct cfattach mainbus_ca = { - sizeof(struct device), mainbus_match, mainbus_attach -}; - -struct cfdriver mainbus_cd = { - NULL, "mainbus", DV_DULL -}; - -/* - * findzs() is called from the zs driver (which is, at least in theory, - * generic to any machine with a Zilog ZSCC chip). It should return the - * address of the corresponding zs channel. It may not fail, and it - * may be called before the VM code can be used. Here we count on the - * FORTH PROM to map in the required zs chips. - */ -void * -findzs(zs) - int zs; -{ - - if (CPU_ISKAP) { - struct rom_reg rr; - register void *vaddr; - - switch (zs) { - case 0: - rr.rr_paddr = (void *)ZS0_BASE; - break; - case 1: - rr.rr_paddr = (void *)ZS1_BASE; - break; - default: - panic("findzs: unknown zs device %d", zs); - } - - rr.rr_iospace = PMAP_OBIO; - rr.rr_len = PAGE_SIZE; - vaddr = mapiodev(&rr, 0, PAGE_SIZE); - if (vaddr != NULL) - return (vaddr); - } - - panic("findzs: cannot find zs%d", zs); - /* NOTREACHED */ -} - -/* - * Return a string property. There is a (small) limit on the length; - * the string is fetched into a static buffer which is overwritten on - * subsequent calls. - */ -char * -getpropstring(node, name) - int node; - char *name; -{ - register int len; - static char stringbuf[32]; - - len = getprop(node, name, (void *)stringbuf, sizeof stringbuf - 1); - if (len == -1) - len = 0; - stringbuf[len] = '\0'; /* usually unnecessary */ - return (stringbuf); -} - -/* - * Fetch an integer (or pointer) property. - * The return value is the property, or the default if there was none. - */ -int -getpropint(node, name, deflt) - int node; - char *name; - int deflt; -{ - register int len; - char intbuf[16]; - - len = getprop(node, name, (void *)intbuf, sizeof intbuf); - if (len != 4) - return (deflt); - return (*(int *)intbuf); -} - -int -node_has_property(node, prop) /* returns 1 if node has given property */ - register int node; - register const char *prop; -{ - - return (getproplen(node, (char *)prop) != -1); -} - -void -callrom() -{ - -#ifdef notyet - promvec->pv_abort(); -#endif -} - -/* - * find a device matching "name" and unit number - */ -struct device * -getdevunit(name, unit) - char *name; - int unit; -{ - struct device *dev = TAILQ_FIRST(&alldevs); - char num[10], fullname[16]; - int lunit; - - /* compute length of name and decimal expansion of unit number */ - snprintf(num, sizeof num, "%d", unit); - lunit = strlen(num); - if (strlen(name) + lunit >= sizeof(fullname) - 1) - panic("config_attach: device name too long"); - - strlcpy(fullname, name, sizeof fullname); - strlcat(fullname, num, sizeof fullname); - - while (strcmp(dev->dv_xname, fullname) != 0) { - if ((dev = TAILQ_NEXT(dev, dv_list)) == NULL) - return NULL; - } - return dev; -} - -void -device_register(struct device *dev, void *aux) -{ -} - -struct nam2blk nam2blk[] = { - { "sd", 7 }, - { "st", 11 }, - { "fd", 16 }, - { "rd", 17 }, - { "cd", 18 }, - { NULL, -1 } -}; diff --git a/sys/arch/solbourne/solbourne/clock.c b/sys/arch/solbourne/solbourne/clock.c deleted file mode 100644 index d42f1f7488b..00000000000 --- a/sys/arch/solbourne/solbourne/clock.c +++ /dev/null @@ -1,169 +0,0 @@ -/* $OpenBSD: clock.c,v 1.1 2005/04/19 21:30:18 miod Exp $ */ -/* OpenBSD: clock.c,v 1.19 2004/04/08 01:11:21 deraadt Exp */ - -/* - * Copyright (c) 1992, 1993 - * The Regents of the University of California. All rights reserved. - * Copyright (c) 1994 Gordon W. Ross - * Copyright (c) 1993 Adam Glass - * Copyright (c) 1996 Paul Kranenburg - * Copyright (c) 1996 - * The President and Fellows of Harvard College. All rights reserved. - * - * This software was developed by the Computer Systems Engineering group - * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and - * contributed to Berkeley. - * - * All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Harvard University. - * This product includes software developed by the University of - * California, Lawrence Berkeley Laboratory. - * - * 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. - * This product includes software developed by Paul Kranenburg. - * This product includes software developed by Harvard University. - * 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. - * - * @(#)clock.c 8.1 (Berkeley) 6/11/93 - * - */ - -/* - * Clock driver. This is the id prom and eeprom driver as well - * and includes the timer register functions too. - */ - -#include <sys/param.h> -#include <sys/kernel.h> -#include <sys/device.h> -#include <sys/systm.h> - -#include <uvm/uvm_extern.h> - -#include <machine/autoconf.h> -#include <machine/cpu.h> - -#include <sparc/sparc/asm.h> -#include <machine/idt.h> -#include <machine/kap.h> - -/* - * Statistics clock interval and variance, in usec. Variance must be a - * power of two. Since this gives us an even number, not an odd number, - * we discard one case and compensate. That is, a variance of 1024 would - * give us offsets in [0..1023]. Instead, we take offsets in [1..1023]. - * This is symmetric about the point 512, or statvar/2, and thus averages - * to that value (assuming uniform random numbers). - */ -/* XXX fix comment to match value */ -int statvar = 8192; -int statmin; /* statclock interval - 1/2*variance */ - -int timerblurb = 10; /* Guess a value; used before clock is attached */ - -/* - * Set up the real-time and statistics clocks. Leave stathz 0 only if - * no alternative timer is available. - * - * The frequencies of these clocks must be an even number of microseconds. - */ -void -cpu_initclocks() -{ - profhz = hz; - tick = 1000000 / hz; -} - -/* - * Dummy setstatclockrate(), since we know profhz==hz. - */ -/* ARGSUSED */ -void -setstatclockrate(newhz) - int newhz; -{ - /* nothing */ -} - -/* - * Level 10 (clock) interrupts. - */ -int -clockintr(cap) - void *cap; -{ - hardclock((struct clockframe *)cap); - - return (1); -} - -/* - * Level 14 (stat clock) interrupt handler. - */ -int -statintr(cap) - void *cap; -{ -#if 1 - panic("level 14 interrupt"); -#else - statclock((struct clockframe *)cap); -#endif - - return (1); -} - -/* - * Return the best possible estimate of the time in the timeval - * to which tvp points. We do this by returning the current time - * plus the amount of time since the last clock interrupt. - * - * Check that this time is no less than any previously-reported time, - * which could happen around the time of a clock adjustment. Just for - * fun, we guarantee that the time will be greater than the value - * obtained by a previous call. - */ -void -microtime(tvp) - struct timeval *tvp; -{ - int s; - static struct timeval lasttime; - static struct timeval oneusec = {0, 1}; - - s = splhigh(); - *tvp = time; - splx(s); - - if (timercmp(tvp, &lasttime, <=)) - timeradd(&lasttime, &oneusec, tvp); - - lasttime = *tvp; -} diff --git a/sys/arch/solbourne/solbourne/genassym.cf b/sys/arch/solbourne/solbourne/genassym.cf deleted file mode 100644 index be35c2e61b8..00000000000 --- a/sys/arch/solbourne/solbourne/genassym.cf +++ /dev/null @@ -1,109 +0,0 @@ -# $OpenBSD: genassym.cf,v 1.3 2015/02/09 09:21:30 miod Exp $ -# -# Copyright (c) 2005, Miodrag Vallat -# -# 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/param.h> -include <sys/syscall.h> -include <sys/user.h> - -include <uvm/uvm_extern.h> - -include <machine/cpu.h> -include <machine/frame.h> -include <machine/kap.h> -include <machine/pmap.h> -include <machine/prom.h> - -include <sparc/sparc/cpuvar.h> - -# -# Solbourne PROM specific constants -# - -struct frame -member FRAME_ARGC fr_argx - -export PROM_DATA_PA - -struct sb_prom SB_ -member REGS sp_regs - -# -# Sparc general constants and structures -# - -export VM_MIN_KERNEL_ADDRESS - -export SYS_exit -export SYS_sigreturn - -export EFAULT -export ENAMETOOLONG - -struct fpstate -member fs_fsr -member fs_qsize -member fs_queue -member fs_regs -export FSR_QNE - -# intrhand fields. -struct intrhand -member ih_arg -member IH_COUNT ih_count.ec_count -member ih_fun -member ih_ipl -member ih_next - -struct pcb -member pcb_nsaved -member pcb_onfault -member pcb_psr -member pcb_rw -member pcb_sp -member pcb_uw -member pcb_wim -member pcb_wcookie - -struct pmap -member PMAP_PSEGTAB pm_psegtab -define VM_PMAP offsetof(struct vmspace, vm_map.pmap) - -struct proc -member p_addr -member p_stat -member p_vmspace -member p_wchan - -export SRUN -export SONPROC - -struct uvmexp V_ -member INTR intrs -member swtch - -# CPU info structure -struct cpu_softc -member CPUINFO_CURPROC ci.ci_curproc diff --git a/sys/arch/solbourne/solbourne/locore.s b/sys/arch/solbourne/solbourne/locore.s deleted file mode 100644 index 2272aac7db3..00000000000 --- a/sys/arch/solbourne/solbourne/locore.s +++ /dev/null @@ -1,4662 +0,0 @@ -/* $OpenBSD: locore.s,v 1.19 2015/02/09 09:21:30 miod Exp $ */ -/* OpenBSD: locore.s,v 1.64 2005/04/17 18:47:50 miod Exp */ - -/* - * Copyright (c) 2005, Miodrag Vallat - * - * 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. - */ -/* - * Copyright (c) 1996 Paul Kranenburg - * Copyright (c) 1996 - * The President and Fellows of Harvard College. All rights reserved. - * Copyright (c) 1992, 1993 - * The Regents of the University of California. All rights reserved. - * - * This software was developed by the Computer Systems Engineering group - * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and - * contributed to Berkeley. - * - * 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, Lawrence Berkeley Laboratory. - * This product includes software developed by Harvard University. - * - * 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. - * This product includes software developed by Harvard University. - * This product includes software developed by Paul Kranenburg. - * 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. - * - * @(#)locore.s 8.4 (Berkeley) 12/10/93 - */ - -#include "assym.h" -#include "ksyms.h" - -#include <machine/param.h> -#include <machine/asm.h> -#include <machine/idt.h> -#include <machine/kap.h> -#include <machine/pte.h> - -#include <sparc/sparc/intreg.h> - -#include <machine/psl.h> -#include <machine/pte.h> -#include <machine/signal.h> -#include <machine/trap.h> - -#include <dev/ic/z8530reg.h> - -/* - * GNU assembler does not understand `.empty' directive; Sun assembler - * gripes about labels without it. To allow cross-compilation using - * the Sun assembler, and because .empty directives are useful documentation, - * we use this trick. - */ -#ifdef SUN_AS -#define EMPTY .empty -#else -#define EMPTY /* .empty */ -#endif - -/* use as needed to align things on longword boundaries */ -#define _ALIGN .align 4 - -/* - * CCFSZ (C Compiler Frame SiZe) is the size of a stack frame required if - * a function is to call C code. It should be just 64, but Sun defined - * their frame with space to hold arguments 0 through 5 (plus some junk), - * and varargs routines (such as printf) demand this, and gcc uses this - * area at times anyway. - */ -#define CCFSZ 96 - -/* - * A handy macro for maintaining instrumentation counters. - * Note that this clobbers %o0 and %o1. Normal usage is - * something like: - * foointr: - * TRAP_SETUP(...) ! makes %o registers safe - * INCR(_C_LABEL(cnt)+V_FOO) ! count a foo - */ -#define INCR(what) \ - sethi %hi(what), %o0; \ - ld [%o0 + %lo(what)], %o1; \ - inc %o1; \ - st %o1, [%o0 + %lo(what)] - -/* - * Another handy macro: load one register window, given `base' address. - * This can be either a simple register (e.g., %sp) or include an initial - * offset (e.g., %g6 + PCB_RW). - */ -#define LOADWIN(addr) \ - ldd [addr], %l0; \ - ldd [addr + 8], %l2; \ - ldd [addr + 16], %l4; \ - ldd [addr + 24], %l6; \ - ldd [addr + 32], %i0; \ - ldd [addr + 40], %i2; \ - ldd [addr + 48], %i4; \ - ldd [addr + 56], %i6 - -/* - * To return from trap we need the two-instruction sequence - * `jmp %l1; rett %l2', which is defined here for convenience. - */ -#define RETT jmp %l1; rett %l2 - -/* - * On some KAP models, the FCR register is not cleared after being read, - * or when being written to by the hardware, so we have to clear it by - * ourselves after every read. - */ -#define CLEAR_FCR \ - sta %g0, [%g0] ASI_FCR - - .data -/* - * The interrupt stack. - * - * This is the very first thing in the data segment, and therefore has - * the lowest kernel stack address. We count on this in the interrupt - * trap-frame setup code, since we may need to switch from the kernel - * stack to the interrupt stack (iff we are not already on the interrupt - * stack). One sethi+cmp is all we need since this is so carefully - * arranged. - */ - .globl _C_LABEL(intstack) - .globl _C_LABEL(eintstack) -_C_LABEL(intstack): - .skip 128 * 128 ! 16k = 128 128-byte stack frames -_C_LABEL(eintstack): - -/* - * When a process exits and its u. area goes away, we set cpcb to point - * to this `u.', leaving us with something to use for an interrupt stack, - * and letting all the register save code have a pcb_uw to examine. - * This is also carefully arranged (to come just before u0, so that - * process 0's kernel stack can quietly overrun into it during bootup, if - * we feel like doing that). - */ - .globl _C_LABEL(idle_u) -_C_LABEL(idle_u): - .skip USPACE - -/* - * Process 0's u. - * - * This must be aligned on an 8 byte boundary. - */ - .globl _C_LABEL(u0) -_C_LABEL(u0): .skip USPACE -estack0: - -#ifdef KGDB -/* - * Another item that must be aligned, easiest to put it here. - */ -KGDB_STACK_SIZE = 2048 - .globl _C_LABEL(kgdb_stack) -_C_LABEL(kgdb_stack): - .skip KGDB_STACK_SIZE ! hope this is enough -#endif - -/* - * cpcb points to the current pcb (and hence u. area). - * Initially this is the special one. - */ - .globl _C_LABEL(cpcb) -_C_LABEL(cpcb): .word _C_LABEL(u0) - -curproc = CPUINFO_VA + CPUINFO_CURPROC - -/* - * cputyp is the current cpu type, used to distinguish between - * the many variations of different sun4* machines. It contains - * the value CPU_SUN4, CPU_SUN4C, or CPU_SUN4M. - */ - .globl _C_LABEL(cputyp) -_C_LABEL(cputyp): - .word CPU_KAP -/* - * cpumod is the current cpu model, used to distinguish between variants - * in the Sun4 and Sun4M families. See /sys/arch/sparc/include/param.h for - * possible values. - */ - .globl _C_LABEL(cpumod) -_C_LABEL(cpumod): - .word 1 - -/* - * nbpg is used by pmap_bootstrap(), pgofset is used internally. - */ - .globl _C_LABEL(nbpg) -_C_LABEL(nbpg): - .word PAGE_SIZE -_C_LABEL(pgofset): - .word PAGE_MASK - - .globl _C_LABEL(trapbase) -_C_LABEL(trapbase): - .word _C_LABEL(trapbase_kap) - - _ALIGN - - .text - -/* - * The first thing in the real text segment is the trap vector table, - * which must be aligned on a page boundary. The text segment - * starts beyond page 0 of KERNBASE so that there is a red zone - * between user and kernel space. We place the message buffer in this - * area. Because the message buffer is in our "red zone" between user - * and kernel space we remap it in configure() to another location and - * invalidate the mapping at KERNBASE. - */ - -/* - * Each trap has room for four instructions, of which one perforce must - * be a branch. On entry the hardware has copied pc and npc to %l1 and - * %l2 respectively. We use two more to read the psr into %l0, and to - * put the trap type value into %l3 (with a few exceptions below). - * We could read the trap type field of %tbr later in the code instead, - * but there is no need, and that would require more instructions - * (read+mask, vs 1 `mov' here). - * - * I used to generate these numbers by address arithmetic, but gas's - * expression evaluator has about as much sense as your average slug - * (oddly enough, the code looks about as slimy too). Thus, all the - * trap numbers are given as arguments to the trap macros. This means - * there is one line per trap. Sigh. - * - * Note that only the local registers may be used, since the trap - * window is potentially the last window. Its `in' registers are - * the previous window's outs (as usual), but more important, its - * `out' registers may be in use as the `topmost' window's `in' registers. - * The global registers are of course verboten (well, until we save - * them away). - * - * Hardware interrupt vectors can be `linked'---the linkage is to regular - * C code---or rewired to fast in-window handlers. The latter are good - * for unbuffered hardware like the Zilog serial chip and the AMD audio - * chip, where many interrupts can be handled trivially with pseudo-DMA or - * similar. Only one `fast' interrupt can be used per level, however, and - * direct and `fast' interrupts are incompatible. Routines in intr.c - * handle setting these, with optional paranoia. - */ - - /* regular vectored traps */ -#define VTRAP(type, label) \ - rd %wim, %l0; mov (type), %l3; b label; mov %psr, %l0 - - /* hardware interrupts (can be linked or made `fast') */ -#define HARDINTKAP(lev) \ - mov (lev), %l3; b sparc_interruptkap; mov %psr, %l0; nop - - /* software interrupts (may not be made direct, sorry---but you - should not be using them trivially anyway) */ -#define SOFTINTKAP(lev, bit) \ - mov (lev), %l3; mov (bit - 1), %l4; b softintr_kap; mov %psr, %l0 - - /* traps that just call trap() */ -#define TRAP(type) VTRAP(type, slowtrap) - - /* architecturally undefined traps (cause panic) */ -#define UTRAP(type) VTRAP(type, slowtrap) - - /* software undefined traps (may be replaced) */ -#define STRAP(type) VTRAP(type, slowtrap) - -/* breakpoint acts differently under kgdb */ -#ifdef KGDB -#define BPT VTRAP(T_BREAKPOINT, bpt) -#define BPT_KGDB_EXEC VTRAP(T_KGDB_EXEC, bpt) -#else -#define BPT TRAP(T_BREAKPOINT) -#define BPT_KGDB_EXEC TRAP(T_KGDB_EXEC) -#endif - -/* special high-speed 1-instruction-shaved-off traps (get nothing in %l3) */ -#define SYSCALL b _C_LABEL(_syscall); mov %psr, %l0; nop; nop -#define TLBTRAP(label) b label; mov %psr, %l0; nop; nop -#define WINDOW_OF b window_of; mov %psr, %l0; nop; nop -#define WINDOW_UF b window_uf; mov %psr, %l0; nop; nop -#ifdef notyet -#define ZS_INTERRUPT b zshard; mov %psr, %l0; nop; nop -#else -#define ZS_INTERRUPTKAP HARDINTKAP(12) -#endif - - .globl start, _C_LABEL(kernel_text) -_C_LABEL(kernel_text): -start: -/* - * The traptable needs to be aligned on a 4096 bytes boundary on KAP. - */ -trapbase_kap: -/* trap 0 is special since we cannot receive it */ - b dostart; nop; nop; nop ! 00 = reset (fake) - VTRAP(T_TEXTFAULT, mem_fault) ! 01 = instr. fetch fault - TRAP(T_ILLINST) ! 02 = illegal instruction - TRAP(T_PRIVINST) ! 03 = privileged instruction - TRAP(T_FPDISABLED) ! 04 = fp instr, but EF bit off in psr - WINDOW_OF ! 05 = window overflow - WINDOW_UF ! 06 = window underflow - TRAP(T_ALIGN) ! 07 = address alignment error - VTRAP(T_FPE, fp_exception) ! 08 = fp exception - VTRAP(T_DATAFAULT, mem_fault) ! 09 = data fetch fault - TRAP(T_TAGOF) ! 0a = tag overflow - UTRAP(0x0b) - UTRAP(0x0c) - UTRAP(0x0d) - UTRAP(0x0e) - UTRAP(0x0f) - UTRAP(0x10) - SOFTINTKAP(1, IE_L1) ! 11 = level 1 interrupt - HARDINTKAP(2) ! 12 = level 2 interrupt - HARDINTKAP(3) ! 13 = level 3 interrupt - SOFTINTKAP(4, IE_L4) ! 14 = level 4 interrupt - HARDINTKAP(5) ! 15 = level 5 interrupt - SOFTINTKAP(6, IE_L6) ! 16 = level 6 interrupt - HARDINTKAP(7) ! 17 = level 7 interrupt - HARDINTKAP(8) ! 18 = level 8 interrupt - HARDINTKAP(9) ! 19 = level 9 interrupt - SOFTINTKAP(10, IE_L10) ! 1a = level 10 interrupt (clock) - HARDINTKAP(11) ! 1b = level 11 interrupt - ZS_INTERRUPTKAP ! 1c = level 12 (zs) interrupt - HARDINTKAP(13) ! 1d = level 13 interrupt - HARDINTKAP(14) ! 1e = level 14 interrupt - VTRAP(15, nmi) ! 1f = nonmaskable interrupt - VTRAP(0x20, double_trap) ! 20 = double trap - UTRAP(0x21) - UTRAP(0x22) - UTRAP(0x23) - TRAP(T_CPDISABLED) ! 24 = coprocessor instr, EC bit off in psr - UTRAP(0x25) - UTRAP(0x26) - UTRAP(0x27) - TRAP(T_CPEXCEPTION) ! 28 = coprocessor exception - UTRAP(0x29) - UTRAP(0x2a) - UTRAP(0x2b) - TLBTRAP(dtlb_miss) ! 2c = dtlb lookup miss - UTRAP(0x2d) - UTRAP(0x2e) - UTRAP(0x2f) - UTRAP(0x30) - UTRAP(0x31) - UTRAP(0x32) - UTRAP(0x33) - UTRAP(0x34) - UTRAP(0x35) - UTRAP(0x36) - UTRAP(0x37) - UTRAP(0x38) - UTRAP(0x39) - UTRAP(0x3a) - UTRAP(0x3b) - TLBTRAP(itlb_miss) ! 3c itlb lookup miss - UTRAP(0x3d) - UTRAP(0x3e) - UTRAP(0x3f) - UTRAP(0x40) - UTRAP(0x41) - UTRAP(0x42) - UTRAP(0x43) - UTRAP(0x44) - UTRAP(0x45) - UTRAP(0x46) - UTRAP(0x47) - UTRAP(0x48) - UTRAP(0x49) - UTRAP(0x4a) - UTRAP(0x4b) - UTRAP(0x4c) - UTRAP(0x4d) - UTRAP(0x4e) - UTRAP(0x4f) - UTRAP(0x50) - UTRAP(0x51) - UTRAP(0x52) - UTRAP(0x53) - UTRAP(0x54) - UTRAP(0x55) - UTRAP(0x56) - UTRAP(0x57) - UTRAP(0x58) - UTRAP(0x59) - UTRAP(0x5a) - UTRAP(0x5b) - UTRAP(0x5c) - UTRAP(0x5d) - UTRAP(0x5e) - UTRAP(0x5f) - UTRAP(0x60) - UTRAP(0x61) - UTRAP(0x62) - UTRAP(0x63) - UTRAP(0x64) - UTRAP(0x65) - UTRAP(0x66) - UTRAP(0x67) - UTRAP(0x68) - UTRAP(0x69) - UTRAP(0x6a) - UTRAP(0x6b) - UTRAP(0x6c) - UTRAP(0x6d) - UTRAP(0x6e) - UTRAP(0x6f) - UTRAP(0x70) - UTRAP(0x71) - UTRAP(0x72) - UTRAP(0x73) - UTRAP(0x74) - UTRAP(0x75) - UTRAP(0x76) - UTRAP(0x77) - UTRAP(0x78) - UTRAP(0x79) - UTRAP(0x7a) - UTRAP(0x7b) - UTRAP(0x7c) - UTRAP(0x7d) - UTRAP(0x7e) - UTRAP(0x7f) - SYSCALL ! 80 = sun syscall - BPT ! 81 = pseudo breakpoint instruction - TRAP(T_DIV0) ! 82 = divide by zero - TRAP(T_FLUSHWIN) ! 83 = flush windows - TRAP(T_CLEANWIN) ! 84 = provide clean windows - TRAP(T_RANGECHECK) ! 85 = ??? - TRAP(T_FIXALIGN) ! 86 = fix up unaligned accesses - TRAP(T_INTOF) ! 87 = integer overflow - SYSCALL ! 88 = svr4 syscall - SYSCALL ! 89 = bsd syscall - BPT_KGDB_EXEC ! 8a = enter kernel gdb on kernel startup - STRAP(0x8b) - STRAP(0x8c) - STRAP(0x8d) - STRAP(0x8e) - STRAP(0x8f) - STRAP(0x90) - STRAP(0x91) - STRAP(0x92) - STRAP(0x93) - STRAP(0x94) - STRAP(0x95) - STRAP(0x96) - STRAP(0x97) - STRAP(0x98) - STRAP(0x99) - STRAP(0x9a) - STRAP(0x9b) - STRAP(0x9c) - STRAP(0x9d) - STRAP(0x9e) - STRAP(0x9f) - STRAP(0xa0) - STRAP(0xa1) - STRAP(0xa2) - STRAP(0xa3) - STRAP(0xa4) - STRAP(0xa5) - STRAP(0xa6) - STRAP(0xa7) - STRAP(0xa8) - STRAP(0xa9) - STRAP(0xaa) - STRAP(0xab) - STRAP(0xac) - STRAP(0xad) - STRAP(0xae) - STRAP(0xaf) - STRAP(0xb0) - STRAP(0xb1) - STRAP(0xb2) - STRAP(0xb3) - STRAP(0xb4) - STRAP(0xb5) - STRAP(0xb6) - STRAP(0xb7) - STRAP(0xb8) - STRAP(0xb9) - STRAP(0xba) - STRAP(0xbb) - STRAP(0xbc) - STRAP(0xbd) - STRAP(0xbe) - STRAP(0xbf) - STRAP(0xc0) - STRAP(0xc1) - STRAP(0xc2) - STRAP(0xc3) - STRAP(0xc4) - STRAP(0xc5) - STRAP(0xc6) - STRAP(0xc7) - STRAP(0xc8) - STRAP(0xc9) - STRAP(0xca) - STRAP(0xcb) - STRAP(0xcc) - STRAP(0xcd) - STRAP(0xce) - STRAP(0xcf) - STRAP(0xd0) - STRAP(0xd1) - STRAP(0xd2) - STRAP(0xd3) - STRAP(0xd4) - STRAP(0xd5) - STRAP(0xd6) - STRAP(0xd7) - STRAP(0xd8) - STRAP(0xd9) - STRAP(0xda) - STRAP(0xdb) - STRAP(0xdc) - STRAP(0xdd) - STRAP(0xde) - STRAP(0xdf) - STRAP(0xe0) - STRAP(0xe1) - STRAP(0xe2) - STRAP(0xe3) - STRAP(0xe4) - STRAP(0xe5) - STRAP(0xe6) - STRAP(0xe7) - STRAP(0xe8) - STRAP(0xe9) - STRAP(0xea) - STRAP(0xeb) - STRAP(0xec) - STRAP(0xed) - STRAP(0xee) - STRAP(0xef) - STRAP(0xf0) - STRAP(0xf1) - STRAP(0xf2) - STRAP(0xf3) - STRAP(0xf4) - STRAP(0xf5) - STRAP(0xf6) - STRAP(0xf7) - STRAP(0xf8) - STRAP(0xf9) - STRAP(0xfa) - STRAP(0xfb) - STRAP(0xfc) - STRAP(0xfd) - STRAP(0xfe) - STRAP(0xff) - -/* - * Pad the trap table to max page size. - * Trap table size is 0x100 * 4instr * 4byte/instr = 4096 bytes only. - */ - .align PAGE_SIZE - -#ifdef DEBUG -/* - * A hardware red zone is impossible. We simulate one in software by - * keeping a `red zone' pointer; if %sp becomes less than this, we panic. - * This is expensive and is only enabled when debugging. - */ -#define REDSIZE (8*96) /* some room for bouncing */ -#define REDSTACK 2048 /* size of `panic: stack overflow' region */ - .data -_C_LABEL(redzone): - .word _C_LABEL(idle_u) + REDSIZE -_C_LABEL(redstack): - .skip REDSTACK - .text -Lpanic_red: - .asciz "stack overflow" - _ALIGN - - /* set stack pointer redzone to base+minstack; alters base */ -#define SET_SP_REDZONE(base, tmp) \ - add base, REDSIZE, base; \ - sethi %hi(_C_LABEL(redzone)), tmp; \ - st base, [tmp + %lo(_C_LABEL(redzone))] - - /* variant with a constant */ -#define SET_SP_REDZONE_CONST(const, tmp1, tmp2) \ - set (const) + REDSIZE, tmp1; \ - sethi %hi(_C_LABEL(redzone)), tmp2; \ - st tmp1, [tmp2 + %lo(_C_LABEL(redzone))] - - /* check stack pointer against redzone (uses two temps) */ -#define CHECK_SP_REDZONE(t1, t2) \ - sethi %hi(_C_LABEL(redzone)), t1; \ - ld [t1 + %lo(_C_LABEL(redzone))], t2; \ - cmp %sp, t2; /* if sp >= t2, not in red zone */ \ - bgeu 7f; nop; /* and can continue normally */ \ - /* move to panic stack */ \ - st %g0, [t1 + %lo(_C_LABEL(redzone))]; \ - set _C_LABEL(redstack) + REDSTACK - 96, %sp; \ - /* prevent panic() from lowering ipl */ \ - sethi %hi(_C_LABEL(panicstr)), t2; \ - set Lpanic_red, t2; \ - st t2, [t1 + %lo(_C_LABEL(panicstr))]; \ - rd %psr, t1; /* t1 = splhigh() */ \ - or t1, PSR_PIL, t2; \ - wr t2, 0, %psr; \ - nop; nop; nop; \ - wr t2, PSR_ET, %psr; /* turn on traps */ \ - nop; nop; nop; \ - save %sp, -CCFSZ, %sp; /* preserve current window */ \ - sethi %hi(Lpanic_red), %o0; \ - call _C_LABEL(panic); or %o0, %lo(Lpanic_red), %o0; \ -7: - -#else - -#define SET_SP_REDZONE(base, tmp) -#define SET_SP_REDZONE_CONST(const, t1, t2) -#define CHECK_SP_REDZONE(t1, t2) -#endif - -/* - * The window code must verify user stack addresses before using them. - * A user stack pointer is invalid if: - * - it is not on an 8 byte boundary; - * - its pages (a register window, being 64 bytes, can occupy - * two pages) are not readable or writable. - * We define three separate macros here for testing user stack addresses. - * - * PTE_OF_ADDR locates a PTE, branching to a `bad address' - * handler if the stack pointer does not have a valid mapping; - * CMP_PTE_USER_READ compares the located PTE against `user read' mode; - * CMP_PTE_USER_WRITE compares the located PTE against `user write' mode. - * The compares give `equal' if read or write is OK. - * - * Note that the user stack pointer usually points into high addresses - * (top 3 bits all 1), so that is what we check first. - * - * The code below also assumes that PTE_OF_ADDR is safe in a delay - * slot; it is, at it merely sets its `pte' register to a temporary value. - */ - - /* input: addr, output: pte; aux: bad address label */ -#define PTE_OF_ADDR(addr, pte, tmp, bad) \ - srl addr, PDT_INDEX_SHIFT, pte; /* get segment */ \ - lda [%g0] ASI_PDBR, tmp; \ - nop; nop; /* XXX */ \ - sll pte, 3, pte; \ - add tmp, pte, tmp; /* get PT pointer */ \ - lda [tmp] ASI_PHYS_CACHED, pte; \ - tst pte; \ - be bad; /* bail if no PT */ \ - srl addr, (PT_INDEX_SHIFT - 2), tmp; \ - and tmp, ((1 << PT_INDEX_SIZE) -1) << 2, tmp; \ - add pte, tmp, pte; /* get PTE */ \ - lda [pte] ASI_PHYS_CACHED, pte; \ - nop; nop /* XXX */ - - /* input: pte; output: condition codes */ -#define CMP_PTE_USER_READ(pte, tmp, label) \ - and pte, PG_V | PG_S, pte; \ - cmp pte, PG_V - - /* input: pte; output: condition codes */ -#define CMP_PTE_USER_WRITE(pte, tmp, label) \ - and pte, PG_V | PG_S | PG_RO, pte; \ - cmp pte, PG_V - -#define INSERT_PTE(addr, pte) \ - sta addr, [%g0] ASI_FVAR; \ - sta pte, [%g0] ASI_GTLB_RANDOM - -/* - * The calculations in PTE_OF_ADDR and CMP_PTE_USER_* are rather slow: - * in particular, according to Gordon Irlam of the University of Adelaide - * in Australia, these consume at least 18 cycles on an SS1 and 37 on an - * SS2. Hence, we try to avoid them in the common case. - * - * A chunk of 64 bytes is on a single page if and only if: - * - * ((base + 64 - 1) & ~(NBPG-1)) == (base & ~(NBPG-1)) - * - * Equivalently (and faster to test), the low order bits (base & 4095) must - * be small enough so that the sum (base + 63) does not carry out into the - * upper page-address bits, i.e., - * - * (base & (NBPG-1)) < (NBPG - 63) - * - * so we allow testing that here. This macro is also assumed to be safe - * in a delay slot (modulo overwriting its temporary). - */ -#define SLT_IF_1PAGE_RW(addr, tmp, tmp1) \ - sethi %hi(~PAGE_MASK), tmp1; \ - andn addr, tmp1, tmp; \ - set PAGE_MASK - 62, tmp1; \ - cmp tmp, tmp1 - -/* - * Every trap that enables traps must set up stack space. - * If the trap is from user mode, this involves switching to the kernel - * stack for the current process, and we must also set cpcb->pcb_uw - * so that the window overflow handler can tell user windows from kernel - * windows. - * - * The number of user windows is: - * - * cpcb->pcb_uw = (cpcb->pcb_wim - 1 - CWP) % nwindows - * - * (where pcb_wim = log2(current %wim) and CWP = low 5 bits of %psr). - * We compute this expression by table lookup in uwtab[CWP - pcb_wim], - * which has been set up as: - * - * for i in [-nwin+1 .. nwin-1] - * uwtab[i] = (nwin - 1 - i) % nwin; - * - * (If you do not believe this works, try it for yourself.) - * - * We also keep one or two more tables: - * - * for i in 0..nwin-1 - * wmask[i] = 1 << ((i + 1) % nwindows); - * - * wmask[CWP] tells whether a `rett' would return into the invalid window. - */ - .data - .skip 32 ! alignment byte & negative indices -uwtab: .skip 32 ! u_char uwtab[-31..31]; -wmask: .skip 32 ! u_char wmask[0..31]; - - .text -/* - * Things begin to grow uglier.... - * - * Each trap handler may (always) be running in the trap window. - * If this is the case, it cannot enable further traps until it writes - * the register windows into the stack (or, if the stack is no good, - * the current pcb). - * - * ASSUMPTIONS: TRAP_SETUP() is called with: - * %l0 = %psr - * %l1 = return pc - * %l2 = return npc - * %l3 = (some value that must not be altered) - * which means we have 4 registers to work with. - * - * The `stackspace' argument is the number of stack bytes to allocate - * for register-saving, and must be at least -64 (and typically more, - * for global registers and %y). - * - * Trapframes should use -CCFSZ-80. (80 = sizeof(struct trapframe); - * see trap.h. This basically means EVERYONE. Interrupt frames could - * get away with less, but currently do not.) - * - * The basic outline here is: - * - * if (trap came from kernel mode) { - * if (we are in the trap window) - * save it away; - * %sp = %fp - stackspace; - * } else { - * compute the number of user windows; - * if (we are in the trap window) - * save it away; - * %sp = (top of kernel stack) - stackspace; - * } - * - * Again, the number of user windows is: - * - * cpcb->pcb_uw = (cpcb->pcb_wim - 1 - CWP) % nwindows - * - * (where pcb_wim = log2(current %wim) and CWP is the low 5 bits of %psr), - * and this is computed as `uwtab[CWP - pcb_wim]'. - * - * NOTE: if you change this code, you will have to look carefully - * at the window overflow and underflow handlers and make sure they - * have similar changes made as needed. - */ -#define CALL_CLEAN_TRAP_WINDOW \ - sethi %hi(clean_trap_window), %l7; \ - jmpl %l7 + %lo(clean_trap_window), %l4; \ - mov %g7, %l7 /* save %g7 in %l7 for clean_trap_window */ - -#define TRAP_SETUP(stackspace) \ - rd %wim, %l4; \ - mov 1, %l5; \ - sll %l5, %l0, %l5; \ - btst PSR_PS, %l0; \ - bz 1f; \ - btst %l5, %l4; \ - /* came from kernel mode; cond codes indicate trap window */ \ - bz,a 3f; \ - add %fp, stackspace, %sp; /* want to just set %sp */ \ - CALL_CLEAN_TRAP_WINDOW; /* but maybe need to clean first */ \ - b 3f; \ - add %fp, stackspace, %sp; \ -1: \ - /* came from user mode: compute pcb_nw */ \ - sethi %hi(_C_LABEL(cpcb)), %l6; \ - ld [%l6 + %lo(_C_LABEL(cpcb))], %l6; \ - ld [%l6 + PCB_WIM], %l5; \ - and %l0, 31, %l4; \ - sub %l4, %l5, %l5; \ - set uwtab, %l4; \ - ldub [%l4 + %l5], %l5; \ - st %l5, [%l6 + PCB_UW]; \ - /* cond codes still indicate whether in trap window */ \ - bz,a 2f; \ - sethi %hi(USPACE+(stackspace)), %l5; \ - /* yes, in trap window; must clean it */ \ - CALL_CLEAN_TRAP_WINDOW; \ - sethi %hi(_C_LABEL(cpcb)), %l6; \ - ld [%l6 + %lo(_C_LABEL(cpcb))], %l6; \ - sethi %hi(USPACE+(stackspace)), %l5; \ -2: \ - /* trap window is (now) clean: set %sp */ \ - or %l5, %lo(USPACE+(stackspace)), %l5; \ - add %l6, %l5, %sp; \ - SET_SP_REDZONE(%l6, %l5); \ -3: \ - CHECK_SP_REDZONE(%l6, %l5) - -/* - * Interrupt setup is almost exactly like trap setup, but we need to - * go to the interrupt stack if (a) we came from user mode or (b) we - * came from kernel mode on the kernel stack. - */ -#define INTR_SETUP(stackspace) \ - rd %wim, %l4; \ - mov 1, %l5; \ - sll %l5, %l0, %l5; \ - btst PSR_PS, %l0; \ - bz 1f; \ - btst %l5, %l4; \ - /* came from kernel mode; cond codes still indicate trap window */ \ - bz,a 0f; \ - sethi %hi(_C_LABEL(eintstack)), %l7; \ - CALL_CLEAN_TRAP_WINDOW; \ - sethi %hi(_C_LABEL(eintstack)), %l7; \ -0: /* now if %fp >= eintstack, we were on the kernel stack */ \ - cmp %fp, %l7; \ - bge,a 3f; \ - add %l7, stackspace, %sp; /* so switch to intstack */ \ - b 4f; \ - add %fp, stackspace, %sp; /* else stay on intstack */ \ -1: \ - /* came from user mode: compute pcb_nw */ \ - sethi %hi(_C_LABEL(cpcb)), %l6; \ - ld [%l6 + %lo(_C_LABEL(cpcb))], %l6; \ - ld [%l6 + PCB_WIM], %l5; \ - and %l0, 31, %l4; \ - sub %l4, %l5, %l5; \ - set uwtab, %l4; \ - ldub [%l4 + %l5], %l5; \ - st %l5, [%l6 + PCB_UW]; \ - /* cond codes still indicate whether in trap window */ \ - bz,a 2f; \ - sethi %hi(_C_LABEL(eintstack)), %l7; \ - /* yes, in trap window; must save regs */ \ - CALL_CLEAN_TRAP_WINDOW; \ - sethi %hi(_C_LABEL(eintstack)), %l7; \ -2: \ - add %l7, stackspace, %sp; \ -3: \ - SET_SP_REDZONE_CONST(_C_LABEL(intstack), %l6, %l5); \ -4: \ - CHECK_SP_REDZONE(%l6, %l5) - -/* - * Handler for making the trap window shiny clean. - * - * On entry: - * cpcb->pcb_nw = number of user windows - * %l0 = %psr - * %l1 must not be clobbered - * %l2 must not be clobbered - * %l3 must not be clobbered - * %l4 = address for `return' - * %l7 = saved %g7 (we put this in a delay slot above, to save work) - * - * On return: - * %wim has changed, along with cpcb->pcb_wim - * %g7 has been restored - * - * Normally, we push only one window. - */ -clean_trap_window: - mov %g5, %l5 ! save %g5 - mov %g6, %l6 ! ... and %g6 -/* mov %g7, %l7 ! ... and %g7 (already done for us) */ - sethi %hi(_C_LABEL(cpcb)), %g6 ! get current pcb - ld [%g6 + %lo(_C_LABEL(cpcb))], %g6 - - /* Figure out whether it is a user window (cpcb->pcb_uw > 0). */ - ld [%g6 + PCB_UW], %g7 - deccc %g7 - bge ctw_user - save %g0, %g0, %g0 ! in any case, enter window to save - - /* The window to be pushed is a kernel window. */ - std %i6, [%sp + (7*8)] - std %l0, [%sp + (0*8)] - -ctw_merge: - !! std %l0, [%sp + (0*8)] ! Done by delay slot or above - std %l2, [%sp + (1*8)] - std %l4, [%sp + (2*8)] - std %l6, [%sp + (3*8)] - std %i0, [%sp + (4*8)] - std %i2, [%sp + (5*8)] - std %i4, [%sp + (6*8)] - !! std %i6, [%sp + (7*8)] ! Done above or by StackGhost - - /* Set up new window invalid mask, and update cpcb->pcb_wim. */ - rd %psr, %g7 ! g7 = (junk << 5) + new_cwp - mov 1, %g5 ! g5 = 1 << new_cwp; - sll %g5, %g7, %g5 - wr %g5, 0, %wim ! setwim(g5); - and %g7, 31, %g7 ! cpcb->pcb_wim = g7 & 31; - sethi %hi(_C_LABEL(cpcb)), %g6 ! re-get current pcb - ld [%g6 + %lo(_C_LABEL(cpcb))], %g6 - st %g7, [%g6 + PCB_WIM] - nop - restore ! back to trap window - - mov %l5, %g5 ! restore g5 - mov %l6, %g6 ! ... and g6 - jmp %l4 + 8 ! return to caller - mov %l7, %g7 ! ... and g7 - /* NOTREACHED */ - - -ctw_stackghost: - !! StackGhost Encrypt - sethi %hi(_C_LABEL(cpcb)), %g6 ! get current *pcb - ld [%g6 + %lo(_C_LABEL(cpcb))], %g6 ! dereference *pcb - ld [%g6 + PCB_WCOOKIE], %l0 ! get window cookie - xor %l0, %i7, %i7 ! mix in cookie - b ctw_merge - std %i6, [%sp + (7*8)] - -ctw_user: - /* - * The window to be pushed is a user window. - * We must verify the stack pointer (alignment & permissions). - * See comments above definition of PTE_OF_ADDR. - */ - st %g7, [%g6 + PCB_UW] ! cpcb->pcb_uw--; - btst 7, %sp ! if not aligned, - bne ctw_invalid ! choke on it - EMPTY - - PTE_OF_ADDR(%sp, %g7, %g6, ctw_invalid) - CMP_PTE_USER_WRITE(%g7, %g5, NOP_ON_4M_2) ! likewise if not writable - bne ctw_invalid - nop - INSERT_PTE(%sp, %g7) - SLT_IF_1PAGE_RW(%sp, %g7, %g6) - bl,a ctw_stackghost ! all ok if only 1 - std %l0, [%sp] - add %sp, 7 * 8, %g5 ! check last addr too - PTE_OF_ADDR(%g5, %g7, %g6, ctw_invalid) - CMP_PTE_USER_WRITE(%g7, %g6, NOP_ON_4M_4) - INSERT_PTE(%g5, %g7) - be,a ctw_stackghost ! all ok: store <l0,l1> and merge - std %l0, [%sp] - - /* - * The window we wanted to push could not be pushed. - * Instead, save ALL user windows into the pcb. - * We will notice later that we did this, when we - * get ready to return from our trap or syscall. - * - * The code here is run rarely and need not be optimal. - */ -ctw_invalid: - /* - * Reread cpcb->pcb_uw. We decremented this earlier, - * so it is off by one. - */ - sethi %hi(_C_LABEL(cpcb)), %g6 ! re-get current pcb - ld [%g6 + %lo(_C_LABEL(cpcb))], %g6 - - ld [%g6 + PCB_UW], %g7 ! (number of user windows) - 1 - add %g6, PCB_RW, %g5 - - /* save g7+1 windows, starting with the current one */ -1: ! do { - std %l0, [%g5 + (0*8)] ! rw->rw_local[0] = l0; - std %l2, [%g5 + (1*8)] ! ... - std %l4, [%g5 + (2*8)] - std %l6, [%g5 + (3*8)] - std %i0, [%g5 + (4*8)] - std %i2, [%g5 + (5*8)] - std %i4, [%g5 + (6*8)] - - !! StackGhost Encrypt (PCP) - ! pcb already dereferenced in %g6 - ld [%g6 + PCB_WCOOKIE], %l0 ! get window cookie - xor %l0, %i7, %i7 ! mix in cookie - std %i6, [%g5 + (7*8)] - - deccc %g7 ! if (n > 0) save(), rw++; - bge,a 1b ! } while (--n >= 0); - save %g5, 64, %g5 - - /* stash sp for bottommost window */ - st %sp, [%g5 + 64 + (7*8)] - - /* set up new wim */ - rd %psr, %g7 ! g7 = (junk << 5) + new_cwp; - mov 1, %g5 ! g5 = 1 << new_cwp; - sll %g5, %g7, %g5 - wr %g5, 0, %wim ! wim = g5; - and %g7, 31, %g7 - st %g7, [%g6 + PCB_WIM] ! cpcb->pcb_wim = new_cwp; - - /* fix up pcb fields */ - ld [%g6 + PCB_UW], %g7 ! n = cpcb->pcb_uw; - add %g7, 1, %g5 - st %g5, [%g6 + PCB_NSAVED] ! cpcb->pcb_nsaved = n + 1; - st %g0, [%g6 + PCB_UW] ! cpcb->pcb_uw = 0; - - /* return to trap window */ -1: deccc %g7 ! do { - bge 1b ! restore(); - restore ! } while (--n >= 0); - - mov %l5, %g5 ! restore g5, g6, & g7, and return - mov %l6, %g6 - jmp %l4 + 8 - mov %l7, %g7 - /* NOTREACHED */ - -/* - * TLB miss handlers - * - * For now, they are the same - we simply extract the faulting PTE, and - * insert it at a random place into the TLB cache. - */ - -dtlb_miss: -itlb_miss: - lda [%g0] ASI_PDER, %l3 - lda [%g0] ASI_PTOR, %l4 - lda [%g0] ASI_PDBR, %l5 - lda [%l3] ASI_PHYS_CACHED, %l3 ! get PDE - add %l3, %l4, %l3 - lda [%l3] ASI_PHYS_CACHED, %l4 ! get PTE -#if 0 - or %l4, PG_U, %l4 ! set PG_U - sta %l4, [%l3] ASI_PHYS_CACHED ! and write modified PTE back -#endif - sta %l4, [%g0] ASI_GTLB_RANDOM ! insert into tlb - mov %l0, %psr ! restore PSR_CC - nop - RETT - -/* - * Double trap - * - * This usually happens during a TLB miss with traps disabled. - * We save a few registers to help debugging, and reset the machine. - */ - -double_trap: - set PROM_DATA_PA + SB_REGS, %l3 - sta %l0, [%l3] ASI_PHYS_BW - add %l3, 4, %l3 - sta %l1, [%l3] ASI_PHYS_BW - add %l3, 4, %l3 - sta %l2, [%l3] ASI_PHYS_BW - add %l3, 4, %l3 - lda [%g0] ASI_FCR, %l0 - sta %l0, [%l3] ASI_PHYS_BW - add %l3, 4, %l3 - lda [%g0] ASI_FVAR, %l0 - sta %l0, [%l3] ASI_PHYS_BW - add %l3, 4, %l3 - lda [%g0] ASI_FPAR, %l0 - sta %l0, [%l3] ASI_PHYS_BW - add %l3, 4, %l3 - lda [%g0] ASI_FPSR, %l0 - sta %l0, [%l3] ASI_PHYS_BW - add %l3, 4, %l3 - lda [%g0] ASI_PDER, %l0 - sta %l0, [%l3] ASI_PHYS_BW - add %l3, 4, %l3 - lda [%g0] ASI_PTOR, %l0 - sta %l0, [%l3] ASI_PHYS_BW - add %l3, 4, %l3 - lda [%g0] ASI_PDBR, %l0 - sta %l0, [%l3] ASI_PHYS_BW - add %l3, 4, %l3 - lda [%g0] ASI_MMCR, %l0 - sta %l0, [%l3] ASI_PHYS_BW - add %l3, 4, %l3 - sta %g0, [%l3] ASI_PHYS_BW - add %l3, 4, %l3 - sta %g1, [%l3] ASI_PHYS_BW - add %l3, 4, %l3 - sta %g2, [%l3] ASI_PHYS_BW - add %l3, 4, %l3 - sta %g3, [%l3] ASI_PHYS_BW - add %l3, 4, %l3 - sta %g4, [%l3] ASI_PHYS_BW - add %l3, 4, %l3 - sta %g5, [%l3] ASI_PHYS_BW - add %l3, 4, %l3 - sta %g6, [%l3] ASI_PHYS_BW - add %l3, 4, %l3 - sta %g7, [%l3] ASI_PHYS_BW - add %l3, 4, %l3 - sta %o0, [%l3] ASI_PHYS_BW - add %l3, 4, %l3 - sta %o1, [%l3] ASI_PHYS_BW - add %l3, 4, %l3 - sta %o2, [%l3] ASI_PHYS_BW - add %l3, 4, %l3 - sta %o3, [%l3] ASI_PHYS_BW - add %l3, 4, %l3 - sta %o4, [%l3] ASI_PHYS_BW - add %l3, 4, %l3 - sta %o5, [%l3] ASI_PHYS_BW - add %l3, 4, %l3 - sta %o6, [%l3] ASI_PHYS_BW - add %l3, 4, %l3 - sta %o7, [%l3] ASI_PHYS_BW - - wr %g0, %wim - nop; nop; nop - restore - - set GLU_RESET, %o0 - sta %g0, [%o0] ASI_PHYS_IO -1: b 1b - nop - -/* - * Each memory access (text or data) fault, from user or kernel mode, - * comes here. We read the error register and figure out what has - * happened. - * - * This cannot be done from C code since we must not enable traps (and - * hence may not use the `save' instruction) until we have decided that - * the error is or is not an asynchronous one that showed up after a - * synchronous error, but which must be handled before the sync err. - * - * Most memory faults are user mode text or data faults, which can cause - * signal delivery or ptracing, for which we must build a full trapframe. - * It does not seem worthwhile to work to avoid this in the other cases, - * so we store all the %g registers on the stack immediately. - * - * On entry: - * %l0 = %psr - * %l1 = return pc - * %l2 = return npc - * %l3 = T_TEXTFAULT or T_DATAFAULT - * - * Internal: - * %l4 = %y, until we call mem_access_fault (then onto trapframe) - * %l5 = IE_reg_addr, if async mem error - * - */ - -mem_fault: - /* - * This ends up close to slowtrap (except for ECC errors), - * but we don't invoke trap() in the end. - */ - - TRAP_SETUP(-CCFSZ-80) - - st %g1, [%sp + CCFSZ + 20] ! save g1 - rd %y, %l4 ! save y - - std %g2, [%sp + CCFSZ + 24] ! save g2, g3 - lda [%g0] ASI_FCR, %o1 ! fault cause reg - std %g4, [%sp + CCFSZ + 32] ! (sneak g4,g5 in here) - lda [%g0] ASI_FVAR, %o2 ! virt addr - btst FCR_ECC_SINGLE | FCR_ECC_MULTIPLE, %o1 ! ECC memory error? - std %g6, [%sp + CCFSZ + 40] - CLEAR_FCR - bz normal_mem_fault ! no, just a regular fault - wr %l0, PSR_ET, %psr ! (and reenable traps) - - /* - * We got an ECC memory error. - */ - clr %o3 - clr %o4 - call _C_LABEL(ecc_fault) ! ecc_fault(0, fcr, va, 0, 0) - clr %o0 - - b mem_fault_return - wr %l4, 0, %y - -normal_mem_fault: - /* - * call C code to deal with the trap. - * Must finish trap frame (psr,pc,npc,%y,%o0..%o7) in case - * we decide to deliver a signal or ptrace the process. - * %g1..%g7 were already set up above. - */ - std %l0, [%sp + CCFSZ + 0] ! set tf.tf_psr, tf.tf_pc - mov %l3, %o0 ! (argument: type) - st %l2, [%sp + CCFSZ + 8] ! set tf.tf_npc - st %l4, [%sp + CCFSZ + 12] ! set tf.tf_y - mov %l1, %o3 ! (argument: pc) - std %i0, [%sp + CCFSZ + 48] ! tf.tf_out[0], etc - std %i2, [%sp + CCFSZ + 56] - mov %l0, %o4 ! (argument: psr) - std %i4, [%sp + CCFSZ + 64] - std %i6, [%sp + CCFSZ + 72] - call _C_LABEL(mem_access_fault) ! mem_access_fault(type, fcr, - ! va, pc, psr, &tf); - add %sp, CCFSZ, %o5 ! (argument: &tf) - - ldd [%sp + CCFSZ + 0], %l0 ! load new values - ldd [%sp + CCFSZ + 8], %l2 - wr %l4, 0, %y - ldd [%sp + CCFSZ + 48], %i0 - ldd [%sp + CCFSZ + 56], %i2 - ldd [%sp + CCFSZ + 64], %i4 - ldd [%sp + CCFSZ + 72], %i6 -mem_fault_return: - ld [%sp + CCFSZ + 20], %g1 - ldd [%sp + CCFSZ + 24], %g2 - ldd [%sp + CCFSZ + 32], %g4 - ldd [%sp + CCFSZ + 40], %g6 - - b return_from_trap ! go return - wr %l0, 0, %psr ! (but first disable traps again) - - -/* - * fp_exception has to check to see if we are trying to save - * the FP state, and if so, continue to save the FP state. - * - * We do not even bother checking to see if we were in kernel mode, - * since users have no access to the special_fp_store instruction. - * - * This whole idea was stolen from Sprite. - */ -fp_exception: - set special_fp_store, %l4 ! see if we came from the special one - cmp %l1, %l4 ! pc == special_fp_store? - bne slowtrap ! no, go handle per usual - EMPTY - sethi %hi(savefpcont), %l4 ! yes, "return" to the special code - or %lo(savefpcont), %l4, %l4 - jmp %l4 - rett %l4 + 4 - -/* - * slowtrap() builds a trap frame and calls trap(). - * This is called `slowtrap' because it *is*.... - * We have to build a full frame for ptrace(), for instance. - * - * Registers: - * %l0 = %psr - * %l1 = return pc - * %l2 = return npc - * %l3 = trap code - */ -slowtrap: - TRAP_SETUP(-CCFSZ-80) - /* - * Phew, ready to enable traps and call C code. - */ - mov %l3, %o0 ! put type in %o0 for later -Lslowtrap_reenter: - wr %l0, PSR_ET, %psr ! traps on again - std %l0, [%sp + CCFSZ] ! tf.tf_psr = psr; tf.tf_pc = ret_pc; - rd %y, %l3 - std %l2, [%sp + CCFSZ + 8] ! tf.tf_npc = return_npc; tf.tf_y = %y; - st %g1, [%sp + CCFSZ + 20] - std %g2, [%sp + CCFSZ + 24] - std %g4, [%sp + CCFSZ + 32] - std %g6, [%sp + CCFSZ + 40] - std %i0, [%sp + CCFSZ + 48] - mov %l0, %o1 ! (psr) - std %i2, [%sp + CCFSZ + 56] - mov %l1, %o2 ! (pc) - std %i4, [%sp + CCFSZ + 64] - add %sp, CCFSZ, %o3 ! (&tf) - call _C_LABEL(trap) ! trap(type, psr, pc, &tf) - std %i6, [%sp + CCFSZ + 72] - - ldd [%sp + CCFSZ], %l0 ! load new values - ldd [%sp + CCFSZ + 8], %l2 - wr %l3, 0, %y - ld [%sp + CCFSZ + 20], %g1 - ldd [%sp + CCFSZ + 24], %g2 - ldd [%sp + CCFSZ + 32], %g4 - ldd [%sp + CCFSZ + 40], %g6 - ldd [%sp + CCFSZ + 48], %i0 - ldd [%sp + CCFSZ + 56], %i2 - ldd [%sp + CCFSZ + 64], %i4 - ldd [%sp + CCFSZ + 72], %i6 - b return_from_trap - wr %l0, 0, %psr - -/* - * Do a `software' trap by re-entering the trap code, possibly first - * switching from interrupt stack to kernel stack. This is used for - * scheduling and signal ASTs (which generally occur from softclock or - * tty or net interrupts) and register window saves (which might occur - * from anywhere). - * - * The current window is the trap window, and it is by definition clean. - * We enter with the trap type in %o0. All we have to do is jump to - * Lslowtrap_reenter above, but maybe after switching stacks.... - */ -softtrap: - sethi %hi(_C_LABEL(eintstack)), %l7 - cmp %sp, %l7 - bge Lslowtrap_reenter - EMPTY - sethi %hi(_C_LABEL(cpcb)), %l6 - ld [%l6 + %lo(_C_LABEL(cpcb))], %l6 - set USPACE-CCFSZ-80, %l5 - add %l6, %l5, %l7 - SET_SP_REDZONE(%l6, %l5) - b Lslowtrap_reenter - mov %l7, %sp - -#ifdef KGDB -/* - * bpt is entered on all breakpoint traps. - * If this is a kernel breakpoint, we do not want to call trap(). - * Among other reasons, this way we can set breakpoints in trap(). - */ -bpt: - btst PSR_PS, %l0 ! breakpoint from kernel? - bz slowtrap ! no, go do regular trap - nop - - /* - * Build a trap frame for kgdb_trap_glue to copy. - * Enable traps but set ipl high so that we will not - * see interrupts from within breakpoints. - */ - TRAP_SETUP(-CCFSZ-80) - or %l0, PSR_PIL, %l4 ! splhigh() - wr %l4, 0, %psr ! the manual claims that this - nop; nop; nop - wr %l4, PSR_ET, %psr ! song and dance is necessary - std %l0, [%sp + CCFSZ + 0] ! tf.tf_psr, tf.tf_pc - mov %l3, %o0 ! trap type arg for kgdb_trap_glue - rd %y, %l3 - std %l2, [%sp + CCFSZ + 8] ! tf.tf_npc, tf.tf_y - rd %wim, %l3 - st %l3, [%sp + CCFSZ + 16] ! tf.tf_wim (a kgdb-only r/o field) - st %g1, [%sp + CCFSZ + 20] ! tf.tf_global[1] - std %g2, [%sp + CCFSZ + 24] ! etc - std %g4, [%sp + CCFSZ + 32] - std %g6, [%sp + CCFSZ + 40] - std %i0, [%sp + CCFSZ + 48] ! tf.tf_in[0..1] - std %i2, [%sp + CCFSZ + 56] ! etc - std %i4, [%sp + CCFSZ + 64] - std %i6, [%sp + CCFSZ + 72] - - /* - * Now call kgdb_trap_glue(); if it returns, call trap(). - */ - mov %o0, %l3 ! gotta save trap type - call _C_LABEL(kgdb_trap_glue) ! kgdb_trap_glue(type, &trapframe) - add %sp, CCFSZ, %o1 ! (&trapframe) - - /* - * Use slowtrap to call trap---but first erase our tracks - * (put the registers back the way they were). - */ - mov %l3, %o0 ! slowtrap will need trap type - ld [%sp + CCFSZ + 12], %l3 - wr %l3, 0, %y - ld [%sp + CCFSZ + 20], %g1 - ldd [%sp + CCFSZ + 24], %g2 - ldd [%sp + CCFSZ + 32], %g4 - b Lslowtrap_reenter - ldd [%sp + CCFSZ + 40], %g6 - -/* - * Enter kernel breakpoint. Write all the windows (not including the - * current window) into the stack, so that backtrace works. Copy the - * supplied trap frame to the kgdb stack and switch stacks. - * - * kgdb_trap_glue(type, tf0) - * int type; - * struct trapframe *tf0; - */ - .globl _C_LABEL(kgdb_trap_glue) -_C_LABEL(kgdb_trap_glue): - save %sp, -CCFSZ, %sp - - call _C_LABEL(write_all_windows) - mov %sp, %l4 ! %l4 = current %sp - - /* copy trapframe to top of kgdb stack */ - set _C_LABEL(kgdb_stack) + KGDB_STACK_SIZE - 80, %l0 - ! %l0 = tfcopy -> end_of_kgdb_stack - mov 80, %l1 -1: ldd [%i1], %l2 - inc 8, %i1 - deccc 8, %l1 - std %l2, [%l0] - bg 1b - inc 8, %l0 - -#ifdef DEBUG - /* save old red zone and then turn it off */ - sethi %hi(_C_LABEL(redzone)), %l7 - ld [%l7 + %lo(_C_LABEL(redzone))], %l6 - st %g0, [%l7 + %lo(_C_LABEL(redzone))] -#endif - /* switch to kgdb stack */ - add %l0, -CCFSZ-80, %sp - - /* if (kgdb_trap(type, tfcopy)) kgdb_rett(tfcopy); */ - mov %i0, %o0 - call _C_LABEL(kgdb_trap) - add %l0, -80, %o1 - tst %o0 - bnz,a kgdb_rett - add %l0, -80, %g1 - - /* - * kgdb_trap() did not handle the trap at all so the stack is - * still intact. A simple `restore' will put everything back, - * after we reset the stack pointer. - */ - mov %l4, %sp -#ifdef DEBUG - st %l6, [%l7 + %lo(_C_LABEL(redzone))] ! restore red zone -#endif - ret - restore - -/* - * Return from kgdb trap. This is sort of special. - * - * We know that kgdb_trap_glue wrote the window above it, so that we will - * be able to (and are sure to have to) load it up. We also know that we - * came from kernel land and can assume that the %fp (%i6) we load here - * is proper. We must also be sure not to lower ipl (it is at splhigh()) - * until we have traps disabled, due to the SPARC taking traps at the - * new ipl before noticing that PSR_ET has been turned off. We are on - * the kgdb stack, so this could be disastrous. - * - * Note that the trapframe argument in %g1 points into the current stack - * frame (current window). We abandon this window when we move %g1->tf_psr - * into %psr, but we will not have loaded the new %sp yet, so again traps - * must be disabled. - */ -kgdb_rett: - rd %psr, %g4 ! turn off traps - wr %g4, PSR_ET, %psr - /* use the three-instruction delay to do something useful */ - ld [%g1], %g2 ! pick up new %psr - ld [%g1 + 12], %g3 ! set %y - wr %g3, 0, %y -#ifdef DEBUG - st %l6, [%l7 + %lo(_C_LABEL(redzone))] ! and restore red zone -#endif - wr %g0, 0, %wim ! enable window changes - nop; nop; nop - /* now safe to set the new psr (changes CWP, leaves traps disabled) */ - wr %g2, 0, %psr ! set rett psr (including cond codes) - /* 3 instruction delay before we can use the new window */ -/*1*/ ldd [%g1 + 24], %g2 ! set new %g2, %g3 -/*2*/ ldd [%g1 + 32], %g4 ! set new %g4, %g5 -/*3*/ ldd [%g1 + 40], %g6 ! set new %g6, %g7 - - /* now we can use the new window */ - mov %g1, %l4 - ld [%l4 + 4], %l1 ! get new pc - ld [%l4 + 8], %l2 ! get new npc - ld [%l4 + 20], %g1 ! set new %g1 - - /* set up returnee's out registers, including its %sp */ - ldd [%l4 + 48], %i0 - ldd [%l4 + 56], %i2 - ldd [%l4 + 64], %i4 - ldd [%l4 + 72], %i6 - - /* load returnee's window, making the window above it be invalid */ - restore - restore %g0, 1, %l1 ! move to inval window and set %l1 = 1 - rd %psr, %l0 - sll %l1, %l0, %l1 - wr %l1, 0, %wim ! %wim = 1 << (%psr & 31) - sethi %hi(_C_LABEL(cpcb)), %l1 - ld [%l1 + %lo(_C_LABEL(cpcb))], %l1 - and %l0, 31, %l0 ! CWP = %psr & 31; - st %l0, [%l1 + PCB_WIM] ! cpcb->pcb_wim = CWP; - save %g0, %g0, %g0 ! back to window to reload - LOADWIN(%sp) - save %g0, %g0, %g0 ! back to trap window - /* note, we have not altered condition codes; safe to just rett */ - RETT -#endif - -/* - * syscall() builds a trap frame and calls syscall(). - * sun_syscall is same but delivers sun system call number - * XXX should not have to save&reload ALL the registers just for - * ptrace... - */ -_C_LABEL(_syscall): - TRAP_SETUP(-CCFSZ-80) - wr %l0, PSR_ET, %psr - std %l0, [%sp + CCFSZ + 0] ! tf_psr, tf_pc - rd %y, %l3 - std %l2, [%sp + CCFSZ + 8] ! tf_npc, tf_y - st %g1, [%sp + CCFSZ + 20] ! tf_g[1] - std %g2, [%sp + CCFSZ + 24] ! tf_g[2], tf_g[3] - std %g4, [%sp + CCFSZ + 32] ! etc - std %g6, [%sp + CCFSZ + 40] - mov %g1, %o0 ! (code) - std %i0, [%sp + CCFSZ + 48] - add %sp, CCFSZ, %o1 ! (&tf) - std %i2, [%sp + CCFSZ + 56] - mov %l1, %o2 ! (pc) - std %i4, [%sp + CCFSZ + 64] - call _C_LABEL(syscall) ! syscall(code, &tf, pc, suncompat) - std %i6, [%sp + CCFSZ + 72] - ! now load em all up again, sigh - ldd [%sp + CCFSZ + 0], %l0 ! new %psr, new pc - ldd [%sp + CCFSZ + 8], %l2 ! new npc, new %y - wr %l3, 0, %y - /* see `proc_trampoline' for the reason for this label */ -return_from_syscall: - ld [%sp + CCFSZ + 20], %g1 - ldd [%sp + CCFSZ + 24], %g2 - ldd [%sp + CCFSZ + 32], %g4 - ldd [%sp + CCFSZ + 40], %g6 - ldd [%sp + CCFSZ + 48], %i0 - ldd [%sp + CCFSZ + 56], %i2 - ldd [%sp + CCFSZ + 64], %i4 - ldd [%sp + CCFSZ + 72], %i6 - b return_from_trap - wr %l0, 0, %psr - -/* - * Interrupts. Software interrupts must be cleared from the software - * interrupt enable register. Rather than calling ienab_bic for each, - * we do them in-line before enabling traps. - * - * After preliminary setup work, the interrupt is passed to each - * registered handler in turn. These are expected to return 1 if they - * took care of the interrupt, 0 if they didn't, and -1 if the device - * isn't sure. If a handler claims the interrupt, we exit - * (hardware interrupts are latched in the requestor so we'll - * just take another interrupt in the unlikely event of simultaneous - * interrupts from two different devices at the same level). If we go - * through all the registered handlers and no one claims it, we report a - * stray interrupt. This is more or less done as: - * - * for (ih = intrhand[intlev]; ih; ih = ih->ih_next) - * if ((*ih->ih_fun)(ih->ih_arg ? ih->ih_arg : &frame)) - * return; - * strayintr(&frame); - * - * Software interrupts are almost the same with three exceptions: - * (1) we clear the interrupt from the software interrupt enable - * register before calling any handler (we have to clear it first - * to avoid an interrupt-losing race), - * (2) we always call all the registered handlers (there is no way - * to tell if the single bit in the software interrupt register - * represents one or many requests) - * (3) we never announce a stray interrupt (because of (1), another - * interrupt request can come in while we're in the handler. If - * the handler deals with everything for both the original & the - * new request, we'll erroneously report a stray interrupt when - * we take the software interrupt for the new request. - * - * Inputs: - * %l0 = %psr - * %l1 = return pc - * %l2 = return npc - * %l3 = interrupt level - * (software interrupt only) %l4 = bits to clear in interrupt register - * - * Internal: - * %l4, %l5: local variables - * %l6 = %y - * %l7 = %g1 - * %g2..%g7 go to stack - * - * An interrupt frame is built in the space for a full trapframe; - * this contains the psr, pc, npc, and interrupt level. - */ -softintr_kap: - sethi %hi(_C_LABEL(kap_sir)), %l6 - mov 1, %l5 - sll %l5, %l4, %l5 ! l5 = 1 << (intno - 1) - ld [%l6 + %lo(_C_LABEL(kap_sir))], %l4 - andn %l4, %l5, %l4 ! clear bit - /* skip loop if kap_sir becomes zero */ - clr %l5 ! intnum = 0; - cmp %l4, 0 - be 2f - st %l4, [%l6 + %lo(_C_LABEL(kap_sir))] - /* now find out the topmost bit set in kap_sir */ -1: srl %l4, 1, %l4 ! while (sir >>= 1) - cmp %l4, 0 - bne 1b - inc %l5 ! intnum++; -2: set GLU_ICR, %l6 - lda [%l6] ASI_PHYS_IO, %l4 ! read icr - srl %l4, 24, %l4 - andn %l4, GICR_DISPATCH_MASK, %l4 ! clear softintr bits - or %l4, %l5, %l4 ! put our number - sll %l4, 24, %l4 - sta %l4, [%l6] ASI_PHYS_IO ! write back icr - -softintr_common: - INTR_SETUP(-CCFSZ-80) - std %g2, [%sp + CCFSZ + 24] ! save registers - INCR(_C_LABEL(uvmexp)+V_INTR) ! cnt.v_intr++; (clobbers %o0,%o1) - mov %g1, %l7 - rd %y, %l6 - std %g4, [%sp + CCFSZ + 32] - andn %l0, PSR_PIL, %l4 ! %l4 = psr & ~PSR_PIL | - sll %l3, 8, %l5 ! intlev << IPLSHIFT - std %g6, [%sp + CCFSZ + 40] - or %l5, %l4, %l4 ! ; - wr %l4, 0, %psr ! the manual claims this - nop; nop; nop - wr %l4, PSR_ET, %psr ! song and dance is necessary - std %l0, [%sp + CCFSZ + 0] ! set up intrframe/clockframe - sll %l3, 2, %l5 - std %l2, [%sp + CCFSZ + 8] - set _C_LABEL(intrhand), %l4 ! %l4 = intrhand[intlev]; - ld [%l4 + %l5], %l4 - b 3f - st %fp, [%sp + CCFSZ + 16] - -1: rd %psr, %o1 - ld [%l4 + IH_IPL], %o0 - and %o1, ~PSR_PIL, %o1 - wr %o1, %o0, %psr - ld [%l4 + IH_ARG], %o0 - ld [%l4 + IH_FUN], %o1 - tst %o0 - bz,a 2f - add %sp, CCFSZ, %o0 -2: jmpl %o1, %o7 ! (void)(*ih->ih_fun)(...) - nop - mov %l4, %l3 - ldd [%l3 + IH_COUNT], %l4 - inccc %l5 - addx %l4, 0, %l4 - std %l4, [%l3 + IH_COUNT] - ld [%l3 + IH_NEXT], %l4 ! and ih = ih->ih_next -3: tst %l4 ! while ih != NULL - bnz 1b - nop - mov %l7, %g1 - wr %l6, 0, %y - ldd [%sp + CCFSZ + 24], %g2 - ldd [%sp + CCFSZ + 32], %g4 - ldd [%sp + CCFSZ + 40], %g6 - b return_from_trap - wr %l0, 0, %psr - - /* - * _sparc_interrupt{44c,4m} is exported for paranoia checking - * (see intr.c). - */ - .globl _C_LABEL(sparc_interrupt44c) -_C_LABEL(sparc_interrupt44c): -_C_LABEL(sparc_interrupt_common): -sparc_interruptkap: - INTR_SETUP(-CCFSZ-80) - std %g2, [%sp + CCFSZ + 24] ! save registers - INCR(_C_LABEL(uvmexp)+V_INTR) ! cnt.v_intr++; (clobbers %o0,%o1) - mov %g1, %l7 - rd %y, %l6 - std %g4, [%sp + CCFSZ + 32] - andn %l0, PSR_PIL, %l4 ! %l4 = psr & ~PSR_PIL | - sll %l3, 8, %l5 ! intlev << IPLSHIFT - std %g6, [%sp + CCFSZ + 40] - or %l5, %l4, %l4 ! ; - wr %l4, 0, %psr ! the manual claims this - nop; nop; nop - wr %l4, PSR_ET, %psr ! song and dance is necessary - std %l0, [%sp + CCFSZ + 0] ! set up intrframe/clockframe - sll %l3, 2, %l5 - std %l2, [%sp + CCFSZ + 8] ! set up intrframe/clockframe - set _C_LABEL(intrhand), %l4 ! %l4 = intrhand[intlev]; - ld [%l4 + %l5], %l4 - clr %l5 ! %l5 = 0 - b 3f - st %fp, [%sp + CCFSZ + 16] - -1: rd %psr, %o1 - ld [%l4 + IH_IPL], %o0 - and %o1, ~PSR_PIL, %o1 - wr %o1, %o0, %psr - ld [%l4 + IH_ARG], %o0 - ld [%l4 + IH_FUN], %o1 - tst %o0 - bz,a 2f - add %sp, CCFSZ, %o0 -2: jmpl %o1, %o7 ! handled = (*ih->ih_fun)(...) - nop - cmp %o0, 1 - bge 4f ! if (handled >= 1) break - or %o0, %l5, %l5 ! and %l5 |= handled - ld [%l4 + IH_NEXT], %l4 ! and ih = ih->ih_next -3: tst %l4 - bnz 1b ! while (ih) - nop - tst %l5 ! if (handled) break - bnz 5f - nop - call _C_LABEL(strayintr) ! strayintr(&intrframe) - add %sp, CCFSZ, %o0 -5: /* all done: restore registers and go return */ - mov %l7, %g1 - wr %l6, 0, %y - ldd [%sp + CCFSZ + 24], %g2 - ldd [%sp + CCFSZ + 32], %g4 - ldd [%sp + CCFSZ + 40], %g6 - b return_from_trap - wr %l0, 0, %psr -4: - mov %l4, %l3 - ldd [%l3 + IH_COUNT], %l4 - inccc %l5 - addx %l4, 0, %l4 - b 5b - std %l4, [%l3 + IH_COUNT] - -/* - * Level 15 interrupt. An async memory error has occurred; - * take care of it (typically by panicking, but hey...). - * %l0 = %psr - * %l1 = return pc - * %l2 = return npc - * %l3 = 15 * 4 (why? just because!) - * - * Internal: - * %l4 = %y - * %l5 = %g1 - * %l6 = %g6 - * %l7 = %g7 - * g2, g3, g4, g5 go to stack - * - * This code is almost the same as that in mem_access_fault, - * except that we already know the problem is not a `normal' fault, - * and that we must be extra-careful with interrupt enables. - */ - -nmi: - INTR_SETUP(-CCFSZ-80) - INCR(_C_LABEL(uvmexp)+V_INTR) ! cnt.v_intr++; (clobbers %o0,%o1) - /* XXX - * We should check for NMI set in the iGLU BSR, and clear it if set. - */ - - /* - * Level 15 interrupts are nonmaskable, so with traps off, - * disable all interrupts to prevent recursion. - */ - wr %l0, PSR_ET, %psr ! okay, turn traps on again - - std %g2, [%sp + CCFSZ + 0] ! save g2, g3 - rd %y, %l4 ! save y - - std %g4, [%sp + CCFSZ + 8] ! save g4,g5 - mov %g1, %l5 ! save g1,g6,g7 - mov %g6, %l6 - mov %g7, %l7 - -nmi_common: - ! and call C code - call _C_LABEL(ecc_fault) - clr %o0 - - mov %l5, %g1 ! restore g1 through g7 - ldd [%sp + CCFSZ + 0], %g2 - ldd [%sp + CCFSZ + 8], %g4 - wr %l0, 0, %psr ! re-disable traps - mov %l6, %g6 - mov %l7, %g7 - - b return_from_trap - wr %l4, 0, %y ! restore y - -#ifdef GPROF - .globl window_of, winof_user - .globl window_uf, winuf_user, winuf_ok, winuf_invalid - .globl return_from_trap, rft_kernel, rft_user, rft_invalid - .globl softtrap, slowtrap - .globl clean_trap_window, _C_LABEL(_syscall) -#endif - -/* - * Window overflow trap handler. - * %l0 = %psr - * %l1 = return pc - * %l2 = return npc - */ -window_of: -#ifdef TRIVIAL_WINDOW_OVERFLOW_HANDLER - /* a trivial version that assumes %sp is ok */ - /* (for testing only!) */ - save %g0, %g0, %g0 - std %l0, [%sp + (0*8)] - rd %psr, %l0 - mov 1, %l1 - sll %l1, %l0, %l0 - wr %l0, 0, %wim - std %l2, [%sp + (1*8)] - std %l4, [%sp + (2*8)] - std %l6, [%sp + (3*8)] - std %i0, [%sp + (4*8)] - std %i2, [%sp + (5*8)] - std %i4, [%sp + (6*8)] - std %i6, [%sp + (7*8)] - restore - RETT -#else - /* - * This is similar to TRAP_SETUP, but we do not want to spend - * a lot of time, so we have separate paths for kernel and user. - * We also know for sure that the window has overflowed. - */ - btst PSR_PS, %l0 - bz winof_user - sethi %hi(clean_trap_window), %l7 - - /* - * Overflow from kernel mode. Call clean_trap_window to - * do the dirty work, then just return, since we know prev - * window is valid. clean_trap_windows might dump all *user* - * windows into the pcb, but we do not care: there is at - * least one kernel window (a trap or interrupt frame!) - * above us. - */ - jmpl %l7 + %lo(clean_trap_window), %l4 - mov %g7, %l7 ! for clean_trap_window - - wr %l0, 0, %psr ! put back the @%*! cond. codes - nop; nop; nop ! (let them settle in) - RETT - -winof_user: - /* - * Overflow from user mode. - * If clean_trap_window dumps the registers into the pcb, - * rft_user will need to call trap(), so we need space for - * a trap frame. We also have to compute pcb_nw. - * - * SHOULD EXPAND IN LINE TO AVOID BUILDING TRAP FRAME ON - * `EASY' SAVES - */ - sethi %hi(_C_LABEL(cpcb)), %l6 - ld [%l6 + %lo(_C_LABEL(cpcb))], %l6 - ld [%l6 + PCB_WIM], %l5 - and %l0, 31, %l3 - sub %l3, %l5, %l5 /* l5 = CWP - pcb_wim */ - set uwtab, %l4 - ldub [%l4 + %l5], %l5 /* l5 = uwtab[l5] */ - st %l5, [%l6 + PCB_UW] - jmpl %l7 + %lo(clean_trap_window), %l4 - mov %g7, %l7 ! for clean_trap_window - sethi %hi(_C_LABEL(cpcb)), %l6 - ld [%l6 + %lo(_C_LABEL(cpcb))], %l6 - set USPACE-CCFSZ-80, %l5 - add %l6, %l5, %sp /* over to kernel stack */ - CHECK_SP_REDZONE(%l6, %l5) - - /* - * Copy return_from_trap far enough to allow us - * to jump directly to rft_user_or_recover_pcb_windows - * (since we know that is where we are headed). - */ -! and %l0, 31, %l3 ! still set (clean_trap_window - ! leaves this register alone) - set wmask, %l6 - ldub [%l6 + %l3], %l5 ! %l5 = 1 << ((CWP + 1) % nwindows) - b rft_user_or_recover_pcb_windows - rd %wim, %l4 ! (read %wim first) -#endif /* end `real' version of window overflow trap handler */ - -/* - * Window underflow trap handler. - * %l0 = %psr - * %l1 = return pc - * %l2 = return npc - * - * A picture: - * - * T R I X - * 0 0 0 1 0 0 0 (%wim) - * [bit numbers increase towards the right; - * `restore' moves right & `save' moves left] - * - * T is the current (Trap) window, R is the window that attempted - * a `Restore' instruction, I is the Invalid window, and X is the - * window we want to make invalid before we return. - * - * Since window R is valid, we cannot use rft_user to restore stuff - * for us. We have to duplicate its logic. YUCK. - * - * Incidentally, TRIX are for kids. Silly rabbit! - */ -window_uf: -#ifdef TRIVIAL_WINDOW_UNDERFLOW_HANDLER - wr %g0, 0, %wim ! allow us to enter I - restore ! to R - nop - nop - restore ! to I - restore %g0, 1, %l1 ! to X - rd %psr, %l0 - sll %l1, %l0, %l0 - wr %l0, 0, %wim - save %g0, %g0, %g0 ! back to I - LOADWIN(%sp) - save %g0, %g0, %g0 ! back to R - save %g0, %g0, %g0 ! back to T - RETT -#else - wr %g0, 0, %wim ! allow us to enter I - btst PSR_PS, %l0 - restore ! enter window R - bz winuf_user - restore ! enter window I - - /* - * Underflow from kernel mode. Just recover the - * registers and go (except that we have to update - * the blasted user pcb fields). - */ - restore %g0, 1, %l1 ! enter window X, then set %l1 to 1 - rd %psr, %l0 ! cwp = %psr & 31; - and %l0, 31, %l0 - sll %l1, %l0, %l1 ! wim = 1 << cwp; - wr %l1, 0, %wim ! setwim(wim); - sethi %hi(_C_LABEL(cpcb)), %l1 - ld [%l1 + %lo(_C_LABEL(cpcb))], %l1 - st %l0, [%l1 + PCB_WIM] ! cpcb->pcb_wim = cwp; - save %g0, %g0, %g0 ! back to window I - LOADWIN(%sp) - save %g0, %g0, %g0 ! back to R - save %g0, %g0, %g0 ! and then to T - wr %l0, 0, %psr ! fix those cond codes.... - nop; nop; nop ! (let them settle in) - RETT - -winuf_user: - /* - * Underflow from user mode. - * - * We cannot use rft_user (as noted above) because - * we must re-execute the `restore' instruction. - * Since it could be, e.g., `restore %l0,0,%l0', - * it is not okay to touch R's registers either. - * - * We are now in window I. - */ - btst 7, %sp ! if unaligned, it is invalid - bne winuf_invalid - EMPTY - - PTE_OF_ADDR(%sp, %l7, %l4, winuf_invalid) - CMP_PTE_USER_READ(%l7, %l5, NOP_ON_4M_6) ! if first page not readable, - bne winuf_invalid ! it is invalid - nop - INSERT_PTE(%sp, %l7) - SLT_IF_1PAGE_RW(%sp, %l7, %l4) ! first page is readable - bl,a winuf_ok ! if only one page, enter window X - restore %g0, 1, %l1 ! and goto ok, & set %l1 to 1 - add %sp, 7 * 8, %l5 - PTE_OF_ADDR(%l5, %l7, %l4, winuf_invalid) - CMP_PTE_USER_READ(%l7, %l5, NOP_ON_4M_8) ! check second page too - INSERT_PTE(%l5, %l7) - be,a winuf_ok ! enter window X and goto ok - restore %g0, 1, %l1 ! (and then set %l1 to 1) - -winuf_invalid: - /* - * We were unable to restore the window because %sp - * is invalid or paged out. Return to the trap window - * and call trap(T_WINUF). This will save R to the user - * stack, then load both R and I into the pcb rw[] area, - * and return with pcb_nsaved set to -1 for success, 0 for - * failure. `Failure' indicates that someone goofed with the - * trap registers (e.g., signals), so that we need to return - * from the trap as from a syscall (probably to a signal handler) - * and let it retry the restore instruction later. Note that - * window R will have been pushed out to user space, and thus - * be the invalid window, by the time we get back here. (We - * continue to label it R anyway.) We must also set %wim again, - * and set pcb_uw to 1, before enabling traps. (Window R is the - * only window, and it is a user window). - */ - save %g0, %g0, %g0 ! back to R - save %g0, 1, %l4 ! back to T, then %l4 = 1 - sethi %hi(_C_LABEL(cpcb)), %l6 - ld [%l6 + %lo(_C_LABEL(cpcb))], %l6 - st %l4, [%l6 + PCB_UW] ! pcb_uw = 1 - ld [%l6 + PCB_WIM], %l5 ! get log2(%wim) - sll %l4, %l5, %l4 ! %l4 = old %wim - wr %l4, 0, %wim ! window I is now invalid again - set USPACE-CCFSZ-80, %l5 - add %l6, %l5, %sp ! get onto kernel stack - nop - CHECK_SP_REDZONE(%l6, %l5) - - /* - * Okay, call trap(T_WINUF, psr, pc, &tf). - * See `slowtrap' above for operation. - */ - wr %l0, PSR_ET, %psr - std %l0, [%sp + CCFSZ + 0] ! tf.tf_psr, tf.tf_pc - rd %y, %l3 - std %l2, [%sp + CCFSZ + 8] ! tf.tf_npc, tf.tf_y - mov T_WINUF, %o0 - st %g1, [%sp + CCFSZ + 20] ! tf.tf_global[1] - mov %l0, %o1 - std %g2, [%sp + CCFSZ + 24] ! etc - mov %l1, %o2 - std %g4, [%sp + CCFSZ + 32] - add %sp, CCFSZ, %o3 - std %g6, [%sp + CCFSZ + 40] - std %i0, [%sp + CCFSZ + 48] ! tf.tf_out[0], etc - std %i2, [%sp + CCFSZ + 56] - std %i4, [%sp + CCFSZ + 64] - call _C_LABEL(trap) ! trap(T_WINUF, pc, psr, &tf) - std %i6, [%sp + CCFSZ + 72] ! tf.tf_out[6] - - ldd [%sp + CCFSZ + 0], %l0 ! new psr, pc - ldd [%sp + CCFSZ + 8], %l2 ! new npc, %y - wr %l3, 0, %y - ld [%sp + CCFSZ + 20], %g1 - ldd [%sp + CCFSZ + 24], %g2 - ldd [%sp + CCFSZ + 32], %g4 - ldd [%sp + CCFSZ + 40], %g6 - ldd [%sp + CCFSZ + 48], %i0 ! %o0 for window R, etc - ldd [%sp + CCFSZ + 56], %i2 - ldd [%sp + CCFSZ + 64], %i4 - wr %l0, 0, %psr ! disable traps: test must be atomic - ldd [%sp + CCFSZ + 72], %i6 - sethi %hi(_C_LABEL(cpcb)), %l6 - ld [%l6 + %lo(_C_LABEL(cpcb))], %l6 - ld [%l6 + PCB_NSAVED], %l7 ! if nsaved is -1, we have our regs - tst %l7 - bl,a 1f ! got them - wr %g0, 0, %wim ! allow us to enter windows R, I - b,a return_from_trap - - /* - * Got 'em. Load 'em up. - */ -1: - mov %g6, %l3 ! save %g6; set %g6 = cpcb - mov %l6, %g6 - st %g0, [%g6 + PCB_NSAVED] ! and clear magic flag - restore ! from T to R - restore ! from R to I - restore %g0, 1, %l1 ! from I to X, then %l1 = 1 - rd %psr, %l0 ! cwp = %psr; - sll %l1, %l0, %l1 - wr %l1, 0, %wim ! make window X invalid - and %l0, 31, %l0 - st %l0, [%g6 + PCB_WIM] ! cpcb->pcb_wim = cwp; - nop ! unnecessary? old wim was 0... - save %g0, %g0, %g0 ! back to I - - !!LOADWIN(%g6 + PCB_RW + 64) ! load from rw[1] - - !! StackGhost Decrypt (PCP) - ! pcb already dereferenced in %g6 - ld [%g6 + PCB_WCOOKIE], %l0 ! get window cookie - ldd [%g6 + PCB_RW + 64 + 56], %i6 - xor %l0, %i7, %i7 ! remove cookie - - ldd [%g6 + PCB_RW + 64], %l0 ! load from rw[1] - ldd [%g6 + PCB_RW + 64 + 8], %l2 - ldd [%g6 + PCB_RW + 64 + 16], %l4 - ldd [%g6 + PCB_RW + 64 + 24], %l6 - ldd [%g6 + PCB_RW + 64 + 32], %i0 - ldd [%g6 + PCB_RW + 64 + 40], %i2 - ldd [%g6 + PCB_RW + 64 + 48], %i4 - - save %g0, %g0, %g0 ! back to R - - !! StackGhost Decrypt (PCP) - ! pcb already dereferenced in %g6 - ! (If I was sober, I could potentially re-use the cookie from above) - ld [%g6 + PCB_WCOOKIE], %l0 ! get window cookie - ldd [%g6 + PCB_RW + 56], %i6 - xor %l0, %i7, %i7 ! remove cookie - - !!LOADWIN(%g6 + PCB_RW) ! load from rw[0] - ldd [%g6 + PCB_RW], %l0 ! load from rw[0] - ldd [%g6 + PCB_RW + 8], %l2 - ldd [%g6 + PCB_RW + 16], %l4 - ldd [%g6 + PCB_RW + 24], %l6 - ldd [%g6 + PCB_RW + 32], %i0 - ldd [%g6 + PCB_RW + 40], %i2 - ldd [%g6 + PCB_RW + 48], %i4 - - save %g0, %g0, %g0 ! back to T - - wr %l0, 0, %psr ! restore condition codes - nop; nop - mov %l3, %g6 ! fix %g6 - RETT - - /* - * Restoring from user stack, but everything has checked out - * as good. We are now in window X, and %l1 = 1. Window R - * is still valid and holds user values. - */ -winuf_ok: - rd %psr, %l0 - sll %l1, %l0, %l1 - wr %l1, 0, %wim ! make this one invalid - sethi %hi(_C_LABEL(cpcb)), %l2 - ld [%l2 + %lo(_C_LABEL(cpcb))], %l2 - and %l0, 31, %l0 - st %l0, [%l2 + PCB_WIM] ! cpcb->pcb_wim = cwp; - save %g0, %g0, %g0 ! back to I - - !! StackGhost Decrypt - sethi %hi(_C_LABEL(cpcb)), %l0 ! get current *pcb - ld [%l0 + %lo(_C_LABEL(cpcb))], %l1 ! dereference *pcb - ld [%l1 + PCB_WCOOKIE], %l0 ! get window cookie - ldd [%sp + 56], %i6 ! get saved return pointer - xor %l0, %i7, %i7 ! remove cookie - - !!LOADWIN(%sp) - ldd [%sp], %l0 - ldd [%sp + 8], %l2 - ldd [%sp + 16], %l4 - ldd [%sp + 24], %l6 - ldd [%sp + 32], %i0 - ldd [%sp + 40], %i2 - ldd [%sp + 48], %i4 - - save %g0, %g0, %g0 ! back to R - save %g0, %g0, %g0 ! back to T - wr %l0, 0, %psr ! restore condition codes - nop; nop; nop ! it takes three to tangle - RETT -#endif /* end `real' version of window underflow trap handler */ - -/* - * Various return-from-trap routines (see return_from_trap). - */ - -/* - * Return from trap, to kernel. - * %l0 = %psr - * %l1 = return pc - * %l2 = return npc - * %l4 = %wim - * %l5 = bit for previous window - */ -rft_kernel: - btst %l5, %l4 ! if (wim & l5) - bnz 1f ! goto reload; - wr %l0, 0, %psr ! but first put !@#*% cond codes back - - /* previous window is valid; just rett */ - nop; nop; nop ! wait for cond codes to settle in - RETT - - /* - * Previous window is invalid. - * Update %wim and then reload l0..i7 from frame. - * - * T I X - * 0 0 1 0 0 (%wim) - * [see picture in window_uf handler] - * - * T is the current (Trap) window, I is the Invalid window, - * and X is the window we want to make invalid. Window X - * currently has no useful values. - */ -1: - wr %g0, 0, %wim ! allow us to enter window I - nop; nop; nop ! (it takes a while) - restore ! enter window I - restore %g0, 1, %l1 ! enter window X, then %l1 = 1 - rd %psr, %l0 ! CWP = %psr & 31; - and %l0, 31, %l0 - sll %l1, %l0, %l1 ! wim = 1 << CWP; - wr %l1, 0, %wim ! setwim(wim); - sethi %hi(_C_LABEL(cpcb)), %l1 - ld [%l1 + %lo(_C_LABEL(cpcb))], %l1 - st %l0, [%l1 + PCB_WIM] ! cpcb->pcb_wim = l0 & 31; - save %g0, %g0, %g0 ! back to window I - LOADWIN(%sp) - save %g0, %g0, %g0 ! back to window T - /* - * Note that the condition codes are still set from - * the code at rft_kernel; we can simply return. - */ - RETT - -/* - * Return from trap, to user. Checks for scheduling trap (`ast') first; - * will re-enter trap() if set. Note that we may have to switch from - * the interrupt stack to the kernel stack in this case. - * %l0 = %psr - * %l1 = return pc - * %l2 = return npc - * %l4 = %wim - * %l5 = bit for previous window - * %l6 = cpcb - * If returning to a valid window, just set psr and return. - */ -rft_user: -! sethi %hi(_C_LABEL(want_ast)), %l7 ! (done below) - ld [%l7 + %lo(_C_LABEL(want_ast))], %l7 - tst %l7 ! want AST trap? - bne,a softtrap ! yes, re-enter trap with type T_AST - mov T_AST, %o0 - - btst %l5, %l4 ! if (wim & l5) - bnz 1f ! goto reload; - wr %l0, 0, %psr ! restore cond codes - nop; nop; nop ! (three instruction delay) - RETT - - /* - * Previous window is invalid. - * Before we try to load it, we must verify its stack pointer. - * This is much like the underflow handler, but a bit easier - * since we can use our own local registers. - */ -1: - btst 7, %fp ! if unaligned, address is invalid - bne rft_invalid - EMPTY - - PTE_OF_ADDR(%fp, %l7, %l3, rft_invalid) - CMP_PTE_USER_READ(%l7, %l5, NOP_ON_4M_10) ! try first page - bne rft_invalid ! no good - nop - INSERT_PTE(%fp, %l7) - SLT_IF_1PAGE_RW(%fp, %l7, %l3) - bl,a rft_user_ok ! only 1 page: ok - wr %g0, 0, %wim - add %fp, 7*8, %l5 - PTE_OF_ADDR(%l5, %l7, %l3, rft_invalid) - INSERT_PTE(%l5, %l7) - CMP_PTE_USER_READ(%l7, %l5, NOP_ON_4M_12) ! check 2nd page too - be,a rft_user_ok - wr %g0, 0, %wim - - /* - * The window we wanted to pull could not be pulled. Instead, - * re-enter trap with type T_RWRET. This will pull the window - * into cpcb->pcb_rw[0] and set cpcb->pcb_nsaved to -1, which we - * will detect when we try to return again. - */ -rft_invalid: - b softtrap - mov T_RWRET, %o0 - - /* - * The window we want to pull can be pulled directly. - */ -rft_user_ok: -! wr %g0, 0, %wim ! allow us to get into it - wr %l0, 0, %psr ! fix up the cond codes now - nop; nop; nop - restore ! enter window I - restore %g0, 1, %l1 ! enter window X, then %l1 = 1 - rd %psr, %l0 ! l0 = (junk << 5) + CWP; - sll %l1, %l0, %l1 ! %wim = 1 << CWP; - wr %l1, 0, %wim - sethi %hi(_C_LABEL(cpcb)), %l1 - ld [%l1 + %lo(_C_LABEL(cpcb))], %l1 - and %l0, 31, %l0 - st %l0, [%l1 + PCB_WIM] ! cpcb->pcb_wim = l0 & 31; - save %g0, %g0, %g0 ! back to window I - - !! StackGhost Decrypt - sethi %hi(_C_LABEL(cpcb)), %l0 ! get current *pcb - ld [%l0 + %lo(_C_LABEL(cpcb))], %l1 ! dereference *pcb - ld [%l1 + PCB_WCOOKIE], %l0 ! get window cookie - ldd [%sp + 56], %i6 ! get saved return pointer - xor %l0, %i7, %i7 ! remove cookie - - !!LOADWIN(%sp) ! suck hard - ldd [%sp], %l0 - ldd [%sp + 8], %l2 - ldd [%sp + 16], %l4 - ldd [%sp + 24], %l6 - ldd [%sp + 32], %i0 - ldd [%sp + 40], %i2 - ldd [%sp + 48], %i4 - - save %g0, %g0, %g0 ! back to window T - RETT - -/* - * Return from trap. Entered after a - * wr %l0, 0, %psr - * which disables traps so that we can rett; registers are: - * - * %l0 = %psr - * %l1 = return pc - * %l2 = return npc - * - * (%l3..%l7 anything). - * - * If we are returning to user code, we must: - * 1. Check for register windows in the pcb that belong on the stack. - * If there are any, reenter trap with type T_WINOF. - * 2. Make sure the register windows will not underflow. This is - * much easier in kernel mode.... - */ -return_from_trap: -! wr %l0, 0, %psr ! disable traps so we can rett -! (someone else did this already) - and %l0, 31, %l5 - set wmask, %l6 - ldub [%l6 + %l5], %l5 ! %l5 = 1 << ((CWP + 1) % nwindows) - btst PSR_PS, %l0 ! returning to userland? - bnz rft_kernel ! no, go return to kernel - rd %wim, %l4 ! (read %wim in any case) - -rft_user_or_recover_pcb_windows: - /* - * (entered with %l4=%wim, %l5=wmask[cwp]; %l0..%l2 as usual) - * - * check cpcb->pcb_nsaved: - * if 0, do a `normal' return to user (see rft_user); - * if > 0, cpcb->pcb_rw[] holds registers to be copied to stack; - * if -1, cpcb->pcb_rw[0] holds user registers for rett window - * from an earlier T_RWRET pseudo-trap. - */ - sethi %hi(_C_LABEL(cpcb)), %l6 - ld [%l6 + %lo(_C_LABEL(cpcb))], %l6 - ld [%l6 + PCB_NSAVED], %l7 - tst %l7 - bz,a rft_user - sethi %hi(_C_LABEL(want_ast)), %l7 ! first instr of rft_user - - bg,a softtrap ! if (pcb_nsaved > 0) - mov T_WINOF, %o0 ! trap(T_WINOF); - - /* - * To get here, we must have tried to return from a previous - * trap and discovered that it would cause a window underflow. - * We then must have tried to pull the registers out of the - * user stack (from the address in %fp==%i6) and discovered - * that it was either unaligned or not loaded in memory, and - * therefore we ran a trap(T_RWRET), which loaded one set of - * registers into cpcb->pcb_pcb_rw[0] (if it had killed the - * process due to a bad stack, we would not be here). - * - * We want to load pcb_rw[0] into the previous window, which - * we know is currently invalid. In other words, we want - * %wim to be 1 << ((cwp + 2) % nwindows). - */ - wr %g0, 0, %wim ! enable restores - mov %g6, %l3 ! save g6 in l3 - mov %l6, %g6 ! set g6 = &u - st %g0, [%g6 + PCB_NSAVED] ! clear cpcb->pcb_nsaved - restore ! enter window I - restore %g0, 1, %l1 ! enter window X, then %l1 = 1 - rd %psr, %l0 - sll %l1, %l0, %l1 ! %wim = 1 << CWP; - wr %l1, 0, %wim - and %l0, 31, %l0 - st %l0, [%g6 + PCB_WIM] ! cpcb->pcb_wim = CWP; - nop ! unnecessary? old wim was 0... - save %g0, %g0, %g0 ! back to window I - - !! StackGhost Decrypt (PCB) - ! pcb already deferenced in %g6 - ld [%g6 + PCB_WCOOKIE], %l0 ! get window cookie - ldd [%g6 + PCB_RW + 56], %i6 ! get saved return pointer - xor %l0, %i7, %i7 ! remove cookie - - !LOADWIN(%g6 + PCB_RW) - ldd [%g6 + PCB_RW], %l0 - ldd [%g6 + PCB_RW + 8], %l2 - ldd [%g6 + PCB_RW + 16], %l4 - ldd [%g6 + PCB_RW + 24], %l6 - ldd [%g6 + PCB_RW + 32], %i0 - ldd [%g6 + PCB_RW + 40], %i2 - ldd [%g6 + PCB_RW + 48], %i4 - - save %g0, %g0, %g0 ! back to window T (trap window) - wr %l0, 0, %psr ! cond codes, cond codes everywhere - nop; nop - mov %l3, %g6 ! restore g6 - RETT - -! exported end marker for kernel gdb - .globl _C_LABEL(endtrapcode) -_C_LABEL(endtrapcode): - -/* - * init_tables(nwin) int nwin; - * - * Set up the uwtab and wmask tables. - * We know nwin > 1. - */ -init_tables: - /* - * for (i = -nwin, j = nwin - 2; ++i < 0; j--) - * uwtab[i] = j; - * (loop runs at least once) - */ - set uwtab, %o3 - sub %g0, %o0, %o1 ! i = -nwin + 1 - inc %o1 - add %o0, -2, %o2 ! j = nwin - 2; -0: - stb %o2, [%o3 + %o1] ! uwtab[i] = j; -1: - inccc %o1 ! ++i < 0? - bl 0b ! yes, continue loop - dec %o2 ! in any case, j-- - - /* - * (i now equals 0) - * for (j = nwin - 1; i < nwin; i++, j--) - * uwtab[i] = j; - * (loop runs at least twice) - */ - sub %o0, 1, %o2 ! j = nwin - 1 -0: - stb %o2, [%o3 + %o1] ! uwtab[i] = j - inc %o1 ! i++ -1: - cmp %o1, %o0 ! i < nwin? - bl 0b ! yes, continue - dec %o2 ! in any case, j-- - - /* - * We observe that, for i in 0..nwin-2, (i+1)%nwin == i+1; - * for i==nwin-1, (i+1)%nwin == 0. - * To avoid adding 1, we run i from 1 to nwin and set - * wmask[i-1]. - * - * for (i = j = 1; i < nwin; i++) { - * j <<= 1; (j now == 1 << i) - * wmask[i - 1] = j; - * } - * (loop runs at least once) - */ - set wmask - 1, %o3 - mov 1, %o1 ! i = 1; - mov 2, %o2 ! j = 2; -0: - stb %o2, [%o3 + %o1] ! (wmask - 1)[i] = j; - inc %o1 ! i++ - cmp %o1, %o0 ! i < nwin? - bl,a 0b ! yes, continue - sll %o2, 1, %o2 ! (and j <<= 1) - - /* - * Now i==nwin, so we want wmask[i-1] = 1. - */ - mov 1, %o2 ! j = 1; - retl - stb %o2, [%o3 + %o1] ! (wmask - 1)[i] = j; - -/* ========================================================================== */ - - .align 8 /* to be sure we won't cross a page boundary */ -ENTRY(masktest) - ret - nop - -#define BLINK(how) \ - call blink; \ - mov how, %o0 - -ENTRY(blink) - save %sp, -64, %sp - set GLU_BSR, %l1 - lda [%l1] ASI_PHYS_IO, %l2 - srl %l2, 24, %l2 - andn %l2, GBSR_LED_MASK, %l2 - or %l2, %i0, %l2 - sll %l2, 24, %l2 - sta %l2, [%l1] ASI_PHYS_IO - ret - restore - -dostart: - /* - * Startup. - * - * We have been loaded in high RAM, in the virtual window 0xfd, but - * physical window 0xf0, which is also the segment we are linked at. - */ - - BLINK(GBSR_LED_AMBER) - -#if defined(DDB) || NKSYMS > 0 - /* - * Initialize esym to a non-dangerous value for now. - */ - set _C_LABEL(end), %l0 - sethi %hi(_C_LABEL(esym)), %l1 - st %l0, [%l1 + %lo(_C_LABEL(esym))] -#endif - - /* - * We are invoked with a regular frame on stack. - */ - ld [%sp + FRAME_ARGC], %g5 ! argc - ld [%sp + FRAME_ARGC + 4], %g6 ! argv - ld [%sp + FRAME_ARGC + 8], %g7 ! environ - - /* - * Here, we should make sure we are really running on an idt - * machine. But we won't, because if we could be loaded correctly, - * and did not fault earlier, chances are good we are running on - * the adequate hardware... - */ - - /* disable external interrupts - this also disables soft interrupts */ - set GLU_ICR, %o0 - mov GICR_DISABLE_ALL, %o1 - sll %o1, 24, %o1 - sta %o1, [%o0] ASI_PHYS_IO - nop - - CLEAR_FCR - - /* disable interrupts, and enable traps */ - rd %psr, %o0 - or %o0, PSR_PIL, %o0 - wr %o0, %psr - nop; nop; nop; - or %o0, PSR_ET, %o0 - wr %o0, %psr - nop; nop; nop - - /* - * Step 1: Reset the MMU to sane defaults. - * We do not disable it because we will be playing with the stack, - * which will not be addressable if translations are disabled. - */ - - sta %g0, [%g0] ASI_PIID - sta %g0, [%g0] ASI_GTLB_INVAL_PID - nop; nop; nop - lda [%g0] ASI_FVAR, %g0 - lda [%g0] ASI_FPAR, %g0 - lda [%g0] ASI_FPSR, %g0 - sta %g0, [%g0] ASI_PID - - rd %psr, %g3 ! paranoia: make sure ... - andn %g3, PSR_ET, %g3 ! we have traps off - wr %g3, 0, %psr ! so that we can fiddle safely - nop; nop; nop - - wr %g0, 0, %wim ! make sure we can set psr - nop; nop; nop - wr %g0, PSR_S|PSR_PS|PSR_PIL, %psr ! set initial psr - nop; nop; nop - - wr %g0, 2, %wim ! set initial %wim (w1 invalid) - mov 1, %g1 ! set pcb_wim (log2(%wim) = 1) - sethi %hi(_C_LABEL(u0) + PCB_WIM), %g2 - st %g1, [%g2 + %lo(_C_LABEL(u0) + PCB_WIM)] - - set VM_MIN_KERNEL_ADDRESS - CCFSZ, %fp ! as if called from user code - set estack0 - CCFSZ - 80, %sp ! via syscall(boot_me_up) or somesuch - rd %psr, %l0 - wr %l0, PSR_ET, %psr - nop; nop; nop - - /* - * Step 2: clear BSS. This may just be paranoia; the boot - * loader might already do it for us; but what the hell. - */ - set _C_LABEL(edata), %o0 ! bzero(edata, end - edata) - set _C_LABEL(end), %o1 - call _C_LABEL(bzero) - sub %o1, %o0, %o1 - - /* - * Stash prom variables now, after bzero, as they live in bss - * (which we just zeroed). - * This depends on the fact that bzero does not use %g5-%g7. - */ - sethi %hi(_C_LABEL(prom_argc)), %o0 - st %g5, [%o0 + %lo(_C_LABEL(prom_argc))] - sethi %hi(_C_LABEL(prom_argv)), %o0 - st %g6, [%o0 + %lo(_C_LABEL(prom_argv))] - sethi %hi(_C_LABEL(prom_environ)), %o0 - st %g7, [%o0 + %lo(_C_LABEL(prom_environ))] - - /* - * Step 3: compute number of windows and set up tables. - * We could do some of this later. - */ - save %sp, -64, %sp - rd %psr, %g1 - restore - and %g1, 31, %g1 ! want just the CWP bits - add %g1, 1, %o0 ! compute nwindows - sethi %hi(_C_LABEL(nwindows)), %o1 ! may as well tell everyone - call init_tables - st %o0, [%o1 + %lo(_C_LABEL(nwindows))] - - /* - * Invoke early C code, still using the PROM trap, so that it can - * do proper TLB insertion for us while we are accessing various - * onboard devices. - */ - - call _C_LABEL(bootstrap) - nop - - /* - * Step 4: change the trap base register, now that our trap handlers - * will function (they need the tables we just set up). - */ - set trapbase_kap, %g6 - wr %g6, 0, %tbr - nop; nop; nop ! paranoia - - /* - * Step 5: activate our translations... - */ - set _C_LABEL(kernel_pmap_store), %o0 - ld [%o0 + PMAP_PSEGTAB], %o1 - sta %o1, [%g0] ASI_PDBR - nop; nop; nop - - /* - * ... and unmap ROM code. - */ - set PTW0_DEFAULT & ~PTW_V, %o1 - sta %o1, [%g0] ASI_PTW0 -#if 0 - set PTW1_DEFAULT, %o1 - sta %o1, [%g0] ASI_PTW1 - set PTW2_DEFAULT, %o1 - sta %o1, [%g0] ASI_PTW2 -#endif - - sta %g0, [%g0] ASI_PIID - sta %g0, [%g0] ASI_GTLB_INVAL_PID - nop; nop; nop - - /* - * Call main. - */ - call _C_LABEL(main) - clr %o0 ! our frame arg is ignored - /*NOTREACHED*/ - - -/* - * The following code is copied to the top of the user stack when each - * process is exec'ed, and signals are `trampolined' off it. - * - * When this code is run, the stack looks like: - * [%sp] 64 bytes to which registers can be dumped - * [%sp + 64] signal number (goes in %o0) - * [%sp + 64 + 4] siginfo_t pointer (goes in %o1) - * [%sp + 64 + 8] sigcontext pointer (goes in %o2) - * [%sp + 64 + 12] argument for %o3, currently unsupported (always 0) - * [%sp + 64 + 16] first word of saved state (sigcontext) - * . - * . - * . - * [%sp + NNN] last word of saved state - * (followed by previous stack contents or top of signal stack). - * The address of the function to call is in %g1; the old %g1 and %o0 - * have already been saved in the sigcontext. We are running in a clean - * window, all previous windows now being saved to the stack. - * - * Note that [%sp + 64 + 8] == %sp + 64 + 16. The copy at %sp+64+8 - * will eventually be removed, with a hole left in its place, if things - * work out. - */ - .globl _C_LABEL(sigcode) - .globl _C_LABEL(esigcode) -_C_LABEL(sigcode): - /* - * XXX the `save' and `restore' below are unnecessary: should - * replace with simple arithmetic on %sp - * - * Make room on the stack for 32 %f registers + %fsr. This comes - * out to 33*4 or 132 bytes, but this must be aligned to a multiple - * of 8, or 136 bytes. - */ - save %sp, -CCFSZ - 136, %sp - mov %g2, %l2 ! save globals in %l registers - mov %g3, %l3 - mov %g4, %l4 - mov %g5, %l5 - mov %g6, %l6 - mov %g7, %l7 - /* - * Saving the fpu registers is expensive, so do it iff the fsr - * stored in the sigcontext shows that the fpu is enabled. - */ - ld [%fp + 64 + 16 + SC_PSR_OFFSET], %l0 - sethi %hi(PSR_EF), %l1 ! FPU enable bit is too high for andcc - andcc %l0, %l1, %l0 ! %l0 = fpu enable bit - be 1f ! if not set, skip the saves - rd %y, %l1 ! in any case, save %y - - ! fpu is enabled, oh well - st %fsr, [%sp + CCFSZ + 0] - std %f0, [%sp + CCFSZ + 8] - std %f2, [%sp + CCFSZ + 16] - std %f4, [%sp + CCFSZ + 24] - std %f6, [%sp + CCFSZ + 32] - std %f8, [%sp + CCFSZ + 40] - std %f10, [%sp + CCFSZ + 48] - std %f12, [%sp + CCFSZ + 56] - std %f14, [%sp + CCFSZ + 64] - std %f16, [%sp + CCFSZ + 72] - std %f18, [%sp + CCFSZ + 80] - std %f20, [%sp + CCFSZ + 88] - std %f22, [%sp + CCFSZ + 96] - std %f24, [%sp + CCFSZ + 104] - std %f26, [%sp + CCFSZ + 112] - std %f28, [%sp + CCFSZ + 120] - std %f30, [%sp + CCFSZ + 128] - -1: - ldd [%fp + 64], %o0 ! sig, sip - ld [%fp + 76], %o3 ! arg3 -#ifdef SIG_DEBUG - subcc %o0, 32, %g0 ! signals are 1-32 - bgu _C_LABEL(suicide) - nop -#endif - call %g1 ! (*sa->sa_handler)(sig,sip,scp,arg3) - add %fp, 64 + 16, %o2 ! scp - - /* - * Now that the handler has returned, re-establish all the state - * we just saved above, then do a sigreturn. - */ - tst %l0 ! reload fpu registers? - be 1f ! if not, skip the loads - wr %l1, %g0, %y ! in any case, restore %y - - ld [%sp + CCFSZ + 0], %fsr - ldd [%sp + CCFSZ + 8], %f0 - ldd [%sp + CCFSZ + 16], %f2 - ldd [%sp + CCFSZ + 24], %f4 - ldd [%sp + CCFSZ + 32], %f6 - ldd [%sp + CCFSZ + 40], %f8 - ldd [%sp + CCFSZ + 48], %f10 - ldd [%sp + CCFSZ + 56], %f12 - ldd [%sp + CCFSZ + 64], %f14 - ldd [%sp + CCFSZ + 72], %f16 - ldd [%sp + CCFSZ + 80], %f18 - ldd [%sp + CCFSZ + 88], %f20 - ldd [%sp + CCFSZ + 96], %f22 - ldd [%sp + CCFSZ + 104], %f24 - ldd [%sp + CCFSZ + 112], %f26 - ldd [%sp + CCFSZ + 120], %f28 - ldd [%sp + CCFSZ + 128], %f30 - -1: - mov %l2, %g2 - mov %l3, %g3 - mov %l4, %g4 - mov %l5, %g5 - mov %l6, %g6 - mov %l7, %g7 - - restore %g0, SYS_sigreturn, %g1 ! get registers back & set syscall # - add %sp, 64 + 16, %o0 ! compute scp - t ST_SYSCALL ! sigreturn(scp) - ! sigreturn does not return unless it fails - mov SYS_exit, %g1 ! exit(errno) - t ST_SYSCALL - -#ifdef SIG_DEBUG - .globl _C_LABEL(suicide) -_C_LABEL(suicide): - mov 139, %g1 ! obsolete syscall, puke... - t ST_SYSCALL -#endif -_C_LABEL(esigcode): - -/* - * Primitives - */ -#if 0 -#ifdef GPROF - .globl mcount -#define ENTRY(x) \ - .globl _C_LABEL(x); _C_LABEL(x): ; \ - save %sp, -CCFSZ, %sp; \ - call mcount; \ - nop; \ - restore -#else -#define ENTRY(x) .globl _C_LABEL(x); _C_LABEL(x): -#endif -#endif -#define ALTENTRY(x) .globl _C_LABEL(x); _C_LABEL(x): - -/* - * General-purpose NULL routine. - */ -ENTRY(sparc_noop) - retl - nop - -/* - * getfp() - get stack frame pointer - */ -ENTRY(getfp) - retl - mov %fp, %o0 - -/* - * copyinstr(fromaddr, toaddr, maxlength, &lencopied) - * - * Copy a null terminated string from the user address space into - * the kernel address space. - */ -ENTRY(copyinstr) - ! %o0 = fromaddr, %o1 = toaddr, %o2 = maxlen, %o3 = &lencopied - mov %o1, %o5 ! save = toaddr; - tst %o2 ! maxlen == 0? - beq,a Lcstoolong0 ! yes, return ENAMETOOLONG - sethi %hi(_C_LABEL(cpcb)), %o4 - - set VM_MIN_KERNEL_ADDRESS, %o4 - cmp %o0, %o4 ! fromaddr < VM_MIN_KERNEL_ADDRESS? - blu Lcsdocopyi ! yes, go do it - sethi %hi(_C_LABEL(cpcb)), %o4 ! (first instr of copy) - - b Lcsdone ! no, return EFAULT - mov EFAULT, %o0 - -/* - * copyoutstr(fromaddr, toaddr, maxlength, &lencopied) - * - * Copy a null terminated string from the kernel - * address space to the user address space. - */ -ENTRY(copyoutstr) - ! %o0 = fromaddr, %o1 = toaddr, %o2 = maxlen, %o3 = &lencopied - mov %o1, %o5 ! save = toaddr; - tst %o2 ! maxlen == 0? - beq,a Lcstoolong0 ! yes, return ENAMETOOLONG - sethi %hi(_C_LABEL(cpcb)), %o4 - - set VM_MIN_KERNEL_ADDRESS, %o4 - cmp %o1, %o4 ! toaddr < VM_MIN_KERNEL_ADDRESS? - blu Lcsdocopyo ! yes, go do it - sethi %hi(_C_LABEL(cpcb)), %o4 ! (first instr of copy) - - b Lcsdone ! no, return EFAULT - mov EFAULT, %o0 - -Lcsdocopyi: -! sethi %hi(_C_LABEL(cpcb)), %o4 ! (done earlier) - ld [%o4 + %lo(_C_LABEL(cpcb))], %o4 ! catch faults - set Lcsfaulti, %g1 - b 0f - st %g1, [%o4 + PCB_ONFAULT] - -Lcsdocopyo: -! sethi %hi(_C_LABEL(cpcb)), %o4 ! (done earlier) - ld [%o4 + %lo(_C_LABEL(cpcb))], %o4 ! catch faults - set Lcsfaulto, %g1 - st %g1, [%o4 + PCB_ONFAULT] - -! XXX should do this in bigger chunks when possible -0: ! loop: - ldsb [%o0], %g1 ! c = *fromaddr; - tst %g1 - stb %g1, [%o1] ! *toaddr++ = c; - be 1f ! if (c == NULL) - inc %o1 ! goto ok; - deccc %o2 ! if (--len > 0) { - bgu 0b ! fromaddr++; - inc %o0 ! goto loop; - ! } -Lcstoolong: ! - deccc %o1 - stb %g0, [%o1] ! *--toaddr = '\0'; -Lcstoolong0: ! - b Lcsdone ! error = ENAMETOOLONG; - mov ENAMETOOLONG, %o0 ! goto done; -1: ! ok: - clr %o0 ! error = 0; -Lcsdone: ! done: - sub %o1, %o5, %o1 ! len = to - save; - tst %o3 ! if (lencopied) - bnz,a 3f - st %o1, [%o3] ! *lencopied = len; -3: - retl ! cpcb->pcb_onfault = 0; - st %g0, [%o4 + PCB_ONFAULT]! return (error); - -Lcsfaulti: - cmp %o1, %o5 ! did we write to the string? - be 1f - nop - deccc %o1 ! --toaddr -1: - stb %g0, [%o1] ! *toaddr = '\0'; - b Lcsdone ! error = EFAULT; - mov EFAULT, %o0 ! goto ret; - -Lcsfaulto: - cmp %o1, %o5 ! did we write to the string? - be 1f - nop - deccc %o1 - stb %g0, [%o1] ! *--toaddr = '\0'; -1: - b Lcsdone ! error = EFAULT; - mov EFAULT, %o0 ! goto ret; - -/* - * copystr(fromaddr, toaddr, maxlength, &lencopied) - * - * Copy a null terminated string from one point to another in - * the kernel address space. (This is a leaf procedure, but - * it does not seem that way to the C compiler.) - */ -ENTRY(copystr) - mov %o1, %o5 ! to0 = to; - tst %o2 ! if (maxlength == 0) - beq,a 2f ! - mov ENAMETOOLONG, %o0 ! ret = ENAMETOOLONG; goto done; - -0: ! loop: - ldsb [%o0], %o4 ! c = *from; - tst %o4 - stb %o4, [%o1] ! *to++ = c; - be 1f ! if (c == 0) - inc %o1 ! goto ok; - deccc %o2 ! if (--len > 0) { - bgu,a 0b ! from++; - inc %o0 ! goto loop; - b 2f ! } - mov ENAMETOOLONG, %o0 ! ret = ENAMETOOLONG; goto done; -1: ! ok: - clr %o0 ! ret = 0; -2: - sub %o1, %o5, %o1 ! len = to - to0; - tst %o3 ! if (lencopied) - bnz,a 3f - st %o1, [%o3] ! *lencopied = len; -3: - retl - nop - -/* - * Copyin(src, dst, len) - * - * Copy specified amount of data from user space into the kernel. - */ -ENTRY(copyin) - set VM_MIN_KERNEL_ADDRESS, %o3 - cmp %o0, %o3 ! src < VM_MIN_KERNEL_ADDRESS? - blu,a Ldocopy ! yes, can try it - sethi %hi(_C_LABEL(cpcb)), %o3 - - /* source address points into kernel space: return EFAULT */ - retl - mov EFAULT, %o0 - -/* - * Copyout(src, dst, len) - * - * Copy specified amount of data from kernel to user space. - * Just like copyin, except that the `dst' addresses are user space - * rather than the `src' addresses. - */ -ENTRY(copyout) - set VM_MIN_KERNEL_ADDRESS, %o3 - cmp %o1, %o3 ! dst < VM_MIN_KERNEL_ADDRESS? - blu,a Ldocopy - sethi %hi(_C_LABEL(cpcb)), %o3 - - /* destination address points into kernel space: return EFAULT */ - retl - mov EFAULT, %o0 - - /* - * ******NOTE****** this depends on bcopy() not using %g7 - */ -Ldocopy: -! sethi %hi(_C_LABEL(cpcb)), %o3 - ld [%o3 + %lo(_C_LABEL(cpcb))], %o3 - set Lcopyfault, %o4 - mov %o7, %g7 ! save return address - call _C_LABEL(bcopy) ! bcopy(src, dst, len) - st %o4, [%o3 + PCB_ONFAULT] - - sethi %hi(_C_LABEL(cpcb)), %o3 - ld [%o3 + %lo(_C_LABEL(cpcb))], %o3 - st %g0, [%o3 + PCB_ONFAULT] - jmp %g7 + 8 - clr %o0 ! return 0 - -! Copyin or copyout fault. Clear cpcb->pcb_onfault and return EFAULT. -! Note that although we were in bcopy, there is no state to clean up; -! the only special thing is that we have to return to [g7 + 8] rather than -! [o7 + 8]. -Lcopyfault: - sethi %hi(_C_LABEL(cpcb)), %o3 - ld [%o3 + %lo(_C_LABEL(cpcb))], %o3 - st %g0, [%o3 + PCB_ONFAULT] - jmp %g7 + 8 - mov EFAULT, %o0 - - -/* - * Write all user windows presently in the CPU back to the user's stack. - * We just do `save' instructions until pcb_uw == 0. - * - * p = cpcb; - * nsaves = 0; - * while (p->pcb_uw > 0) - * save(), nsaves++; - * while (--nsaves >= 0) - * restore(); - */ -ENTRY(write_user_windows) - sethi %hi(_C_LABEL(cpcb)), %g6 - ld [%g6 + %lo(_C_LABEL(cpcb))], %g6 - b 2f - clr %g5 -1: - save %sp, -64, %sp -2: - ld [%g6 + PCB_UW], %g7 - tst %g7 - bg,a 1b - inc %g5 -3: - deccc %g5 - bge,a 3b - restore - retl - nop - - - .comm _C_LABEL(want_resched),4 -/* - * Masterpaddr is the p->p_addr of the last process on the processor. - * XXX masterpaddr is almost the same as cpcb - * XXX should delete this entirely - */ - .comm _C_LABEL(masterpaddr), 4 - -/* - * cpu_switchto(struct proc *oldproc, struct proc *newproc) - */ -ENTRY(cpu_switchto) - sethi %hi(_C_LABEL(cpcb)), %g6 - sethi %hi(_C_LABEL(curproc)), %g7 - ld [%g6 + %lo(_C_LABEL(cpcb))], %o2 - std %o6, [%o2 + PCB_SP] ! cpcb->pcb_<sp,pc> = <sp,pc>; - rd %psr, %g1 ! oldpsr = %psr; - st %g1, [%o2 + PCB_PSR] ! cpcb->pcb_psr = oldpsr; - andn %g1, PSR_PIL, %g1 ! oldpsr &= ~PSR_PIL; - - /* - * REGISTER USAGE: - * %g1 = oldpsr (excluding ipl bits) - * %g2 = newpsr - * %g5 = newpcb - * %g6 = %hi(_C_LABEL(cpcb)) - * %g7 = %hi(_C_LABEL(curproc)) - * %o0 = oldproc - * %o1 = newproc - * %o2 = tmp 3 - * %o3 = vm - * %o4 = sswap - * %o5 = <free> - */ - - /* - * Committed to running process p (in o1). - */ - mov %o1, %g3 - - mov SONPROC, %o0 ! p->p_stat = SONPROC - stb %o0, [%g3 + P_STAT] - ld [%g3 + P_ADDR], %g5 ! newpcb = p->p_addr; - ld [%g5 + PCB_PSR], %g2 ! newpsr = newpcb->pcb_psr; - st %g3, [%g7 + %lo(_C_LABEL(curproc))] ! curproc = p; - - /* - * Save the old process, if any; then load p. - */ - tst %o0 - be,a Lsw_load ! if no old process, go load -#if 0 - wr %g1, (IPL_SCHED << 8) | PSR_ET, %psr -#else - wr %g1, (IPL_SCHED << 8), %psr -#endif - - /* - * save: write back all windows (including the current one). - * XXX crude; knows nwindows <= 8 - */ -#define SAVE save %sp, -64, %sp -wb1: SAVE; SAVE; SAVE; SAVE; SAVE; SAVE; SAVE /* 7 of each: */ - restore; restore; restore; restore; restore; restore; restore - - /* - * Load the new process. To load, we must change stacks and - * alter cpcb and %wim, hence we must disable traps. %psr is - * currently equal to oldpsr (%g1) ^ (IPL_SCHED << 8); - * this means that PSR_ET is on. Likewise, PSR_ET is on - * in newpsr (%g2), although we do not know newpsr's ipl. - * - * We also must load up the `in' and `local' registers. - */ -#if 0 - wr %g1, (IPL_SCHED << 8) | PSR_ET, %psr -#else - wr %g1, (IPL_SCHED << 8), %psr -#endif -Lsw_load: -#if 0 -! wr %g1, (IPL_SCHED << 8) | PSR_ET, %psr ! done above -#else -! wr %g1, (IPL_SCHED << 8), %psr ! done above -#endif - - /* - * Access the new pcb while we still enable traps. This is - * simpler (for us) than doing manual TLB insertion, and - * is faster if this is a TLB hit. - */ - ld [%g5 + PCB_SP], %o1 ! access pcb - ld [%g3 + P_VMSPACE], %o3 ! access p - ld [%o3 + VM_PMAP], %o3 ! access p->p_vmspace - ld [%o3 + PMAP_PSEGTAB], %o3 ! access pmap - - /* - * Disable traps now. - */ - wr %g1, PSR_ET, %psr - - /* compute new wim */ - ld [%g5 + PCB_WIM], %o0 - mov 1, %o1 - sll %o1, %o0, %o0 - wr %o0, 0, %wim ! %wim = 1 << newpcb->pcb_wim; - /* now must not change %psr for 3 more instrs */ -/*1*/ set PSR_EF|PSR_EC, %o0 -/*2*/ andn %g2, %o0, %g2 ! newpsr &= ~(PSR_EF|PSR_EC); -/*3*/ nop - /* set new psr, but with traps disabled */ - wr %g2, PSR_ET, %psr ! %psr = newpsr ^ PSR_ET; - /* set new cpcb */ - st %g5, [%g6 + %lo(_C_LABEL(cpcb))] ! cpcb = newpcb; - - /* - * Now we need to set up the new translations; but we have to be - * careful not to fault (TLB miss) while dereferencing the proper - * structures. - */ - - ld [%g3 + P_VMSPACE], %o3 ! vm = p->p_vmspace; -#if 0 - PTE_OF_ADDR(%o3, %o1, %o2, badstack) - INSERT_PTE(%o3, %o1) -#endif - - ld [%o3 + VM_PMAP], %o3 ! pm = vm->vm_map.pmap; - add %o3, PMAP_PSEGTAB, %o3 -#if 0 - PTE_OF_ADDR(%o3, %o1, %o2, badstack) - INSERT_PTE(%o3, %o1) -#endif - - ld [%o3], %o3 ! pmap->pm_psegtab - lda [%g0] ASI_PDBR, %o4 ! get old psegtab - ldd [%g5 + PCB_SP], %o6 ! <sp,pc> = newpcb->pcb_<sp,pc> - - /* skip flushes if no PDBR change */ - cmp %o3, %o4 - be 9f - clr %o0 - - /* flush cache */ - lda [%g0] ASI_MMCR, %o2 - andn %o2, MMCR_DSET0 | MMCR_DSET1, %o2 - - or %o2, MMCR_DSET0, %o1 ! flush DSET 0 - sta %o1, [%g0] ASI_MMCR - mov DCACHE_LINE(DCACHE_LINES - 1), %o1 -1: lda [%o0] ASI_DCACHE_FLUSH, %g0 - cmp %o0, %o1 - bl 1b - add %o0, DCACHE_INCR, %o0 - - or %o2, MMCR_DSET1, %o2 ! flush DSET 1 - clr %o0 - sta %o2, [%g0] ASI_MMCR -1: lda [%o0] ASI_DCACHE_FLUSH, %g0 - cmp %o0, %o1 - bl 1b - add %o0, DCACHE_INCR, %o0 - - /* invalidate caches */ - sta %g0, [%g0] ASI_DCACHE_INVAL - sta %g0, [%g0] ASI_ICACHE_INVAL - - /* invalidate TLBs */ - sta %g0, [%g0] ASI_PID - sta %g0, [%g0] ASI_PIID - sta %g0, [%g0] ASI_GTLB_INVAL_PID - nop; nop; nop - - /* set up new page tables */ - sta %o3, [%g0] ASI_PDBR - nop; nop; nop - - sta %g0, [%g0] ASI_GTLB_INVALIDATE - nop - - /* - * Before we restore the window from the stack, we have to make - * sure it is in the TLB... - */ - mov %o6, %o3 - PTE_OF_ADDR(%o3, %o1, %o2, badstack) - INSERT_PTE(%o3, %o1) - - SLT_IF_1PAGE_RW(%o3, %o1, %o2) - bl 9f - add %o3, 7 * 8, %o3 - PTE_OF_ADDR(%o3, %o1, %o2, badstack) - INSERT_PTE(%o3, %o1) - /* b 9f; nop */ - -badstack: - /* - * If control goes there, the stack we are restoring does not have - * a valid mapping. We can't recover and will double fault very quickly. - */ - -9: - /* load window */ - ldd [%sp + (0*8)], %l0 - ldd [%sp + (1*8)], %l2 - ldd [%sp + (2*8)], %l4 - ldd [%sp + (3*8)], %l6 - ldd [%sp + (4*8)], %i0 - ldd [%sp + (5*8)], %i2 - ldd [%sp + (6*8)], %i4 - ldd [%sp + (7*8)], %i6 -#ifdef DEBUG - mov %g5, %o0 - SET_SP_REDZONE(%o0, %o1) - CHECK_SP_REDZONE(%o0, %o1) -#endif - /* finally, enable traps */ - wr %g2, 0, %psr ! psr = newpsr; - - /* - * Now running p. Make sure it has a context so that it - * can talk about user space stuff. (Its pcb_uw is currently - * zero so it is safe to have interrupts going here.) - */ - - retl - nop - -ENTRY(cpu_idle_enter) - retl - nop - -ENTRY(cpu_idle_cycle) - retl - nop - -ENTRY(cpu_idle_leave) - retl - nop - - -/* - * Snapshot the current process so that stack frames are up to date. - * Only used just before a crash dump. - */ -ENTRY(snapshot) - std %o6, [%o0 + PCB_SP] ! save sp - rd %psr, %o1 ! save psr - st %o1, [%o0 + PCB_PSR] - - /* - * Just like switch(); same XXX comments apply. - * 7 of each. Minor tweak: the 7th restore is - * done after a ret. - */ - SAVE; SAVE; SAVE; SAVE; SAVE; SAVE; SAVE - restore; restore; restore; restore; restore; restore; ret; restore - - -/* - * cpu_set_kpc() and cpu_fork() arrange for proc_trampoline() to run - * after after a process gets chosen in switch(). The stack frame will - * contain a function pointer in %l0, and an argument to pass to it in %l2. - * - * If the function *(%l0) returns, we arrange for an immediate return - * to user mode. This happens in two known cases: after execve(2) of init, - * and when returning a child to user mode after a fork(2). - */ -ENTRY(proc_trampoline) - /* Reset interrupt level */ - rd %psr, %o0 - andn %o0, PSR_PIL, %o0 ! psr &= ~PSR_PIL; - wr %o0, 0, %psr ! (void) spl0(); - nop ! psr delay; the next 2 instructions - ! can safely be made part of the - ! required 3 instructions psr delay - call %l0 ! re-use current frame - mov %l1, %o0 - - /* - * Here we finish up as in syscall, but simplified. We need to - * fiddle pc and npc a bit, as execve() / setregs() /cpu_set_kpc() - * have only set npc, in anticipation that trap.c will advance past - * the trap instruction; but we bypass that, so we must do it manually. - */ - mov PSR_S, %l0 ! user psr (no need to load it) - !?wr %g0, 2, %wim ! %wim = 2 - ld [%sp + CCFSZ + 4], %l1 ! pc - b return_from_syscall - ld [%sp + CCFSZ + 8], %l2 ! npc - -/* probeget is meant to be used during autoconfiguration */ - -/* - * probeget(addr, size) caddr_t addr; int size; - * - * Read a (byte,short,int) from the given address. - * Like copyin but our caller is supposed to know what he is doing... - * the address can be anywhere. - * - * We optimize for space, rather than time, here. - */ -ENTRY(probeget) - ! %o0 = addr, %o1 = (1,2,4) - sethi %hi(_C_LABEL(cpcb)), %o2 - ld [%o2 + %lo(_C_LABEL(cpcb))], %o2 ! cpcb->pcb_onfault = Lfserr; - set Lfserr, %o5 - st %o5, [%o2 + PCB_ONFAULT] - btst 1, %o1 - bnz,a 0f ! if (len & 1) - ldub [%o0], %o0 ! value = *(char *)addr; -0: btst 2, %o1 - bnz,a 0f ! if (len & 2) - lduh [%o0], %o0 ! value = *(short *)addr; -0: btst 4, %o1 - bnz,a 0f ! if (len & 4) - ld [%o0], %o0 ! value = *(int *)addr; -0: retl ! made it, clear onfault and return - st %g0, [%o2 + PCB_ONFAULT] - -Lfserr: - st %g0, [%o2 + PCB_ONFAULT]! error in r/w, clear pcb_onfault - retl ! and return error indicator - mov -1, %o0 - -/* - * copywords(src, dst, nbytes) - * - * Copy `nbytes' bytes from src to dst, both of which are word-aligned; - * nbytes is a multiple of four. It may, however, be zero, in which case - * nothing is to be copied. - */ -ENTRY(copywords) - ! %o0 = src, %o1 = dst, %o2 = nbytes - b 1f - deccc 4, %o2 -0: - st %o3, [%o1 + %o2] - deccc 4, %o2 ! while ((n -= 4) >= 0) -1: - bge,a 0b ! *(int *)(dst+n) = *(int *)(src+n); - ld [%o0 + %o2], %o3 - retl - nop - -/* - * qcopy(src, dst, nbytes) - * - * (q for `quad' or `quick', as opposed to b for byte/block copy) - * - * Just like copywords, but everything is multiples of 8. - */ -ENTRY(qcopy) - b 1f - deccc 8, %o2 -0: - std %o4, [%o1 + %o2] - deccc 8, %o2 -1: - bge,a 0b - ldd [%o0 + %o2], %o4 - retl - nop - -/* - * qzero(addr, nbytes) - * - * Zeroes `nbytes' bytes of a quad-aligned virtual address, - * where nbytes is itself a multiple of 8. - */ -ENTRY(qzero) - ! %o0 = addr, %o1 = len (in bytes) - clr %g1 -0: - deccc 8, %o1 ! while ((n =- 8) >= 0) - bge,a 0b - std %g0, [%o0 + %o1] ! *(quad *)(addr + n) = 0; - retl - nop - -/* - * kernel bcopy/memcpy - * Assumes regions do not overlap; has no useful return value. - * - * Must not use %g7 (see copyin/copyout above). - */ - -#define BCOPY_SMALL 32 /* if < 32, copy by bytes */ - -ENTRY(memcpy) - /* - * Swap args for bcopy. Gcc generates calls to memcpy for - * structure assignments. - */ - mov %o0, %o3 - mov %o1, %o0 - mov %o3, %o1 -Lbcopy_old: - cmp %o2, BCOPY_SMALL -Lbcopy_start: - bge,a Lbcopy_fancy ! if >= this many, go be fancy. - btst 7, %o0 ! (part of being fancy) - - /* - * Not much to copy, just do it a byte at a time. - */ - deccc %o2 ! while (--len >= 0) - bl 1f - EMPTY -0: - inc %o0 - ldsb [%o0 - 1], %o4 ! (++dst)[-1] = *src++; - stb %o4, [%o1] - deccc %o2 - bge 0b - inc %o1 -1: - retl - nop - /* NOTREACHED */ - - /* - * Plenty of data to copy, so try to do it optimally. - */ -Lbcopy_fancy: - ! check for common case first: everything lines up. -! btst 7, %o0 ! done already - bne 1f - EMPTY - btst 7, %o1 - be,a Lbcopy_doubles - dec 8, %o2 ! if all lined up, len -= 8, goto bcopy_doubes - - ! If the low bits match, we can make these line up. -1: - xor %o0, %o1, %o3 ! t = src ^ dst; - btst 1, %o3 ! if (t & 1) { - be,a 1f - btst 1, %o0 ! [delay slot: if (src & 1)] - - ! low bits do not match, must copy by bytes. -0: - ldsb [%o0], %o4 ! do { - inc %o0 ! (++dst)[-1] = *src++; - inc %o1 - deccc %o2 - bnz 0b ! } while (--len != 0); - stb %o4, [%o1 - 1] - retl - nop - /* NOTREACHED */ - - ! lowest bit matches, so we can copy by words, if nothing else -1: - be,a 1f ! if (src & 1) { - btst 2, %o3 ! [delay slot: if (t & 2)] - - ! although low bits match, both are 1: must copy 1 byte to align - ldsb [%o0], %o4 ! *dst++ = *src++; - stb %o4, [%o1] - inc %o0 - inc %o1 - dec %o2 ! len--; - btst 2, %o3 ! } [if (t & 2)] -1: - be,a 1f ! if (t & 2) { - btst 2, %o0 ! [delay slot: if (src & 2)] - dec 2, %o2 ! len -= 2; -0: - ldsh [%o0], %o4 ! do { - sth %o4, [%o1] ! *(short *)dst = *(short *)src; - inc 2, %o0 ! dst += 2, src += 2; - deccc 2, %o2 ! } while ((len -= 2) >= 0); - bge 0b - inc 2, %o1 - b Lbcopy_mopb ! goto mop_up_byte; - btst 1, %o2 ! } [delay slot: if (len & 1)] - /* NOTREACHED */ - - ! low two bits match, so we can copy by longwords -1: - be,a 1f ! if (src & 2) { - btst 4, %o3 ! [delay slot: if (t & 4)] - - ! although low 2 bits match, they are 10: must copy one short to align - ldsh [%o0], %o4 ! (*short *)dst = *(short *)src; - sth %o4, [%o1] - inc 2, %o0 ! dst += 2; - inc 2, %o1 ! src += 2; - dec 2, %o2 ! len -= 2; - btst 4, %o3 ! } [if (t & 4)] -1: - be,a 1f ! if (t & 4) { - btst 4, %o0 ! [delay slot: if (src & 4)] - dec 4, %o2 ! len -= 4; -0: - ld [%o0], %o4 ! do { - st %o4, [%o1] ! *(int *)dst = *(int *)src; - inc 4, %o0 ! dst += 4, src += 4; - deccc 4, %o2 ! } while ((len -= 4) >= 0); - bge 0b - inc 4, %o1 - b Lbcopy_mopw ! goto mop_up_word_and_byte; - btst 2, %o2 ! } [delay slot: if (len & 2)] - /* NOTREACHED */ - - ! low three bits match, so we can copy by doublewords -1: - be 1f ! if (src & 4) { - dec 8, %o2 ! [delay slot: len -= 8] - ld [%o0], %o4 ! *(int *)dst = *(int *)src; - st %o4, [%o1] - inc 4, %o0 ! dst += 4, src += 4, len -= 4; - inc 4, %o1 - dec 4, %o2 ! } -1: -Lbcopy_doubles: - ldd [%o0], %o4 ! do { - std %o4, [%o1] ! *(double *)dst = *(double *)src; - inc 8, %o0 ! dst += 8, src += 8; - deccc 8, %o2 ! } while ((len -= 8) >= 0); - bge Lbcopy_doubles - inc 8, %o1 - - ! check for a usual case again (save work) - btst 7, %o2 ! if ((len & 7) == 0) - be Lbcopy_done ! goto bcopy_done; - - btst 4, %o2 ! if ((len & 4) == 0) - be,a Lbcopy_mopw ! goto mop_up_word_and_byte; - btst 2, %o2 ! [delay slot: if (len & 2)] - ld [%o0], %o4 ! *(int *)dst = *(int *)src; - st %o4, [%o1] - inc 4, %o0 ! dst += 4; - inc 4, %o1 ! src += 4; - btst 2, %o2 ! } [if (len & 2)] - -1: - ! mop up trailing word (if present) and byte (if present). -Lbcopy_mopw: - be Lbcopy_mopb ! no word, go mop up byte - btst 1, %o2 ! [delay slot: if (len & 1)] - ldsh [%o0], %o4 ! *(short *)dst = *(short *)src; - be Lbcopy_done ! if ((len & 1) == 0) goto done; - sth %o4, [%o1] - ldsb [%o0 + 2], %o4 ! dst[2] = src[2]; - retl - stb %o4, [%o1 + 2] - /* NOTREACHED */ - - ! mop up trailing byte (if present). -Lbcopy_mopb: - bne,a 1f - ldsb [%o0], %o4 - -Lbcopy_done: - retl - nop - -1: - retl - stb %o4,[%o1] -/* - * bcopy(src, dst, len): regions may overlap. - */ -ENTRY(bcopy) - cmp %o0, %o1 ! src < dst? - bgeu Lbcopy_start ! no, go copy forwards as via bcopy - cmp %o2, BCOPY_SMALL! (check length for doublecopy first) - - /* - * Since src comes before dst, and the regions might overlap, - * we have to do the copy starting at the end and working backwards. - */ - add %o2, %o0, %o0 ! src += len - add %o2, %o1, %o1 ! dst += len - bge,a Lback_fancy ! if len >= BCOPY_SMALL, go be fancy - btst 3, %o0 - - /* - * Not much to copy, just do it a byte at a time. - */ - deccc %o2 ! while (--len >= 0) - bl 1f - EMPTY -0: - dec %o0 ! *--dst = *--src; - ldsb [%o0], %o4 - dec %o1 - deccc %o2 - bge 0b - stb %o4, [%o1] -1: - retl - nop - - /* - * Plenty to copy, try to be optimal. - * We only bother with word/halfword/byte copies here. - */ -Lback_fancy: -! btst 3, %o0 ! done already - bnz 1f ! if ((src & 3) == 0 && - btst 3, %o1 ! (dst & 3) == 0) - bz,a Lback_words ! goto words; - dec 4, %o2 ! (done early for word copy) - -1: - /* - * See if the low bits match. - */ - xor %o0, %o1, %o3 ! t = src ^ dst; - btst 1, %o3 - bz,a 3f ! if (t & 1) == 0, can do better - btst 1, %o0 - - /* - * Nope; gotta do byte copy. - */ -2: - dec %o0 ! do { - ldsb [%o0], %o4 ! *--dst = *--src; - dec %o1 - deccc %o2 ! } while (--len != 0); - bnz 2b - stb %o4, [%o1] - retl - nop - -3: - /* - * Can do halfword or word copy, but might have to copy 1 byte first. - */ -! btst 1, %o0 ! done earlier - bz,a 4f ! if (src & 1) { /* copy 1 byte */ - btst 2, %o3 ! (done early) - dec %o0 ! *--dst = *--src; - ldsb [%o0], %o4 - dec %o1 - stb %o4, [%o1] - dec %o2 ! len--; - btst 2, %o3 ! } - -4: - /* - * See if we can do a word copy ((t&2) == 0). - */ -! btst 2, %o3 ! done earlier - bz,a 6f ! if (t & 2) == 0, can do word copy - btst 2, %o0 ! (src&2, done early) - - /* - * Gotta do halfword copy. - */ - dec 2, %o2 ! len -= 2; -5: - dec 2, %o0 ! do { - ldsh [%o0], %o4 ! src -= 2; - dec 2, %o1 ! dst -= 2; - deccc 2, %o2 ! *(short *)dst = *(short *)src; - bge 5b ! } while ((len -= 2) >= 0); - sth %o4, [%o1] - b Lback_mopb ! goto mop_up_byte; - btst 1, %o2 ! (len&1, done early) - -6: - /* - * We can do word copies, but we might have to copy - * one halfword first. - */ -! btst 2, %o0 ! done already - bz 7f ! if (src & 2) { - dec 4, %o2 ! (len -= 4, done early) - dec 2, %o0 ! src -= 2, dst -= 2; - ldsh [%o0], %o4 ! *(short *)dst = *(short *)src; - dec 2, %o1 - sth %o4, [%o1] - dec 2, %o2 ! len -= 2; - ! } - -7: -Lback_words: - /* - * Do word copies (backwards), then mop up trailing halfword - * and byte if any. - */ -! dec 4, %o2 ! len -= 4, done already -0: ! do { - dec 4, %o0 ! src -= 4; - dec 4, %o1 ! src -= 4; - ld [%o0], %o4 ! *(int *)dst = *(int *)src; - deccc 4, %o2 ! } while ((len -= 4) >= 0); - bge 0b - st %o4, [%o1] - - /* - * Check for trailing shortword. - */ - btst 2, %o2 ! if (len & 2) { - bz,a 1f - btst 1, %o2 ! (len&1, done early) - dec 2, %o0 ! src -= 2, dst -= 2; - ldsh [%o0], %o4 ! *(short *)dst = *(short *)src; - dec 2, %o1 - sth %o4, [%o1] ! } - btst 1, %o2 - - /* - * Check for trailing byte. - */ -1: -Lback_mopb: -! btst 1, %o2 ! (done already) - bnz,a 1f ! if (len & 1) { - ldsb [%o0 - 1], %o4 ! b = src[-1]; - retl - nop -1: - retl ! dst[-1] = b; - stb %o4, [%o1 - 1] ! } - -/* - * kcopy() is exactly like old bcopy except that it set pcb_onfault such that - * when a fault occurs, it is able to return EFAULT to indicate this to the - * caller. - */ -ENTRY(kcopy) - sethi %hi(_C_LABEL(cpcb)), %o5 ! cpcb->pcb_onfault = Lkcerr; - ld [%o5 + %lo(_C_LABEL(cpcb))], %o5 - set Lkcerr, %o3 - ld [%o5 + PCB_ONFAULT], %g1! save current onfault handler - st %o3, [%o5 + PCB_ONFAULT] - - cmp %o2, BCOPY_SMALL -Lkcopy_start: - bge,a Lkcopy_fancy ! if >= this many, go be fancy. - btst 7, %o0 ! (part of being fancy) - - /* - * Not much to copy, just do it a byte at a time. - */ - deccc %o2 ! while (--len >= 0) - bl 1f - EMPTY -0: - ldsb [%o0], %o4 ! *dst++ = *src++; - inc %o0 - stb %o4, [%o1] - deccc %o2 - bge 0b - inc %o1 -1: - st %g1, [%o5 + PCB_ONFAULT] ! restore onfault - retl - mov 0, %o0 ! delay slot: return success - /* NOTREACHED */ - - /* - * Plenty of data to copy, so try to do it optimally. - */ -Lkcopy_fancy: - ! check for common case first: everything lines up. -! btst 7, %o0 ! done already - bne 1f - EMPTY - btst 7, %o1 - be,a Lkcopy_doubles - dec 8, %o2 ! if all lined up, len -= 8, goto bcopy_doubes - - ! If the low bits match, we can make these line up. -1: - xor %o0, %o1, %o3 ! t = src ^ dst; - btst 1, %o3 ! if (t & 1) { - be,a 1f - btst 1, %o0 ! [delay slot: if (src & 1)] - - ! low bits do not match, must copy by bytes. -0: - ldsb [%o0], %o4 ! do { - inc %o0 ! *dst++ = *src++; - stb %o4, [%o1] - deccc %o2 - bnz 0b ! } while (--len != 0); - inc %o1 - st %g1, [%o5 + PCB_ONFAULT] ! restore onfault - retl - mov 0, %o0 ! delay slot: return success - /* NOTREACHED */ - - ! lowest bit matches, so we can copy by words, if nothing else -1: - be,a 1f ! if (src & 1) { - btst 2, %o3 ! [delay slot: if (t & 2)] - - ! although low bits match, both are 1: must copy 1 byte to align - ldsb [%o0], %o4 ! *dst++ = *src++; - inc %o0 - stb %o4, [%o1] - dec %o2 ! len--; - inc %o1 - btst 2, %o3 ! } [if (t & 2)] -1: - be,a 1f ! if (t & 2) { - btst 2, %o0 ! [delay slot: if (src & 2)] - dec 2, %o2 ! len -= 2; -0: - ldsh [%o0], %o4 ! do { - inc 2, %o0 ! dst += 2, src += 2; - sth %o4, [%o1] ! *(short *)dst = *(short *)src; - deccc 2, %o2 ! } while ((len -= 2) >= 0); - bge 0b - inc 2, %o1 - b Lkcopy_mopb ! goto mop_up_byte; - btst 1, %o2 ! } [delay slot: if (len & 1)] - /* NOTREACHED */ - - ! low two bits match, so we can copy by longwords -1: - be,a 1f ! if (src & 2) { - btst 4, %o3 ! [delay slot: if (t & 4)] - - ! although low 2 bits match, they are 10: must copy one short to align - ldsh [%o0], %o4 ! (*short *)dst = *(short *)src; - inc 2, %o0 ! dst += 2; - sth %o4, [%o1] - dec 2, %o2 ! len -= 2; - inc 2, %o1 ! src += 2; - btst 4, %o3 ! } [if (t & 4)] -1: - be,a 1f ! if (t & 4) { - btst 4, %o0 ! [delay slot: if (src & 4)] - dec 4, %o2 ! len -= 4; -0: - ld [%o0], %o4 ! do { - inc 4, %o0 ! dst += 4, src += 4; - st %o4, [%o1] ! *(int *)dst = *(int *)src; - deccc 4, %o2 ! } while ((len -= 4) >= 0); - bge 0b - inc 4, %o1 - b Lkcopy_mopw ! goto mop_up_word_and_byte; - btst 2, %o2 ! } [delay slot: if (len & 2)] - /* NOTREACHED */ - - ! low three bits match, so we can copy by doublewords -1: - be 1f ! if (src & 4) { - dec 8, %o2 ! [delay slot: len -= 8] - ld [%o0], %o4 ! *(int *)dst = *(int *)src; - inc 4, %o0 ! dst += 4, src += 4, len -= 4; - st %o4, [%o1] - dec 4, %o2 ! } - inc 4, %o1 -1: -Lkcopy_doubles: - ! swap %o4 with %o2 during doubles copy, since %o5 is verboten - mov %o2, %o4 -Lkcopy_doubles2: - ldd [%o0], %o2 ! do { - inc 8, %o0 ! dst += 8, src += 8; - std %o2, [%o1] ! *(double *)dst = *(double *)src; - deccc 8, %o4 ! } while ((len -= 8) >= 0); - bge Lkcopy_doubles2 - inc 8, %o1 - mov %o4, %o2 ! restore len - - ! check for a usual case again (save work) - btst 7, %o2 ! if ((len & 7) == 0) - be Lkcopy_done ! goto bcopy_done; - - btst 4, %o2 ! if ((len & 4) == 0) - be,a Lkcopy_mopw ! goto mop_up_word_and_byte; - btst 2, %o2 ! [delay slot: if (len & 2)] - ld [%o0], %o4 ! *(int *)dst = *(int *)src; - inc 4, %o0 ! dst += 4; - st %o4, [%o1] - inc 4, %o1 ! src += 4; - btst 2, %o2 ! } [if (len & 2)] - -1: - ! mop up trailing word (if present) and byte (if present). -Lkcopy_mopw: - be Lkcopy_mopb ! no word, go mop up byte - btst 1, %o2 ! [delay slot: if (len & 1)] - ldsh [%o0], %o4 ! *(short *)dst = *(short *)src; - be Lkcopy_done ! if ((len & 1) == 0) goto done; - sth %o4, [%o1] - ldsb [%o0 + 2], %o4 ! dst[2] = src[2]; - stb %o4, [%o1 + 2] - st %g1, [%o5 + PCB_ONFAULT]! restore onfault - retl - mov 0, %o0 ! delay slot: return success - /* NOTREACHED */ - - ! mop up trailing byte (if present). -Lkcopy_mopb: - bne,a 1f - ldsb [%o0], %o4 - -Lkcopy_done: - st %g1, [%o5 + PCB_ONFAULT] ! restore onfault - retl - mov 0, %o0 ! delay slot: return success - /* NOTREACHED */ - -1: - stb %o4, [%o1] - st %g1, [%o5 + PCB_ONFAULT] ! restore onfault - retl - mov 0, %o0 ! delay slot: return success - /* NOTREACHED */ - -Lkcerr: - st %g1, [%o5 + PCB_ONFAULT] ! restore onfault - retl - mov EFAULT, %o0 ! delay slot: return error indicator - /* NOTREACHED */ - -/* - * savefpstate(f) struct fpstate *f; - * - * Store the current FPU state. The first `st %fsr' may cause a trap; - * our trap handler knows how to recover (by `returning' to savefpcont). - */ -ENTRY(savefpstate) - rd %psr, %o1 ! enable FP before we begin - set PSR_EF, %o2 - or %o1, %o2, %o1 - wr %o1, 0, %psr - /* do some setup work while we wait for PSR_EF to turn on */ - set FSR_QNE, %o5 ! QNE = 0x2000, too big for immediate - clr %o3 ! qsize = 0; - nop ! (still waiting for PSR_EF) -special_fp_store: - st %fsr, [%o0 + FS_FSR] ! f->fs_fsr = getfsr(); - /* - * Even if the preceding instruction did not trap, the queue - * is not necessarily empty: this state save might be happening - * because user code tried to store %fsr and took the FPU - * from `exception pending' mode to `exception' mode. - * So we still have to check the blasted QNE bit. - * With any luck it will usually not be set. - */ - ld [%o0 + FS_FSR], %o4 ! if (f->fs_fsr & QNE) - btst %o5, %o4 - bnz Lfp_storeq ! goto storeq; - std %f0, [%o0 + FS_REGS + (4*0)] ! f->fs_f0 = etc; -Lfp_finish: - st %o3, [%o0 + FS_QSIZE] ! f->fs_qsize = qsize; - std %f2, [%o0 + FS_REGS + (4*2)] - std %f4, [%o0 + FS_REGS + (4*4)] - std %f6, [%o0 + FS_REGS + (4*6)] - std %f8, [%o0 + FS_REGS + (4*8)] - std %f10, [%o0 + FS_REGS + (4*10)] - std %f12, [%o0 + FS_REGS + (4*12)] - std %f14, [%o0 + FS_REGS + (4*14)] - std %f16, [%o0 + FS_REGS + (4*16)] - std %f18, [%o0 + FS_REGS + (4*18)] - std %f20, [%o0 + FS_REGS + (4*20)] - std %f22, [%o0 + FS_REGS + (4*22)] - std %f24, [%o0 + FS_REGS + (4*24)] - std %f26, [%o0 + FS_REGS + (4*26)] - std %f28, [%o0 + FS_REGS + (4*28)] - retl - std %f30, [%o0 + FS_REGS + (4*30)] - -/* - * Store the (now known nonempty) FP queue. - * We have to reread the fsr each time in order to get the new QNE bit. - */ -Lfp_storeq: - add %o0, FS_QUEUE, %o1 ! q = &f->fs_queue[0]; -1: - std %fq, [%o1 + %o3] ! q[qsize++] = fsr_qfront(); - st %fsr, [%o0 + FS_FSR] ! reread fsr - ld [%o0 + FS_FSR], %o4 ! if fsr & QNE, loop - btst %o5, %o4 - bnz 1b - inc 8, %o3 - b Lfp_finish ! set qsize and finish storing fregs - srl %o3, 3, %o3 ! (but first fix qsize) - -/* - * The fsr store trapped. Do it again; this time it will not trap. - * We could just have the trap handler return to the `st %fsr', but - * if for some reason it *does* trap, that would lock us into a tight - * loop. This way we panic instead. Whoopee. - */ -savefpcont: - b special_fp_store + 4 ! continue - st %fsr, [%o0 + FS_FSR] ! but first finish the %fsr store - -/* - * Load FPU state. - */ -ENTRY(loadfpstate) - rd %psr, %o1 ! enable FP before we begin - set PSR_EF, %o2 - or %o1, %o2, %o1 - wr %o1, 0, %psr - nop; nop; nop ! paranoia - ldd [%o0 + FS_REGS + (4*0)], %f0 - ldd [%o0 + FS_REGS + (4*2)], %f2 - ldd [%o0 + FS_REGS + (4*4)], %f4 - ldd [%o0 + FS_REGS + (4*6)], %f6 - ldd [%o0 + FS_REGS + (4*8)], %f8 - ldd [%o0 + FS_REGS + (4*10)], %f10 - ldd [%o0 + FS_REGS + (4*12)], %f12 - ldd [%o0 + FS_REGS + (4*14)], %f14 - ldd [%o0 + FS_REGS + (4*16)], %f16 - ldd [%o0 + FS_REGS + (4*18)], %f18 - ldd [%o0 + FS_REGS + (4*20)], %f20 - ldd [%o0 + FS_REGS + (4*22)], %f22 - ldd [%o0 + FS_REGS + (4*24)], %f24 - ldd [%o0 + FS_REGS + (4*26)], %f26 - ldd [%o0 + FS_REGS + (4*28)], %f28 - ldd [%o0 + FS_REGS + (4*30)], %f30 - retl - ld [%o0 + FS_FSR], %fsr ! setfsr(f->fs_fsr); - -/* - * ffs(), using table lookup. - * The process switch code shares the table, so we just put the - * whole thing here. - */ -ffstab: - .byte -24,1,2,1,3,1,2,1,4,1,2,1,3,1,2,1 /* 00-0f */ - .byte 5,1,2,1,3,1,2,1,4,1,2,1,3,1,2,1 /* 10-1f */ - .byte 6,1,2,1,3,1,2,1,4,1,2,1,3,1,2,1 /* 20-2f */ - .byte 5,1,2,1,3,1,2,1,4,1,2,1,3,1,2,1 /* 30-3f */ - .byte 7,1,2,1,3,1,2,1,4,1,2,1,3,1,2,1 /* 40-4f */ - .byte 5,1,2,1,3,1,2,1,4,1,2,1,3,1,2,1 /* 50-5f */ - .byte 6,1,2,1,3,1,2,1,4,1,2,1,3,1,2,1 /* 60-6f */ - .byte 5,1,2,1,3,1,2,1,4,1,2,1,3,1,2,1 /* 70-7f */ - .byte 8,1,2,1,3,1,2,1,4,1,2,1,3,1,2,1 /* 80-8f */ - .byte 5,1,2,1,3,1,2,1,4,1,2,1,3,1,2,1 /* 10-9f */ - .byte 6,1,2,1,3,1,2,1,4,1,2,1,3,1,2,1 /* a0-af */ - .byte 5,1,2,1,3,1,2,1,4,1,2,1,3,1,2,1 /* b0-bf */ - .byte 7,1,2,1,3,1,2,1,4,1,2,1,3,1,2,1 /* c0-cf */ - .byte 5,1,2,1,3,1,2,1,4,1,2,1,3,1,2,1 /* d0-df */ - .byte 6,1,2,1,3,1,2,1,4,1,2,1,3,1,2,1 /* e0-ef */ - .byte 5,1,2,1,3,1,2,1,4,1,2,1,3,1,2,1 /* f0-ff */ - -/* - * We use a table lookup on each byte. - * - * In each section below, %o1 is the current byte (0, 1, 2, or 3). - * The last byte is handled specially: for the first three, - * if that byte is nonzero, we return the table value - * (plus 0, 8, or 16 for the byte number), but for the last - * one, we just return the table value plus 24. This means - * that ffstab[0] must be -24 so that ffs(0) will return 0. - */ -ENTRY(ffs) - set ffstab, %o2 - andcc %o0, 0xff, %o1 ! get low byte - bz,a 1f ! try again if 0 - srl %o0, 8, %o0 ! delay slot, get ready for next byte - - retl ! return ffstab[%o1] - ldsb [%o2 + %o1], %o0 - -1: - andcc %o0, 0xff, %o1 ! byte 1 like byte 0... - bz,a 2f - srl %o0, 8, %o0 ! (use delay to prepare for byte 2) - - ldsb [%o2 + %o1], %o0 - retl ! return ffstab[%o1] + 8 - add %o0, 8, %o0 - -2: - andcc %o0, 0xff, %o1 - bz,a 3f - srl %o0, 8, %o0 ! (prepare for byte 3) - - ldsb [%o2 + %o1], %o0 - retl ! return ffstab[%o1] + 16 - add %o0, 16, %o0 - -3: ! just return ffstab[%o0] + 24 - ldsb [%o2 + %o0], %o0 - retl - add %o0, 24, %o0 - -/* - * V8 sparc .{,u}{mul,div,rem} replacements. - * We try to mimic them 100%. Full 64 bit sources or outputs, and - * these routines are required to update the condition codes. - */ -.globl _C_LABEL(_mulreplace), _C_LABEL(_mulreplace_end) -_C_LABEL(_mulreplace): - smulcc %o0, %o1, %o0 - retl - rd %y, %o1 -_C_LABEL(_mulreplace_end): - -.globl _C_LABEL(_umulreplace), _C_LABEL(_umulreplace_end) -_C_LABEL(_umulreplace): - umulcc %o0, %o1, %o0 - retl - rd %y, %o1 -_C_LABEL(_umulreplace_end): - -.globl _C_LABEL(_divreplace), _C_LABEL(_divreplace_end) -_C_LABEL(_divreplace): - sra %o0, 31, %g1 - wr %g1, 0, %y - nop - nop - nop - retl - sdivcc %o0, %o1, %o0 -_C_LABEL(_divreplace_end): - -.globl _C_LABEL(_udivreplace), _C_LABEL(_udivreplace_end) -_C_LABEL(_udivreplace): - wr %g0, 0, %y - nop - nop - nop - retl - udivcc %o0, %o1, %o0 -_C_LABEL(_udivreplace_end): - -.globl _C_LABEL(_remreplace), _C_LABEL(_remreplace_end) -_C_LABEL(_remreplace): - sra %o0, 31, %g1 - wr %g1, 0, %y - nop - nop - nop - sdiv %o0, %o1, %o2 - smul %o1, %o2, %o2 - retl - subcc %o0, %o2, %o0 -_C_LABEL(_remreplace_end): - -.globl _C_LABEL(_uremreplace), _C_LABEL(_uremreplace_end) -_C_LABEL(_uremreplace): - wr %g0, 0, %y - nop - nop - nop - udiv %o0, %o1, %o2 - umul %o1, %o2, %o2 - retl - subcc %o0, %o2, %o0 -_C_LABEL(_uremreplace_end): - -/* - * Signed multiply, from Appendix E of the Sparc Version 8 - * Architecture Manual. - * - * Returns %o0 * %o1 in %o1%o0 (i.e., %o1 holds the upper 32 bits of - * the 64-bit product). - * - * This code optimizes short (less than 13-bit) multiplies. - */ -.globl .mul, _C_LABEL(_mul) -.mul: -_C_LABEL(_mul): - mov %o0, %y ! multiplier -> Y - andncc %o0, 0xfff, %g0 ! test bits 12..31 - be Lmul_shortway ! if zero, can do it the short way - andcc %g0, %g0, %o4 ! zero the partial product and clear N and V - - /* - * Long multiply. 32 steps, followed by a final shift step. - */ - mulscc %o4, %o1, %o4 ! 1 - mulscc %o4, %o1, %o4 ! 2 - mulscc %o4, %o1, %o4 ! 3 - mulscc %o4, %o1, %o4 ! 4 - mulscc %o4, %o1, %o4 ! 5 - mulscc %o4, %o1, %o4 ! 6 - mulscc %o4, %o1, %o4 ! 7 - mulscc %o4, %o1, %o4 ! 8 - mulscc %o4, %o1, %o4 ! 9 - mulscc %o4, %o1, %o4 ! 10 - mulscc %o4, %o1, %o4 ! 11 - mulscc %o4, %o1, %o4 ! 12 - mulscc %o4, %o1, %o4 ! 13 - mulscc %o4, %o1, %o4 ! 14 - mulscc %o4, %o1, %o4 ! 15 - mulscc %o4, %o1, %o4 ! 16 - mulscc %o4, %o1, %o4 ! 17 - mulscc %o4, %o1, %o4 ! 18 - mulscc %o4, %o1, %o4 ! 19 - mulscc %o4, %o1, %o4 ! 20 - mulscc %o4, %o1, %o4 ! 21 - mulscc %o4, %o1, %o4 ! 22 - mulscc %o4, %o1, %o4 ! 23 - mulscc %o4, %o1, %o4 ! 24 - mulscc %o4, %o1, %o4 ! 25 - mulscc %o4, %o1, %o4 ! 26 - mulscc %o4, %o1, %o4 ! 27 - mulscc %o4, %o1, %o4 ! 28 - mulscc %o4, %o1, %o4 ! 29 - mulscc %o4, %o1, %o4 ! 30 - mulscc %o4, %o1, %o4 ! 31 - mulscc %o4, %o1, %o4 ! 32 - mulscc %o4, %g0, %o4 ! final shift - - ! If %o0 was negative, the result is - ! (%o0 * %o1) + (%o1 << 32)) - ! We fix that here. - - tst %o0 - bge 1f - rd %y, %o0 - - ! %o0 was indeed negative; fix upper 32 bits of result by subtracting - ! %o1 (i.e., return %o4 - %o1 in %o1). - retl - sub %o4, %o1, %o1 - -1: - retl - mov %o4, %o1 - -Lmul_shortway: - /* - * Short multiply. 12 steps, followed by a final shift step. - * The resulting bits are off by 12 and (32-12) = 20 bit positions, - * but there is no problem with %o0 being negative (unlike above). - */ - mulscc %o4, %o1, %o4 ! 1 - mulscc %o4, %o1, %o4 ! 2 - mulscc %o4, %o1, %o4 ! 3 - mulscc %o4, %o1, %o4 ! 4 - mulscc %o4, %o1, %o4 ! 5 - mulscc %o4, %o1, %o4 ! 6 - mulscc %o4, %o1, %o4 ! 7 - mulscc %o4, %o1, %o4 ! 8 - mulscc %o4, %o1, %o4 ! 9 - mulscc %o4, %o1, %o4 ! 10 - mulscc %o4, %o1, %o4 ! 11 - mulscc %o4, %o1, %o4 ! 12 - mulscc %o4, %g0, %o4 ! final shift - - /* - * %o4 has 20 of the bits that should be in the low part of the - * result; %y has the bottom 12 (as %y's top 12). That is: - * - * %o4 %y - * +----------------+----------------+ - * | -12- | -20- | -12- | -20- | - * +------(---------+------)---------+ - * --hi-- ----low-part---- - * - * The upper 12 bits of %o4 should be sign-extended to form the - * high part of the product (i.e., highpart = %o4 >> 20). - */ - - rd %y, %o5 - sll %o4, 12, %o0 ! shift middle bits left 12 - srl %o5, 20, %o5 ! shift low bits right 20, zero fill at left - or %o5, %o0, %o0 ! construct low part of result - retl - sra %o4, 20, %o1 ! ... and extract high part of result - -/* - * Unsigned multiply. Returns %o0 * %o1 in %o1%o0 (i.e., %o1 holds the - * upper 32 bits of the 64-bit product). - * - * This code optimizes short (less than 13-bit) multiplies. Short - * multiplies require 25 instruction cycles, and long ones require - * 45 instruction cycles. - * - * On return, overflow has occurred (%o1 is not zero) if and only if - * the Z condition code is clear, allowing, e.g., the following: - * - * call .umul - * nop - * bnz overflow (or tnz) - */ -.globl .umul, _C_LABEL(_umul) -.umul: -_C_LABEL(_umul): - or %o0, %o1, %o4 - mov %o0, %y ! multiplier -> Y - andncc %o4, 0xfff, %g0 ! test bits 12..31 of *both* args - be Lumul_shortway ! if zero, can do it the short way - andcc %g0, %g0, %o4 ! zero the partial product and clear N and V - - /* - * Long multiply. 32 steps, followed by a final shift step. - */ - mulscc %o4, %o1, %o4 ! 1 - mulscc %o4, %o1, %o4 ! 2 - mulscc %o4, %o1, %o4 ! 3 - mulscc %o4, %o1, %o4 ! 4 - mulscc %o4, %o1, %o4 ! 5 - mulscc %o4, %o1, %o4 ! 6 - mulscc %o4, %o1, %o4 ! 7 - mulscc %o4, %o1, %o4 ! 8 - mulscc %o4, %o1, %o4 ! 9 - mulscc %o4, %o1, %o4 ! 10 - mulscc %o4, %o1, %o4 ! 11 - mulscc %o4, %o1, %o4 ! 12 - mulscc %o4, %o1, %o4 ! 13 - mulscc %o4, %o1, %o4 ! 14 - mulscc %o4, %o1, %o4 ! 15 - mulscc %o4, %o1, %o4 ! 16 - mulscc %o4, %o1, %o4 ! 17 - mulscc %o4, %o1, %o4 ! 18 - mulscc %o4, %o1, %o4 ! 19 - mulscc %o4, %o1, %o4 ! 20 - mulscc %o4, %o1, %o4 ! 21 - mulscc %o4, %o1, %o4 ! 22 - mulscc %o4, %o1, %o4 ! 23 - mulscc %o4, %o1, %o4 ! 24 - mulscc %o4, %o1, %o4 ! 25 - mulscc %o4, %o1, %o4 ! 26 - mulscc %o4, %o1, %o4 ! 27 - mulscc %o4, %o1, %o4 ! 28 - mulscc %o4, %o1, %o4 ! 29 - mulscc %o4, %o1, %o4 ! 30 - mulscc %o4, %o1, %o4 ! 31 - mulscc %o4, %o1, %o4 ! 32 - mulscc %o4, %g0, %o4 ! final shift - - - /* - * Normally, with the shift-and-add approach, if both numbers are - * positive you get the correct result. WIth 32-bit two's-complement - * numbers, -x is represented as - * - * x 32 - * ( 2 - ------ ) mod 2 * 2 - * 32 - * 2 - * - * (the `mod 2' subtracts 1 from 1.bbbb). To avoid lots of 2^32s, - * we can treat this as if the radix point were just to the left - * of the sign bit (multiply by 2^32), and get - * - * -x = (2 - x) mod 2 - * - * Then, ignoring the `mod 2's for convenience: - * - * x * y = xy - * -x * y = 2y - xy - * x * -y = 2x - xy - * -x * -y = 4 - 2x - 2y + xy - * - * For signed multiplies, we subtract (x << 32) from the partial - * product to fix this problem for negative multipliers (see mul.s). - * Because of the way the shift into the partial product is calculated - * (N xor V), this term is automatically removed for the multiplicand, - * so we don't have to adjust. - * - * But for unsigned multiplies, the high order bit wasn't a sign bit, - * and the correction is wrong. So for unsigned multiplies where the - * high order bit is one, we end up with xy - (y << 32). To fix it - * we add y << 32. - */ - tst %o1 - bl,a 1f ! if %o1 < 0 (high order bit = 1), - add %o4, %o0, %o4 ! %o4 += %o0 (add y to upper half) -1: rd %y, %o0 ! get lower half of product - retl - addcc %o4, %g0, %o1 ! put upper half in place and set Z for %o1==0 - -Lumul_shortway: - /* - * Short multiply. 12 steps, followed by a final shift step. - * The resulting bits are off by 12 and (32-12) = 20 bit positions, - * but there is no problem with %o0 being negative (unlike above), - * and overflow is impossible (the answer is at most 24 bits long). - */ - mulscc %o4, %o1, %o4 ! 1 - mulscc %o4, %o1, %o4 ! 2 - mulscc %o4, %o1, %o4 ! 3 - mulscc %o4, %o1, %o4 ! 4 - mulscc %o4, %o1, %o4 ! 5 - mulscc %o4, %o1, %o4 ! 6 - mulscc %o4, %o1, %o4 ! 7 - mulscc %o4, %o1, %o4 ! 8 - mulscc %o4, %o1, %o4 ! 9 - mulscc %o4, %o1, %o4 ! 10 - mulscc %o4, %o1, %o4 ! 11 - mulscc %o4, %o1, %o4 ! 12 - mulscc %o4, %g0, %o4 ! final shift - - /* - * %o4 has 20 of the bits that should be in the result; %y has - * the bottom 12 (as %y's top 12). That is: - * - * %o4 %y - * +----------------+----------------+ - * | -12- | -20- | -12- | -20- | - * +------(---------+------)---------+ - * -----result----- - * - * The 12 bits of %o4 left of the `result' area are all zero; - * in fact, all top 20 bits of %o4 are zero. - */ - - rd %y, %o5 - sll %o4, 12, %o0 ! shift middle bits left 12 - srl %o5, 20, %o5 ! shift low bits right 20 - or %o5, %o0, %o0 - retl - addcc %g0, %g0, %o1 ! %o1 = zero, and set Z - -/* - * delay function - * - * void delay(N) -- delay N microseconds - * - * Register usage: %o0 = "N" number of usecs to go (counts down to zero) - * %o1 = "timerblurb" (stays constant) - * %o2 = counter for 1 usec (counts down from %o1 to zero) - * - */ - -ENTRY(delay) ! %o0 = n - subcc %o0, %g0, %g0 - be 2f - - sethi %hi(_C_LABEL(timerblurb)), %o1 - ld [%o1 + %lo(_C_LABEL(timerblurb))], %o1 ! %o1 = timerblurb - - addcc %o1, %g0, %o2 ! %o2 = cntr (start @ %o1), clear CCs - ! first time through only - - ! delay 1 usec -1: bne 1b ! come back here if not done - subcc %o2, 1, %o2 ! %o2 = %o2 - 1 [delay slot] - - subcc %o0, 1, %o0 ! %o0 = %o0 - 1 - bne 1b ! done yet? - addcc %o1, %g0, %o2 ! reinit %o2 and CCs [delay slot] - ! harmless if not branching -2: - retl ! return - nop ! [delay slot] - -#if defined(KGDB) || defined(DDB) || defined(DIAGNOSTIC) -/* - * Write all windows (user or otherwise), except the current one. - * - * THIS COULD BE DONE IN USER CODE - */ -ENTRY(write_all_windows) - /* - * g2 = g1 = nwindows - 1; - * while (--g1 > 0) save(); - * while (--g2 > 0) restore(); - */ - sethi %hi(_C_LABEL(nwindows)), %g1 - ld [%g1 + %lo(_C_LABEL(nwindows))], %g1 - dec %g1 - mov %g1, %g2 - -1: deccc %g1 - bg,a 1b - save %sp, -64, %sp - -2: deccc %g2 - bg,a 2b - restore - - retl - nop -#endif /* KGDB */ - -ENTRY(setjmp) - std %sp, [%o0+0] ! stack pointer & return pc - st %fp, [%o0+8] ! frame pointer - retl - clr %o0 - -Lpanic_ljmp: - .asciz "longjmp botch" - _ALIGN - -ENTRY(longjmp) - mov 1, %g6 - mov %o0, %g1 ! save a in another global register - ld [%g1+8], %g7 /* get caller's frame */ -1: - cmp %fp, %g7 ! compare against desired frame - bl,a 1b ! if below, - restore ! pop frame and loop - be,a 2f ! if there, - ldd [%g1+0], %o2 ! fetch return %sp and pc, and get out - -Llongjmpbotch: - ! otherwise, went too far; bomb out - save %sp, -CCFSZ, %sp /* preserve current window */ - sethi %hi(Lpanic_ljmp), %o0 - call _C_LABEL(panic) - or %o0, %lo(Lpanic_ljmp), %o0; - unimp 0 - -2: - cmp %o2, %sp ! %sp must not decrease - bge,a 3f - mov %o2, %sp ! it is OK, put it in place - b,a Llongjmpbotch -3: - jmp %o3 + 8 ! success, return %g6 - mov %g6, %o0 - -/* - * Early console code. Ugly, but works. - */ -ENTRY(earlycnputc) - save %sp, -64, %sp - sethi %hi(ZS0_BASE), %l1 -1: ldub [%l1 + %lo(ZS0_BASE) + 0x10], %l2 - btst ZSRR0_TX_READY, %l2 - be 1b - nop - stb %i1, [%l1 + %lo(ZS0_BASE) + 0x18] - set 0x2000, %l1 -1: cmp %l1, 0 - bne 1b - dec %l1 - ret - restore - -ENTRY(earlycngetc) - save %sp, -64, %sp - sethi %hi(ZS0_BASE), %l1 -1: ldub [%l1 + %lo(ZS0_BASE) + 0x10], %l2 - btst ZSRR0_RX_READY, %l2 - be 1b - nop - ldub [%l1 + %lo(ZS0_BASE) + 0x18], %i0 - set 0x2000, %l1 -1: cmp %l1, 0 - bne 1b - dec %l1 - ret - restore - - .data -#if defined(DDB) || NKSYMS > 0 - .globl _C_LABEL(esym) -_C_LABEL(esym): - .word 0 -#endif - .globl _C_LABEL(cold) -_C_LABEL(cold): - .word 1 ! cold start flag - - .globl _C_LABEL(proc0paddr) -_C_LABEL(proc0paddr): - .word _C_LABEL(u0) ! KVA of proc0 uarea - -! StackGhost: added 2 symbols to ease debugging - .globl slowtrap - .globl winuf_invalid - - .comm _C_LABEL(nwindows), 4 diff --git a/sys/arch/solbourne/solbourne/machdep.c b/sys/arch/solbourne/solbourne/machdep.c deleted file mode 100644 index cc6b2c4d4a1..00000000000 --- a/sys/arch/solbourne/solbourne/machdep.c +++ /dev/null @@ -1,745 +0,0 @@ -/* $OpenBSD: machdep.c,v 1.46 2015/01/16 20:17:07 kettenis Exp $ */ -/* OpenBSD: machdep.c,v 1.105 2005/04/11 15:13:01 deraadt Exp */ - -/* - * Copyright (c) 1992, 1993 - * The Regents of the University of California. All rights reserved. - * - * This software was developed by the Computer Systems Engineering group - * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and - * contributed to Berkeley. - * - * 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, Lawrence Berkeley Laboratory. - * - * 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. 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. - * - * @(#)machdep.c 8.6 (Berkeley) 1/14/94 - */ - -#include <sys/param.h> -#include <sys/signal.h> -#include <sys/signalvar.h> -#include <sys/proc.h> -#include <sys/user.h> -#include <sys/buf.h> -#include <sys/device.h> -#include <sys/reboot.h> -#include <sys/systm.h> -#include <sys/conf.h> -#include <sys/file.h> -#include <sys/timeout.h> -#include <sys/malloc.h> -#include <sys/mbuf.h> -#include <sys/mount.h> -#include <sys/msgbuf.h> -#include <sys/syscallargs.h> -#include <sys/exec.h> -#include <sys/sysctl.h> -#include <sys/extent.h> - -#include <net/if.h> -#include <uvm/uvm.h> - -#include <dev/rndvar.h> - -#include <machine/autoconf.h> -#include <machine/frame.h> -#include <machine/cpu.h> -#include <machine/pmap.h> -#include <machine/oldmon.h> -#include <machine/bsd_openprom.h> - -#include <machine/idt.h> -#include <machine/kap.h> -#include <machine/prom.h> - -#include <sparc/sparc/asm.h> -#include <sparc/sparc/cache.h> -#include <sparc/sparc/cpuvar.h> - -#include "auxreg.h" - -#include <sparc/sparc/intreg.h> - -struct vm_map *exec_map = NULL; -struct vm_map *phys_map = NULL; - -int physmem; - -/* sysctl settable */ -int sparc_led_blink = 1; - -/* - * safepri is a safe priority for sleep to set for a spin-wait - * during autoconfiguration or after a panic. - */ -int safepri = 0; - -/* - * dvmamap is used to manage DVMA memory. Note: this coincides with - * the memory range in `phys_map' (which is mostly a place-holder). - */ -vaddr_t dvma_base, dvma_end; -struct extent *dvmamap_extent; - -void dumpsys(void); -static int kap_maskcheck(void); - -/* - * Machine-dependent startup code - */ -void -cpu_startup() -{ -#ifdef DEBUG - extern int pmapdebug; - int opmapdebug = pmapdebug; -#endif - vaddr_t minaddr, maxaddr; - extern struct user *proc0paddr; - -#ifdef DEBUG - pmapdebug = 0; -#endif - - /* - * fix message buffer mapping - */ - pmap_map(MSGBUF_VA, MSGBUF_PA, MSGBUF_PA + MSGBUFSIZE, - PROT_READ | PROT_WRITE); - initmsgbuf((caddr_t)(MSGBUF_VA + (CPU_ISSUN4 ? 4096 : 0)), MSGBUFSIZE); - - proc0.p_addr = proc0paddr; - - /* I would print this earlier, but I want it in the message buffer */ - if (kap_maskcheck() == 0) { - printf("WARNING: KAP M2C3 or earlier mask detected.\n" -"THE PROCESSOR IN THIS MACHINE SUFFERS FROM SEVERE HARDWARE ISSUES.\n" -"M2C3 PROCESSORS MAY RUN RELIABLY ENOUGH, OLDER WILL DEFINITELY NOT.\n\n"); - } - - /* - * Good {morning,afternoon,evening,night}. - */ - printf(version); - /*identifycpu();*/ - printf("real mem = %d (%dMB)\n", ptoa(physmem), - ptoa(physmem) / 1024 / 1024); - - /* - * Allocate a submap for exec arguments. This map effectively - * limits the number of processes exec'ing at any time. - */ - minaddr = vm_map_min(kernel_map); - exec_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr, - 16*NCARGS, VM_MAP_PAGEABLE, FALSE, NULL); - - /* - * Allocate a map for physio. Others use a submap of the kernel - * map, but we want one completely separate, even though it uses - * the same pmap. - */ - dvma_base = CPU_ISSUN4M ? DVMA4M_BASE : DVMA_BASE; - dvma_end = CPU_ISSUN4M ? DVMA4M_END : DVMA_END; - phys_map = uvm_map_create(pmap_kernel(), dvma_base, dvma_end, - VM_MAP_INTRSAFE); - if (phys_map == NULL) - panic("unable to create DVMA map"); - - /* - * Allocate DVMA space and dump into a privately managed - * extent for double mappings which is usable from - * interrupt contexts. - */ - if (uvm_km_valloc_wait(phys_map, (dvma_end-dvma_base)) != dvma_base) - panic("unable to allocate from DVMA map"); - dvmamap_extent = extent_create("dvmamap", dvma_base, dvma_end, - M_DEVBUF, NULL, 0, EX_NOWAIT); - if (dvmamap_extent == 0) - panic("unable to allocate extent for dvma"); - -#ifdef DEBUG - pmapdebug = opmapdebug; -#endif - printf("avail mem = %lu (%luMB)\n", ptoa(uvmexp.free), - ptoa(uvmexp.free) / 1024 / 1024); - - /* - * Set up buffers, so they can be used to read disk labels. - */ - bufinit(); - - /* Early interrupt handlers initialization */ - intr_init(); -} - -/* - * Set up registers on exec. - * - * XXX this entire mess must be fixed - */ -/* ARGSUSED */ -void -setregs(p, pack, stack, retval) - struct proc *p; - struct exec_package *pack; - u_long stack; - register_t *retval; -{ - struct trapframe *tf = p->p_md.md_tf; - struct fpstate *fs; - int psr; - - /* - * Setup the process StackGhost cookie which will be XORed into - * the return pointer as register windows are over/underflowed - */ - p->p_addr->u_pcb.pcb_wcookie = arc4random(); - - /* The cookie needs to guarantee invalid alignment after the XOR */ - switch (p->p_addr->u_pcb.pcb_wcookie % 3) { - case 0: /* Two lsb's already both set except if the cookie is 0 */ - p->p_addr->u_pcb.pcb_wcookie |= 0x3; - break; - case 1: /* Set the lsb */ - p->p_addr->u_pcb.pcb_wcookie = 1 | - (p->p_addr->u_pcb.pcb_wcookie & ~0x3); - break; - case 2: /* Set the second most lsb */ - p->p_addr->u_pcb.pcb_wcookie = 2 | - (p->p_addr->u_pcb.pcb_wcookie & ~0x3); - break; - } - - /* Don't allow misaligned code by default */ - p->p_md.md_flags &= ~MDP_FIXALIGN; - - /* - * The syscall will ``return'' to npc or %g7 or %g2; set them all. - * Set the rest of the registers to 0 except for %o6 (stack pointer, - * built in exec()) and psr (retain CWP and PSR_S bits). - */ - psr = tf->tf_psr & (PSR_S | PSR_CWP); - if ((fs = p->p_md.md_fpstate) != NULL) { - /* - * We hold an FPU state. If we own *the* FPU chip state - * we must get rid of it, and the only way to do that is - * to save it. In any case, get rid of our FPU state. - */ - if (p == cpuinfo.fpproc) { - savefpstate(fs); - cpuinfo.fpproc = NULL; - } - free((void *)fs, M_SUBPROC, 0); - p->p_md.md_fpstate = NULL; - } - bzero((caddr_t)tf, sizeof *tf); - tf->tf_psr = psr; - tf->tf_npc = pack->ep_entry & ~3; - tf->tf_global[2] = tf->tf_global[7] = tf->tf_npc; - /* XXX exec of init(8) returns via proc_trampoline() */ - if (p->p_pid == 1) { - tf->tf_pc = tf->tf_npc; - tf->tf_npc += 4; - } - stack -= sizeof(struct rwindow); - tf->tf_out[6] = stack; - retval[1] = 0; -} - -#ifdef DEBUG -int sigdebug = 0; -pid_t sigpid = 0; -#define SDB_FOLLOW 0x01 -#define SDB_KSTACK 0x02 -#define SDB_FPSTATE 0x04 -#endif - -struct sigframe { - int sf_signo; /* signal number */ - siginfo_t *sf_sip; /* points to siginfo_t */ - int sf_xxx; /* placeholder */ - caddr_t sf_addr; /* SunOS compat */ - struct sigcontext sf_sc; /* actual sigcontext */ - siginfo_t sf_si; -}; - -/* - * machine dependent system variables. - */ -int -cpu_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p) - int *name; - u_int namelen; - void *oldp; - size_t *oldlenp; - void *newp; - size_t newlen; - struct proc *p; -{ -#if (NLED > 0) || (NAUXREG > 0) || (NSCF > 0) - int oldval; - int ret; -#endif - extern int v8mul; - - /* all sysctl names are this level are terminal */ - if (namelen != 1) - return (ENOTDIR); /* overloaded */ - - switch (name[0]) { - case CPU_LED_BLINK: -#if (NLED > 0) || (NAUXREG > 0) || (NSCF > 0) - oldval = sparc_led_blink; - ret = sysctl_int(oldp, oldlenp, newp, newlen, - &sparc_led_blink); - - /* - * If we were false and are now true, call led_blink(). - * led_blink() itself will catch the other case. - */ - if (!oldval && sparc_led_blink > oldval) { -#if NAUXREG > 0 - led_blink((caddr_t *)0); -#endif -#if NLED > 0 - led_cycle((caddr_t *)led_sc); -#endif -#if NSCF > 0 - scfblink((caddr_t *)0); -#endif - } - - return (ret); -#else - return (EOPNOTSUPP); -#endif - case CPU_CPUTYPE: - return (sysctl_rdint(oldp, oldlenp, newp, cputyp)); - case CPU_V8MUL: - return (sysctl_rdint(oldp, oldlenp, newp, v8mul)); - default: - return (EOPNOTSUPP); - } - /* NOTREACHED */ -} - -/* - * Send an interrupt to process. - */ -void -sendsig(catcher, sig, mask, code, type, val) - sig_t catcher; - int sig, mask; - u_long code; - int type; - union sigval val; -{ - struct proc *p = curproc; - struct sigacts *psp = p->p_p->ps_sigacts; - struct sigframe *fp; - struct trapframe *tf; - int caddr, oldsp, newsp; - struct sigframe sf; - - tf = p->p_md.md_tf; - oldsp = tf->tf_out[6]; - - /* - * Compute new user stack addresses, subtract off - * one signal frame, and align. - */ - if ((p->p_sigstk.ss_flags & SS_DISABLE) == 0 && - !sigonstack(oldsp) && (psp->ps_sigonstack & sigmask(sig))) - fp = (struct sigframe *)(p->p_sigstk.ss_sp + - p->p_sigstk.ss_size); - else - fp = (struct sigframe *)oldsp; - fp = (struct sigframe *)((int)(fp - 1) & ~7); - -#ifdef DEBUG - if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid) - printf("sendsig: %s[%d] sig %d newusp %p scp %p\n", - p->p_comm, p->p_pid, sig, fp, &fp->sf_sc); -#endif - /* - * Now set up the signal frame. We build it in kernel space - * and then copy it out. We probably ought to just build it - * directly in user space.... - */ - bzero(&sf, sizeof(sf)); - sf.sf_signo = sig; - sf.sf_sip = NULL; - - /* - * Build the signal context to be used by sigreturn. - */ - sf.sf_sc.sc_mask = mask; - sf.sf_sc.sc_sp = oldsp; - sf.sf_sc.sc_pc = tf->tf_pc; - sf.sf_sc.sc_npc = tf->tf_npc; - sf.sf_sc.sc_psr = tf->tf_psr; - sf.sf_sc.sc_g1 = tf->tf_global[1]; - sf.sf_sc.sc_o0 = tf->tf_out[0]; - - if (psp->ps_siginfo & sigmask(sig)) { - sf.sf_sip = &fp->sf_si; - initsiginfo(&sf.sf_si, sig, code, type, val); - } - - /* - * Put the stack in a consistent state before we whack away - * at it. Note that write_user_windows may just dump the - * registers into the pcb; we need them in the process's memory. - * We also need to make sure that when we start the signal handler, - * its %i6 (%fp), which is loaded from the newly allocated stack area, - * joins seamlessly with the frame it was in when the signal occurred, - * so that the debugger and _longjmp code can back up through it. - */ - newsp = (int)fp - sizeof(struct rwindow); - write_user_windows(); - /* XXX do not copyout siginfo if not needed */ - if (rwindow_save(p) || copyout((caddr_t)&sf, (caddr_t)fp, sizeof sf) || - copyout(&oldsp, &((struct rwindow *)newsp)->rw_in[6], - sizeof(register_t)) != 0) { - /* - * Process has trashed its stack; give it an illegal - * instruction to halt it in its tracks. - */ -#ifdef DEBUG - if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid) - printf("sendsig: window save or copyout error\n"); -#endif - sigexit(p, SIGILL); - /* NOTREACHED */ - } -#ifdef DEBUG - if (sigdebug & SDB_FOLLOW) - printf("sendsig: %s[%d] sig %d scp %p\n", - p->p_comm, p->p_pid, sig, &fp->sf_sc); -#endif - /* - * Arrange to continue execution at the code copied out in exec(). - * It needs the function to call in %g1, and a new stack pointer. - */ - caddr = p->p_p->ps_sigcode; - tf->tf_global[1] = (int)catcher; - tf->tf_pc = caddr; - tf->tf_npc = caddr + 4; - tf->tf_out[6] = newsp; -#ifdef DEBUG - if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid) - printf("sendsig: about to return to catcher\n"); -#endif -} - -/* - * System call to cleanup state after a signal - * has been taken. Reset signal mask and - * stack state from context left by sendsig (above), - * and return to the given trap frame (if there is one). - * Check carefully to make sure that the user has not - * modified the state to gain improper privileges or to cause - * a machine fault. - */ -/* ARGSUSED */ -int -sys_sigreturn(p, v, retval) - struct proc *p; - void *v; - register_t *retval; -{ - struct sys_sigreturn_args /* { - syscallarg(struct sigcontext *) sigcntxp; - } */ *uap = v; - struct sigcontext ksc; - struct trapframe *tf; - int error; - - /* First ensure consistent stack state (see sendsig). */ - write_user_windows(); - if (rwindow_save(p)) - sigexit(p, SIGILL); -#ifdef DEBUG - if (sigdebug & SDB_FOLLOW) - printf("sigreturn: %s[%d], sigcntxp %p\n", - p->p_comm, p->p_pid, SCARG(uap, sigcntxp)); -#endif - if ((error = copyin(SCARG(uap, sigcntxp), &ksc, sizeof(ksc))) != 0) - return (error); - tf = p->p_md.md_tf; - /* - * Only the icc bits in the psr are used, so it need not be - * verified. pc and npc must be multiples of 4. This is all - * that is required; if it holds, just do it. - */ - if (((ksc.sc_pc | ksc.sc_npc) & 3) != 0) - return (EINVAL); - /* take only psr ICC field */ - tf->tf_psr = (tf->tf_psr & ~PSR_ICC) | (ksc.sc_psr & PSR_ICC); - tf->tf_pc = ksc.sc_pc; - tf->tf_npc = ksc.sc_npc; - tf->tf_global[1] = ksc.sc_g1; - tf->tf_out[0] = ksc.sc_o0; - tf->tf_out[6] = ksc.sc_sp; - p->p_sigmask = ksc.sc_mask & ~sigcantmask; - return (EJUSTRETURN); -} - -int waittime = -1; - -__dead void -boot(int howto) -{ - int i; - static char str[4]; /* room for "-sd\0" */ - - if (cold) { - if ((howto & RB_USERREQ) == 0) - howto |= RB_HALT; - goto haltsys; - } - - fb_unblank(); - boothowto = howto; - if ((howto & RB_NOSYNC) == 0 && waittime < 0) { - waittime = 0; - vfs_shutdown(); - - if ((howto & RB_TIMEBAD) == 0) { - resettodr(); - } else { - printf("WARNING: not updating battery clock\n"); - } - } - if_downall(); - - uvm_shutdown(); - splhigh(); - cold = 1; - - if ((howto & RB_DUMP) != 0) - dumpsys(); - -haltsys: - config_suspend_all(DVACT_POWERDOWN); - - if ((howto & RB_HALT) != 0 || (howto & RB_POWERDOWN) != 0) { - printf("halted\n\n"); - romhalt(); - } - - printf("rebooting\n\n"); - i = 1; - if ((howto & RB_SINGLE) != 0) - str[i++] = 's'; - if ((howto & RB_KDB) != 0) - str[i++] = 'd'; - if (i > 1) { - str[0] = '-'; - str[i] = 0; - } else - str[0] = 0; - romboot(str); - for (;;) ; - /* NOTREACHED */ -} - -/* XXX - needs to be written */ -void -dumpconf(void) -{ -} - -/* - * Write a crash dump. - */ -void -dumpsys() -{ - printf("dump: TBD\n"); -} - -/* - * Map an I/O device given physical address and size in bytes, e.g., - * - * mydev = (struct mydev *)mapdev(myioaddr, 0, - * 0, sizeof(struct mydev)); - * - * See also machine/autoconf.h. - * - * XXXART - verify types (too tired now). - */ -void * -mapdev(phys, virt, offset, size) - struct rom_reg *phys; - int offset, virt, size; -{ - vaddr_t va; - paddr_t pa; - void *ret; - static vaddr_t iobase; - unsigned int pmtype; - - if (iobase == NULL) - iobase = IODEV_BASE; - - size = round_page(size); - if (size == 0) - panic("mapdev: zero size"); - - if (virt) - va = trunc_page(virt); - else { - va = iobase; - iobase += size; - if (iobase > IODEV_END) /* unlikely */ - panic("mapiodev"); - } - ret = (void *)(va | (((u_long)phys->rr_paddr + offset) & PGOFSET)); - /* note: preserve page offset */ - - pa = trunc_page((vaddr_t)phys->rr_paddr + offset); - pmtype = PMAP_IOENC(phys->rr_iospace); - - do { - pmap_kenter_pa(va, pa | pmtype | PMAP_NC, - PROT_READ | PROT_WRITE); - va += PAGE_SIZE; - pa += PAGE_SIZE; - } while ((size -= PAGE_SIZE) > 0); - pmap_update(pmap_kernel()); - return (ret); -} - -/* - * Soft interrupt handling - */ - -int kap_sir; - -void -ienab_bis(int bis) -{ - int s; - int mask = 1 << (bis - 1); - u_int32_t icr; - - s = splhigh(); - if (kap_sir < mask) { - /* - * We become the most important bit in kap_sir. Reprogram - * the GLU_ICR soft interrupt dispatcher. - */ - icr = lda(GLU_ICR, ASI_PHYS_IO) >> 24; - icr = (icr & ~GICR_DISPATCH_MASK) | bis; - sta(GLU_ICR, ASI_PHYS_IO, icr << 24); - } - kap_sir |= mask; - splx(s); -} - -/* - * minimal console routines - */ - -#include <sys/conf.h> -#include <dev/cons.h> - -cons_decl(early); - -struct consdev consdev_early = { - earlycnprobe, - earlycninit, - earlycngetc, - earlycnputc, - nullcnpollc -}; - -struct consdev *cn_tab = &consdev_early; - -void -earlycnprobe(struct consdev *cn) -{ - cn->cn_dev = makedev(0, 0); - cn->cn_pri = CN_MIDPRI; -} - -void -earlycninit(struct consdev *cn) -{ -} - -/* getc, putc in locore.s */ - -int kapmask_m2c4; -static void kap_maskfault(void); - -void -kap_maskfault() -{ - kapmask_m2c4 = 1; -} - -/* - * This routine checks whether we are running on a M2C4 or later mask, by - * checking for M2C4 behaviour. - * - * After mapping a kernel text page with the ``byte-writeable shared'' - * memory attribute, we will attempt to execute code from the new mapping. - * - * On M2C4 and later masks, this will cause a text fault, supposedly for - * us to be able to invalidate the instruction cache first, before resuming - * execution; while M2C3 and earlier masks will not fault. - * - * Since OpenBSD does not use BWS pages and does explicit instruction cache - * invalidation in ddb and the ptrace interface, this fault never happens in - * real life. mem_access_fault() in trap.c knows this and will direct - * execution to kap_maskfault(). Since the test code we have been invoking - * is a simple empty function, kap_maskfault() will return here. - * - * XXX Find some way to identify M2C3, which _should_ run. - */ -int -kap_maskcheck() -{ - extern void masktest(void); - void (*test)(void); - - pmap_enter(pmap_kernel(), TMPMAP_VA, - trunc_page((vaddr_t)masktest) | PMAP_BWS, PROT_READ, 0); - test = (void (*)(void))(TMPMAP_VA + ((vaddr_t)masktest & PAGE_MASK)); - - cpcb->pcb_onfault = (caddr_t)kap_maskfault; - (*test)(); - cpcb->pcb_onfault = NULL; - - pmap_remove(pmap_kernel(), TMPMAP_VA, TMPMAP_VA + PAGE_SIZE); - - return (kapmask_m2c4); -} diff --git a/sys/arch/solbourne/solbourne/mem.c b/sys/arch/solbourne/solbourne/mem.c deleted file mode 100644 index 22e06376d92..00000000000 --- a/sys/arch/solbourne/solbourne/mem.c +++ /dev/null @@ -1,225 +0,0 @@ -/* $OpenBSD: mem.c,v 1.5 2015/02/10 22:44:35 miod Exp $ */ -/* OpenBSD: mem.c,v 1.21 2003/06/02 23:27:55 millert Exp */ - -/* - * Copyright (c) 1988 University of Utah. - * Copyright (c) 1982, 1986, 1990, 1993 - * The Regents of the University of California. 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. - * - * 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. 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. - * - * @(#)mem.c 8.3 (Berkeley) 1/12/94 - */ - -/* - * Memory special file - */ - -#include <sys/param.h> -#include <sys/buf.h> -#include <sys/systm.h> -#include <sys/uio.h> -#include <sys/malloc.h> -#include <sys/proc.h> -#include <sys/conf.h> - -#include <machine/eeprom.h> -#include <machine/conf.h> - -#include <uvm/uvm_extern.h> - -extern vaddr_t prom_vstart; -extern vaddr_t prom_vend; -caddr_t zeropage; -vaddr_t mem_page; - -/*ARGSUSED*/ -int -mmopen(dev, flag, mode, p) - dev_t dev; - int flag, mode; - struct proc *p; -{ - - switch (minor(dev)) { - case 0: - case 1: - case 2: - case 11: - case 12: - return (0); - default: - return (ENXIO); - } -} - -/*ARGSUSED*/ -int -mmclose(dev, flag, mode, p) - dev_t dev; - int flag, mode; - struct proc *p; -{ - - return (0); -} - -/*ARGSUSED*/ -int -mmrw(dev, uio, flags) - dev_t dev; - struct uio *uio; - int flags; -{ - paddr_t pa; - vaddr_t va; - size_t c, o; - struct iovec *iov; - int error = 0; - static int physlock; - - if (minor(dev) == 0) { - /* lock against other uses of shared mem_page */ - while (physlock > 0) { - physlock++; - error = tsleep((caddr_t)&physlock, PZERO | PCATCH, - "mmrw", 0); - if (error) - return (error); - } - physlock = 1; - if (mem_page == 0) - mem_page = uvm_km_valloc_wait(kernel_map, NBPG); - if (mem_page == 0) - panic("mmrw: out of space in kernel_map"); - } - while (uio->uio_resid > 0 && error == 0) { - iov = uio->uio_iov; - if (iov->iov_len == 0) { - uio->uio_iov++; - uio->uio_iovcnt--; - if (uio->uio_iovcnt < 0) - panic("mmrw"); - continue; - } - switch (minor(dev)) { - - /* minor device 0 is physical memory */ - case 0: - pa = (paddr_t)uio->uio_offset; - if (!pmap_pa_exists(pa)) { - error = EFAULT; - goto unlock; - } - pmap_enter(pmap_kernel(), mem_page, - trunc_page(pa), uio->uio_rw == UIO_READ ? - PROT_READ : PROT_WRITE, PMAP_WIRED); - pmap_update(pmap_kernel()); - o = uio->uio_offset & PGOFSET; - c = ulmin(uio->uio_resid, NBPG - o); - error = uiomove((caddr_t)mem_page + o, c, uio); - pmap_remove(pmap_kernel(), mem_page, mem_page + NBPG); - pmap_update(pmap_kernel()); - continue; - - /* minor device 1 is kernel memory */ - case 1: - va = (vaddr_t)uio->uio_offset; - if (va >= MSGBUF_VA && va < MSGBUF_VA+MSGBUFSIZE) { - c = ulmin(iov->iov_len, MSGBUFSIZE); -#if 0 - } else if (va >= prom_vstart && va < prom_vend && - uio->uio_rw == UIO_READ) { - /* Allow read-only access to the PROM */ - c = ulmin(iov->iov_len, prom_vend - prom_vstart); -#endif - } else { - c = ulmin(iov->iov_len, MAXPHYS); - if (!uvm_kernacc((caddr_t)va, c, - uio->uio_rw == UIO_READ ? B_READ : B_WRITE)) - return (EFAULT); - } - error = uiomove((caddr_t)va, c, uio); - continue; - - /* minor device 2 is EOF/RATHOLE */ - case 2: - if (uio->uio_rw == UIO_WRITE) - uio->uio_resid = 0; - return (0); - -/* XXX should add sbus, etc */ - -/* minor device 12 (/dev/zero) is source of nulls on read, rathole on write */ - case 12: - if (uio->uio_rw == UIO_WRITE) { - uio->uio_resid = 0; - return 0; - } - if (zeropage == NULL) - zeropage = malloc(PAGE_SIZE, M_TEMP, - M_WAITOK | M_ZERO); - c = ulmin(iov->iov_len, PAGE_SIZE); - error = uiomove(zeropage, c, uio); - continue; - - default: - return (ENXIO); - } - } - if (minor(dev) == 0) { -unlock: - if (physlock > 1) - wakeup((caddr_t)&physlock); - physlock = 0; - } - return (error); -} - -paddr_t -mmmmap(dev, off, prot) - dev_t dev; - off_t off; - int prot; -{ - - return (-1); -} - -/*ARGSUSED*/ -int -mmioctl(dev, cmd, data, flags, p) - dev_t dev; - u_long cmd; - caddr_t data; - int flags; - struct proc *p; -{ - return (EOPNOTSUPP); -} diff --git a/sys/arch/solbourne/solbourne/pmap.c b/sys/arch/solbourne/solbourne/pmap.c deleted file mode 100644 index 131c99cc016..00000000000 --- a/sys/arch/solbourne/solbourne/pmap.c +++ /dev/null @@ -1,1625 +0,0 @@ -/* $OpenBSD: pmap.c,v 1.12 2015/09/08 21:28:36 kettenis Exp $ */ -/* - * Copyright (c) 2005, Miodrag Vallat - * - * 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. - */ - -/* - * KAP physical memory management code. - */ - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/malloc.h> -#include <sys/pool.h> -#include <sys/proc.h> - -#include <uvm/uvm.h> - -#include <machine/idt.h> -#include <machine/kap.h> -#include <machine/prom.h> - -#include <sparc/sparc/asm.h> -#include <sparc/sparc/cache.h> -#include <sparc/sparc/cpuvar.h> - -#include <sparc/dev/if_lereg.h> - -#ifdef PMAPDEBUG -#define PDB_ACTIVATE 0x000001 -#define PDB_CLEAR_M 0x000002 -#define PDB_CLEAR_U 0x000004 -#define PDB_COLLECT 0x000008 -#define PDB_COPY 0x000010 -#define PDB_CREATE 0x000020 -#define PDB_DESTROY 0x000040 -#define PDB_ENTER 0x000080 -#define PDB_EXTRACT 0x000100 -#define PDB_IS_M 0x000200 -#define PDB_IS_U 0x000400 -#define PDB_KENTER 0x000800 -#define PDB_KREMOVE 0x001000 -#define PDB_PROTECT 0x002000 -#define PDB_REFERENCE 0x004000 -#define PDB_RELEASE 0x008000 -#define PDB_REMOVE 0x010000 -#define PDB_UNWIRE 0x020000 -#define PDB_ZERO 0x040000 - -#define DPRINTF(flg,stmt) \ -do { \ - if (pmapdebug & (flg)) \ - printf stmt; \ -} while (0) - -u_int _pmapdebug_cold = 0; -u_int _pmapdebug = -1; -#define pmapdebug ((cold) ? _pmapdebug_cold : _pmapdebug) -#else -#define DPRINTF(flg,stmt) do { } while (0) -#endif - -/* pmap and pde/pte pool allocators */ -struct pool pmappool, pvpool; - -struct pmap kernel_pmap_store; - -pt_entry_t *pmap_grow_pte(struct pmap *, vaddr_t); -static pd_entry_t *pmap_pde(pmap_t, vaddr_t); -static pt_entry_t *pde_pte(pd_entry_t *, vaddr_t); -pt_entry_t *pmap_pte(pmap_t, vaddr_t); - -void pg_flushcache(struct vm_page *); - -void tlb_flush(vaddr_t); -void tlb_flush_all(void); - -vaddr_t virtual_avail; -vaddr_t virtual_end; - -vaddr_t vreserve; /* two reserved pages for copy and zero operations... */ -pt_entry_t *ptereserve; /* ...and their PTEs */ - -vaddr_t lance_va; /* a fixed buffer for the on-board lance */ - -/* - * Attribute caching - */ - -typedef struct pvlist *pv_entry_t; - -static pv_entry_t pg_to_pvl(struct vm_page *); - -static __inline__ -pv_entry_t -pg_to_pvl(struct vm_page *pg) -{ - return (&pg->mdpage.pv_head); -} - -/* - * TLB operations - */ - -void -tlb_flush(vaddr_t va) -{ -#if 0 - u_int32_t fvar; - - fvar = lda(0, ASI_FVAR); -#endif - - sta(0, ASI_PID, 0); - sta(0, ASI_FVAR, va); - sta(0, ASI_GTLB_INVAL_ENTRY, 0); -#if 0 - sta(0, ASI_FVAR, fvar); -#endif -} - -void -tlb_flush_all() -{ - /* - * Note that loaded TLB for PTEs with PG_G do NOT get invalidated - * by this command (because they are common to all PID), and need - * to be invalidated with ASI_GTLB_INVAL_ENTRY. - * This does not matter to us, as we don't use PG_G for now. - */ - sta(0, ASI_PID, 0); - sta(0, ASI_GTLB_INVALIDATE, 0); -} - -/* - * Simple pde and pte access routines. - */ - -#define trunc_seg(va) ((va) & PDT_INDEX_MASK) - -static __inline__ -pd_entry_t * -pmap_pde(pmap_t pmap, vaddr_t va) -{ - return (&pmap->pm_segtab[va >> PDT_INDEX_SHIFT]); -} - -static __inline__ -pt_entry_t * -pde_pte(pd_entry_t *pde, vaddr_t va) -{ - pt_entry_t *pte; - - pte = (pt_entry_t *)pde->pde_va; - pte += (va & PT_INDEX_MASK) >> PT_INDEX_SHIFT; - - return (pte); -} - -pt_entry_t * -pmap_pte(pmap_t pmap, vaddr_t va) -{ - pd_entry_t *pde; - - pde = pmap_pde(pmap, va); - if (pde->pde_va == NULL) - return (NULL); - - return (pde_pte(pde, va)); -} - -/* - * Setup virtual memory for the kernel. The new tables are not activated yet, - * they will be in locore.s after bootstrap() returns. - */ -void -pmap_bootstrap(size_t promdata) -{ - extern caddr_t end; - extern vaddr_t esym; - u_int32_t icuconf; - u_int8_t imcmcr; - vaddr_t ekern; - vaddr_t va, eva; - paddr_t pa; - unsigned int tabidx; - pd_entry_t *pde; - pt_entry_t *pte; - struct sb_prom *sp; - paddr_t prompa; - psize_t promlen; - extern vaddr_t prom_data; - - /* - * Compute memory size by checking the iCU for the number of iMC, - * then each iMC for its status. - */ - - icuconf = lda(ICU_CONF, ASI_PHYS_IO); - physmem = 0; - -#if 0 - imcmcr = lduba(MC0_MCR, ASI_PHYS_IO); -#else - imcmcr = *(u_int8_t *)MC0_MCR; -#endif - if (imcmcr & MCR_BANK0_AVAIL) - physmem += (imcmcr & MCR_BANK0_32M) ? 32 : 8; - if (imcmcr & MCR_BANK1_AVAIL) - physmem += (imcmcr & MCR_BANK1_32M) ? 32 : 8; - - if ((icuconf & CONF_NO_EXTRA_MEMORY) == 0) { -#if 0 - imcmcr = lduba(MC1_MCR, ASI_PHYS_IO); -#else - imcmcr = *(u_int8_t *)MC1_MCR; -#endif - if (imcmcr & MCR_BANK0_AVAIL) - physmem += (imcmcr & MCR_BANK0_32M) ? 32 : 8; - if (imcmcr & MCR_BANK1_AVAIL) - physmem += (imcmcr & MCR_BANK1_32M) ? 32 : 8; - } - - /* scale to pages */ - physmem <<= (20 - PAGE_SHIFT); - - /* - * Get a grip on the PROM communication area. - */ - sp = (struct sb_prom *)PROM_DATA_VA; - - /* - * Set virtual page size. - */ - uvmexp.pagesize = PAGE_SIZE; - uvm_setpagesize(); - - /* - * Initialize kernel pmap. - */ - pmap_kernel()->pm_refcount = 1; - - /* - * Compute kernel fixed memory usage. - */ - ekern = (vaddr_t)&end; -#if defined(DDB) || NKSYMS > 0 - if (esym != 0) - ekern = esym; -#endif - - /* - * Reserve room for the prom data we're interested in. - */ - prom_data = ekern; - ekern += promdata; - - /* - * From then on, all allocations will be multiples of the - * page size. - */ - ekern = round_page(ekern); - - /* - * Reserve buffers for the on-board Lance chip - the whole buffer - * must be in the same 128KB segment. - * This should disappear once iCU is tamed... - */ - if ((ekern >> 17) != ((ekern + MEMSIZE) >> 17)) - ekern = roundup(ekern, 1 << 17); - lance_va = ekern; - ekern += MEMSIZE; - - /* - * Initialize fixed mappings. - * We want to keep the PTW mapping the kernel for now, but all - * devices needed during early bootstrap needs to have their own - * mappings. - */ - - /* - * Step 1: reserve memory for the kernel pde. - */ - - bzero((caddr_t)ekern, PDT_SIZE); - pmap_kernel()->pm_segtab = (pd_entry_t *)ekern; - pmap_kernel()->pm_psegtab = PTW1_TO_PHYS(ekern); - ekern += PDT_SIZE; /* not rounded anymore ! */ - - /* - * Step 2: create as many pages tables as necessary. - * We'll provide page tables for the kernel virtual memory range - * and the top of memory (i.e. PTW1, PTW2 and I/O maps), so that - * we can invoke mapdev() early in the boot process. - * - * For the early console, we will also provide an 1:1 mapping - * of the I/O space. - */ - - tabidx = 0; - - va = VM_MIN_KERNEL_ADDRESS; - while (va != 0) { - pde = pmap_pde(pmap_kernel(), va); - - pde->pde_va = (pt_entry_t *)(ekern + tabidx * PT_SIZE); - pde->pde_pa = PTW1_TO_PHYS((vaddr_t)pde->pde_va); - - tabidx++; - va += NBSEG; - } - - va = (vaddr_t)OBIO_PA_START; - while (va < (vaddr_t)OBIO_PA_END) { - pde = pmap_pde(pmap_kernel(), va); - - pde->pde_va = (pt_entry_t *)(ekern + tabidx * PT_SIZE); - pde->pde_pa = PTW1_TO_PHYS((vaddr_t)pde->pde_va); - - tabidx++; - va += NBSEG; - } - - va = IOSPACE_BASE; - while (va < IOSPACE_BASE + IOSPACE_LEN) { - pde = pmap_pde(pmap_kernel(), va); - - pde->pde_va = (pt_entry_t *)(ekern + tabidx * PT_SIZE); - pde->pde_pa = PTW1_TO_PHYS((vaddr_t)pde->pde_va); - - tabidx++; - /* watch out for wraparound! */ - if ((va += NBSEG) == 0) - break; - } - - bzero((caddr_t)ekern, tabidx * PT_SIZE); - ekern += tabidx * PT_SIZE; - ekern = round_page(ekern); - - /* - * Step 3: fill them. We fill the page tables backing PTW1 and - * PTW2 to simplify pmap_extract(), by not having to check if - * the va is in a PTW. - */ - - va = PTW1_BASE; - pa = PHYSMEM_BASE; - while (va < PTW1_BASE + PTW_WINDOW_SIZE) { - pde = pmap_pde(pmap_kernel(), va); - eva = trunc_seg(va) + NBSEG; - if (eva > PTW1_BASE + PTW_WINDOW_SIZE) - eva = PTW1_BASE + PTW_WINDOW_SIZE; - pte = pde_pte(pde, va); - while (va < eva) { - *pte++ = pa | PG_V | PG_S | PG_U | PG_CACHE; - va += PAGE_SIZE; - pa += PAGE_SIZE; - } - } - - va = PTW2_BASE; - pa = PHYSMEM_BASE; - while (va < PTW2_BASE + PTW_WINDOW_SIZE) { - pde = pmap_pde(pmap_kernel(), va); - eva = trunc_seg(va) + NBSEG; - if (eva > PTW2_BASE + PTW_WINDOW_SIZE) - eva = PTW2_BASE + PTW_WINDOW_SIZE; - pte = pde_pte(pde, va); - while (va < eva) { - *pte++ = pa | PG_V | PG_S | PG_U | PG_SHARED; - va += PAGE_SIZE; - pa += PAGE_SIZE; - } - } - - va = (vaddr_t)OBIO_PA_START; - while (va < (vaddr_t)OBIO_PA_END) { - pde = pmap_pde(pmap_kernel(), va); - eva = trunc_seg(va) + NBSEG; - if (eva > OBIO_PA_END) - eva = OBIO_PA_END; - pte = pde_pte(pde, va); - for (; va < eva; va += PAGE_SIZE) - *pte++ = va | PG_V | PG_S | PG_U | PG_IO; - } - - /* - * Compute the virtual memory space. - * Note that the kernel is mapped by PTW1 and PTW2, and is outside - * this range. - */ - - virtual_avail = VM_MIN_KERNEL_ADDRESS; - virtual_end = VM_MAX_KERNEL_ADDRESS; - - /* - * Reserve two _virtual_ pages for copy and zero operations. - * Since we need to be able to tweak their PTE, they need to be - * outside PTW1 and PTW2. We'll steal them from the top of the - * virtual space; thus we are sure they will be in the same - * segment as well. - */ - - virtual_end -= 2* PAGE_SIZE; - vreserve = virtual_end; - ptereserve = pmap_pte(pmap_kernel(), vreserve); - - /* - * Tell the VM system about the available memory. - * Physical memory starts at PHYSMEM_BASE; kernel uses space - * from PTW1_TO_PHYS(KERNBASE) to ekern at this point. - * - * The physical memory below the kernel is reserved for the PROM - * data and bss, and need to be left intact when invoking it, so - * we do not upload (manage) it. - * - * The PROM communication area may claim another area, way above - * the kernel (usually less than 200 KB, immediately under 8MB - * physical). - */ - - if (sp->sp_interface >= PROM_INTERFACE) { - prompa = atop(PHYSMEM_BASE) + sp->sp_reserve_start; - promlen = sp->sp_reserve_len; - } else - promlen = 0; - - if (promlen != 0) { -#ifdef DIAGNOSTIC - if (PTW1_TO_PHYS(ekern) > ptoa(prompa)) - panic("kernel overlaps PROM reserved area"); -#endif - uvm_page_physload( - atop(PTW1_TO_PHYS(ekern)), prompa, - atop(PTW1_TO_PHYS(ekern)), prompa, 0); - uvm_page_physload( - prompa + promlen, atop(PHYSMEM_BASE) + physmem, - prompa + promlen, atop(PHYSMEM_BASE) + physmem, 0); - } else { - uvm_page_physload( - atop(PTW1_TO_PHYS(ekern)), atop(PHYSMEM_BASE) + physmem, - atop(PTW1_TO_PHYS(ekern)), atop(PHYSMEM_BASE) + physmem, 0); - } -} - -/* - * Return the virtual area range available to the kernel. - */ -void -pmap_virtual_space(vaddr_t *v_start, vaddr_t *v_end) -{ - *v_start = virtual_avail; - *v_end = virtual_end; -} - -/* - * Secondary initialization, at uvm_init() time. - * We can now create the pools we'll use for pmap and pvlist allocations. - */ -void -pmap_init() -{ - pool_init(&pmappool, sizeof(struct pmap), 0, 0, 0, "pmappl", - &pool_allocator_single); - pool_init(&pvpool, sizeof(struct pvlist), 0, 0, 0, "pvpl", NULL); -} - -/* - * Create a new pmap. - * - * We initialize pmaps with an empty pde, and a shadow of the kernel - * space (VM_MIN_KERNEL_ADDRESS onwards). - */ -pmap_t -pmap_create() -{ - pmap_t pmap; - u_int pde; - - DPRINTF(PDB_CREATE, ("pmap_create()")); - - pmap = pool_get(&pmappool, PR_WAITOK | PR_ZERO); - - pmap->pm_refcount = 1; - - /* - * Allocate the page directory. - */ - pmap->pm_segtab = (pd_entry_t *)uvm_km_zalloc(kernel_map, PDT_SIZE); - if (pmap_extract(pmap_kernel(), (vaddr_t)pmap->pm_segtab, - &pmap->pm_psegtab) == FALSE) - panic("pmap_create: pmap_extract failed!"); - - /* - * Shadow the kernel map in all user pmaps. - */ - for (pde = (VM_MIN_KERNEL_ADDRESS >> PDT_INDEX_SHIFT); - pde < NBR_PDE; pde++) { - pmap->pm_segtab[pde].pde_pa = - pmap_kernel()->pm_segtab[pde].pde_pa; - pmap->pm_segtab[pde].pde_va = - pmap_kernel()->pm_segtab[pde].pde_va; - } - - DPRINTF(PDB_CREATE, (" -> %p\n", pmap)); - - return (pmap); -} - -/* - * Destroy a pmap. - * Its mappings will not actually be removed until the reference count - * drops to zero. - */ -void -pmap_destroy(struct pmap *pmap) -{ - int count; - - DPRINTF(PDB_DESTROY, ("pmap_destroy(%p)\n", pmap)); - - count = --pmap->pm_refcount; - if (count == 0) { - pmap_release(pmap); - pool_put(&pmappool, pmap); - } -} - -/* - * Release all mappings and resources associated to a given pmap. - */ -void -pmap_release(struct pmap *pmap) -{ - u_int pde; - pt_entry_t *pdeva; -#ifdef DIAGNOSTIC - u_int pte; -#endif - - DPRINTF(PDB_RELEASE, ("pmap_release(%p)\n", pmap)); - - /* - * Free all page tables. - */ - for (pde = 0; pde < (VM_MIN_KERNEL_ADDRESS >> PDT_INDEX_SHIFT); pde++) { - if ((pdeva = pmap->pm_segtab[pde].pde_va) != NULL) { -#ifdef DIAGNOSTIC - for (pte = 0; pte < NBR_PTE; pte++) - if (pdeva[pte] & PG_V) { - DPRINTF(PDB_RELEASE, - ("pmap_release: unreleased pte " - "%p (%08x)\n", - pdeva + pte, pdeva[pte])); - } -#endif - uvm_km_free(kernel_map, (vaddr_t)pdeva, PT_SIZE); - } - } - - /* - * Free the page directory. - */ - uvm_km_free(kernel_map, (vaddr_t)pmap->pm_segtab, PDT_SIZE); -} - -/* - * Returns a preferred virtual address for the given address, which - * does not cause a VAC aliasing situation. - */ -vaddr_t -pmap_prefer(vaddr_t foff, vaddr_t va) -{ - /* XXX assume no cache aliasing yet */ - return va; -} - -/* - * Activate the pmap associated to a given process. - * Called from the scheduler. - */ -void -pmap_activate(struct proc *p) -{ - pmap_t pmap = p->p_vmspace->vm_map.pmap; - int s; - - DPRINTF(PDB_ACTIVATE, - ("pmap_activate(%p/pmap %p/segtab pa %08x va %08x)\n", - p, pmap, pmap->pm_psegtab, (vaddr_t)pmap->pm_segtab)); - - s = splvm(); - - if (p == curproc) { - write_user_windows(); - cache_flush_context(); - sta(0, ASI_PID, 0); - sta(0, ASI_PDBR, pmap->pm_psegtab); - tlb_flush_all(); - } - - splx(s); -} - -/* - * Increment the pmap reference counter. - */ -void -pmap_reference(struct pmap *pmap) -{ - DPRINTF(PDB_REFERENCE, ("pmap_reference(%p)\n", pmap)); - - pmap->pm_refcount++; -} - -/* - * Remove a range of virtual addresses from the given pmap. - * Addresses are expected to be page-aligned. - */ -void -pmap_remove(struct pmap *pmap, vaddr_t sva, vaddr_t e) -{ - vaddr_t va, eva; - paddr_t pa; - pd_entry_t *pde; - pt_entry_t *pte, opte; - struct vm_page *pg; - struct pvlist *pvl, *prev, *cur; - int s; - - s = splvm(); - - DPRINTF(PDB_REMOVE, ("pmap_remove(%p,%08x,%08x)\n", pmap, sva, e)); - - va = sva; - while (va != e) { - pde = pmap_pde(pmap, va); - eva = trunc_seg(va) + NBSEG; - if (eva > e || eva == 0) - eva = e; - - if (pde == NULL) { - va = eva; - continue; - } - - pte = pde_pte(pde, va); - for (; va != eva; va += PAGE_SIZE, pte++) { - opte = *pte; - if ((opte & PG_V) == 0) - continue; - - pmap->pm_stats.resident_count--; - - pa = opte & PG_FRAME; - -#ifdef DIAGNOSTIC - if (opte & PG_W) { - printf("pmap_remove(%p): wired mapping for %08x", - pmap, va); - pmap->pm_stats.wired_count--; - } -#endif - - *pte = PG_NV; - tlb_flush(va); - - pg = PHYS_TO_VM_PAGE(pa); - if (pg == NULL) - continue; - - /* - * Remove the mapping from the pvlist for this - * physical page. - */ - pvl = pg_to_pvl(pg); -#ifdef DIAGNOSTIC - if (pvl->pv_pmap == NULL) - panic("pmap_remove: NULL pmap in pvlist"); -#endif - prev = NULL; - for (cur = pvl; cur != NULL; cur = cur->pv_next) { - if (cur->pv_va == va && cur->pv_pmap == pmap) - break; - prev = cur; - } -#ifdef DIAGNOSTIC - if (cur == NULL) { - panic("pmap_remove: va not in pvlist"); - } -#endif - if (prev == NULL) { - cur = cur->pv_next; - if (cur != NULL) { - cur->pv_flags = pvl->pv_flags; - *pvl = *cur; - pool_put(&pvpool, cur); - } else { - pvl->pv_pmap = NULL; - } - } else { - prev->pv_next = cur->pv_next; - pool_put(&pvpool, cur); - } - - /* update saved attributes for managed page */ - pvl->pv_flags |= (opte & (PG_U | PG_M)); - } - } - - splx(s); -} - -/* - * Release any unnecessary management resources for the given pmap, - * before swapping it out. - */ -void -pmap_collect(struct pmap *pmap) -{ - u_int pde, pte; - pt_entry_t *pdeva; - int s; - - s = splvm(); - - DPRINTF(PDB_COLLECT, ("pmap_collect(%p)\n", pmap)); - - /* - * Free all empty page tables. - */ - for (pde = 0; pde < (VM_MIN_KERNEL_ADDRESS >> PDT_INDEX_SHIFT); pde++) { - if ((pdeva = pmap->pm_segtab[pde].pde_va) == NULL) - continue; - for (pte = 0; pte < NBR_PTE; pte++) - if (pdeva[pte] & PG_V) - break; - if (pte != NBR_PTE) - continue; - - /* - * Free the unused page table. - */ - pmap->pm_segtab[pde].pde_va = NULL; - pmap->pm_segtab[pde].pde_pa = 0; - uvm_km_free(kernel_map, (vaddr_t)pdeva, PT_SIZE); - } - - splx(s); -} - -/* - * Change the protection for a given vm_page. The protection can only - * become more strict, i.e. protection rights get removed. - * - * Note that this pmap does not manage execution protection yet. - */ -void -pmap_page_protect(struct vm_page *pg, vm_prot_t prot) -{ - struct pvlist *pvl; - int s; - - if ((prot & PROT_READ) == PROT_NONE) { /* remove all */ - s = splvm(); - pvl = pg_to_pvl(pg); - - DPRINTF(PDB_REMOVE, ("pmap_page_protect(%p/pmap %p,%x)\n", - pg, pvl->pv_pmap, prot)); - - while (pvl->pv_pmap != NULL) { - pmap_remove(pvl->pv_pmap, pvl->pv_va, - pvl->pv_va + PAGE_SIZE); - } - - splx(s); - } else if ((prot & PROT_WRITE) == PROT_NONE) { - s = splvm(); - pvl = pg_to_pvl(pg); - - DPRINTF(PDB_REMOVE, ("pmap_page_protect(%p/pmap %p,%x)\n", - pg, pvl->pv_pmap, prot)); - - if (pvl->pv_pmap != NULL) - for (; pvl != NULL; pvl = pvl->pv_next) - pmap_protect(pvl->pv_pmap, pvl->pv_va, - pvl->pv_va + PAGE_SIZE, prot); - - splx(s); - } else { - DPRINTF(PDB_REMOVE, ("pmap_page_protect(%p,%x)\n", pg, prot)); - } -} - -/* - * Set the protection for a virtual address range in the given pmap. - * - * Note that this pmap does not manage execution protection yet. - */ -void -pmap_protect(struct pmap *pmap, vaddr_t sva, vaddr_t e, vm_prot_t prot) -{ - vaddr_t va, eva; - pd_entry_t *pde; - pt_entry_t *pte, opte, npte; - int s; - - s = splvm(); - - DPRINTF(PDB_PROTECT, - ("pmap_protect(%p,%08x,%08x,%x)\n", pmap, sva, e, prot)); - - if ((prot & PROT_READ) == PROT_NONE) { - pmap_remove(pmap, sva, e); - splx(s); - return; - } - - va = sva; - while (va != e) { - pde = pmap_pde(pmap, va); - eva = trunc_seg(va) + NBSEG; - if (eva > e || eva == 0) - eva = e; - - if (pde == NULL) { - va = eva; - continue; - } - - pte = pde_pte(pde, va); - for (; va != eva; va += PAGE_SIZE, pte++) { - opte = *pte; - if ((opte & PG_V) == 0) - continue; - - npte = (opte & ~PG_RO) | - (prot & PROT_WRITE) ? PG_RW : PG_RO; - if (opte != npte) { - *pte = npte; - tlb_flush(va); - } - } - } - - splx(s); -} - -/* - * Expand a pmap, if necessary, to include a pte. - */ -pt_entry_t * -pmap_grow_pte(struct pmap *pmap, vaddr_t va) -{ - pd_entry_t *pde; - - pde = pmap_pde(pmap, va); - if (pde->pde_va == NULL) { - pde->pde_va = (pt_entry_t *)uvm_km_zalloc(kernel_map, PT_SIZE); - if (pde->pde_va == NULL) - return (NULL); - if (pmap_extract(pmap_kernel(), (vaddr_t)pde->pde_va, - (paddr_t *)&pde->pde_pa) == FALSE) - panic("pmap_grow_pte: pmap_extract on PT failed!"); - tlb_flush((vaddr_t)pmap->pm_segtab); - } - - return (pde_pte(pde, va)); -} - -/* - * Create or update a mapping for the page at the given physical and - * virtual addresses, for the given pmap. - */ -int -pmap_enter(struct pmap *pmap, vaddr_t va, paddr_t pa, vm_prot_t prot, int flags) -{ - pt_entry_t *pte, opte, npte; - struct vm_page *pg; - struct pvlist *pvl, *cur; - int s; - - s = splvm(); - - DPRINTF(PDB_ENTER, - ("pmap_enter(%p,%08x,%08x,%x,%x)", pmap, va, pa, prot, flags)); - - if ((pte = pmap_grow_pte(pmap, va)) == NULL) { - DPRINTF(PDB_ENTER, (" -> pmap_grow_pte failed\n")); - if (flags & PMAP_CANFAIL) { - splx(s); - return (ENOMEM); - } else - panic("pmap_enter: unable to allocate PT"); - } - - opte = *pte; - DPRINTF(PDB_ENTER, (" opte %08x", opte)); - - /* - * Enable cache, by default, if on physical memory, unless - * PMAP_NC has been passed in pa. - */ - switch (pa & PAGE_MASK) { - case PMAP_NC: - npte = PG_IO; - break; - case PMAP_BWS: - npte = PG_BYTE_SHARED; - break; - default: - if (pa >= PHYSMEM_BASE && pa < PHYSMEM_BASE + ptoa(physmem)) - npte = PG_CACHE; - else - npte = PG_IO; - break; - } - - pa = trunc_page(pa); - npte |= pa | PG_V | (prot & PROT_WRITE ? PG_RW : PG_RO); - - pg = PHYS_TO_VM_PAGE(pa); - if (pg != NULL) { - /* - * For a managed page, enter the mapping in the pvlist. - */ - pvl = pg_to_pvl(pg); - - if (pvl->pv_pmap == NULL) { - /* - * We are the first mapping. - */ - pvl->pv_pmap = pmap; - pvl->pv_va = va; - pvl->pv_next = NULL; - } else { - /* - * Add ourselves to the list. - * Note that, if we are only changing attributes - * and/or protection, we are already in the list! - */ - for (cur = pvl; cur != NULL; cur = cur->pv_next) { - if (pmap == cur->pv_pmap && va == cur->pv_va) - break; - } - - if (cur == NULL) { - cur = pool_get(&pvpool, PR_NOWAIT); - if (cur == NULL) { - if (flags & PMAP_CANFAIL) { - splx(s); - return (ENOMEM); - } else - panic("pmap_enter: " - "pvlist pool exhausted"); - } - /* - * Add the new entry after the header. - */ - cur->pv_pmap = pmap; - cur->pv_va = va; - cur->pv_flags = 0; - cur->pv_next = pvl->pv_next; - pvl->pv_next = cur; - } - } - } - - if (flags & PMAP_WIRED) { - npte |= PG_W; - if ((opte & PG_W) == 0) - pmap->pm_stats.wired_count++; - } else { - if ((opte & PG_W) != 0) - pmap->pm_stats.wired_count--; - } - if ((opte & PG_V) == 0) - pmap->pm_stats.resident_count++; - if (pa >= VM_MIN_KERNEL_ADDRESS) - npte |= PG_S; - - /* - * Now update the pte. - */ - if (opte != npte) { - DPRINTF(PDB_ENTER, (" -> npte %08x", npte)); - *pte = npte; - tlb_flush(va); - } - - DPRINTF(PDB_ENTER, ("\n")); - - splx(s); - - return (0); -} - -/* - * Specific flavour of pmap_enter() for unmanaged wired mappings in the - * kernel pmap. - */ -void -pmap_kenter_pa(vaddr_t va, paddr_t pa, vm_prot_t prot) -{ - pt_entry_t *pte, opte, npte; - int s; - - s = splvm(); - - DPRINTF(PDB_KENTER, - ("pmap_kenter_pa(%08x,%08x,%x)", va, pa, prot)); - - if ((pte = pmap_grow_pte(pmap_kernel(), va)) == NULL) { - DPRINTF(PDB_KENTER, (" -> pmap_grow_pte failed\n")); - panic("pmap_kenter_pa: unable to allocate PT"); - } - - opte = *pte; - DPRINTF(PDB_KENTER, (" opte %08x", opte)); - - /* - * Enable cache, by default, if on physical memory, unless - * PMAP_NC has been passed in pa. - */ - switch (pa & PAGE_MASK) { - case PMAP_NC: - npte = PG_IO; - break; - case PMAP_BWS: - npte = PG_BYTE_SHARED; - break; - default: - if (pa >= PHYSMEM_BASE && pa < PHYSMEM_BASE + ptoa(physmem)) - npte = PG_CACHE; - else - npte = PG_IO; - break; - } - - pa = trunc_page(pa); - npte |= pa | PG_V | PG_W | (prot & PROT_WRITE ? PG_RW : PG_RO); - - if ((opte & PG_W) == 0) - pmap_kernel()->pm_stats.wired_count++; - if ((opte & PG_V) == 0) - pmap_kernel()->pm_stats.resident_count++; - if (pa >= VM_MIN_KERNEL_ADDRESS) - npte |= PG_S; - - /* - * Now update the pte. - */ - if (opte != npte) { - DPRINTF(PDB_KENTER, (" -> npte %08x", npte)); - *pte = npte; - tlb_flush(va); - } - - DPRINTF(PDB_KENTER, ("\n")); - - splx(s); -} - -/* - * Specific flavour of pmap_remove for unmanaged wired mappings in the - * kernel pmap. - */ -void -pmap_kremove(vaddr_t va, vsize_t len) -{ - vaddr_t e, eva; - pd_entry_t *pde; - pt_entry_t *pte, opte; - int s; - - s = splvm(); - - DPRINTF(PDB_KREMOVE, ("pmap_kremove(%08x,%08x)\n", va, len)); - - e = va + len; - while (va != e) { - pde = pmap_pde(pmap_kernel(), va); - eva = trunc_seg(va) + NBSEG; - if (eva > e || eva == 0) - eva = e; - - if (pde == NULL) { - va = eva; - continue; - } - - pte = pde_pte(pde, va); - for (; va != eva; va += PAGE_SIZE, pte++) { - opte = *pte; - if ((opte & PG_V) == 0) - continue; - - pmap_kernel()->pm_stats.resident_count--; - -#ifdef DIAGNOSTIC - if (!(opte & PG_W)) { - printf("pmap_kremove: non-wired mapping for %08x", - va); - } else -#endif - pmap_kernel()->pm_stats.wired_count--; - - *pte = PG_NV; - tlb_flush(va); - } - } - - splx(s); -} - -/* - * Remove the wiring state of a page in the given pmap. - */ -void -pmap_unwire(struct pmap *pmap, vaddr_t va) -{ - pt_entry_t *pte; - int s; - - s = splvm(); - - DPRINTF(PDB_UNWIRE, ("pmap_unwire(%p,%08x)\n", pmap, va)); - - pte = pmap_pte(pmap, va); - - if (*pte & PG_V) - if (*pte & PG_W) { - pmap->pm_stats.wired_count--; - /* No need to flush TLB, it's a software flag */ - *pte &= ~PG_W; - } - - splx(s); -} - -/* - * Compute the physical address of a given virtual address in the given pmap. - * If the physical address is not mapped by this pmap, FALSE is returned. - */ -boolean_t -pmap_extract(struct pmap *pmap, vaddr_t va, paddr_t *pap) -{ - pt_entry_t *pte; - paddr_t pa; - boolean_t rv; - int s; - - DPRINTF(PDB_EXTRACT, ("pmap_extract(%p,%08x)", pmap, va)); - - s = splvm(); - - pte = pmap_pte(pmap, va); - if (pte != NULL && (*pte & PG_V) != 0) { - rv = TRUE; - pa = (*pte & PG_FRAME) | (va & PAGE_MASK); - DPRINTF(PDB_EXTRACT, (" -> %08x\n", pa)); - if (pap != NULL) - *pap = pa; - } else { - DPRINTF(PDB_EXTRACT, (" -> FALSE\n")); - rv = FALSE; - } - - splx(s); - - return (rv); -} - -/* - * Walk a vm_page and flush all existing mappings. - */ -void -pg_flushcache(struct vm_page *pg) -{ - struct pvlist *pvl; - int s; - - s = splvm(); - - pvl = pg_to_pvl(pg); - if (pvl->pv_pmap == NULL) { - splx(s); - return; - } - - /* - * Since cache_flush_page() causes the whole cache to be flushed, - * there is no need to loop - flush once. - */ - /* for (; pvl != NULL; pvl = pvl->pv_next) */ - cache_flush_page(pvl->pv_va); - - splx(s); -} - -/* - * Fill a vm_page with zeroes. - */ -void -pmap_zero_page(struct vm_page *pg) -{ - paddr_t pa; - vaddr_t va; - pt_entry_t *pte; - int s; - - s = splvm(); - - pa = VM_PAGE_TO_PHYS(pg); - va = vreserve; - pte = ptereserve; - - DPRINTF(PDB_ZERO, ("pmap_zero_page(%p/pa %x) pte %p\n", pg, pa, pte)); - - pg_flushcache(pg); - - *pte = PG_V | PG_S | (pa & PG_FRAME); - tlb_flush(va); - - qzero((caddr_t)va, PAGE_SIZE); - cache_flush_page(va); - - /* paranoia */ - *pte = PG_NV; - tlb_flush(va); - - splx(s); -} - -/* - * Copy the contents of a vm_page to another. - */ -void -pmap_copy_page(struct vm_page *srcpg, struct vm_page *dstpg) -{ - paddr_t srcpa, dstpa; - vaddr_t srcva, dstva; - pt_entry_t *srcpte, *dstpte; - int s; - - s = splvm(); - - DPRINTF(PDB_COPY, ("pmap_copy_page(%p,%p)\n", srcpg, dstpg)); - - srcpa = VM_PAGE_TO_PHYS(srcpg); - dstpa = VM_PAGE_TO_PHYS(dstpg); - srcva = vreserve; - dstva = srcva + PAGE_SIZE; - - dstpte = ptereserve; - srcpte = dstpte++; - - pg_flushcache(srcpg); - /* - * Since pg_flushcache() causes the whole cache to be flushed, - * there is no need flush dstpg. - */ - /* pg_flushcache(dstpg); */ - - *srcpte = PG_V | PG_S | PG_RO | (srcpa & PG_FRAME); - *dstpte = PG_V | PG_S | (dstpa & PG_FRAME); - - tlb_flush(srcva); - tlb_flush(dstva); - - qcopy((caddr_t)srcva, (caddr_t)dstva, PAGE_SIZE); - cache_flush_page(srcva); - - *srcpte = *dstpte = PG_NV; - tlb_flush(srcva); - tlb_flush(dstva); - - splx(s); -} - -/* - * Clear the modify bits on all mappings associated to the given vm_page. - */ -boolean_t -pmap_clear_modify(struct vm_page *pg) -{ - struct pvlist *pvl; - pt_entry_t *pte; - boolean_t rv; - int s; - int flushed; - - s = splvm(); - - pvl = pg_to_pvl(pg); - - DPRINTF(PDB_CLEAR_M, - ("pmap_clear_modify(%p/pmap %p)\n", pg, pvl->pv_pmap)); - - if (pvl->pv_flags & PG_M) { - pvl->pv_flags &= ~PG_M; - rv = TRUE; - } - - if (pvl->pv_pmap != NULL) { - flushed = 0; - for (; pvl != NULL; pvl = pvl->pv_next) { - pte = pmap_pte(pvl->pv_pmap, pvl->pv_va); - if ((*pte & PG_V) != 0 && (*pte & PG_M) != 0) { - /* - * Since cache_flush_page() causes the whole - * cache to be flushed, only flush once. - */ - if (flushed == 0) { - cache_flush_page(pvl->pv_va); - flushed = 1; - } - - rv = TRUE; - /* No need to flush TLB, it's a software flag */ - *pte &= ~PG_M; - } - } - } - - splx(s); - - return (rv); -} - -/* - * Clear the reference bits on all mappings associated to the given vm_page. - */ -boolean_t -pmap_clear_reference(struct vm_page *pg) -{ - struct pvlist *pvl; - pt_entry_t *pte; - boolean_t rv; - int s; - - s = splvm(); - - pvl = pg_to_pvl(pg); - - DPRINTF(PDB_CLEAR_U, - ("pmap_clear_reference(%p/pmap %p)\n", pg, pvl->pv_pmap)); - - if (pvl->pv_flags & PG_U) { - pvl->pv_flags &= ~PG_U; - rv = TRUE; - } - - if (pvl->pv_pmap != NULL) - for (; pvl != NULL; pvl = pvl->pv_next) { - pte = pmap_pte(pvl->pv_pmap, pvl->pv_va); - if ((*pte & PG_V) != 0 && (*pte & PG_U) != 0) { - rv = TRUE; - /* No need to flush TLB, it's a software flag */ - *pte &= ~PG_U; - } - } - - splx(s); - - return (rv); -} - -/* - * Check the reference bit attribute for the given vm_page. - */ -boolean_t -pmap_is_referenced(struct vm_page *pg) -{ - struct pvlist *pvl; - boolean_t rv; - int s; - - s = splvm(); - - pvl = pg_to_pvl(pg); - rv = (pvl->pv_flags & PG_U) != 0; - - DPRINTF(PDB_IS_U, - ("pmap_is_referenced(%p/pmap %p) -> %d\n", pg, pvl->pv_pmap, rv)); - - splx(s); - - return (rv); -} - -/* - * Check the modify bit attribute for the given vm_page. - */ -boolean_t -pmap_is_modified(struct vm_page *pg) -{ - struct pvlist *pvl; - boolean_t rv; - int s; - - s = splvm(); - - pvl = pg_to_pvl(pg); - rv = (pvl->pv_flags & PG_M) != 0; - - DPRINTF(PDB_IS_M, - ("pmap_is_modified(%p/pmap %p) -> %d\n", pg, pvl->pv_pmap, rv)); - - splx(s); - - return (rv); -} - -/* - * Flush instruction cache on the given dirty area. - * - * The KAP is the only sparc implementation OpenBSD runs on with independent - * instruction and data caches; for now, we won't add a function pointer - * to the cpu structure, but will directly invoke the necessary operation. - */ -void -pmap_proc_iflush(struct proc *p, vaddr_t va, vsize_t len) -{ - /* There is no way to invalidate a subset of the icache */ - sta(0, ASI_ICACHE_INVAL, 0); -} - -/* - * The following routines are not part of the MI pmap API, but are - * necessary to use the common sparc code. - */ - -/* - * Enable caching of the page tables if necessary. - */ -void -pmap_cache_enable() -{ - /* nothing to do */ -} - -/* - * Change the protection for a specific kernel mapping. - * Used by machdep.c only. - */ -void -pmap_changeprot(struct pmap *pmap, vaddr_t va, vm_prot_t prot, int wired) -{ - pt_entry_t *pte, npte; - int s; - - s = splvm(); - - npte = PG_S | (prot & PROT_WRITE ? PG_RW : PG_RO); - - pte = pmap_pte(pmap, va); - if ((*pte & PG_PROT) != npte) { - *pte = (*pte & ~PG_PROT) | npte; - tlb_flush(va); - } - - splx(s); -} - -/* - * Set a ``red zone'' below the kernel. - */ -void -pmap_redzone() -{ -} - -/* - * Write a given byte in a protected page; used by the ddb breakpoints. - */ -void -pmap_writetext(unsigned char *dst, int ch) -{ - pt_entry_t *pte, opte; - int s; - - /* - * Check for a PTW hit first. - */ - switch ((vaddr_t)dst >> PTW_WINDOW_SHIFT) { - case PTW1_WINDOW: - case PTW2_WINDOW: - *dst = (unsigned char)ch; - cpuinfo.cache_flush(dst, 1); - return; - } - - s = splvm(); - - pte = pmap_pte(pmap_kernel(), (vaddr_t)dst); - if (pte != NULL) { - opte = *pte; - if ((opte & PG_V) != 0) { - cpuinfo.cache_flush(dst, 1); - - if ((opte & PG_RO) != 0) { - *pte &= ~PG_RO; - tlb_flush(trunc_page((vaddr_t)dst)); - } - - *dst = (unsigned char)ch; - - if ((opte & PG_RO) != 0) { - *pte = opte; - tlb_flush(trunc_page((vaddr_t)dst)); - } - - cpuinfo.cache_flush(dst, 1); - } - } - - splx(s); -} - -/* - * Enable or disable cache for the given number of pages at the given - * virtual address. - */ -void -kvm_setcache(caddr_t addr, int npages, int cached) -{ - pt_entry_t *pte, opte; - vaddr_t va = (vaddr_t)addr; - int s; - int flushed; - -#ifdef DIAGNOSTIC - if (va & PAGE_MASK) { - printf("kvm_setcache: unaligned va %08x\n", va); - va = trunc_page(va); - } -#endif - -#ifdef DIAGNOSTIC - /* - * Check for a PTW hit first. - */ - switch (va >> PTW_WINDOW_SHIFT) { - case PTW1_WINDOW: - case PTW2_WINDOW: - printf("kvm_setcache(%08x, %08x, %d) in a PTW\n", - va, npages << PAGE_SHIFT, cached); - return; - } -#endif - - s = splvm(); - - pte = pmap_pte(pmap_kernel(), va); - flushed = 0; - for (; --npages >= 0; va += PAGE_SIZE, pte++) { - opte = *pte & ~PG_MA; - - if (cached) - opte |= PG_CACHE; - else - opte |= PG_IO; - - *pte = opte; - tlb_flush(va); - - /* - * Since cache_flush_page() causes the whole - * cache to be flushed, only flush once. - */ - if (flushed == 0) { - cache_flush_page(va); - flushed = 1; - } - } - - splx(s); -} - -/* - * Simple wrapper around pmap_kenter_pa() for multiple pages. - */ -vaddr_t -pmap_map(vaddr_t va, paddr_t pa, paddr_t epa, int prot) -{ - while (pa < epa) { - pmap_kenter_pa(va, pa, (vm_prot_t)prot); - va += PAGE_SIZE; - pa += PAGE_SIZE; - } - return (va); -} - -/* - * Checks whether a given physical address is in physical memory or - * in device space. - * Used by mem.c. - */ -int -pmap_pa_exists(paddr_t pa) -{ - return (pa >= PHYSMEM_BASE && pa < PHYSMEM_BASE + ptoa(physmem)); -} diff --git a/sys/arch/solbourne/solbourne/prom_machdep.c b/sys/arch/solbourne/solbourne/prom_machdep.c deleted file mode 100644 index 25eb21d8a63..00000000000 --- a/sys/arch/solbourne/solbourne/prom_machdep.c +++ /dev/null @@ -1,302 +0,0 @@ -/* $OpenBSD: prom_machdep.c,v 1.1 2005/04/19 21:30:18 miod Exp $ */ -/* - * Copyright (c) 2005, Miodrag Vallat - * - * 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. - */ - -/* - * Routines to hide the Solbourne PROM specifics. - */ - -#include <sys/param.h> -#include <sys/systm.h> - -#include <machine/autoconf.h> -#include <machine/bsd_openprom.h> /* romboot() prototype */ -#include <machine/idt.h> -#include <machine/kap.h> -#include <machine/prom.h> - -#include <uvm/uvm_extern.h> - -#include <sparc/sparc/asm.h> - -int sysmodel; - -void myetheraddr(u_char *); -void prom_map(void); -void prom_unmap(void); - -extern void tlb_flush_all(void); - -/* - * Lookup a variable in the environment strings. - */ -const char * -prom_getenv(const char *var) -{ - u_int i; - const char *eq, *env; - size_t len; - extern char **prom_environ; - - len = strlen(var); - - for (i = 0; (env = prom_environ[i]) != NULL; i++) { - eq = strchr(env, '='); -#ifdef DIAGNOSTIC - if (eq == NULL) - continue; /* can't happen */ -#endif - if (eq - env != len) - continue; - - if (strncasecmp(var, env, len) == 0) { - return (eq + 1); - } - } - - return (NULL); -} - -void -myetheraddr(u_char *cp) -{ - const char *enetaddr; - int i; - - enetaddr = prom_getenv(ENV_ETHERADDR); - if (enetaddr == NULL) { - cp[0] = cp[1] = cp[2] = cp[3] = cp[4] = cp[5] = 0xff; - } else { - for (i = 0; i < 6; i++) { - cp[i] = 0; - for (;;) { - if (*enetaddr >= '0' && *enetaddr <= '9') - cp[i] = cp[i] * 0x10 + - (*enetaddr - '0'); - else if (*enetaddr >= 'A' && *enetaddr <= 'F') - cp[i] = cp[i] * 0x10 + - (*enetaddr + 10 - 'A'); - else if (*enetaddr >= 'a' && *enetaddr <= 'f') - cp[i] = cp[i] * 0x10 + - (*enetaddr + 10 - 'a'); - else - break; - - enetaddr++; - } - if (*enetaddr++ != ':') - break; - } - /* fill remaining digits if necessary */ - while (i++ < 6) - cp[i] = 0; - } -} - -/* - * Set up PROM-friendly mappings - */ - -void -prom_map(void) -{ - sta(0, ASI_PTW0, PTW0_DEFAULT); - tlb_flush_all(); -} - -void -prom_unmap(void) -{ - sta(0, ASI_PTW0, 0); - tlb_flush_all(); -} - -/* - * Prom property access - * - * Note that if we are passed addresses in the fd va window, we need to - * temporarily copy these pointers to a ``safe'' address (in this case, - * a global variable, thus in the f0 or f1 window). - */ - -int -getprop(int node, char *name, void *buf, int bufsiz) -{ - struct prom_node *n = (struct prom_node *)node; - struct prom_prop *p; - char *propname, *eq; - int len, proplen; - - len = strlen(name); - -#ifdef DIAGNOSTIC - if (node == 0) -#if 0 - node = findroot(); -#else - panic("getprop(%s) invoked on invalid node", name); -#endif -#endif - - for (p = (struct prom_prop *)n->pn_props; p != NULL; p = p->pp_next) { - propname = p->pp_data; - eq = strchr(propname, '='); -#ifdef DIAGNOSTIC - if (eq == NULL) - continue; /* can't happen */ -#endif - if (eq - propname != len) - continue; - - if (strncmp(name, propname, len) == 0) { - proplen = p->pp_size; - if (proplen > bufsiz) { - printf("node %p property %s length %d > %d", - node, name, proplen, bufsiz); -#ifdef DEBUG - panic("getprop"); -#else - return (0); -#endif - } else - bcopy(eq + 1, buf, proplen); - break; - } - } - - if (p == NULL) - proplen = -1; - - return (proplen); -} - -int -getproplen(int node, char *name) -{ - struct prom_node *n = (struct prom_node *)node; - struct prom_prop *p; - char *propname, *eq; - int len, proplen; - -#ifdef DIAGNOSTIC - if (node == 0) - panic("getproplen(%s) invoked on invalid node", name); -#endif - - len = strlen(name); - - for (p = (struct prom_prop *)n->pn_props; p != NULL; p = p->pp_next) { - propname = p->pp_data; - eq = strchr(propname, '='); -#ifdef DIAGNOSTIC - if (eq == NULL) - continue; /* can't happen */ -#endif - if (eq - propname != len) - continue; - - if (strncmp(name, propname, len) == 0) { - proplen = p->pp_size; - break; - } - } - - if (p == NULL) - proplen = -1; - - return (proplen); -} - -int -firstchild(int node) -{ - return ((struct prom_node *)node)->pn_child; -} - -int -nextsibling(int node) -{ - if (node == 0) - return (findroot()); - else - return (((struct prom_node *)node)->pn_sibling); -} - -int -findroot() -{ - struct sb_prom *sp; - - sp = (struct sb_prom *)PROM_DATA_VA; - if (sp->sp_interface >= PROM_INTERFACE) - return (sp->sp_rootnode); - - panic("findroot: PROM communication interface is too old (%d)", - sp->sp_interface); - /* NOTREACHED */ -} - -/* - * Shutdown and reboot interface - */ - -void -romhalt() -{ - struct sb_prom *sp; - - sp = (struct sb_prom *)PROM_DATA_VA; - if (sp->sp_interface >= PROM_INTERFACE) { - prom_map(); - (*sp->sp_interp)("reset " PROM_RESET_HALT); - prom_unmap(); - } - - panic("PROM exit failed"); -} - -void -romboot(char *str) -{ - char command[256]; - struct sb_prom *sp; - - if (*str != '\0') { - strlcpy(command, "boot ", sizeof command); - strlcat(command, str, sizeof command); - } else { - strlcpy(command, "reset ", sizeof command); - strlcat(command, PROM_RESET_WARM, sizeof command); - } - - sp = (struct sb_prom *)PROM_DATA_VA; - if (sp->sp_interface >= PROM_INTERFACE) { - prom_map(); - (*sp->sp_interp)(command); - prom_unmap(); - } - - panic("PROM boot failed"); -} diff --git a/sys/arch/solbourne/solbourne/trap.c b/sys/arch/solbourne/solbourne/trap.c deleted file mode 100644 index 798773463aa..00000000000 --- a/sys/arch/solbourne/solbourne/trap.c +++ /dev/null @@ -1,902 +0,0 @@ -/* $OpenBSD: trap.c,v 1.22 2014/11/16 12:30:58 deraadt Exp $ */ -/* OpenBSD: trap.c,v 1.42 2004/12/06 20:12:25 miod Exp */ - -/* - * Copyright (c) 1996 - * The President and Fellows of Harvard College. All rights reserved. - * Copyright (c) 1992, 1993 - * The Regents of the University of California. All rights reserved. - * - * This software was developed by the Computer Systems Engineering group - * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and - * contributed to Berkeley. - * - * 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, Lawrence Berkeley Laboratory. - * This product includes software developed by Harvard University. - * - * 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. - * This product includes software developed by Harvard University. - * 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. - * - * @(#)trap.c 8.4 (Berkeley) 9/23/93 - */ - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/proc.h> -#include <sys/signalvar.h> -#include <sys/user.h> -#include <sys/kernel.h> -#include <sys/malloc.h> -#include <sys/resource.h> -#include <sys/signal.h> -#include <sys/wait.h> -#include <sys/syscall.h> -#include <sys/syscall_mi.h> -#include <sys/syslog.h> - -#include <uvm/uvm_extern.h> - -#include <sparc/sparc/asm.h> -#include <machine/cpu.h> -#include <machine/ctlreg.h> -#include <machine/trap.h> -#include <machine/instr.h> -#include <machine/pmap.h> - -#include <machine/idt.h> -#include <machine/kap.h> - -#ifdef DDB -#include <machine/db_machdep.h> -#else -#include <machine/frame.h> -#endif - -#include <sparc/fpu/fpu_extern.h> -#include <sparc/sparc/memreg.h> -#include <sparc/sparc/cpuvar.h> - -#ifdef DEBUG -int rwindow_debug = 0; -#endif - -/* - * Initial FPU state is all registers == all 1s, everything else == all 0s. - * This makes every floating point register a signalling NaN, with sign bit - * set, no matter how it is interpreted. Appendix N of the Sparc V8 document - * seems to imply that we should do this, and it does make sense. - */ -struct fpstate initfpstate = { - { ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, - ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0 } -}; - -/* - * There are more than 100 trap types, but most are unused. - * - * Trap type 0 is taken over as an `Asynchronous System Trap'. - * This is left-over Vax emulation crap that should be fixed. - * - * Note that some of the Sparc v8 traps are actually handled by - * the corresponding v7 routine, but listed here for completeness. - * The Fujitsu Turbo-Sparc Guide also alludes to several more - * unimplemented trap types, but doesn't give the nominal coding. - */ -static const char T[] = "trap"; -const char *trap_type[] = { - /* non-user vectors */ - "ast", /* 0 */ - "text fault", /* 1 */ - "illegal instruction", /* 2 */ - "privileged instruction",/*3 */ - "fp disabled", /* 4 */ - "window overflow", /* 5 */ - "window underflow", /* 6 */ - "alignment fault", /* 7 */ - "fp exception", /* 8 */ - "data fault", /* 9 */ - "tag overflow", /* 0a */ - "watchpoint", /* 0b */ - T, T, T, T, T, /* 0c..10 */ - "level 1 int", /* 11 */ - "level 2 int", /* 12 */ - "level 3 int", /* 13 */ - "level 4 int", /* 14 */ - "level 5 int", /* 15 */ - "level 6 int", /* 16 */ - "level 7 int", /* 17 */ - "level 8 int", /* 18 */ - "level 9 int", /* 19 */ - "level 10 int", /* 1a */ - "level 11 int", /* 1b */ - "level 12 int", /* 1c */ - "level 13 int", /* 1d */ - "level 14 int", /* 1e */ - "level 15 int", /* 1f */ - "double trap", /* 20 */ - "v8 text error", /* 21 */ - T, T, /* 22..23 */ - "v8 cp disabled", /* 24 */ - "v8 unimp flush", /* 25 */ - T, T, /* 26..27 */ - "v8 cp exception", /* 28 */ - "v8 data error", /* 29 */ - "v8 idiv by zero", /* 2a */ - "v8 store error", /* 2b */ - "dtlb miss", /* 2c */ - T, T, T, /* 2d..2f */ - T, T, T, T, T, T, T, T, /* 30..37 */ - T, T, T, T, /* 38..3b */ - "itlb miss", /* 3c */ - T, T, T, /* 3d..3f */ - T, T, T, T, T, T, T, T, /* 40..48 */ - T, T, T, T, T, T, T, T, /* 48..4f */ - T, T, T, T, T, T, T, T, /* 50..57 */ - T, T, T, T, T, T, T, T, /* 58..5f */ - T, T, T, T, T, T, T, T, /* 60..67 */ - T, T, T, T, T, T, T, T, /* 68..6f */ - T, T, T, T, T, T, T, T, /* 70..77 */ - T, T, T, T, T, T, T, T, /* 78..7f */ - - /* user (software trap) vectors */ - "syscall", /* 80 */ - "breakpoint", /* 81 */ - "zero divide", /* 82 */ - "flush windows", /* 83 */ - "clean windows", /* 84 */ - "range check", /* 85 */ - "fix align", /* 86 */ - "integer overflow", /* 87 */ - "svr4 syscall", /* 88 */ - "4.4 syscall", /* 89 */ - "kgdb exec", /* 8a */ - T, T, T, T, T, /* 8b..8f */ - T, T, T, T, T, T, T, T, /* 9a..97 */ - T, T, T, T, T, T, T, T, /* 98..9f */ - "svr4 getcc", /* a0 */ - "svr4 setcc", /* a1 */ - "svr4 getpsr", /* a2 */ - "svr4 setpsr", /* a3 */ - "svr4 gethrtime", /* a4 */ - "svr4 gethrvtime", /* a5 */ - T, /* a6 */ - "svr4 gethrestime", /* a7 */ -}; - -#define N_TRAP_TYPES (sizeof trap_type / sizeof *trap_type) - -void trap(unsigned, int, int, struct trapframe *); -static __inline void share_fpu(struct proc *, struct trapframe *); -void mem_access_fault(unsigned, int, u_int, int, int, struct trapframe *); -void ecc_fault(unsigned, int, u_int, int, int, struct trapframe *); -void syscall(register_t, struct trapframe *, register_t); - -int ignore_bogus_traps = 0; - -int want_ast = 0; - -/* - * If someone stole the FPU while we were away, do not enable it - * on return. This is not done in userret() above as it must follow - * the ktrsysret() in syscall(). Actually, it is likely that the - * ktrsysret should occur before the call to userret. - */ -static __inline void share_fpu(p, tf) - struct proc *p; - struct trapframe *tf; -{ - if ((tf->tf_psr & PSR_EF) != 0 && cpuinfo.fpproc != p) - tf->tf_psr &= ~PSR_EF; -} - -/* - * Called from locore.s trap handling, for non-MMU-related traps. - * (MMU-related traps go through mem_access_fault, below.) - */ -void -trap(type, psr, pc, tf) - unsigned type; - int psr, pc; - struct trapframe *tf; -{ - struct proc *p; - struct pcb *pcb; - int n; - union sigval sv; - - sv.sival_int = pc; /* XXX fix for parm five of trapsignal() */ - - /* This steps the PC over the trap. */ -#define ADVANCE (n = tf->tf_npc, tf->tf_pc = n, tf->tf_npc = n + 4) - - uvmexp.traps++; - /* - * Generally, kernel traps cause a panic. Any exceptions are - * handled early here. - */ - if (psr & PSR_PS) { -#ifdef DDB - if (type == T_BREAKPOINT) { - write_all_windows(); - if (kdb_trap(type, tf)) { - return; - } - } -#endif -#ifdef DIAGNOSTIC - /* - * Currently, we allow DIAGNOSTIC kernel code to - * flush the windows to record stack traces. - */ - if (type == T_FLUSHWIN) { - write_all_windows(); - ADVANCE; - return; - } -#endif - /* - * Storing %fsr in cpu_attach will cause this trap - * even though the fpu has been enabled, if and only - * if there is no FPU. - */ - if (type == T_FPDISABLED && cold) { - ADVANCE; - return; - } - dopanic: - printf("trap type 0x%x: pc=0x%x npc=0x%x psr=%b\n", - type, pc, tf->tf_npc, psr, PSR_BITS); - if (type == T_RREGERROR) /* 0x20 double fault */ - printf("fcr %b fvar %08x fpar %08x fpsr %08x pdbr %08x\n", - lda(0, ASI_FCR), FCR_BITS, lda(0, ASI_FPAR), - lda(0, ASI_FPSR), lda(0, ASI_PDBR)); - panic(type < N_TRAP_TYPES ? trap_type[type] : T); - /* NOTREACHED */ - } - if ((p = curproc) == NULL) - p = &proc0; - pcb = &p->p_addr->u_pcb; - p->p_md.md_tf = tf; /* for ptrace/signals */ - refreshcreds(p); - - switch (type) { - - default: - if (type < 0x80) { - if (!ignore_bogus_traps) - goto dopanic; - printf("trap type 0x%x: pc=0x%x npc=0x%x psr=%b\n", - type, pc, tf->tf_npc, psr, PSR_BITS); - trapsignal(p, SIGILL, type, ILL_ILLOPC, sv); - break; - } - /* the following message is gratuitous */ - /* ... but leave it in until we find anything */ - printf("%s[%d]: unimplemented software trap 0x%x\n", - p->p_comm, p->p_pid, type); - trapsignal(p, SIGILL, type, ILL_ILLOPC, sv); - break; - - case T_AST: - want_ast = 0; - uvmexp.softs++; - mi_ast(p, want_resched); - break; - - case T_ILLINST: - if ((n = emulinstr(pc, tf)) == 0) { - ADVANCE; - break; - } - trapsignal(p, SIGILL, 0, ILL_ILLOPC, sv); - break; - - case T_PRIVINST: - trapsignal(p, SIGILL, 0, ILL_PRVOPC, sv); - break; - - case T_FPDISABLED: { - struct fpstate *fs = p->p_md.md_fpstate; - - if (fs == NULL) { - fs = malloc(sizeof *fs, M_SUBPROC, M_WAITOK); - *fs = initfpstate; - p->p_md.md_fpstate = fs; - } - /* - * If we have not found an FPU, we have to emulate it. - */ - if (!foundfpu) { -#ifdef notyet - fpu_emulate(p, tf, fs); - break; -#else - trapsignal(p, SIGFPE, 0, FPE_FLTINV, sv); - break; -#endif - } - /* - * We may have more FPEs stored up and/or ops queued. - * If they exist, handle them and get out. Otherwise, - * resolve the FPU state, turn it on, and try again. - */ - if (fs->fs_qsize) { - fpu_cleanup(p, fs); - break; - } - if (cpuinfo.fpproc != p) { /* we do not have it */ - if (cpuinfo.fpproc != NULL) /* someone else had it */ - savefpstate(cpuinfo.fpproc->p_md.md_fpstate); - loadfpstate(fs); - cpuinfo.fpproc = p; /* now we do have it */ - uvmexp.fpswtch++; - } - tf->tf_psr |= PSR_EF; - break; - } - - case T_WINOF: - if (rwindow_save(p)) - sigexit(p, SIGILL); - break; - -#define read_rw(src, dst) \ - copyin((caddr_t)(src), (caddr_t)(dst), sizeof(struct rwindow)) - - case T_RWRET: - /* - * T_RWRET is a window load needed in order to rett. - * It simply needs the window to which tf->tf_out[6] - * (%sp) points. There are no user or saved windows now. - * Copy the one from %sp into pcb->pcb_rw[0] and set - * nsaved to -1. If we decide to deliver a signal on - * our way out, we will clear nsaved. - */ - if (pcb->pcb_uw || pcb->pcb_nsaved) - panic("trap T_RWRET 1"); -#ifdef DEBUG - if (rwindow_debug) - printf("%s[%d]: rwindow: pcb<-stack: 0x%x\n", - p->p_comm, p->p_pid, tf->tf_out[6]); -#endif - if (read_rw(tf->tf_out[6], &pcb->pcb_rw[0])) - sigexit(p, SIGILL); - if (pcb->pcb_nsaved) - panic("trap T_RWRET 2"); - pcb->pcb_nsaved = -1; /* mark success */ - break; - - case T_WINUF: - /* - * T_WINUF is a real window underflow, from a restore - * instruction. It needs to have the contents of two - * windows---the one belonging to the restore instruction - * itself, which is at its %sp, and the one belonging to - * the window above, which is at its %fp or %i6---both - * in the pcb. The restore's window may still be in - * the cpu; we need to force it out to the stack. - */ -#ifdef DEBUG - if (rwindow_debug) - printf("%s[%d]: rwindow: T_WINUF 0: pcb<-stack: 0x%x\n", - p->p_comm, p->p_pid, tf->tf_out[6]); -#endif - write_user_windows(); - if (rwindow_save(p) || read_rw(tf->tf_out[6], &pcb->pcb_rw[0])) - sigexit(p, SIGILL); -#ifdef DEBUG - if (rwindow_debug) - printf("%s[%d]: rwindow: T_WINUF 1: pcb<-stack: 0x%x\n", - p->p_comm, p->p_pid, pcb->pcb_rw[0].rw_in[6]); -#endif - if (read_rw(pcb->pcb_rw[0].rw_in[6], &pcb->pcb_rw[1])) - sigexit(p, SIGILL); - if (pcb->pcb_nsaved) - panic("trap T_WINUF"); - pcb->pcb_nsaved = -1; /* mark success */ - break; - - case T_ALIGN: - if ((p->p_md.md_flags & MDP_FIXALIGN) != 0 && - fixalign(p, tf) == 0) { - ADVANCE; - break; - } - trapsignal(p, SIGBUS, 0, BUS_ADRALN, sv); - break; - - case T_FPE: - /* - * Clean up after a floating point exception. - * fpu_cleanup can (and usually does) modify the - * state we save here, so we must `give up' the FPU - * chip context. (The software and hardware states - * will not match once fpu_cleanup does its job, so - * we must not save again later.) - */ - if (p != cpuinfo.fpproc) - panic("fpe without being the FP user"); - savefpstate(p->p_md.md_fpstate); - cpuinfo.fpproc = NULL; - /* tf->tf_psr &= ~PSR_EF; */ /* share_fpu will do this */ - fpu_cleanup(p, p->p_md.md_fpstate); - /* fpu_cleanup posts signals if needed */ -#if 0 /* ??? really never??? */ - ADVANCE; -#endif - break; - - case T_TAGOF: - trapsignal(p, SIGEMT, 0, EMT_TAGOVF, sv); - break; - - case T_CPDISABLED: - uprintf("coprocessor instruction\n"); /* XXX */ - trapsignal(p, SIGILL, 0, ILL_COPROC, sv); - break; - - case T_BREAKPOINT: - trapsignal(p, SIGTRAP, 0, TRAP_BRKPT, sv); - break; - - case T_DIV0: - case T_IDIV0: - ADVANCE; - trapsignal(p, SIGFPE, 0, FPE_INTDIV, sv); - break; - - case T_FLUSHWIN: - write_user_windows(); -#ifdef probably_slower_since_this_is_usually_false - if (pcb->pcb_nsaved && rwindow_save(p)) - sigexit(p, SIGILL); -#endif - ADVANCE; - break; - - case T_CLEANWIN: - uprintf("T_CLEANWIN\n"); /* XXX */ - ADVANCE; - break; - - case T_RANGECHECK: - uprintf("T_RANGECHECK\n"); /* XXX */ - ADVANCE; - trapsignal(p, SIGILL, 0, ILL_ILLOPN, sv); - break; - - case T_FIXALIGN: -#ifdef DEBUG_ALIGN - uprintf("T_FIXALIGN\n"); -#endif - /* User wants us to fix alignment faults */ - p->p_md.md_flags |= MDP_FIXALIGN; - ADVANCE; - break; - - case T_INTOF: - uprintf("T_INTOF\n"); /* XXX */ - ADVANCE; - trapsignal(p, SIGFPE, FPE_INTOVF_TRAP, FPE_INTOVF, sv); - break; - } - userret(p); - share_fpu(p, tf); -#undef ADVANCE -} - -/* - * Save windows from PCB into user stack, and return 0. This is used on - * window overflow pseudo-traps (from locore.s, just before returning to - * user mode) and when ptrace or sendsig needs a consistent state. - * As a side effect, rwindow_save() always sets pcb_nsaved to 0, - * clobbering the `underflow restore' indicator if it was -1. - * - * If the windows cannot be saved, pcb_nsaved is restored and we return -1. - */ -int -rwindow_save(p) - struct proc *p; -{ - struct pcb *pcb = &p->p_addr->u_pcb; - struct rwindow *rw = &pcb->pcb_rw[0]; - int i; - - i = pcb->pcb_nsaved; - if (i < 0) { - pcb->pcb_nsaved = 0; - return (0); - } - if (i == 0) - return (0); -#ifdef DEBUG - if (rwindow_debug) - printf("%s[%d]: rwindow: pcb->stack:", p->p_comm, p->p_pid); -#endif - do { -#ifdef DEBUG - if (rwindow_debug) - printf(" 0x%x", rw[1].rw_in[6]); -#endif - if (copyout((caddr_t)rw, (caddr_t)rw[1].rw_in[6], - sizeof *rw)) - return (-1); - rw++; - } while (--i > 0); -#ifdef DEBUG - if (rwindow_debug) - printf("\n"); -#endif - pcb->pcb_nsaved = 0; - return (0); -} - -/* - * Kill user windows (before exec) by writing back to stack or pcb - * and then erasing any pcb tracks. Otherwise we might try to write - * the registers into the new process after the exec. - */ -void -pmap_unuse_final(p) - struct proc *p; -{ - - write_user_windows(); - p->p_addr->u_pcb.pcb_nsaved = 0; -} - -/* - * Called from locore.s trap handling, for synchronous memory faults. - * - * This duplicates a lot of logic in trap() and perhaps should be - * moved there; but the bus-error-register parameters are unique to - * this routine. - * - * Since synchronous errors accumulate during prefetch, we can have - * more than one `cause'. But we do not care what the cause, here; - * we just want to page in the page and try again. - */ -void -mem_access_fault(type, ser, v, pc, psr, tf) - unsigned type; - int ser; - u_int v; - int pc, psr; - struct trapframe *tf; -{ - struct proc *p; - struct vmspace *vm; - vaddr_t va; - int rv; - vm_prot_t ftype; - int onfault; - union sigval sv; - u_int isr; - - uvmexp.traps++; - if ((p = curproc) == NULL) /* safety check */ - p = &proc0; - - if (type == T_DATAFAULT && (ser & FCR_EXTERNAL) != 0) { - /* - * For external faults, check the iCU status. - */ - - isr = lda(ICU_ISR, ASI_PHYS_IO); - - /* - * Sometimes the interrupt register is empty... and I have - * no idea what we are supposed to do in such situations. - */ - if (isr == 0) { -#ifdef DEBUG - printf("external data fault, fcr %b pc %08x fvar %08x fpar %08x fpsr %08x pdbr %08x\n", - ser, FCR_BITS, pc, v, lda(0, ASI_FPAR), lda(0, ASI_FPSR), lda(0, ASI_PDBR)); -#ifdef DDB - Debugger(); -#endif -#endif - ser &= ~FCR_EXTERNAL; - if (ser == 0) - goto out; - } else { - /* - * This is either an unrecoverable DMA or ECC error, - * or a bus timeout. - * XXX should restart the operation if retry timeout. - */ - panic("data fault: fcr %b isr %b pc %08x addr %08x fpar %08x fpsr %08x", - ser, FCR_BITS, isr, ISR_BITS, - pc, v, lda(0, ASI_FPAR), lda(0, ASI_FPSR)); - } - } - - /* - * Figure out what to pass the VM code, and ignore the sva register - * value in v on text faults (text faults are always at pc). - * Kernel faults are somewhat different: text faults are always - * illegal, and data faults are extra complex. User faults must - * set p->p_md.md_tf, in case we decide to deliver a signal. Check - * for illegal virtual addresses early since those can induce more - * faults. - */ - if (type == T_TEXTFAULT) - v = pc; - ftype = ser & FCR_RO ? PROT_WRITE : PROT_READ; - va = trunc_page(v); - if (psr & PSR_PS) { - if (type == T_TEXTFAULT) { - /* - * If we are trying to figure on which processor mask - * we run, we might trigger a text fault with - * pcb_onfault set. - * This is normal; don't panic there. - */ - if (cold && p->p_addr->u_pcb.pcb_onfault != NULL) - goto kfault; - (void) splhigh(); - printf("text fault: pc=0x%x fcr=%b\n", pc, - ser, FCR_BITS); - panic("kernel fault"); - /* NOTREACHED */ - } - - /* - * During autoconfiguration, faults are never OK unless - * pcb_onfault is set. Once running normally we must allow - * exec() to cause copy-on-write faults to kernel addresses. - */ - if (cold) - goto kfault; - if (va >= VM_MIN_KERNEL_ADDRESS) { - if (uvm_fault(kernel_map, va, 0, ftype) == 0) - return; - goto kfault; - } - } else - p->p_md.md_tf = tf; - - vm = p->p_vmspace; - rv = uvm_fault(&vm->vm_map, (vaddr_t)va, 0, ftype); - - /* - * If this was a stack access we keep track of the maximum - * accessed stack size. Also, if vm_fault gets a protection - * failure it is due to accessing the stack region outside - * the current limit and we need to reflect that as an access - * error. - */ - if ((caddr_t)va >= vm->vm_maxsaddr) { - if (rv == 0) - uvm_grow(p, va); - else if (rv == EACCES) - rv = EFAULT; - } - if (rv != 0) { - /* - * If doing copyin/out, return to onfault address. Any - * other page fault in kernel, die; if user fault, deliver - * SIGSEGV. - */ - if (psr & PSR_PS) { -kfault: - onfault = p->p_addr ? - (int)p->p_addr->u_pcb.pcb_onfault : 0; - if (!onfault) { - (void) splhigh(); - printf("data fault: pc=0x%x addr=0x%x fcr=%b\n", - pc, v, ser, FCR_BITS); - panic("kernel fault"); - /* NOTREACHED */ - } - tf->tf_pc = onfault; - tf->tf_npc = onfault + 4; - return; - } - - sv.sival_int = v; - trapsignal(p, SIGSEGV, (ser & FCR_RO) ? PROT_WRITE : - PROT_READ, SEGV_MAPERR, sv); - } -out: - if ((psr & PSR_PS) == 0) { - userret(p); - share_fpu(p, tf); - } -} - -void -ecc_fault(type, ser, v, pc, psr, tf) - unsigned type; - int ser; - u_int v; - int pc, psr; - struct trapframe *tf; -{ - /* XXX */ - panic("ecc_fault"); -} - -/* - * System calls. `pc' is just a copy of tf->tf_pc. - * - * Note that the things labelled `out' registers in the trapframe were the - * `in' registers within the syscall trap code (because of the automatic - * `save' effect of each trap). They are, however, the %o registers of the - * thing that made the system call, and are named that way here. - */ -void -syscall(code, tf, pc) - register_t code; - struct trapframe *tf; - register_t pc; -{ - int i, nsys, *ap, nap; - struct sysent *callp; - struct proc *p; - int error, new; - struct args { - register_t i[8]; - } args; - register_t rval[2]; -#ifdef DIAGNOSTIC - extern struct pcb *cpcb; -#endif - - uvmexp.syscalls++; - p = curproc; -#ifdef DIAGNOSTIC - if (tf->tf_psr & PSR_PS) - panic("syscall"); - if (cpcb != &p->p_addr->u_pcb) - panic("syscall cpcb/ppcb"); - if (tf != (struct trapframe *)((caddr_t)cpcb + USPACE) - 1) - panic("syscall trapframe"); -#endif - p->p_md.md_tf = tf; - new = code & (SYSCALL_G7RFLAG | SYSCALL_G2RFLAG); - code &= ~(SYSCALL_G7RFLAG | SYSCALL_G2RFLAG); - - callp = p->p_p->ps_emul->e_sysent; - nsys = p->p_p->ps_emul->e_nsysent; - - /* - * The first six system call arguments are in the six %o registers. - * Any arguments beyond that are in the `argument extension' area - * of the user's stack frame (see <machine/frame.h>). - * - * Check for ``special'' codes that alter this, namely syscall and - * __syscall. The latter takes a quad syscall number, so that other - * arguments are at their natural alignments. Adjust the number - * of ``easy'' arguments as appropriate; we will copy the hard - * ones later as needed. - */ - ap = &tf->tf_out[0]; - nap = 6; - - switch (code) { - case SYS_syscall: - code = *ap++; - nap--; - break; - case SYS___syscall: - if (callp != sysent) - break; - code = ap[_QUAD_LOWWORD]; - ap += 2; - nap -= 2; - break; - } - - if (code < 0 || code >= nsys) - callp += p->p_p->ps_emul->e_nosys; - else { - callp += code; - i = callp->sy_argsize / sizeof(register_t); - if (i > nap) { /* usually false */ - if (i > 8) - panic("syscall nargs"); - if ((error = copyin((caddr_t)tf->tf_out[6] + - offsetof(struct frame, fr_argx), - &args.i[nap], (i - nap) * sizeof(register_t)))) - goto bad; - i = nap; - } - if (error == 0) - copywords(ap, args.i, i * sizeof(register_t)); - } - - rval[0] = 0; - rval[1] = tf->tf_out[1]; - - error = mi_syscall(p, code, callp, args.i, rval); - - switch (error) { - case 0: - /* Note: fork() does not return here in the child */ - tf->tf_out[0] = rval[0]; - tf->tf_out[1] = rval[1]; - if (new) { - /* jmp %g2 (or %g7, deprecated) on success */ - i = tf->tf_global[new & SYSCALL_G2RFLAG ? 2 : 7]; - if (i & 3) { - error = EINVAL; - goto bad; - } - } else { - /* old system call convention: clear C on success */ - tf->tf_psr &= ~PSR_C; /* success */ - i = tf->tf_npc; - } - tf->tf_pc = i; - tf->tf_npc = i + 4; - break; - - case ERESTART: - case EJUSTRETURN: - /* nothing to do */ - break; - - default: - bad: - tf->tf_out[0] = error; - tf->tf_psr |= PSR_C; /* fail */ - i = tf->tf_npc; - tf->tf_pc = i; - tf->tf_npc = i + 4; - break; - } - - mi_syscall_return(p, code, error, rval); - - share_fpu(p, tf); -} - -/* - * Process the tail end of a fork() for the child. - */ -void -child_return(arg) - void *arg; -{ - struct proc *p = arg; - struct trapframe *tf = p->p_md.md_tf; - - /* - * Return values in the frame set by cpu_fork(). - */ - tf->tf_out[0] = 0; - tf->tf_out[1] = 0; - tf->tf_psr &= ~PSR_C; - - mi_child_return(p); -} |