-/* $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
#include <sys/param.h>
#include <sys/extent.h>
-#include <sys/malloc.h>
#include <sys/mbuf.h>
#include <sys/proc.h>
* 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);
#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;
* 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;
* 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;
-/* $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 $ */
/*-
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.
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
/* 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
goto out;
}
+ marks[MARK_START] = 0;
if ((error = fdloadfile(fd, marks, COUNT_KERNEL)) != 0)
goto out;
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);