Only attempt to load /etc/random.seed from the boot device after the kernel
authormiod <miod@openbsd.org>
Tue, 19 May 2015 20:42:11 +0000 (20:42 +0000)
committermiod <miod@openbsd.org>
Tue, 19 May 2015 20:42:11 +0000 (20:42 +0000)
image has been succesfully loaded (with the recent loadfile changes allowing
us to know where the randomness needs to be loaded). While there, don't
bother doing this when booting from tape.

This works around the sun4e PROM 1.6, which gets confused by PROM open() -
close() sequences without any I/O happening in between.

Crank boot blocks version to 2.11.

sys/arch/sparc/sparc/dvma.c
sys/arch/sparc/stand/boot/boot.c
sys/arch/sparc/stand/boot/loadfile_sparc.c
sys/arch/sparc/stand/common/version.c

index c5ffdb9..78c2a66 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: dvma.c,v 1.1 2015/03/30 20:30:22 miod Exp $   */
+/*     $OpenBSD: dvma.c,v 1.2 2015/05/19 20:42:11 miod Exp $   */
 
 /*
  * Copyright (c) 1996
@@ -50,7 +50,6 @@
 
 #include <sys/param.h>
 #include <sys/extent.h>
-#include <sys/malloc.h>
 #include <sys/mbuf.h>
 #include <sys/proc.h>
 
@@ -83,9 +82,7 @@ dvma_init(void)
  * so drivers need not include VM goo to get at kernel_map.
  */
 caddr_t
-kdvma_mapin(va, len, canwait)
-       caddr_t va;
-       int     len, canwait;
+kdvma_mapin(caddr_t va, int len, int canwait)
 {
        return (caddr_t)dvma_mapin_space(kernel_map, (vaddr_t)va, len, canwait,
            0);
@@ -96,54 +93,85 @@ extern int has_iocache;
 #endif
 
 caddr_t
-dvma_malloc_space(len, kaddr, flags, space)
-       size_t  len;
-       void    *kaddr;
-       int     flags;
+dvma_malloc_space(size_t len, void *kaddr, int flags, int space)
 {
+       int waitok = (flags & M_NOWAIT) == 0;
+       vsize_t maplen, tmplen;
        vaddr_t kva;
        vaddr_t dva;
+       int s;
 
        len = round_page(len);
-       kva = (vaddr_t)malloc(len, M_DEVBUF, flags);
+       /* XXX - verify if maybe uvm_km_valloc from kernel_map would be ok. */
+       s = splvm();
+       kva = uvm_km_valloc(kmem_map, len);
+       splx(s);
        if (kva == 0)
                return (NULL);
 
+       for (maplen = 0; maplen < len; maplen += PAGE_SIZE) {
+               struct vm_page *pg;
+               paddr_t pa;
+
+again:
+               pg = uvm_pagealloc(NULL, 0, NULL, 0);
+               if (pg == NULL) {
+                       if (waitok) {
+                               uvm_wait("dvmapg");
+                               goto again;
+                       }
+                       goto dropit;
+               }
+               pa = VM_PAGE_TO_PHYS(pg);
 #if defined(SUN4M)
-       if (!has_iocache)
+               if (!has_iocache)
 #endif
-               kvm_uncache((caddr_t)kva, atop(len));
+                       pa |= PMAP_NC;
+               pmap_kenter_pa(kva + maplen, pa, PROT_READ | PROT_WRITE);
+       }
 
        *(vaddr_t *)kaddr = kva;
-       dva = dvma_mapin_space(kernel_map, kva, len, (flags & M_NOWAIT) ? 0 : 1, space);
+       dva = dvma_mapin_space(kernel_map, kva, len, waitok ? 1 : 0, space);
        if (dva == 0) {
-               free((void *)kva, M_DEVBUF, 0);
-               return (NULL);
+               goto dropit;
        }
        return (caddr_t)dva;
+dropit:
+       for (tmplen = 0; tmplen < maplen; tmplen += PAGE_SIZE) {
+               paddr_t pa;
+
+               if (pmap_extract(pmap_kernel(), kva + tmplen, &pa) == FALSE)
+                       panic("dvma_malloc_space: pmap_extract");
+
+               pmap_kremove(kva + tmplen, PAGE_SIZE);
+               uvm_pagefree(PHYS_TO_VM_PAGE(pa));
+       }
+
+       uvm_km_free(kmem_map, kva, len);
+
+       return NULL;
 }
 
 void
-dvma_free(dva, len, kaddr)
-       caddr_t dva;
-       size_t  len;
-       void    *kaddr;
+dvma_free(caddr_t dva, size_t len, void        *kaddr)
 {
+       size_t tmplen;
        vaddr_t kva = *(vaddr_t *)kaddr;
 
        len = round_page(len);
 
        dvma_mapout((vaddr_t)dva, kva, len);
-       /*
-        * Even if we're freeing memory here, we can't be sure that it will
-        * be unmapped, so we must recache the memory range to avoid impact
-        * on other kernel subsystems.
-        */
-#if defined(SUN4M)
-       if (!has_iocache)
-#endif
-               kvm_recache(kaddr, atop(len));
-       free((void *)kva, M_DEVBUF, 0);
+       for (tmplen = 0; tmplen < len; tmplen += PAGE_SIZE) {
+               paddr_t pa;
+
+               if (pmap_extract(pmap_kernel(), kva + tmplen, &pa) == FALSE)
+                       panic("dvma_free: pmap_extract");
+
+               pmap_kremove(kva + tmplen, PAGE_SIZE);
+               uvm_pagefree(PHYS_TO_VM_PAGE(pa));
+       }
+
+       uvm_km_free(kmem_map, kva, len);
 }
 
 u_long dvma_cachealign = 0;
@@ -154,10 +182,8 @@ u_long dvma_cachealign = 0;
  * second mapping of that range.
  */
 vaddr_t
-dvma_mapin_space(map, va, len, canwait, space)
-       struct vm_map   *map;
-       vaddr_t va;
-       int             len, canwait, space;
+dvma_mapin_space(struct vm_map *map, vaddr_t va, int len, int canwait,
+    int space)
 {
        vaddr_t kva, tva;
        int npf, s;
@@ -236,9 +262,7 @@ dvma_mapin_space(map, va, len, canwait, space)
  * Remove DVMA mapping of `va' in DVMA space at `dva'.
  */
 void
-dvma_mapout(dva, va, len)
-       vaddr_t dva, va;
-       int             len;
+dvma_mapout(vaddr_t dva, vaddr_t va, int len)
 {
        int s, off;
        int error;
index 35a41cd..14686a7 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: boot.c,v 1.13 2015/03/05 20:46:13 miod Exp $  */
+/*     $OpenBSD: boot.c,v 1.14 2015/05/19 20:42:11 miod Exp $  */
 /*     $NetBSD: boot.c,v 1.2 1997/09/14 19:27:21 pk Exp $      */
 
 /*-
@@ -158,6 +158,8 @@ loadk(char *file, u_long *marks)
        u_long minsize, size;
        vaddr_t extra;
 
+       marks[MARK_RANDOM] = marks[MARK_ERANDOM] = 0;
+
        /*
         * Regardless of the address where we load the kernel, we need to
         * make sure it has enough valid space to use during pmap_bootstrap.
@@ -178,6 +180,8 @@ loadk(char *file, u_long *marks)
 
        if (files[fd].f_flags & F_RAW) {
                flags = (COUNT_KERNEL & ~COUNT_SYM) | (LOAD_KERNEL & ~LOAD_SYM);
+               if (rnd_loaded == 0)
+                       flags &= ~LOAD_RANDOM;
                minsize = FOURMB;
                va = 0xf8000000;                /* KERNBASE */
 #ifdef DEBUG
@@ -187,27 +191,9 @@ loadk(char *file, u_long *marks)
                /* compensate for extra room below */
                minsize -= extra;
        } else {
-               /*
-                * If we did not load a random.seed file yet, try and load
-                * one.
-                */
-               if (rnd_loaded == 0) {
-                       /*
-                        * Some PROM do not like having a network device
-                        * open()ed twice; better close and reopen after
-                        * trying to get randomness.
-                        */
-                       close(fd);
-
-                       rnd_loaded = loadrandom(BOOTRANDOM, rnddata,
-                           sizeof(rnddata));
-
-                       if ((fd = open(file, O_RDONLY)) < 0)
-                               return (errno ? errno : ENOENT);
-               }
-
                flags = LOAD_KERNEL;
-               marks[MARK_START] = 0;
+               if (rnd_loaded == 0)
+                       flags &= ~LOAD_RANDOM;
 
                /*
                 * Even though we just have opened the file, the gzip code
@@ -220,6 +206,7 @@ loadk(char *file, u_long *marks)
                        goto out;
                }
 
+               marks[MARK_START] = 0;
                if ((error = fdloadfile(fd, marks, COUNT_KERNEL)) != 0)
                        goto out;
 
@@ -299,6 +286,33 @@ loadk(char *file, u_long *marks)
 
        marks[MARK_START] = 0;
        error = fdloadfile(fd, marks, flags);
+
+       /*
+        * If we did not load a random.seed file yet, and we know we can try,
+        * load one.
+        */
+       if (error == 0 && rnd_loaded == 0 && marks[MARK_RANDOM] != 0) {
+               /*
+                * Some PROM do not like having a network device open()ed
+                * twice; better close the kernel fd before trying to get
+                * randomness.
+                */
+               close(fd);
+
+               rnd_loaded = loadrandom(BOOTRANDOM, rnddata, sizeof(rnddata));
+               if (rnd_loaded != 0) {
+                       while (marks[MARK_RANDOM] < marks[MARK_ERANDOM]) {
+                               u_long m;
+                               m = MIN(marks[MARK_ERANDOM] -
+                                   marks[MARK_RANDOM], sizeof(rnddata));
+                               memcpy((void *)marks[MARK_RANDOM], rnddata, m);
+                               marks[MARK_RANDOM] += m;
+                       }
+               }
+
+               return 0;
+       }
+
 out:
        close(fd);
        return (error);
index 13a3db4..0348721 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: loadfile_sparc.c,v 1.3 2014/02/25 21:28:30 miod Exp $ */
+/* $OpenBSD: loadfile_sparc.c,v 1.4 2015/05/19 20:42:11 miod Exp $ */
 
 /*-
  * Copyright (c) 1997 The NetBSD Foundation, Inc.
@@ -198,7 +198,7 @@ elf32_exec(int fd, off_t filepos, Elf_Ehdr *elf, u_long *marks, int flags)
                        int m;
 
                        /* Fill segment is asked for. */
-                       if (flags & LOAD_DATA) {
+                       if (flags & LOAD_RANDOM) {
                                for (pos = 0; pos < phdr[i].p_filesz;
                                    pos += m) {
                                        m = MIN(phdr[i].p_filesz - pos,
@@ -207,6 +207,11 @@ elf32_exec(int fd, off_t filepos, Elf_Ehdr *elf, u_long *marks, int flags)
                                            m);
                                }
                        }
+                       if (flags & (LOAD_RANDOM | COUNT_RANDOM)) {
+                               marks[MARK_RANDOM] = LOADADDR(phdr[i].p_paddr);
+                               marks[MARK_ERANDOM] =
+                                   marks[MARK_RANDOM] + phdr[i].p_filesz;
+                       }
                        continue;
                }
 
index a65f48c..36acfac 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: version.c,v 1.11 2015/03/05 20:46:13 miod Exp $       */
+/*     $OpenBSD: version.c,v 1.12 2015/05/19 20:42:11 miod Exp $       */
 /*     $NetBSD: version.c,v 1.4 1995/09/16 23:20:39 pk Exp $ */
 
 /*
  *     2.9     Cope with DMA transfer size limits of old sun4 PROMs
  *     2.10    Allocate more memory beyond the kernel image on sun4d/sun4m
  *             systems to allow for larger kernel page tables
+ *     2.11    Only attempt to load /etc/random.seed after a successful
+ *             kernel load, and never if booting from tape. This works
+ *             around sun4e PROM 1.6, which apparently gets confused by
+ *             open() - close() sequences without any I/O in between.
  */
 
-char *version = "2.10";
+char *version = "2.11";