diff options
author | Miod Vallat <miod@cvs.openbsd.org> | 2010-06-29 21:33:55 +0000 |
---|---|---|
committer | Miod Vallat <miod@cvs.openbsd.org> | 2010-06-29 21:33:55 +0000 |
commit | 07f81d1ec7f9a00d77ebeac722af8e828796359c (patch) | |
tree | a619bef47d79b4f92b7d53580ef398ec276f58da /sys/arch | |
parent | e4860bc94976949e5141b134229c8c6973b499f7 (diff) |
In the boot blocks, stop assuming we have a 1:1 mapping of low physical
memory, but instead gather memory layout information and work with the MMU
(or the PROM) to make sure we can actually load the kernel image in a proper
contiguous physical memory area.
In order to do this, we look at the kernel image twice; during the first pass,
the kernel footprint is computed, and then after making sure it can be
loaded, the second pass loads the actual image.
Since such a logic doesn't work on media which can not seek backwards, such
as tapes, we check for the boot device being a tape and, in that case, assume
a fixed (generous) image size and don't load the kernel symbol table (to
avoid seeking backwards); since tape boot is supposed to be only used to
boot bsd.rd, this is something we can live with.
While there, lower the address the boot blocks are loaded in memory, because
the last crank did not work with some early sun4c OpenPROM, which only
map about 3.5MB of memory.
Memory games logic from NetBSD, tape handling by me.
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 |