Subject: Re: port-i386/34186 mapping of msgbuf during startup may map invalid physical adresses
To: None <port-i386-maintainer@netbsd.org, gnats-admin@netbsd.org,>
From: Pavel Cahyna <pavel@NetBSD.org>
List: netbsd-bugs
Date: 12/15/2006 12:00:04
The following reply was made to PR port-i386/34186; it has been noted by GNATS.

From: Pavel Cahyna <pavel@NetBSD.org>
To: gnats-bugs@NetBSD.org
Cc: netbsd-bugs@NetBSD.org
Subject: Re: port-i386/34186 mapping of msgbuf during startup may map invalid physical adresses
Date: Fri, 15 Dec 2006 12:57:01 +0100

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