Subject: Re: port-i386/34186 mapping of msgbuf during startup may map invalid physical adresses
To: None <gnats-bugs@NetBSD.org>
From: Pavel Cahyna <pavel@NetBSD.org>
List: netbsd-bugs
Date: 12/15/2006 12:57:01
here is an updated patch that I would like to commit soon.
Index: machdep.c
===================================================================
RCS file: /cvsroot/src/sys/arch/i386/i386/machdep.c,v
retrieving revision 1.577
diff -u -p -r1.577 machdep.c
--- machdep.c 31 Jul 2006 20:59:07 -0000 1.577
+++ machdep.c 15 Dec 2006 10:51:42 -0000
@@ -240,7 +240,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;
@@ -396,25 +400,30 @@ native_loader(int bl_boothowto, int bl_b
void
cpu_startup()
{
- int x;
+ int x, y;
vaddr_t minaddr, maxaddr;
+ psize_t sz;
char pbuf[9];
/*
* 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);
+ 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);
@@ -1810,6 +1819,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)
@@ -1824,7 +1834,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) {
@@ -1838,10 +1849,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);
+ }
}
/*
Index: pmap.c
===================================================================
RCS file: /cvsroot/src/sys/arch/i386/i386/pmap.c,v
retrieving revision 1.192
diff -u -p -r1.192 pmap.c
--- pmap.c 15 May 2006 12:47:42 -0000 1.192
+++ pmap.c 15 Dec 2006 10:52:15 -0000
@@ -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 */