PR port-i386/34186 by Wolfgang Stukenbrock:
mapping of msgbuf during startup may map invalid physical adresses "If the last available physical memory segment on a system is less 16k, than the startup code that will map the kernel message buffer, will fail and map physical pages behind the last segment. This may either only lead to a message buffer without physical memory behind it, or to an overlapping message buffer with something else." Fix by allowing multiple physical memory segments to be used for msgbuf. Also remove some leftover msgbuf manipulation from pmap.c. Fix supplied by Wolfgang Stukenbrock in the PR, with some modifications from me, mainly to use the already existing constant VM_PHYSSEG_MAX as the static limit of number of msgbuf segments.
This commit is contained in:
parent
df83b9e26d
commit
9e8014fe50
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: machdep.c,v 1.588 2007/01/05 04:07:23 jmcneill Exp $ */
|
||||
/* $NetBSD: machdep.c,v 1.589 2007/01/06 15:29:02 pavel Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1996, 1997, 1998, 2000, 2004, 2006 The NetBSD Foundation, Inc.
|
||||
|
@ -72,7 +72,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.588 2007/01/05 04:07:23 jmcneill Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.589 2007/01/06 15:29:02 pavel Exp $");
|
||||
|
||||
#include "opt_beep.h"
|
||||
#include "opt_compat_ibcs2.h"
|
||||
|
@ -248,7 +248,11 @@ int i386_has_sse2;
|
|||
int tmx86_has_longrun;
|
||||
|
||||
vaddr_t msgbuf_vaddr;
|
||||
paddr_t msgbuf_paddr;
|
||||
struct {
|
||||
paddr_t paddr;
|
||||
psize_t sz;
|
||||
} msgbuf_p_seg[VM_PHYSSEG_MAX];
|
||||
unsigned int msgbuf_p_cnt = 0;
|
||||
|
||||
vaddr_t idt_vaddr;
|
||||
paddr_t idt_paddr;
|
||||
|
@ -404,8 +408,9 @@ native_loader(int bl_boothowto, int bl_bootdev,
|
|||
void
|
||||
cpu_startup()
|
||||
{
|
||||
int x;
|
||||
int x, y;
|
||||
vaddr_t minaddr, maxaddr;
|
||||
psize_t sz;
|
||||
char pbuf[9];
|
||||
|
||||
/*
|
||||
|
@ -417,18 +422,23 @@ cpu_startup()
|
|||
/*
|
||||
* Initialize error message buffer (et end of core).
|
||||
*/
|
||||
msgbuf_vaddr = uvm_km_alloc(kernel_map, x86_round_page(MSGBUFSIZE), 0,
|
||||
UVM_KMF_VAONLY);
|
||||
if (msgbuf_p_cnt == 0)
|
||||
panic("msgbuf paddr map has not been set up");
|
||||
for (x = 0, sz = 0; x < msgbuf_p_cnt; sz += msgbuf_p_seg[x++].sz)
|
||||
continue;
|
||||
msgbuf_vaddr = uvm_km_alloc(kernel_map, sz, 0, UVM_KMF_VAONLY);
|
||||
if (msgbuf_vaddr == 0)
|
||||
panic("failed to valloc msgbuf_vaddr");
|
||||
|
||||
/* msgbuf_paddr was init'd in pmap */
|
||||
for (x = 0; x < btoc(MSGBUFSIZE); x++)
|
||||
pmap_kenter_pa((vaddr_t)msgbuf_vaddr + x * PAGE_SIZE,
|
||||
msgbuf_paddr + x * PAGE_SIZE, VM_PROT_READ|VM_PROT_WRITE);
|
||||
for (y = 0, sz = 0; y < msgbuf_p_cnt; y++) {
|
||||
for (x = 0; x < btoc(msgbuf_p_seg[y].sz); x++, sz += PAGE_SIZE)
|
||||
pmap_kenter_pa((vaddr_t)msgbuf_vaddr + sz,
|
||||
msgbuf_p_seg[y].paddr + x * PAGE_SIZE, VM_PROT_READ|VM_PROT_WRITE);
|
||||
}
|
||||
pmap_update(pmap_kernel());
|
||||
|
||||
initmsgbuf((caddr_t)msgbuf_vaddr, round_page(MSGBUFSIZE));
|
||||
initmsgbuf((caddr_t)msgbuf_vaddr, sz);
|
||||
|
||||
printf("%s%s", copyright, version);
|
||||
|
||||
|
@ -1874,6 +1884,7 @@ init386(paddr_t first_avail)
|
|||
psize_t sz = round_page(MSGBUFSIZE);
|
||||
psize_t reqsz = sz;
|
||||
|
||||
search_again:
|
||||
for (x = 0; x < vm_nphysseg; x++) {
|
||||
vps = &vm_physmem[x];
|
||||
if (ptoa(vps->avail_end) == avail_end)
|
||||
|
@ -1888,7 +1899,8 @@ init386(paddr_t first_avail)
|
|||
|
||||
vps->avail_end -= atop(sz);
|
||||
vps->end -= atop(sz);
|
||||
msgbuf_paddr = ptoa(vps->avail_end);
|
||||
msgbuf_p_seg[msgbuf_p_cnt].sz = sz;
|
||||
msgbuf_p_seg[msgbuf_p_cnt++].paddr = ptoa(vps->avail_end);
|
||||
|
||||
/* Remove the last segment if it now has no pages. */
|
||||
if (vps->start == vps->end) {
|
||||
|
@ -1902,10 +1914,17 @@ init386(paddr_t first_avail)
|
|||
avail_end = vm_physmem[x].avail_end;
|
||||
avail_end = ptoa(avail_end);
|
||||
|
||||
if (sz != reqsz) {
|
||||
reqsz -= sz;
|
||||
if (msgbuf_p_cnt != VM_PHYSSEG_MAX) {
|
||||
/* if still segments available, get memory from next one ... */
|
||||
sz = reqsz;
|
||||
goto search_again;
|
||||
}
|
||||
/* Warn if the message buffer had to be shrunk. */
|
||||
if (sz != reqsz)
|
||||
printf("WARNING: %ld bytes not available for msgbuf "
|
||||
"in last cluster (%ld used)\n", reqsz, sz);
|
||||
"in last cluster (%ld used)\n", (long)MSGBUFSIZE, MSGBUFSIZE - reqsz);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: pmap.c,v 1.194 2006/11/16 01:32:38 christos Exp $ */
|
||||
/* $NetBSD: pmap.c,v 1.195 2007/01/06 15:29:02 pavel Exp $ */
|
||||
|
||||
/*
|
||||
*
|
||||
|
@ -60,7 +60,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.194 2006/11/16 01:32:38 christos Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.195 2007/01/06 15:29:02 pavel Exp $");
|
||||
|
||||
#include "opt_cputype.h"
|
||||
#include "opt_user_ldt.h"
|
||||
|
@ -446,9 +446,6 @@ int pmap_pdp_ctor(void *, void *, int);
|
|||
|
||||
caddr_t vmmap; /* XXX: used by mem.c... it should really uvm_map_reserve it */
|
||||
|
||||
extern vaddr_t msgbuf_vaddr;
|
||||
extern paddr_t msgbuf_paddr;
|
||||
|
||||
extern vaddr_t idt_vaddr; /* we allocate IDT early */
|
||||
extern paddr_t idt_paddr;
|
||||
|
||||
|
@ -983,9 +980,6 @@ pmap_bootstrap(kva_start)
|
|||
vmmap = (char *)virtual_avail; /* don't need pte */
|
||||
virtual_avail += PAGE_SIZE;
|
||||
|
||||
msgbuf_vaddr = virtual_avail; /* don't need pte */
|
||||
virtual_avail += round_page(MSGBUFSIZE);
|
||||
|
||||
idt_vaddr = virtual_avail; /* don't need pte */
|
||||
virtual_avail += PAGE_SIZE;
|
||||
idt_paddr = avail_start; /* steal a page */
|
||||
|
|
Loading…
Reference in New Issue