diff options
Diffstat (limited to 'sys/arch')
-rw-r--r-- | sys/arch/sparc/include/loadfile_machdep.h | 50 | ||||
-rw-r--r-- | sys/arch/sparc/stand/Makefile.inc | 49 | ||||
-rw-r--r-- | sys/arch/sparc/stand/boot/Makefile | 9 | ||||
-rw-r--r-- | sys/arch/sparc/stand/boot/boot.c | 270 | ||||
-rw-r--r-- | sys/arch/sparc/stand/boot/loadfile.c | 371 | ||||
-rw-r--r-- | sys/arch/sparc/stand/boot/loadfile_sparc.c | 358 | ||||
-rw-r--r-- | sys/arch/sparc/stand/bootxx/bootxx.c | 8 | ||||
-rw-r--r-- | sys/arch/sparc/stand/common/dvma.c | 59 | ||||
-rw-r--r-- | sys/arch/sparc/stand/common/mmu.c | 175 | ||||
-rw-r--r-- | sys/arch/sparc/stand/common/promdev.c | 338 | ||||
-rw-r--r-- | sys/arch/sparc/stand/common/promdev.h | 30 | ||||
-rw-r--r-- | sys/arch/sparc/stand/common/srt0.S | 69 | ||||
-rw-r--r-- | sys/arch/sparc/stand/common/version.c | 5 | ||||
-rw-r--r-- | sys/arch/sparc/stand/libsa/Makefile | 4 |
14 files changed, 1221 insertions, 574 deletions
diff --git a/sys/arch/sparc/include/loadfile_machdep.h b/sys/arch/sparc/include/loadfile_machdep.h new file mode 100644 index 00000000000..51b665d1d62 --- /dev/null +++ b/sys/arch/sparc/include/loadfile_machdep.h @@ -0,0 +1,50 @@ +/* $OpenBSD: loadfile_machdep.h,v 1.1 2010/06/29 21:33:52 miod Exp $ */ +/* $NetBSD: loadfile_machdep.h,v 1.3 2000/08/16 08:16:58 mrg Exp $ */ + +/*- + * Copyright (c) 1999 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Christos Zoulas. + * + * 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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#define BOOT_ELF +#define ELFSIZE 32 + +#define LOAD_KERNEL LOAD_ALL +#define COUNT_KERNEL COUNT_ALL + +#define LOADADDR(a) (a) +#define ALIGNENTRY(a) ((u_long)(a)) +#define READ(f, b, c) read((f), (void *)LOADADDR(b), (c)) +#define BCOPY(s, d, c) memcpy((void *)LOADADDR(d), (void *)(s), (c)) +#define BZERO(d, c) memset((void *)LOADADDR(d), 0, (c)) +#define WARN(a) (void)(printf a, \ + printf((errno ? ": %s\n" : "\n"), \ + strerror(errno))) +#define PROGRESS(a) (void) printf a +#define ALLOC(a) alloc(a) +#define FREE(a, b) free(a, b) +#define OKMAGIC(a) ((a) == OMAGIC) diff --git a/sys/arch/sparc/stand/Makefile.inc b/sys/arch/sparc/stand/Makefile.inc index 8c0911d25ca..ec409ea3fc7 100644 --- a/sys/arch/sparc/stand/Makefile.inc +++ b/sys/arch/sparc/stand/Makefile.inc @@ -1,20 +1,49 @@ -# $OpenBSD: Makefile.inc,v 1.15 2009/06/30 04:32:35 miod Exp $ +# $OpenBSD: Makefile.inc,v 1.16 2010/06/29 21:33:54 miod Exp $ # $NetBSD: Makefile.inc,v 1.5 1996/02/01 22:33:01 mycroft Exp $ BINDIR= /usr/mdec -RELOC_TEST= 0x380000 -RELOC_SUN4= 0x240000 -RELOC_SUN4C= 0x380000 -RELOC_SUN4M= 0x440000 - -# Note: a `RELOC' value of 0x380000 seems to work on most machines -RELOC?= ${RELOC_TEST} -RELOC2!= perl -e 'printf "0x%x", ${RELOC_TEST} + 0x40000' +# sun4: +# The first 8MB of physical memory are mapped 1:1. +# sun4c: +# Worst case sun4c systems have their memory in non-contiguous 4MB +# areas, therefore we must ensure the boot code never crosses a 4MB +# boundary. +# A SPARCstation IPC with 12MB memory in 1MB SIMMs, running PROM 2.9, +# only maps virtual memory up to 0x3aefff. +# sun4m: +# The minimal contiguous memory area will be 8MB (SS4/SS5 8MB DIMMs), +# but there is no guarantee anything will be mapped at address zero +# if the DIMM are set in a pathological (dis)order, as in: +# ok cd /memory +# ok .attributes +# reg 00000000 08000000 00800000 +# 00000000 0a000000 00800000 +# 00000000 0c000000 00800000 +# 00000000 0e000000 00800000 +# available 00000000 0e000000 007a6000 +# 00000000 0c000000 00800000 +# 00000000 0a000000 00800000 +# 00000000 08000000 00800000 +# name memory +# where the four 8MB DIMMs are mapped at 32MB intervals from 128MB +# onwards. +# sun4d: +# Similar to sun4m, but the minimal contiguous memory area will be 32MB, +# and all physical memory will be packed contiguous from address zero +# onwards. +# +# The following values of RELOC and RELOC2 have been choosen to work on as +# many systems as possible, yet allowing small enough kernels to be loaded +# at the beginning of the physical memory. +RELOC= 0x358000 +RELOC2= 0x398000 CFLAGS+= -fno-stack-protector -DEFS= -DSTANDALONE -DRELOC=${RELOC} -DSUN4 -DSUN4C -DSUN_BOOTPARAMS +# XXX <machine/param.h> incorrectly uses STANDALONE instead of _STANDALONE +DEFS= -DSTANDALONE -D_STANDALONE -DRELOC=${RELOC} -DSUN_BOOTPARAMS \ + -DSUN4 -DSUN4C -DSUN4D -DSUN4M ### Figure out what to use for libsa LIBSADIR= ${.CURDIR}/../libsa diff --git a/sys/arch/sparc/stand/boot/Makefile b/sys/arch/sparc/stand/boot/Makefile index 8b48dcbde9d..551cba331fa 100644 --- a/sys/arch/sparc/stand/boot/Makefile +++ b/sys/arch/sparc/stand/boot/Makefile @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile,v 1.16 2007/11/27 21:52:30 martin Exp $ +# $OpenBSD: Makefile,v 1.17 2010/06/29 21:33:54 miod Exp $ # $NetBSD: Makefile,v 1.2 1995/09/30 21:43:38 pk Exp $ PROG= boot @@ -8,16 +8,15 @@ INSTALL_STRIP= S= ${.CURDIR}/../../../.. .PATH: ${.CURDIR}/../common -SRCS= srt0.S conf.c dvma.c net.c netif_sun.c promdev.c version.c +SRCS= srt0.S conf.c dvma.c mmu.c net.c netif_sun.c promdev.c version.c -SRCS+= boot.c loadfile.c +SRCS+= boot.c loadfile_sparc.c .PATH: ${S}/lib/libkern/arch/sparc ${S}/lib/libkern SRCS+= bzero.S strlen.c mul.S umul.S strcmp.c sdiv.S urem.S udiv.S rem.S CFLAGS= -O2 -I${.CURDIR}/../common -I${.CURDIR}/../../../../arch \ - -I${.CURDIR}/../../../.. -I${.CURDIR}/../../../../lib/libsa ${DEFS} \ - -DSPARC_BOOT_AOUT -DSPARC_BOOT_ELF + -I${.CURDIR}/../../../.. -I${.CURDIR}/../../../../lib/libsa ${DEFS} CLEANFILES+=${PROG}.aout ${PROG}.elf elfclean LIBS=${LIBSA} ${LIBZ} diff --git a/sys/arch/sparc/stand/boot/boot.c b/sys/arch/sparc/stand/boot/boot.c index 078ae4a9e35..306b8513e01 100644 --- a/sys/arch/sparc/stand/boot/boot.c +++ b/sys/arch/sparc/stand/boot/boot.c @@ -1,4 +1,4 @@ -/* $OpenBSD: boot.c,v 1.6 2003/08/14 17:13:57 deraadt Exp $ */ +/* $OpenBSD: boot.c,v 1.7 2010/06/29 21:33:54 miod Exp $ */ /* $NetBSD: boot.c,v 1.2 1997/09/14 19:27:21 pk Exp $ */ /*- @@ -34,16 +34,16 @@ #include <sys/param.h> #include <sys/reboot.h> -#include <a.out.h> +#include <lib/libsa/loadfile.h> #include <lib/libsa/stand.h> #include <sparc/stand/common/promdev.h> -void copyunix(int, char *); -void promsyms(int, struct exec *); int debug; int netif_debug; +#define FOURMB 0x400000 + /* * Boot device is derived from ROM provided information. */ @@ -53,19 +53,254 @@ extern char *version; extern vaddr_t esym; char fbuf[80], dbuf[128]; -typedef void (*entry_t)(caddr_t, int, int, int, long, long); -int loadfile(int, vaddr_t *); +paddr_t bstart, bend; /* physical start & end address of the boot program */ +u_long loadaddrmask = -1UL; +int compat = 1; /* try to load in compat mode */ + +typedef void (*entry_t)(u_long, int, int, int, long, long); + +int fdloadfile(int, u_long *, int); + +static paddr_t +getphysmem(u_long size) +{ + struct memarr *pmemarr; /* physical memory regions */ + u_int npmemarr; /* number of entries in pmemarr */ + struct memarr *mp; + int i; +#ifdef DEBUG + static int arrdpy; +#endif + + /* + * Get available physical memory from the prom. + */ + npmemarr = prom_makememarr(NULL, 0, MEMARR_AVAILPHYS); + pmemarr = alloc(npmemarr*sizeof(struct memarr)); + if (pmemarr == NULL) + return ((paddr_t)-1); + npmemarr = prom_makememarr(pmemarr, npmemarr, MEMARR_AVAILPHYS); + +#ifdef DEBUG + if (arrdpy == 0) { + arrdpy = 1; + printf("Available physical memory:\n"); + for (mp = pmemarr, i = (int)npmemarr; --i >= 0; mp++) { + uint64_t addr; + addr = pmemarr[i].addr_hi; + addr <<= 32; + addr |= pmemarr[i].addr_lo; + printf("%p at 0x%llx\n", pmemarr[i].len, addr); + } + } +#endif + + /* + * Find a suitable loading address. + */ + for (mp = pmemarr, i = (int)npmemarr; --i >= 0; mp++) { + paddr_t pa; + u_long len; + + /* Skip memory ranges the kernel can't use yet on sun4d */ + if (pmemarr[i].addr_hi != 0) + continue; + pa = (paddr_t)pmemarr[i].addr_lo; + if (pa >= 0x80000000) + continue; + len = (u_long)pmemarr[i].len; + if (len >= 0x80000000) + len = 0x80000000; + if (pa + len > 0x80000000) + len = 0x80000000 - pa; + + if (len < size) + continue; + + /* Check whether it will fit in front of us */ + if (pa < bstart && len >= size && (bstart - pa) >= size) + return (pa); + + /* Skip the boot program memory */ + if (pa < bend) { + if (len < bend - pa) + /* Not large enough */ + continue; + + /* Shrink this segment */ + len -= bend - pa; + pa = bend; + } + + /* Does it fit in the remainder of this segment? */ + if (len >= size) + return (pa); + } + return ((paddr_t)-1); +} + +static int +loadk(char *file, u_long *marks) +{ + int fd, error, flags; + vaddr_t va; + paddr_t pa; + u_long minsize, size; + + if ((fd = open(file, 0)) < 0) + return (errno ? errno : ENOENT); + + /* + * We need to know whether we are booting off a tape or not, + * because we can not seek backwards off tapes. + */ + + if (files[fd].f_flags & F_RAW) { + flags = (COUNT_KERNEL & ~COUNT_SYM) | (LOAD_KERNEL & ~LOAD_SYM); + minsize = RELOC + 0x40000; /* RELOC2 */ + va = 0xf8000000; /* KERNBASE */ +#ifdef DEBUG + printf("Tape boot: expecting a bsd.rd kernel smaller than %p\n", + minsize); +#endif + /* compensate for extra room below */ + minsize -= 512 * 1024; + } else { + flags = LOAD_KERNEL; + marks[MARK_START] = 0; + + /* + * Even though we just have opened the file, the gzip code + * has tried to read from it. Be sure to reset position in + * case the file is not compressed (transparent mode isn't + * so transparent...) + */ + if (lseek(fd, 0, SEEK_SET) == (off_t)-1) { + error = errno; + goto out; + } + + if ((error = fdloadfile(fd, marks, COUNT_KERNEL)) != 0) + goto out; + /* rewind file for the actual load operation later */ + if (lseek(fd, 0, SEEK_SET) == (off_t)-1) { + error = errno; + goto out; + } + + minsize = marks[MARK_END] - marks[MARK_START]; + + /* We want that leading 16K in front of the kernel image */ + minsize += PROM_LOADADDR; + va = marks[MARK_START] - PROM_LOADADDR; + } + + /* + * If the kernel would entirely fit under the boot code, and the + * boot code has been loaded 1:1, we do not need to allocate + * breathing room after it. + */ + if (compat != 0) { + if (minsize < bstart) + size = minsize; + else + compat = 0; + } + + /* + * If we are not loading the kernel in low physical addresses, + * we need to make sure it has enough valid space to use during + * pmap_bootstrap; 512KB ought to be enough. + */ + if (compat == 0) { + size = minsize + 512 * 1024; +#ifdef DEBUG + printf("kernel footprint %p, requesting %p\n", minsize, size); +#endif + } + + /* Get a physical load address */ + pa = getphysmem(size); + if (pa == (paddr_t)-1) { + /* + * That 512KB extra might have been too much, if physical + * memory doesn't have any contiguous large chunks (e.g. + * on sun4c systems with 4MB regions). + * If that 512KB increase caused us to cross a 4MB + * boundary, try to limit ourselves to a 4MB multiple. + */ + if (compat == 0 && size / FOURMB != minsize / FOURMB) { + size = roundup(minsize, FOURMB); +#ifdef DEBUG + printf("now trying %p\n", size); +#endif + pa = getphysmem(size); + } + if (pa == (paddr_t)-1) { + error = EFBIG; + goto out; + } + } + + printf("Loading at physical address %lx\n", pa); + if (pmap_map(va, pa, size) != 0) { + error = EFAULT; + goto out; + } + + /* try and double-map at VA 0 for compatibility */ + if (pa + size >= bstart) { + printf("WARNING: %s is too large for compat mode.\n" + "If your kernel is too old, it will not run correctly.\n", + file); + } else { + if (pa != 0 && pmap_map(0, pa, size) != 0) { + error = EFAULT; + goto out; + } + loadaddrmask = 0x07ffffffUL; + } + + marks[MARK_START] = 0; + error = fdloadfile(fd, marks, flags); +out: + close(fd); + return (error); +} + +int main(int argc, char *argv[]) { - int io; + int error; char *file; - entry_t entry; + u_long marks[MARK_MAX]; + extern char start[]; /* top of stack (see srt0.S) */ + vaddr_t bstart_va; prom_init(); + mmu_init(); printf(">> OpenBSD BOOT %s\n", version); + /* + * Find the physical memory area that's in use by the boot loader. + * Our stack grows down from label `start'; assume we need no more + * than 16K of stack space. + * The top of the boot loader is the next 4MB boundary. + */ + bstart_va = (vaddr_t)start - 16 * 1024; + if (pmap_extract(bstart_va, &bstart) != 0) + panic("can't figure out where we have been loaded"); + + if (bstart != bstart_va) + compat = 0; + + bend = roundup(bstart, FOURMB); +#ifdef DEBUG + printf("bstart %p bend %p\n", bstart, bend); +#endif + file = prom_bootfile; if (file == 0 || *file == 0) file = DEFAULT_KERNEL; @@ -81,18 +316,21 @@ main(int argc, char *argv[]) if (fbuf[0]) file = fbuf; } - if ((io = open(file, 0)) >= 0) + + printf("Booting %s\n", file); + if ((error = loadk(file, marks)) == 0) break; - printf("open: %s: %s\n", file, strerror(errno)); - prom_boothow |= RB_ASKNAME; - } - printf("Booting %s @ 0x%x\n", file, LOADADDR); - loadfile(io, (vaddr_t *)&entry); + if (error != ENOENT) { + printf("Cannot load %s: error=%d\n", file, error); + prom_boothow |= RB_ASKNAME; + } + } /* Note: args 2-4 not used due to conflicts with SunOS loaders */ - (*entry)(cputyp == CPU_SUN4 ? LOADADDR : (caddr_t)promvec, - 0, 0, 0, esym, DDB_MAGIC1); + (*(entry_t)marks[MARK_ENTRY])(cputyp == CPU_SUN4 ? + PROM_LOADADDR : (u_long)promvec, 0, 0, 0, + marks[MARK_END] & loadaddrmask, DDB_MAGIC1); _rtt(); } diff --git a/sys/arch/sparc/stand/boot/loadfile.c b/sys/arch/sparc/stand/boot/loadfile.c deleted file mode 100644 index 470512a1bea..00000000000 --- a/sys/arch/sparc/stand/boot/loadfile.c +++ /dev/null @@ -1,371 +0,0 @@ -/* $OpenBSD: loadfile.c,v 1.5 2003/08/14 17:13:57 deraadt Exp $ */ -/* $NetBSD: loadfile.c,v 1.3 1997/04/06 08:40:59 cgd Exp $ */ - -/* - * Copyright (c) 1992, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Ralph Campbell. - * - * 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. - * - * @(#)boot.c 8.1 (Berkeley) 6/10/93 - */ - -#define ELFSIZE 32 - -#include <lib/libkern/libkern.h> -#include <lib/libsa/stand.h> -#include <sparc/stand/common/promdev.h> - -#include <sys/param.h> -#include <sys/exec.h> -#include <sys/exec_elf.h> - -#include <ddb/db_aout.h> - -#ifdef SPARC_BOOT_AOUT -static int aout_exec(int, struct exec *, vaddr_t *); -#endif -#ifdef SPARC_BOOT_ELF -static int elf_exec(int, Elf_Ehdr *, vaddr_t *); -#endif -int loadfile(int, vaddr_t *); - -vaddr_t ssym, esym; - -union { -#ifdef SPARC_BOOT_AOUT - struct exec aout; -#endif -#ifdef SPARC_BOOT_ELF - Elf_Ehdr elf; -#endif -} hdr; - -/* - * Open 'filename', read in program and return the entry point or -1 if error. - */ -int -loadfile(int fd, vaddr_t *entryp) -{ - struct devices *dp; - int rval; - - /* Read the exec header. */ - if (read(fd, &hdr, sizeof(hdr)) != sizeof(hdr)) { - printf("read header: %s\n", strerror(errno)); - goto err; - } - -#ifdef SPARC_BOOT_ELF - if (memcmp(ELFMAG, hdr.elf.e_ident, SELFMAG) == 0) { - rval = elf_exec(fd, &hdr.elf, entryp); - } else -#endif -#ifdef SPARC_BOOT_AOUT - if (!N_BADMAG(hdr.aout)) { - rval = aout_exec(fd, &hdr.aout, entryp); - } else -#endif - { - printf("unknown executable format\n"); - } - -err: - if (fd >= 0) - close(fd); - return (rval); -} - -#ifdef SPARC_BOOT_AOUT -static int -aout_exec(int fd, struct exec *aout, vaddr_t *entryp) -{ - caddr_t addr = (caddr_t)LOADADDR; - int strtablen; - char *strtab; - vaddr_t entry = (vaddr_t)LOADADDR; - int i; - - printf("%d", aout->a_text); - if (N_GETMAGIC(*aout) == ZMAGIC) { - entry = (vaddr_t)(addr+sizeof(struct exec)); - addr += sizeof(struct exec); - } - /* we can't lseek() here - we may be booting off tape */ - bcopy((char *)aout + sizeof(struct exec), addr, - sizeof(hdr) - sizeof(struct exec)); - if (read(fd, (char *)addr + sizeof(hdr) - sizeof(struct exec), - aout->a_text - (sizeof(hdr) - sizeof(struct exec))) != - aout->a_text - (sizeof(hdr) - sizeof(struct exec))) - goto shread; - addr += aout->a_text; - if (N_GETMAGIC(*aout) == ZMAGIC || N_GETMAGIC(*aout) == NMAGIC) - while ((int)addr & __LDPGSZ) - *addr++ = 0; - printf("+%d", aout->a_data); - if (read(fd, addr, aout->a_data) != aout->a_data) - goto shread; - addr += aout->a_data; - printf("+%d", aout->a_bss); - for (i = aout->a_bss; i ; --i) - *addr++ = 0; - if (aout->a_syms != 0) { - bcopy(&aout->a_syms, addr, sizeof(aout->a_syms)); - addr += sizeof(aout->a_syms); - printf("+[%d", aout->a_syms); - if (read(fd, addr, aout->a_syms) != aout->a_syms) - goto shread; - addr += aout->a_syms; - - if (read(fd, &strtablen, sizeof(int)) != sizeof(int)) - goto shread; - - bcopy(&strtablen, addr, sizeof(int)); - if (i = strtablen) { - i -= sizeof(int); - addr += sizeof(int); - if (read(fd, addr, i) != i) - goto shread; - addr += i; - } - printf("+%d]", i); - esym = ((u_int)aout->a_entry - (u_int)LOADADDR) + - (((int)addr + sizeof(int) - 1) & ~(sizeof(int) - 1)); - } - printf("=0x%x\n", addr); - close(fd); - - *entryp = entry; - return (0); - -shread: - printf("boot: short read\n"); - return (1); -} -#endif /* SPARC_BOOT_AOUT */ - -#ifdef SPARC_BOOT_ELF - -/* - * If we're booting off tape, we can't seek. - * Emulate forward moves with reads, and give up on backwards moves. - * bsd.rd ought to be correctly ordered. - */ -static int -elf_seek(int fd, off_t relpos) -{ -#define DUMBBUFSIZE 4096 - char dumbbuf[DUMBBUFSIZE]; - int len; - - if (relpos < 0) { -#ifdef DEBUG - printf("elf_seek: attempting to seek backwards from %llx bytes, " - "may fail!\n", -relpos); -#endif - if (lseek(fd, relpos, SEEK_CUR) < 0) - return (-1); - return (0); - } - - while (relpos != 0) { - len = relpos > DUMBBUFSIZE ? DUMBBUFSIZE : relpos; - if (read(fd, dumbbuf, len) != len) - return (-1); - relpos -= len; - } - - return (0); -#undef DUMBBUFSIZE -} - -static int -elf_exec(int fd, Elf_Ehdr *elf, vaddr_t *entryp) -{ - int i; - int first = 1, havesyms; - Elf_Shdr *shp; - Elf_Off off; - size_t sz; - vaddr_t addr = 0; - Elf_Ehdr *fake_elf; -#define NUM_HEADERS 12 /* should be more than enough */ - Elf_Phdr headers[NUM_HEADERS], *phdr; - off_t pos, newpos; - - *entryp = 0; - -#define A(x) ((x) - *entryp + (vaddr_t)LOADADDR) - - pos = sizeof(hdr); - - /* load the headers */ - if (elf->e_phnum > NUM_HEADERS) - elf->e_phnum = NUM_HEADERS; /* amnesia rules */ - newpos = elf->e_phoff; - if (elf_seek(fd, newpos - pos)) - return (1); - pos = newpos; - if (read(fd, (void *)headers, elf->e_phnum * sizeof(Elf_Phdr)) != - elf->e_phnum * sizeof(Elf_Phdr)) { - printf("read phdr: %s\n", strerror(errno)); - return (1); - } - pos += elf->e_phnum * sizeof(Elf_Phdr); - - /* loop through the pheaders and find the entry point. */ - for (i = 0; i < elf->e_phnum; i++) { - phdr = &headers[i]; - if (phdr->p_type != PT_LOAD || - (phdr->p_flags & (PF_W|PF_X)) == 0 || - (phdr->p_vaddr != elf->e_entry)) - continue; - - *entryp = phdr->p_vaddr; - } - - if (*entryp == 0) { - printf("Can't find entry point.\n"); - return (-1); - } - - for (i = 0; i < elf->e_phnum; i++) { - phdr = &headers[i]; - if (phdr->p_type != PT_LOAD || - (phdr->p_flags & (PF_W|PF_X)) == 0) - continue; - - /* Read in segment. */ - printf("%s%lu", first ? "" : "+", phdr->p_filesz); - newpos = phdr->p_offset; - if (elf_seek(fd, newpos - pos)) - return (1); - pos = newpos; - - if (read(fd, (caddr_t)A(phdr->p_vaddr), phdr->p_filesz) != - phdr->p_filesz) { - (void)printf("read text: %s\n", strerror(errno)); - return (1); - } - pos += phdr->p_filesz; - - /* keep track of highest addr we loaded. */ - if (first || addr < (phdr->p_vaddr + phdr->p_memsz)) - addr = (phdr->p_vaddr + phdr->p_memsz); - - /* Zero out bss. */ - if (phdr->p_filesz < phdr->p_memsz) { - printf("+%lu", phdr->p_memsz - phdr->p_filesz); - bzero((caddr_t)A(phdr->p_vaddr) + phdr->p_filesz, - phdr->p_memsz - phdr->p_filesz); - } - first = 0; - } - - addr = A(addr); - addr = roundup(addr, sizeof(long)); - - ssym = addr; - /* - * Retrieve symbols. - */ - addr += sizeof(Elf_Ehdr); - - newpos = elf->e_shoff; - if (elf_seek(fd, newpos - pos)) { - printf("seek to section headers: %s\n", strerror(errno)); - return (1); - } - pos = newpos; - - sz = elf->e_shnum * sizeof(Elf_Shdr); - shp = (Elf_Shdr *)addr; - addr += roundup(sz, sizeof(long)); - - if (read(fd, shp, sz) != sz) { - printf("read section headers: %d\n", strerror(errno)); - return (1); - } - pos += sz; - - /* - * Now load the symbol sections themselves. Make sure the - * sections are aligned. Don't bother with string tables if - * there are no symbol sections. - */ - off = roundup((sizeof(Elf_Ehdr) + sz), sizeof(long)); - - for (havesyms = i = 0; i < elf->e_shnum; i++) - if (shp[i].sh_type == SHT_SYMTAB) - havesyms = 1; - - if (!havesyms) - goto no_syms; - - for (first = 1, i = 0; i < elf->e_shnum; i++) { - if (shp[i].sh_type == SHT_SYMTAB || - shp[i].sh_type == SHT_STRTAB) { - printf("%s%ld", first ? " [" : "+", - (u_long)shp[i].sh_size); - newpos = shp[i].sh_offset; - if (elf_seek(fd, newpos - pos)) { - printf("lseek symbols: %s\n", strerror(errno)); - return (1); - } - pos = newpos; - if (read(fd, (void *)addr, shp[i].sh_size) != - shp[i].sh_size) { - printf("read symbols: %s\n", strerror(errno)); - return (1); - } - pos += shp[i].sh_size; - addr += roundup(shp[i].sh_size, sizeof(long)); - shp[i].sh_offset = off; - off += roundup(shp[i].sh_size, sizeof(long)); - first = 0; - } - } - if (havesyms && first == 0) - printf("]"); - - elf->e_phoff = 0; - elf->e_shoff = sizeof(Elf_Ehdr); - elf->e_phentsize = 0; - elf->e_phnum = 0; - bcopy(elf, (void *)ssym, sizeof(*elf)); - -no_syms: - esym = (addr - (vaddr_t)LOADADDR) + *entryp; - - *entryp = (vaddr_t)LOADADDR; - - printf("\n"); - return (0); -#undef NUM_HEADERS -} -#endif /* SPARC_BOOT_ELF */ diff --git a/sys/arch/sparc/stand/boot/loadfile_sparc.c b/sys/arch/sparc/stand/boot/loadfile_sparc.c new file mode 100644 index 00000000000..3a661a40c34 --- /dev/null +++ b/sys/arch/sparc/stand/boot/loadfile_sparc.c @@ -0,0 +1,358 @@ +/* $OpenBSD: loadfile_sparc.c,v 1.1 2010/06/29 21:33:54 miod Exp $ */ + +/*- + * Copyright (c) 1997 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, + * NASA Ames Research Center and by Christos Zoulas. + * + * 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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Ralph Campbell. + * + * 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. + * + * @(#)boot.c 8.1 (Berkeley) 6/10/93 + */ + +#include <lib/libkern/libkern.h> +#include <lib/libsa/stand.h> + +#include <sys/param.h> +#include <sys/exec.h> + +#include "loadfile.h" + +#include <sys/exec_elf.h> + +int elf32_exec(int, off_t, Elf_Ehdr *, u_long *, int); + +/* + * If we're booting off tape, we can't seek. + * Emulate forward moves with reads, and give up on backward moves. + * bsd.rd ought to be correctly ordered. + */ +static off_t relseek(int fd, off_t relpos) +{ + struct open_file *f = &files[fd]; +#define DUMBBUFSIZE 4096 + char dumbbuf[DUMBBUFSIZE]; + int len; + + if ((unsigned)fd >= SOPEN_MAX || f->f_flags == 0) { + errno = EBADF; + return (-1); + } + + if (f->f_flags & F_RAW) { + if (relpos < 0) { +#ifdef DEBUG + printf("relseek: attempting to seek backward\n"); +#endif + errno = EIO; + return -1; + } + + while (relpos != 0) { + len = relpos > DUMBBUFSIZE ? DUMBBUFSIZE : relpos; + if (read(fd, dumbbuf, len) != len) + return -1; + relpos -= len; + } + + return 0; + } + + return lseek(fd, relpos, SEEK_CUR); +} + +/* + * Read in program from the given file descriptor. + * Caller is reponsible for seeking the file descriptor at the correct + * position. + * Returns error code (0 on success). + * Fills in marks. + */ +int +fdloadfile(int fd, u_long *marks, int flags) +{ + union { + Elf32_Ehdr elf32; + } hdr; + ssize_t nr; + int rval; + + /* Read the exec header. */ + nr = read(fd, &hdr, sizeof(hdr)); + if (nr == -1) { + WARN(("read header failed")); + goto err; + } + if (nr != sizeof(hdr)) { + WARN(("read header short")); + errno = EFTYPE; + goto err; + } + + if (memcmp(hdr.elf32.e_ident, ELFMAG, SELFMAG) == 0 && + hdr.elf32.e_ident[EI_CLASS] == ELFCLASS32) { + rval = elf32_exec(fd, (off_t)sizeof(hdr), &hdr.elf32, + marks, flags); + } else { + rval = 1; + errno = EFTYPE; + } + + if (rval == 0) { + if ((flags & LOAD_ALL) != 0) + PROGRESS(("=0x%lx\n", + marks[MARK_END] - marks[MARK_START])); + return 0; + } +err: + return errno; +} + +int +elf32_exec(int fd, off_t filepos, Elf_Ehdr *elf, u_long *marks, int flags) +{ + Elf_Shdr *shp; + Elf_Phdr *phdr; + Elf_Off off; + int i; + size_t sz; + int first; + int havesyms; + paddr_t minp = ~0, maxp = 0, pos = 0; + paddr_t offset = marks[MARK_START], shpp, elfp; + off_t newpos; + + sz = elf->e_phnum * sizeof(Elf_Phdr); + phdr = ALLOC(sz); + + newpos = (off_t)elf->e_phoff; + if (relseek(fd, newpos - filepos) == -1) { + WARN(("lseek phdr")); + FREE(phdr, sz); + return 1; + } + filepos = newpos; + if (read(fd, phdr, sz) != sz) { + WARN(("read program headers")); + FREE(phdr, sz); + return 1; + } + filepos += sz; + + for (first = 1, i = 0; i < elf->e_phnum; i++) { + if (phdr[i].p_type != PT_LOAD || + (phdr[i].p_flags & (PF_W|PF_R|PF_X)) == 0) + continue; + +#ifdef CHECK_PHDR + if (CHECK_PHDR(ELFSIZE, &phdr[i])) { + FREE(phdr, sz); + return 1; + } +#endif + +#define IS_TEXT(p) (p.p_flags & PF_X) +#define IS_DATA(p) ((p.p_flags & PF_X) == 0) +#define IS_BSS(p) (p.p_filesz < p.p_memsz) + /* + * XXX: Assume first address is lowest + */ + if ((IS_TEXT(phdr[i]) && (flags & LOAD_TEXT)) || + (IS_DATA(phdr[i]) && (flags & LOAD_DATA))) { + + /* Read in segment. */ + PROGRESS(("%s%lu", first ? "" : "+", + (u_long)phdr[i].p_filesz)); + + newpos = (off_t)phdr[i].p_offset; + if (relseek(fd, newpos - filepos) == -1) { + WARN(("lseek text")); + FREE(phdr, sz); + return 1; + } + filepos = newpos; + if (READ(fd, phdr[i].p_paddr, phdr[i].p_filesz) != + phdr[i].p_filesz) { + WARN(("read text")); + FREE(phdr, sz); + return 1; + } + filepos += phdr[i].p_filesz; + + first = 0; + } + + if ((IS_TEXT(phdr[i]) && (flags & (LOAD_TEXT | COUNT_TEXT))) || + (IS_DATA(phdr[i]) && (flags & (LOAD_DATA | COUNT_TEXT)))) { + pos = phdr[i].p_paddr; + if (minp > pos) + minp = pos; + pos += phdr[i].p_filesz; + if (maxp < pos) + maxp = pos; + } + + /* Zero out BSS. */ + if (IS_BSS(phdr[i]) && (flags & LOAD_BSS)) { + PROGRESS(("+%lu", + (u_long)(phdr[i].p_memsz - phdr[i].p_filesz))); + BZERO((phdr[i].p_paddr + phdr[i].p_filesz), + phdr[i].p_memsz - phdr[i].p_filesz); + } + if (IS_BSS(phdr[i]) && (flags & (LOAD_BSS|COUNT_BSS))) { + pos += phdr[i].p_memsz - phdr[i].p_filesz; + if (maxp < pos) + maxp = pos; + } + } + FREE(phdr, sz); + + /* + * Copy the ELF and section headers. + */ + elfp = maxp = roundup(maxp, sizeof(Elf_Addr)); + if (flags & (LOAD_HDR | COUNT_HDR)) + maxp += sizeof(Elf_Ehdr); + + if (flags & (LOAD_SYM | COUNT_SYM)) { + newpos = (off_t)elf->e_shoff; + if (relseek(fd, newpos - filepos) == -1) { + WARN(("lseek section headers")); + return 1; + } + filepos = newpos; + sz = elf->e_shnum * sizeof(Elf_Shdr); + shp = ALLOC(sz); + + if (read(fd, shp, sz) != sz) { + WARN(("read section headers")); + FREE(shp, sz); + return 1; + } + filepos += sz; + + shpp = maxp; + maxp += roundup(sz, sizeof(Elf_Addr)); + + /* + * Now load the symbol sections themselves. Make sure the + * sections are aligned. Don't bother with string tables if + * there are no symbol sections. + */ + off = roundup((sizeof(Elf_Ehdr) + sz), sizeof(Elf_Addr)); + + for (havesyms = i = 0; i < elf->e_shnum; i++) + if (shp[i].sh_type == SHT_SYMTAB) + havesyms = 1; + + for (first = 1, i = 0; i < elf->e_shnum; i++) { + if (shp[i].sh_type == SHT_SYMTAB || + shp[i].sh_type == SHT_STRTAB) { + if (havesyms && (flags & LOAD_SYM)) { + PROGRESS(("%s%ld", first ? " [" : "+", + (u_long)shp[i].sh_size)); + newpos = (off_t)shp[i].sh_offset; + if (relseek(fd, newpos - filepos) == -1) { + WARN(("lseek symbols")); + FREE(shp, sz); + return 1; + } + filepos = newpos; + if (READ(fd, maxp, shp[i].sh_size) != + shp[i].sh_size) { + WARN(("read symbols")); + FREE(shp, sz); + return 1; + } + filepos += shp[i].sh_size; + } + maxp += roundup(shp[i].sh_size, + sizeof(Elf_Addr)); + shp[i].sh_offset = off; + off += roundup(shp[i].sh_size, sizeof(Elf_Addr)); + first = 0; + } + } + if (flags & LOAD_SYM) { + BCOPY(shp, shpp, sz); + + if (havesyms && first == 0) + PROGRESS(("]")); + } + FREE(shp, sz); + } + + /* + * Frob the copied ELF header to give information relative + * to elfp. + */ + if (flags & LOAD_HDR) { + elf->e_phoff = 0; + elf->e_shoff = sizeof(Elf_Ehdr); + elf->e_phentsize = 0; + elf->e_phnum = 0; + BCOPY(elf, elfp, sizeof(*elf)); + } + + marks[MARK_START] = LOADADDR(minp); + marks[MARK_ENTRY] = LOADADDR(elf->e_entry); + marks[MARK_NSYM] = 1; /* XXX: Kernel needs >= 0 */ + marks[MARK_SYM] = LOADADDR(elfp); + marks[MARK_END] = LOADADDR(maxp); + + return 0; +} diff --git a/sys/arch/sparc/stand/bootxx/bootxx.c b/sys/arch/sparc/stand/bootxx/bootxx.c index 3a2046a0b11..4947ea8f0eb 100644 --- a/sys/arch/sparc/stand/bootxx/bootxx.c +++ b/sys/arch/sparc/stand/bootxx/bootxx.c @@ -1,4 +1,4 @@ -/* $OpenBSD: bootxx.c,v 1.5 2003/11/14 19:05:36 miod Exp $ */ +/* $OpenBSD: bootxx.c,v 1.6 2010/06/29 21:33:54 miod Exp $ */ /* $NetBSD: bootxx.c,v 1.2 1997/09/14 19:28:17 pk Exp $ */ /* @@ -67,7 +67,7 @@ main(int argc, char *argv[]) { char *dummy; size_t n; - register void (*entry)(caddr_t) = (void (*)(caddr_t))LOADADDR; + register void (*entry)(caddr_t) = (void (*)(caddr_t))PROM_LOADADDR; prom_init(); io.f_flags = F_RAW; @@ -75,9 +75,9 @@ main(int argc, char *argv[]) panic("%s: can't open device", progname); } - (void)loadboot(&io, LOADADDR); + (void)loadboot(&io, (caddr_t)PROM_LOADADDR); (io.f_dev->dv_close)(&io); - (*entry)(cputyp == CPU_SUN4 ? LOADADDR : (caddr_t)promvec); + (*entry)(cputyp == CPU_SUN4 ? (caddr_t)PROM_LOADADDR : (caddr_t)promvec); _rtt(); } diff --git a/sys/arch/sparc/stand/common/dvma.c b/sys/arch/sparc/stand/common/dvma.c index 3540511d218..02ee2a846fd 100644 --- a/sys/arch/sparc/stand/common/dvma.c +++ b/sys/arch/sparc/stand/common/dvma.c @@ -1,4 +1,4 @@ -/* $OpenBSD: dvma.c,v 1.3 2003/08/14 17:13:57 deraadt Exp $ */ +/* $OpenBSD: dvma.c,v 1.4 2010/06/29 21:33:54 miod Exp $ */ /* $NetBSD: dvma.c,v 1.2 1995/09/17 00:50:56 pk Exp $ */ /* * Copyright (c) 1995 Gordon W. Ross @@ -31,33 +31,50 @@ */ /* - * The easiest way to deal with the need for DVMA mappings is - * to just map the entire third megabyte of RAM into DVMA space. - * That way, dvma_mapin can just compute the DVMA alias address, - * and dvma_mapout does nothing. Note that this assumes all - * standalone programs stay in the range SA_MIN_VA .. SA_MAX_VA + * The easiest way to deal with the need for DVMA mappings is to just + * map the entire megabyte of RAM where we are loaded into DVMA space. + * That way, dvma_mapin can just compute the DVMA alias address, and + * dvma_mapout does nothing. Note that this assumes all standalone + * programs stay in the range `base_va' .. `base_va + DVMA_MAPLEN' */ #include <sys/param.h> #include <machine/pte.h> #include <machine/ctlreg.h> -#include <sparc/stand/common/promdev.h> +#include <sparc/sparc/asm.h> #define DVMA_BASE 0xFFF00000 #define DVMA_MAPLEN 0xE0000 /* 1 MB - 128K (save MONSHORTSEG) */ -#define SA_MIN_VA (RELOC - 0x40000) /* XXX - magic constant */ -#define SA_MAX_VA (SA_MIN_VA + DVMA_MAPLEN) +static int base_va; + +/* + * This module is only used on sun4, so: + */ +#define getsegmap(va) (lduha(va, ASI_SEGMAP)) +#define setsegmap(va, pmeg) do stha(va, ASI_SEGMAP, pmeg); while(0) void dvma_init(void) { - register int segva, dmava; - + u_int segva, dmava; + int nseg; + extern int start; + + /* + * Align our address base with the DVMA segment. + * Allocate one DVMA segment to cover the stack, which + * grows downward from `start'. + */ dmava = DVMA_BASE; - for (segva = SA_MIN_VA; segva < SA_MAX_VA; segva += NBPSG) { + base_va = segva = (((int)&start) & -NBPSG) - NBPSG; + + /* Then double-map the DVMA addresses */ + nseg = (DVMA_MAPLEN + NBPSG - 1) >> SGSHIFT; + while (nseg-- > 0) { setsegmap(dmava, getsegmap(segva)); + segva += NBPSG; dmava += NBPSG; } } @@ -68,13 +85,17 @@ dvma_init(void) char * dvma_mapin(char *addr, size_t len) { - register int va = (int)addr; + int va = (int)addr; + va -= base_va; + +#ifndef BOOTXX /* Make sure the address is in the DVMA map. */ - if ((va < SA_MIN_VA) || (va >= SA_MAX_VA)) + if (va < 0 || va >= DVMA_MAPLEN) panic("dvma_mapin"); +#endif - va += DVMA_BASE - SA_MIN_VA; + va += DVMA_BASE; return ((char *)va); } @@ -87,11 +108,15 @@ dvma_mapout(char *addr, size_t len) { int va = (int)addr; + va -= DVMA_BASE; + +#ifndef BOOTXX /* Make sure the address is in the DVMA map. */ - if ((va < DVMA_BASE) || (va >= (DVMA_BASE + DVMA_MAPLEN))) + if (va < 0 || va >= DVMA_MAPLEN) panic("dvma_mapout"); +#endif - va -= DVMA_BASE - SA_MIN_VA; + va += base_va; return ((char *)va); } diff --git a/sys/arch/sparc/stand/common/mmu.c b/sys/arch/sparc/stand/common/mmu.c new file mode 100644 index 00000000000..9a554bd11f3 --- /dev/null +++ b/sys/arch/sparc/stand/common/mmu.c @@ -0,0 +1,175 @@ +/* $OpenBSD: mmu.c,v 1.1 2010/06/29 21:33:54 miod Exp $ */ +/* $NetBSD: mmu.c,v 1.8 2008/04/28 20:23:36 martin Exp $ */ + +/*- + * Copyright (c) 2003 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Paul Kranenburg. + * + * 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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/param.h> +#include <lib/libsa/stand.h> +#include <machine/ctlreg.h> +#include <machine/idprom.h> +#include <machine/pte.h> +#include <sparc/sparc/asm.h> +#include <sparc/stand/common/promdev.h> + +static int sun4_mmu3l; /* sun4 3-lvl MMU */ +static int rcookie; /* sun4 3-lvl MMU region resource */ +static int scookie; /* sun4/sun4c MMU segment resource */ +static int obmem; /* SRMMU on-board memory space */ + +static int pmap_map4(vaddr_t va, paddr_t pa, psize_t size); +static int pmap_extract4(vaddr_t va, paddr_t *ppa); +static int pmap_map_srmmu(vaddr_t va, paddr_t pa, psize_t size); +static int pmap_extract_srmmu(vaddr_t va, paddr_t *ppa); + +int (*pmap_map)(vaddr_t va, paddr_t pa, psize_t size); +int (*pmap_extract)(vaddr_t va, paddr_t *ppa); + +int +mmu_init(void) +{ + if (CPU_ISSUN4 || CPU_ISSUN4C) { + pmap_map = pmap_map4; + pmap_extract = pmap_extract4; + if (CPU_ISSUN4) { + /* Find out if we're on a 3-lvl sun4 MMU. */ + struct idprom *idp = prom_getidprom(); + if (idp->id_machine == ID_SUN4_400) + sun4_mmu3l = 1; + } + /* + * XXX - we just guess which MMU cookies are free: + * region 0 maps [0-16MB] + * segment 0-16 map [0-4MB] + * the PROM mappings use high-valued cookies. + */ + rcookie = 2; + scookie = 17; + } else if (CPU_ISSUN4M || CPU_ISSUN4D) { + char buf[32]; + pmap_map = pmap_map_srmmu; + pmap_extract = pmap_extract_srmmu; + snprintf(buf, sizeof buf, "obmem %lx L!", (u_long)&obmem); + prom_interpret(buf); + } else + return (ENOTSUP); + + return (0); +} + + +/* + * SUN4 & SUN4C VM routines. + * Limited functionality wrt. MMU resource management. + */ + +#define getpte4(va) lda(va, ASI_PTE) +#define setpte4(va, pte) sta(va, ASI_PTE, pte) + +int +pmap_map4(vaddr_t va, paddr_t pa, psize_t size) +{ + u_int n = (size + NBPG - 1) >> PGSHIFT; + u_int pte; + + if (sun4_mmu3l) + setregmap((va & -NBPRG), rcookie++); + +#ifdef DEBUG + printf("Mapping %lx -> %lx (%d pages)\n", va, pa, n); +#endif + setsegmap((va & -NBPSG), ++scookie); + while (n--) { + pte = PG_S | PG_V | PG_W | PG_NC | ((pa >> PGSHIFT) & PG_PFNUM); + setpte4(va, pte); + va += NBPG; + pa += NBPG; + if ((va & (NBPSG - 1)) == 0) { +#ifdef DEBUG + printf("%d ", scookie); +#endif + setsegmap(va, ++scookie); + } + } +#ifdef DEBUG + printf("\n"); +#endif + return (0); +} + +int +pmap_extract4(vaddr_t va, paddr_t *ppa) +{ + u_int pte; + + va &= -NBPG; + pte = getpte4(va); + if ((pte & PG_V) == 0) + return (EFAULT); + + *ppa = (pte & PG_PFNUM) << PGSHIFT; + return (0); +} + + +/* + * SRMMU VM routines. + * We use the PROM's Forth services to do all the hard work. + */ +int +pmap_map_srmmu(vaddr_t va, paddr_t pa, psize_t size) +{ + char buf[64]; + + snprintf(buf, sizeof buf, "%lx %x %lx %lx map-pages", + pa, obmem, va, size); + +#ifdef DEBUG + printf("Mapping kernel: %s\n", buf); +#endif + + prom_interpret(buf); + return (0); +} + +int +pmap_extract_srmmu(vaddr_t va, paddr_t *ppa) +{ + char buf[32]; + u_int pte; + + va &= -NBPG; + snprintf(buf, sizeof buf, "%lx pgmap@ %lx L!", va, (u_long)&pte); + prom_interpret(buf); + if ((pte & SRMMU_TETYPE) != SRMMU_TEPTE) + return (EFAULT); + + *ppa = (pte & SRMMU_PPNMASK) << SRMMU_PPNPASHIFT; + return (0); +} diff --git a/sys/arch/sparc/stand/common/promdev.c b/sys/arch/sparc/stand/common/promdev.c index 835e42236f4..7356452e186 100644 --- a/sys/arch/sparc/stand/common/promdev.c +++ b/sys/arch/sparc/stand/common/promdev.c @@ -1,4 +1,4 @@ -/* $OpenBSD: promdev.c,v 1.9 2003/08/14 17:13:57 deraadt Exp $ */ +/* $OpenBSD: promdev.c,v 1.10 2010/06/29 21:33:54 miod Exp $ */ /* $NetBSD: promdev.c,v 1.16 1995/11/14 15:04:01 pk Exp $ */ /* @@ -62,9 +62,14 @@ ssize_t prom0_recv(struct promdata *, void *, size_t); static char *prom_mapin(u_long, int, int); +int prom_findnode(int, const char *); +int prom_findroot(void); +int prom_firstchild(int); int getdevtype(int, char *); -int getprop(int, char *, void *, int); -char *getpropstring(int, char *); +int prom_getprop(int, char *, void *, int); +int prom_getproplen(int, char *); +char *prom_getpropstring(int, char *); +int prom_nextsibling(int); static void prom0_fake(void); @@ -98,68 +103,6 @@ int prom_boothow; struct promvec *promvec; static int saveecho; -void -prom_init() -{ - register char *ap, *cp, *dp; - - if (cputyp == CPU_SUN4) - prom0_fake(); - - if (promvec->pv_romvec_vers >= 2) { - static char filestore[16]; - - prom_bootdevice = *promvec->pv_v2bootargs.v2_bootpath; - -#ifndef BOOTXX - cp = *promvec->pv_v2bootargs.v2_bootargs; - dp = prom_bootfile = filestore; - while (*cp && *cp != '-') - *dp++ = *cp++; - while (dp > prom_bootfile && *--dp == ' '); - *++dp = '\0'; - ap = cp; -#endif - } else { - static char bootstore[16]; - dp = prom_bootdevice = bootstore; - cp = (*promvec->pv_v0bootargs)->ba_argv[0]; - while (*cp) { - *dp++ = *cp; - if (*cp++ == ')') - break; - } - *dp = '\0'; -#ifndef BOOTXX - prom_bootfile = (*promvec->pv_v0bootargs)->ba_kernel; - ap = (*promvec->pv_v0bootargs)->ba_argv[1]; -#endif - } - -#ifndef BOOTXX - if (ap == NULL || *ap != '-') - return; - - while (*ap) { - switch (*ap++) { - case 'a': - prom_boothow |= RB_ASKNAME; - break; - case 'c': - prom_boothow |= RB_CONFIG; - break; - case 'd': - prom_boothow |= RB_KDB; - debug = 1; - break; - case 's': - prom_boothow |= RB_SINGLE; - break; - } - } -#endif -} - int devopen(f, fname, file) struct open_file *f; @@ -290,7 +233,7 @@ prom0_strategy(devdata, flag, dblk, size, buf, rsize) #endif dmabuf = dvma_mapin(buf, size); - + si->si_bn = dblk; si->si_ma = dmabuf; si->si_cc = size; @@ -419,7 +362,7 @@ getchar() { char c; register int n; - + if (promvec->pv_romvec_vers > 2) while ((n = (*promvec->pv_v2devops.v2_read) (*promvec->pv_v2bootargs.v2_fd0, (caddr_t)&c, 1)) != 1); @@ -431,7 +374,7 @@ getchar() if (CPU_ISSUN4) { saveecho = *(oldpvec->echo); *(oldpvec->echo) = 0; - } + } c = (*promvec->pv_getchar)(); if (CPU_ISSUN4) *(oldpvec->echo) = saveecho; @@ -441,7 +384,7 @@ getchar() c = '\n'; return (c); } - + int cngetc(void) { @@ -453,7 +396,7 @@ peekchar(void) { char c; register int n; - + if (promvec->pv_romvec_vers > 2) { n = (*promvec->pv_v2devops.v2_read) (*promvec->pv_v2bootargs.v2_fd0, (caddr_t)&c, 1); @@ -484,7 +427,7 @@ void putchar(c) int c; { - + if (c == '\n') pv_putchar('\r'); pv_putchar(c); @@ -519,8 +462,8 @@ getticks(void) return *(promvec->pv_ticks); } -void -prom_getether(int fd, u_char *ea) +struct idprom * +prom_getidprom() { if (cputyp == CPU_SUN4) { static struct idprom sun4_idprom; @@ -536,7 +479,18 @@ prom_getether(int fd, u_char *ea) *dst++ = x; } while (--len > 0); } - bcopy(sun4_idprom.id_ether, ea, 6); + + return &sun4_idprom; + } else + return NULL; +} + +void +prom_getether(int fd, u_char *ea) +{ + if (cputyp == CPU_SUN4) { + struct idprom *idp = prom_getidprom(); + bcopy(idp->id_ether, ea, 6); } else if (promvec->pv_romvec_vers <= 2) { (void)(*promvec->pv_enaddr)(fd, (char *)ea); } else { @@ -546,7 +500,6 @@ prom_getether(int fd, u_char *ea) } } - /* * A number of well-known devices on sun4s. */ @@ -555,7 +508,7 @@ static struct dtab { int type; } dtab[] = { { "sd", DT_BLOCK }, - { "st", DT_BLOCK }, + { "st", DT_BYTE }, { "xd", DT_BLOCK }, { "xy", DT_BLOCK }, { "fd", DT_BLOCK }, @@ -571,7 +524,7 @@ getdevtype(fd, name) { if (promvec->pv_romvec_vers >= 2) { int node = (*promvec->pv_v2devops.v2_fd_phandle)(fd); - char *cp = getpropstring(node, "device_type"); + char *cp = prom_getpropstring(node, "device_type"); if (strcmp(cp, "block") == 0) return DT_BLOCK; else if (strcmp(cp, "network") == 0) @@ -592,12 +545,38 @@ getdevtype(fd, name) /* * OpenPROM nodes & property routines (from <sparc/autoconf.c>). */ + int -getprop(node, name, buf, bufsiz) +prom_findnode(int first, const char *name) +{ + int node; + + for (node = first; node != 0; node = prom_nextsibling(node)) + if (strcmp(prom_getpropstring(node, "name"), name) == 0) + return (node); + return (0); +} + +int +prom_findroot() +{ + static int rootnode; int node; - char *name; - void *buf; - register int bufsiz; + + if ((node = rootnode) == 0 && (node = prom_nextsibling(0)) == 0) + panic("no PROM root device"); + rootnode = node; + return (node); +} + +int +prom_firstchild(int node) +{ + return promvec->pv_nodeops->no_child(node); +} + +int +prom_getprop(int node, char *name, void *buf, int bufsiz) { register struct nodeops *no; register int len; @@ -613,27 +592,212 @@ getprop(node, name, buf, bufsiz) return (len); } +int +prom_getproplen(int node, char *name) +{ + return promvec->pv_nodeops->no_proplen(node, name); +} + /* * 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; +prom_getpropstring(int node, char *name) { register int len; static char stringbuf[64]; - len = getprop(node, name, (void *)stringbuf, sizeof stringbuf - 1); + len = prom_getprop(node, name, (void *)stringbuf, sizeof stringbuf - 1); if (len == -1) len = 0; stringbuf[len] = '\0'; /* usually unnecessary */ return (stringbuf); } + +int +prom_nextsibling(int node) +{ + return (promvec->pv_nodeops->no_nextnode(node)); +} + +void +prom_interpret(char *s) +{ + if (promvec->pv_romvec_vers < 2) + promvec->pv_fortheval.v0_eval(strlen(s), s); + else + promvec->pv_fortheval.v2_eval(s); +} + +int +prom_makememarr(struct memarr *ap, u_int xmax, int which) +{ + struct v0mlist *mp; + int node, n; + char *prop; + + if (which != MEMARR_AVAILPHYS && which != MEMARR_TOTALPHYS) + panic("makememarr"); + + if (CPU_ISSUN4) { + struct om_vector *oldpvec = (struct om_vector *)PROM_BASE; + if (ap != NULL && xmax != 0) { + ap[0].addr_hi = 0; + ap[0].addr_lo = 0; + ap[0].len = which == MEMARR_AVAILPHYS ? + *oldpvec->memoryAvail : *oldpvec->memorySize; + } + return 1; + } + + switch (n = promvec->pv_romvec_vers) { + case 0: + /* + * Version 0 PROMs use a linked list to describe these + * guys. + */ + mp = which == MEMARR_AVAILPHYS ? + *promvec->pv_v0mem.v0_physavail : + *promvec->pv_v0mem.v0_phystot; + + for (n = 0; mp != NULL; mp = mp->next, n++) { + if (ap == NULL || n >= xmax) + continue; + ap->addr_hi = 0; + ap->addr_lo = (u_int)mp->addr; + ap->len = mp->nbytes; + ap++; + } + break; + default: + printf("makememarr: hope version %d PROM is like version 2\n", + n); + /* FALLTHROUGH */ + case 3: + case 2: + /* + * Version 2 PROMs use a property array to describe them. + */ + if ((node = prom_findnode(prom_firstchild(prom_findroot()), + "memory")) == 0) + panic("makememarr: cannot find \"memory\" node"); + prop = which == MEMARR_AVAILPHYS ? "available" : "reg"; + n = prom_getproplen(node, prop) / sizeof(struct memarr); + if (ap != NULL) { + if (prom_getprop(node, prop, ap, + xmax * sizeof(struct memarr)) <= 0) + panic("makememarr: cannot get property"); + } + break; + } + + if (n <= 0) + panic("makememarr: no memory found"); + return (n); +} #endif /* BOOTXX */ +void +prom_init() +{ + char *ap, *cp, *dp; +#ifndef BOOTXX + int node; +#endif + + if (cputyp == CPU_SUN4) { + prom0_fake(); + dvma_init(); + } + + if (promvec->pv_romvec_vers >= 2) { + static char filestore[16]; + + prom_bootdevice = *promvec->pv_v2bootargs.v2_bootpath; + +#ifndef BOOTXX + cp = *promvec->pv_v2bootargs.v2_bootargs; + dp = prom_bootfile = filestore; + while (*cp && *cp != '-') + *dp++ = *cp++; + while (dp > prom_bootfile && *--dp == ' '); + *++dp = '\0'; + ap = cp; +#endif + } else { + static char bootstore[16]; + dp = prom_bootdevice = bootstore; + cp = (*promvec->pv_v0bootargs)->ba_argv[0]; + while (*cp) { + *dp++ = *cp; + if (*cp++ == ')') + break; + } + *dp = '\0'; +#ifndef BOOTXX + prom_bootfile = (*promvec->pv_v0bootargs)->ba_kernel; + ap = (*promvec->pv_v0bootargs)->ba_argv[1]; +#endif + } + +#ifndef BOOTXX + if (ap != NULL && *ap == '-') { + while (*ap) { + switch (*ap++) { + case 'a': + prom_boothow |= RB_ASKNAME; + break; + case 'c': + prom_boothow |= RB_CONFIG; + break; + case 'd': + prom_boothow |= RB_KDB; + debug = 1; + break; + case 's': + prom_boothow |= RB_SINGLE; + break; + } + } + } +#endif + +#ifndef BOOTXX + /* + * Find out what type of machine we're running on. + * + * This process is actually started in srt0.S, which has discovered + * the minimal set of machine specific parameters for the 1st-level + * boot program (bootxx) to run. The page size has already been set + * and the CPU type is either CPU_SUN4 or CPU_SUN4C. + */ + + if (cputyp == CPU_SUN4) + return; + + /* + * We have SUN4C, SUN4M or SUN4D. + * Use the PROM `compatible' property to determine which. + * Absence of the `compatible' property means `sun4c'. + */ + + node = prom_findroot(); + cp = prom_getpropstring(node, "compatible"); + if (*cp == '\0' || strcmp(cp, "sun4c") == 0) + cputyp = CPU_SUN4C; + else if (strcmp(cp, "sun4m") == 0) + cputyp = CPU_SUN4M; +#ifdef CPU_SUN4D + else if (strcmp(cp, "sun4d") == 0) + cputyp = CPU_SUN4D; +#endif + else + printf("Unknown CPU type (compatible=`%s')\n", cp); +#endif +} + /* * Old monitor routines */ @@ -671,8 +835,6 @@ prom0_iopen(pd) printf("d_maxiobytes=%d\n", dip->d_maxiobytes); #endif - dvma_init(); - si = &prom_si; bzero((caddr_t)si, sizeof(*si)); si->si_boottab = ops; @@ -756,7 +918,7 @@ static struct mapinfo { { MAP_MAINMEM, PG_OBMEM, 0 }, { MAP_OBIO, PG_OBIO, 0 }, { MAP_MBMEM, PG_VME16, 0xFF000000 }, - { MAP_MBIO, PG_VME16, 0xFFFF0000 }, + { MAP_MBIO, PG_VME16, 0xFFFF0000 }, { MAP_VME16A16D, PG_VME16, 0xFFFF0000 }, { MAP_VME16A32D, PG_VME32, 0xFFFF0000 }, { MAP_VME24A16D, PG_VME16, 0xFF000000 }, diff --git a/sys/arch/sparc/stand/common/promdev.h b/sys/arch/sparc/stand/common/promdev.h index 2cd93e27cad..d8e2a7d6d54 100644 --- a/sys/arch/sparc/stand/common/promdev.h +++ b/sys/arch/sparc/stand/common/promdev.h @@ -1,4 +1,4 @@ -/* $OpenBSD: promdev.h,v 1.3 2003/08/14 17:13:57 deraadt Exp $ */ +/* $OpenBSD: promdev.h,v 1.4 2010/06/29 21:33:54 miod Exp $ */ /* $NetBSD: promdev.h,v 1.3 1995/09/18 21:31:50 pk Exp $ */ /* @@ -41,11 +41,11 @@ struct promdata { #define DT_NET 2 #define DT_BYTE 3 /* Hooks for netif.c */ - int (*xmit)(struct promdata *, void *, size_t); - int (*recv)(struct promdata *, void *, size_t); + ssize_t (*xmit)(struct promdata *, void *, size_t); + ssize_t (*recv)(struct promdata *, void *, size_t); }; -#define LOADADDR ((caddr_t)0x4000) +#define PROM_LOADADDR 0x4000 #define DDB_MAGIC0 ( ('D'<<24) | ('D'<<16) | ('B'<<8) | ('0') ) #define DDB_MAGIC1 ( ('D'<<24) | ('D'<<16) | ('B'<<8) | ('1') ) #define DDB_MAGIC DDB_MAGIC0 @@ -58,14 +58,20 @@ extern int hz; extern int cputyp, nbpg, pgofset, pgshift; extern int debug; -extern void prom_init(void); +void prom_init(void); +struct idprom *prom_getidprom(void); +void prom_interpret(char *); /* Note: dvma_*() routines are for "oldmon" machines only */ -extern void dvma_init(void); -extern char *dvma_mapin(char *, size_t); -extern char *dvma_mapout(char *, size_t); -extern char *dvma_alloc(int); -extern void dvma_free(char *, int); +void dvma_init(void); +char *dvma_mapin(char *, size_t); +char *dvma_mapout(char *, size_t); +char *dvma_alloc(int); +void dvma_free(char *, int); + +int mmu_init(void); +extern int (*pmap_map)(vaddr_t, paddr_t, psize_t); +extern int (*pmap_extract)(vaddr_t, paddr_t *); /* * duplicates from pmap.c for mapping device on "oldmon" machines. @@ -80,8 +86,8 @@ extern void dvma_free(char *, int); #define setsegmap(va, pmeg) (cputyp == CPU_SUN4C \ ? stba(va, ASI_SEGMAP, pmeg) \ : stha(va, ASI_SEGMAP, pmeg)) -#define getregmap(va) ((unsigned)lduha(va+2, ASI_REGMAP) >> 8) -#define setregmap(va, smeg) stha(va+2, ASI_REGMAP, (smeg << 8)) +#define getregmap(va) ((unsigned)lduha((va) + 2, ASI_REGMAP) >> 8) +#define setregmap(va, smeg) stha((va) + 2, ASI_REGMAP, (smeg << 8)) #define getpte(va) lda(va, ASI_PTE) #define setpte(va, pte) sta(va, ASI_PTE, pte) diff --git a/sys/arch/sparc/stand/common/srt0.S b/sys/arch/sparc/stand/common/srt0.S index 55a7a5e8272..fec67633e0b 100644 --- a/sys/arch/sparc/stand/common/srt0.S +++ b/sys/arch/sparc/stand/common/srt0.S @@ -1,4 +1,4 @@ -/* $OpenBSD: srt0.S,v 1.2 2002/08/11 12:20:43 art Exp $ */ +/* $OpenBSD: srt0.S,v 1.3 2010/06/29 21:33:54 miod Exp $ */ /* $NetBSD: srt0.S,v 1.5.4.2 1996/07/17 01:51:46 jtc Exp $ */ /* @@ -62,11 +62,19 @@ start: save %o1, -CCFSZ, %sp /* - * Relocate. + * Find which address we are at. */ 1: call 2f + sethi %hi(1b), %l0 +2: or %l0, %lo(1b), %l0 + cmp %l0, %o7 ! %o7 contains actual address of 1b + beq 4f ! already there, no need to relocate nop -2: add %o7, (start-1b), %l0 + + /* + * Relocate. + */ + add %o7, (start-1b), %l0 set start, %l1 set _C_LABEL(end), %o0 sub %o0, %l1, %l2 ! length @@ -102,8 +110,17 @@ start: */ set _C_LABEL(edata), %o0 ! bzero(edata, end - edata) set _C_LABEL(end), %o1 - call _C_LABEL(bzero) - sub %o1, %o0, %o1 + /* note: bzero() expanded inline for compactness */ + subcc %o1, %o0, %o1 + bz 2f ! in case there is no BSS + + srl %o1, 2, %o1 ! assume edata and end are aligned +1: + st %g0, [%o0] ! while (n--) + subcc %o1, 1, %o1 ! *p++ = 0; + bnz 1b + add %o0, 4, %o0 +2: /* * Enable interrupts, but only above level 11. This enables "L1-A", @@ -156,45 +173,3 @@ start: ret restore - - -#ifdef TIGHT - -/* - * XXX - Space saving .div & .rem routines (small & non-negative numbres only) - */ - .align 4 - .global .div, .udiv -! int n = 0; while (a >= b) { a -= b; n++; }; return n; -.div: -.udiv: - cmp %o0, %o1 - bl 2f - mov 0, %o5 -1: - sub %o0, %o1, %o0 - cmp %o0, %o1 - bge 1b - add %o5, 1, %o5 -2: - retl - mov %o5, %o0 - - .align 4 - .global .rem, .urem -! while (a>=b) a -= b; return a; -.rem: -.urem: - cmp %o0, %o1 - bl 2f - nop - sub %o0, %o1, %o0 -1: - cmp %o0, %o1 - bge,a 1b - sub %o0, %o1, %o0 -2: - retl - nop - -#endif /* TIGHT */ diff --git a/sys/arch/sparc/stand/common/version.c b/sys/arch/sparc/stand/common/version.c index a8fdea0e73d..66642e57f0d 100644 --- a/sys/arch/sparc/stand/common/version.c +++ b/sys/arch/sparc/stand/common/version.c @@ -1,4 +1,4 @@ -/* $OpenBSD: version.c,v 1.4 2009/07/01 20:13:39 miod Exp $ */ +/* $OpenBSD: version.c,v 1.5 2010/06/29 21:33:54 miod Exp $ */ /* $NetBSD: version.c,v 1.4 1995/09/16 23:20:39 pk Exp $ */ /* @@ -43,6 +43,7 @@ * 2.1 Bumped RELOC * 2.2 ELF support added. * 2.3 Bumped RELOC + * 2.4 Support for larger kernels and fragmented memory layouts. */ -char *version = "2.3"; +char *version = "2.4"; diff --git a/sys/arch/sparc/stand/libsa/Makefile b/sys/arch/sparc/stand/libsa/Makefile index 88714bf37de..44356215b10 100644 --- a/sys/arch/sparc/stand/libsa/Makefile +++ b/sys/arch/sparc/stand/libsa/Makefile @@ -1,10 +1,10 @@ -# $OpenBSD: Makefile,v 1.4 2005/12/30 02:03:49 millert Exp $ +# $OpenBSD: Makefile,v 1.5 2010/06/29 21:33:54 miod Exp $ LIB= sa .PATH: ${.CURDIR}/../../../../lib/libsa -CFLAGS= -O2 -D__INTERNAL_LIBSA_CREAD \ +CFLAGS= -O2 -D_STANDALONE -D__INTERNAL_LIBSA_CREAD \ -I${.CURDIR} -I${.CURDIR}/../include -I${.CURDIR}/../.. \ -I${.CURDIR}/../../.. -I${.CURDIR}/../../../.. \ -I${.CURDIR}/../../../../lib/libsa |