From 498f08232b3ce39761767041cdaa93f1bd308aaf Mon Sep 17 00:00:00 2001 From: miod Date: Tue, 19 May 2015 20:42:11 +0000 Subject: [PATCH] Only attempt to load /etc/random.seed from the boot device after the kernel 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 | 96 ++++++++++++++-------- sys/arch/sparc/stand/boot/boot.c | 56 ++++++++----- sys/arch/sparc/stand/boot/loadfile_sparc.c | 9 +- sys/arch/sparc/stand/common/version.c | 8 +- 4 files changed, 108 insertions(+), 61 deletions(-) diff --git a/sys/arch/sparc/sparc/dvma.c b/sys/arch/sparc/sparc/dvma.c index c5ffdb91bdc..78c2a667732 100644 --- a/sys/arch/sparc/sparc/dvma.c +++ b/sys/arch/sparc/sparc/dvma.c @@ -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 #include -#include #include #include @@ -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; diff --git a/sys/arch/sparc/stand/boot/boot.c b/sys/arch/sparc/stand/boot/boot.c index 35a41cd5a8d..14686a7f356 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.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); diff --git a/sys/arch/sparc/stand/boot/loadfile_sparc.c b/sys/arch/sparc/stand/boot/loadfile_sparc.c index 13a3db4d6c2..03487216aa5 100644 --- a/sys/arch/sparc/stand/boot/loadfile_sparc.c +++ b/sys/arch/sparc/stand/boot/loadfile_sparc.c @@ -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; } diff --git a/sys/arch/sparc/stand/common/version.c b/sys/arch/sparc/stand/common/version.c index a65f48c19aa..36acfacda13 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.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 $ */ /* @@ -52,6 +52,10 @@ * 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"; -- 2.20.1