Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/arch/sparc Add support for large kernels by searching fo...



details:   https://anonhg.NetBSD.org/src/rev/bf9f9c9b7511
branches:  trunk
changeset: 543634:bf9f9c9b7511
user:      pk <pk%NetBSD.org@localhost>
date:      Sat Mar 01 13:01:55 2003 +0000

description:
Add support for large kernels by searching for a physical memory segment
to fit it in. As a bonus, the kernel is now also mapped to the virtual
address (i.e. KERNBASE) it is linked at.

diffstat:

 sys/arch/sparc/include/loadfile_machdep.h |    4 +-
 sys/arch/sparc/sparc/promlib.c            |   37 ++++++-
 sys/arch/sparc/stand/Makefile.buildboot   |    4 +-
 sys/arch/sparc/stand/boot/Makefile        |    4 +-
 sys/arch/sparc/stand/boot/boot.c          |  127 ++++++++++++++++----
 sys/arch/sparc/stand/boot/version         |    3 +-
 sys/arch/sparc/stand/common/mmu.c         |  180 ++++++++++++++++++++++++++++++
 sys/arch/sparc/stand/common/promdev.h     |    7 +-
 8 files changed, 330 insertions(+), 36 deletions(-)

diffs (truncated from 508 to 300 lines):

diff -r ba96ad411b4e -r bf9f9c9b7511 sys/arch/sparc/include/loadfile_machdep.h
--- a/sys/arch/sparc/include/loadfile_machdep.h Sat Mar 01 12:59:54 2003 +0000
+++ b/sys/arch/sparc/include/loadfile_machdep.h Sat Mar 01 13:01:55 2003 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: loadfile_machdep.h,v 1.7 2002/12/08 14:36:55 uwe Exp $  */
+/*     $NetBSD: loadfile_machdep.h,v 1.8 2003/03/01 13:01:55 pk Exp $   */
 
 /*-
  * Copyright (c) 1999 The NetBSD Foundation, Inc.
@@ -40,7 +40,7 @@
 #define COUNT_KERNEL   COUNT_ALL
 
 #ifdef _STANDALONE
-#define LOADADDR(a)            (((u_long)(a) & 0x07ffffff) + (u_long)offset)
+#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))
diff -r ba96ad411b4e -r bf9f9c9b7511 sys/arch/sparc/sparc/promlib.c
--- a/sys/arch/sparc/sparc/promlib.c    Sat Mar 01 12:59:54 2003 +0000
+++ b/sys/arch/sparc/sparc/promlib.c    Sat Mar 01 13:01:55 2003 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: promlib.c,v 1.16 2003/02/26 17:39:07 pk Exp $ */
+/*     $NetBSD: promlib.c,v 1.17 2003/03/01 13:01:56 pk Exp $ */
 
 /*-
  * Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -1168,6 +1168,10 @@
 void
 prom_init()
 {
+#ifdef _STANDALONE
+       int node;
+       char *cp;
+#endif
 
        if (CPU_ISSUN4) {
                prom_init_oldmon();
@@ -1179,4 +1183,35 @@
                 */
                prom_init_opf();
        }
+
+#ifdef _STANDALONE
+       /*
+        * 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;
+       else if (strcmp(cp, "sun4d") == 0)
+               cputyp = CPU_SUN4D;
+       else
+               printf("Unknown CPU type (compatible=`%s')\n", cp);
+#endif /* _STANDALONE */
 }
diff -r ba96ad411b4e -r bf9f9c9b7511 sys/arch/sparc/stand/Makefile.buildboot
--- a/sys/arch/sparc/stand/Makefile.buildboot   Sat Mar 01 12:59:54 2003 +0000
+++ b/sys/arch/sparc/stand/Makefile.buildboot   Sat Mar 01 13:01:55 2003 +0000
@@ -1,4 +1,4 @@
-#      $NetBSD: Makefile.buildboot,v 1.18 2002/07/20 11:43:43 mrg Exp $
+#      $NetBSD: Makefile.buildboot,v 1.19 2003/03/01 13:01:56 pk Exp $
 #
 # This file is for the sparc `boot' and `bootxx' only; it does not
 # currently play well on a 64-bit system.
@@ -31,7 +31,7 @@
 # flushing issues on Hypersparcs
 RELOC_BOOTXX=  300000
 
-CPPFLAGS+=     -D_STANDALONE -DSUN4 -DSUN4C -DHEAP_VARIABLE
+CPPFLAGS+=     -D_STANDALONE -DSUN4 -DSUN4C -DSUN4M -DSUN4D -DHEAP_VARIABLE
 
 CPPFLAGS+=     -I. -I${.CURDIR}/../../.. -I${.CURDIR}/../../../..
 CFLAGS=                -O2
diff -r ba96ad411b4e -r bf9f9c9b7511 sys/arch/sparc/stand/boot/Makefile
--- a/sys/arch/sparc/stand/boot/Makefile        Sat Mar 01 12:59:54 2003 +0000
+++ b/sys/arch/sparc/stand/boot/Makefile        Sat Mar 01 13:01:55 2003 +0000
@@ -1,8 +1,8 @@
-#      $NetBSD: Makefile,v 1.27 2001/12/04 18:54:34 thorpej Exp $
+#      $NetBSD: Makefile,v 1.28 2003/03/01 13:01:56 pk Exp $
 
 STRIPFLAG=
 PROGSOURCE=    boot.c net.c netif_sun.c conf.c openfirm.c bootinfo.c \
-               prompatch.c vers.c
+               mmu.c prompatch.c vers.c
 NEWVERSWHAT=   "Secondary Boot"
 FILES=         boot.net ${RELOCS:S/^/boot./g}
 CLEANFILES:=   vers.c ${FILES}
diff -r ba96ad411b4e -r bf9f9c9b7511 sys/arch/sparc/stand/boot/boot.c
--- a/sys/arch/sparc/stand/boot/boot.c  Sat Mar 01 12:59:54 2003 +0000
+++ b/sys/arch/sparc/stand/boot/boot.c  Sat Mar 01 13:01:55 2003 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: boot.c,v 1.14 2003/02/25 08:09:30 pk Exp $ */
+/*     $NetBSD: boot.c,v 1.15 2003/03/01 13:01:56 pk Exp $ */
 
 /*-
  * Copyright (c) 1982, 1986, 1990, 1993
@@ -57,7 +57,10 @@
 int    netif_debug;
 
 char   fbuf[80], dbuf[128];
-u_long maxkernsize;
+paddr_t bstart, bend;  /* physical start & end address of the boot program */
+
+int    compatmode = 0;         /* For loading older kernels */
+u_long loadaddrmask = -1UL;
 
 extern char bootprog_name[], bootprog_rev[], bootprog_date[], bootprog_maker[];
 
@@ -104,10 +107,69 @@
        return (v);
 }
 
+static paddr_t getphysmem(u_long size)
+{
+       struct  memarr *pmemarr;        /* physical memory regions */
+       int     npmemarr;               /* number of entries in pmemarr */
+       struct memarr *mp;
+       int i;
+       extern char start[];    /* top of stack (see srt0.S) */
+
+       /*
+        * 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.
+        */
+       if (pmap_extract((vaddr_t)start - (16*1024), &bstart) != 0)
+               return ((paddr_t)-1);
+
+       bend = roundup(bstart, 0x400000);
+
+       /*
+        * 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);
+
+       /*
+        * Find a suitable loading address.
+        */
+       for (mp = pmemarr, i = npmemarr; --i >= 0; mp++) {
+               paddr_t pa = (paddr_t)pmemarr[i].addr;
+               u_long len = (u_long)pmemarr[i].len;
+
+               /* 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 *kernel, u_long *marks)
 {
        int fd, error;
+       vaddr_t va;
+       paddr_t pa;
        u_long size;
 
        if ((fd = open(kernel, 0)) < 0)
@@ -118,15 +180,36 @@
                goto out;
 
        size = marks[MARK_END] - marks[MARK_START];
-       if (size > maxkernsize) {
-               printf("kernel too large: %lu"
-                       " (maximum kernel size is %lu)\n",
-                       marks[MARK_END] - marks[MARK_START],
-                       maxkernsize);
+
+       /* We want that leading 4K in front of the kernel image */
+       size += PROM_LOADADDR;
+       va = marks[MARK_START] - PROM_LOADADDR;
+
+       /* Extra space for bootinfo and kernel bootstrap */
+       size += 512 * 1024;
+
+       /* Get a physical load address */
+       pa = getphysmem(size);
+       if (pa == (paddr_t)-1) {
                error = EFBIG;
                goto out;
        }
 
+       if (boothowto & AB_VERBOSE)
+               printf("Loading at physical address %lx\n", pa);
+       if (pmap_map(va, pa, size) != 0) {
+               error = EFAULT;
+               goto out;
+       }
+
+       /* XXX - to do: inspect kernel image and set compat mode */
+       if (compatmode) {
+               /* Double-map at VA 0 for compatibility; ignore errors */
+               if (pa + size < bstart)
+                       (void)pmap_map(0, pa, size);
+               loadaddrmask = 0x07ffffffUL;
+       }
+
        marks[MARK_START] = 0;
        error = fdloadfile(fd, marks, LOAD_KERNEL);
 out:
@@ -149,17 +232,8 @@
                setheap((void *)ALIGN(end), (void *)0xffffffff);
        }
 #endif
-       {
-               /*
-                * Find maximum the kernel size that we can handle.
-                * Our stack grows down from label `start'; assume
-                * we need no more that 16K of stack space.
-                */
-               extern char start[];    /* top of stack (see srt0.S) */
-               maxkernsize = (u_long)start - (16*1024) - PROM_LOADADDR;
-               
-       }
        prom_init();
+       mmu_init();
 
        printf(">> %s, Revision %s\n", bootprog_name, bootprog_rev);
        printf(">> (%s, %s)\n", bootprog_maker, bootprog_date);
@@ -228,21 +302,20 @@
                }
        }
 
-       marks[MARK_END] = (((u_long)marks[MARK_END] + sizeof(int) - 1)) &
-           (-sizeof(int));
+       marks[MARK_END] = (((u_long)marks[MARK_END] + sizeof(u_long) - 1)) &
+           (-sizeof(u_long));
        arg = (prom_version() == PROM_OLDMON) ? (caddr_t)PROM_LOADADDR : romp;
 
-       /* Should work with both a.out and ELF, but somehow ELF is busted */
-       bootinfo = bi_init(marks[MARK_END]);
+       /* Setup boot info structure at the end of the kernel image */
+       bootinfo = bi_init(marks[MARK_END] & loadaddrmask);
 
-       bi_sym.nsym = marks[MARK_NSYM];
-       bi_sym.ssym = marks[MARK_SYM];
-       bi_sym.esym = marks[MARK_END];
+       /* Add kernel symbols to bootinfo */
+       bi_sym.nsym = marks[MARK_NSYM] & loadaddrmask;
+       bi_sym.ssym = marks[MARK_SYM] & loadaddrmask;
+       bi_sym.esym = marks[MARK_END] & loadaddrmask;
        bi_add(&bi_sym, BTINFO_SYMTAB, sizeof(bi_sym));
 
-       /*
-        * Add kernel path to bootinfo
-        */
+       /* Add kernel path to bootinfo */
        i = sizeof(struct btinfo_common) + strlen(kernel) + 1;
        /* Impose limit (somewhat arbitrary) */
        if (i < BOOTINFO_SIZE / 2) {
diff -r ba96ad411b4e -r bf9f9c9b7511 sys/arch/sparc/stand/boot/version
--- a/sys/arch/sparc/stand/boot/version Sat Mar 01 12:59:54 2003 +0000
+++ b/sys/arch/sparc/stand/boot/version Sat Mar 01 13:01:55 2003 +0000
@@ -1,4 +1,4 @@
-$NetBSD: version,v 1.16 2002/12/16 13:02:58 jdc Exp $
+$NetBSD: version,v 1.17 2003/03/01 13:01:56 pk Exp $
 
 NOTE ANY CHANGES YOU MAKE TO THE BOOTBLOCKS HERE.  The format of this
 file is important - make sure the entries are appended on end, last item
@@ -16,3 +16,4 @@
 1.11:  loadfile() update to avoid backwards seeks for ELF Program Headers.



Home | Main Index | Thread Index | Old Index