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 */