NetBSD Problem Report #6152

Received: (qmail 3027 invoked from network); 13 Sep 1998 17:15:05 -0000
Message-Id: <199809131711.LAA00255@amiga.msu.montana.edu>
Date: Sun, 13 Sep 1998 11:11:43 -0600 (MDT)
From: mhitch@montana.edu
Reply-To: mhitch@montana.edu
To: gnats-bugs@gnats.netbsd.org
Subject: UVM breaks gdb breakpoints on m680[46]0 and potentially mips
X-Send-Pr-Version: 3.95

>Number:         6152
>Category:       port-sun3
>Synopsis:       UVM breaks gdb breakpoints on m680[46]0 and potentially mips
>Confidential:   no
>Severity:       critical
>Priority:       high
>Responsible:    port-sun3-maintainer
>State:          closed
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Sun Sep 13 10:20:00 +0000 1998
>Closed-Date:    Sat Nov 30 20:04:24 +0000 2002
>Last-Modified:  Sat Nov 30 20:04:24 +0000 2002
>Originator:     Michael L. Hitch
>Release:        September 5, 1998 -current
>Organization:
	Montana State University - Bozeman
>Environment:
	68040 or 68060 with UVM
System: NetBSD amiga.msu.montana.edu 1.3H NetBSD 1.3H (A4000) #980905-3: Mon Sep 7 21:20:11 MDT 1998 mhitch@:/work/tmp/src/sys/arch/amiga/compile/A4000 amiga


>Description:
Breakponts in gdb on a UVM 680[46]0 kernel no longer work.  The same
problem will occur on pmax [MIPS] UVM kernels, even with pmap.c modified
to work correctly with non-UVM kernels.

Breakpoints on m68k and mips architectures are done by replacing the
instruction at the breakpoint addresses with a breakpoint instruction.
Gdb appears to do this using ptrace(), which accomplishes the actual
modification through procfs_domem().  The Mach VM version of
procfs_domem() uses procfs_rwmem(), which changes the page protection on
text pages to read/write prior to writing the data to the process
address space.  The page protection is then changed back to read-only,
and the m68k pmap_protect() will invalidate the instruction cache on
that page, and push the data cache to memory. [The mips pmap.c currently
does not have any provision for this, and has random failures with
breakpoints on R3000 systems.  Adding the appropriate instruction cache
flushing on R3000 systems does allow breakpoints to work reliably - but
at a cost.]

With UVM, procfs_domem() modifies process text pages differently using
uvm_io(), which does not change the page protections.  Since pmap_protect()
is never called, the instruction cache is no longer coherent and will
most likely cause stale instruction execution.  On the m68040, the
breakpoint instruction is very likely only in the data cache and may not
even be written to memory when the instruction at that location is executed.
In that case, the original instruction is executed rather than the breakpoint,
and the breakpoint never occurs.  On the R3000, the breakpoint instruction
will be written to memory, but the instruction cache may still contain
the original instruction and the breakpoint will be missed.  Other times,
the instruction cache may be loaded with the breakpoint and the breakpoint
will occur, but when proceeding from that breakpoint, the original instruction
is replaced (in memory), but the breakpoint instruction is still in the
instruction cache and gets a "spurious" breakpoint.

>How-To-Repeat:
Build and run a UVM kernel, build a simple test program and try to run
it with gdb and set a breakpoint on "main".  The breakpoint will be ignored,
unless something else causes the data cache to be pushed to memory, and
the instruction cache is invalidated at the breakpoint address.

>Fix:
One possibility would be to have procfs_domem() explicitly call a new
pmap routine with the address and length of the operation, and that pmap
routine would handle any cache-coherency operations required.  I have
such a work-around in my m68k and R3000 kernels, and they appear to work.
>Release-Note:
>Audit-Trail:

From: "Michael L. Hitch" <mhitch@msu.oscs.montana.edu>
To: gnats-bugs@gnats.netbsd.org
Cc: mhitch@msu.oscs.montana.edu
Subject: Re: kern/6152: UVM breaks gdb breakpoints on m680[46]0 and potentially
         mips
Date: Sat, 6 Feb 1999 14:07:42 -0700

 This is my rather crude work-around I have working in my amiga and pmax
 kernels.  The amiga makes no attempt to deal with segments that span
 more than one cache line;  all I needed was to get gdb breakpoints working.

 Michael

 diff -cr /usr/src/sys/miscfs/procfs/procfs_mem.c sys/miscfs/procfs/procfs_mem.c
 *** /usr/src/sys/miscfs/procfs/procfs_mem.c	Thu Aug 13 05:11:48 1998
 --- sys/miscfs/procfs/procfs_mem.c	Sat Jan 23 13:16:21 1999
 ***************
 *** 221,226 ****
 --- 221,228 ----
   	struct uio *uio;
   {
   	int error;
 + /*XXX*/ int len = uio->uio_resid;
 + /*XXX*/ vm_offset_t addr = uio->uio_offset;

   	if (uio->uio_resid == 0)
   		return (0);
 ***************
 *** 242,247 ****
 --- 244,253 ----
   	error = procfs_rwmem(p, uio);
   	PRELE(p);
   #endif
 + /*XXX*/	if (uio->uio_rw == UIO_WRITE)
 + /*XXX*/		pmap_procwr(p->p_vmspace->vm_map.pmap, addr,
 + /*XXX*/		    len);
 + /*XXX*/ if (error) printf("procfs_domem: error %d\n", error);
   	return (error);
   }

 diff -cr /usr/src/sys/arch/amiga/amiga/pmap.c sys/arch/amiga/amiga/pmap.c
 *** /usr/src/sys/arch/amiga/amiga/pmap.c	Sun Jan 17 05:12:06 1999
 --- sys/arch/amiga/amiga/pmap.c	Sat Jan 23 13:16:08 1999
 ***************
 *** 1419,1424 ****
 --- 1431,1454 ----
   			TBIS(va);
   		pte++;
   	}
 + }
 + 
 + void
 + pmap_procwr(pmap, va, len)
 + 	pmap_t		pmap;
 + 	vm_offset_t	va;
 + 	u_long		len;
 + {
 + #if defined(M68040) || defined(M68060)
 + #if 0
 + 	printf("pmap_procwr: va %lx len %lx\n", va, len);
 + #endif
 + 	if (mmutype == MMU_68040) {
 + 		vm_offset_t pa = pmap_extract(pmap, va);
 + 		DCFL(pa);		/* XXX len? */
 + 		ICPL(pa);		/* XXX len? */
 + 	}
 + #endif
   }

   /*
 diff -cr /usr/src/sys/arch/amiga/include/pmap.h sys/arch/amiga/include/pmap.h
 *** /usr/src/sys/arch/amiga/include/pmap.h	Mon Mar 23 05:12:32 1998
 --- sys/arch/amiga/include/pmap.h	Sat Jan 23 13:16:18 1999
 ***************
 *** 137,142 ****
 --- 137,143 ----
   #define	pmap_wired_count(pmap)		((pmap)->pm_stats.wired_count)

   vm_offset_t	pmap_map __P((vm_offset_t, vm_offset_t, vm_offset_t, int));
 + void	pmap_procwr __P((pmap_t, vm_offset_t, u_long));

   #endif	/* _KERNEL */

 diff -cr /c/src/sys/arch/mips/include/pmap.h sys/arch/mips/include/pmap.h
 *** /c/src/sys/arch/mips/include/pmap.h	Fri Jan 15 05:09:59 1999
 --- sys/arch/mips/include/pmap.h	Sun Jan 17 15:40:00 1999
 ***************
 *** 122,127 ****
 --- 122,129 ----
   void	pmap_bootstrap __P((void));

   void	pmap_set_modified __P((paddr_t));
 + 
 + void	pmap_procwr __P((pmap_t, vaddr_t, u_long));

   /*
    * pmap_prefer()  helps reduce virtual-coherency exceptions in

 diff -cr /c/src/sys/arch/mips/mips/pmap.c sys/arch/mips/mips/pmap.c
 *** /c/src/sys/arch/mips/mips/pmap.c	Sat Jan 16 05:20:32 1999
 --- sys/arch/mips/mips/pmap.c	Sun Jan 17 15:36:23 1999
 ***************
 *** 1013,1018 ****
 --- 1129,1172 ----
   	}
   }

 + void
 + pmap_procwr(pmap, va, len)
 + 	pmap_t		pmap;
 + 	vm_offset_t	va;
 + 	u_long		len;
 + {
 + 	if (CPUISMIPS3) {
 + #if 0
 + 		printf("pmap_procwr: va %lx len %lx\n", va, len);
 + #endif
 + 		mips3_FlushDCache(va, len);
 + 		mips3_FlushICache(MIPS_PHYS_TO_KSEG0(va &
 + 		    (mips_L1ICacheSize - 1)), len);
 + 	} else {
 + 		pt_entry_t *pte;
 + 		unsigned entry;
 + 
 + #if 0
 + printf("pmap_procwr: va %lx", va);
 + #endif
 + 		if (!(pte = pmap_segmap(pmap, va)))
 + 			return;
 + 		pte += (va >> PGSHIFT) & (NPTEPG - 1);
 + 		entry = pte->pt_entry;
 + 		if (!mips_pg_v(entry))
 + 			return;
 + #if 0
 + printf(" flush %lx", pfn_to_vad(entry) + (va & PGOFSET));
 + #endif
 + 		mips1_FlushICache(MIPS_PHYS_TO_KSEG0(mips1_pfn_to_vad(entry)
 + 		    + (va & PGOFSET)),
 + 		    len);
 + #if 0
 + printf("\n");
 + #endif
 + 	}
 + }
 + 
   /*
    *	Return RO protection of page.
    */


 ---
 Michael L. Hitch                        mhitch@montana.edu
 Computer Consultant,  Information Technology Center
 Montana State University, Bozeman, MT     USA
State-Changed-From-To: open->analyzed 
State-Changed-By: is 
State-Changed-When: Thu Feb 25 12:41:58 PST 1999 
State-Changed-Why:  
* Other affected architecutres (should) be ARM32 and PPC. 
* Yes, I think this is the right handling of this problem. 
Actually, we migth want to only sync if it was a PT_WRITE_I operation, and 
fix gdb to create PT_WRITE_I instead of PT_WRITE_D (while it creates PT_READ_I!) 
However, procfs needs also to be fixed. Procfs does not know about instruction vs. 
vs. data space, but has the notion of running-state vs. debugging-sate  
processes. We would sync on trasnsition to running. For this, we'd need to 
remember wether we wrote (and syc all the processes address space)or remember  
a list of addresses written to and not yet synced. Both seem expensive.  
Syncing each time is easier to implement. 


Responsible-Changed-From-To: kern-bug-people->is 
Responsible-Changed-By: is 
Responsible-Changed-When: Thu Feb 25 12:41:58 PST 1999 
Responsible-Changed-Why:  
I'm working on this. 

Comment added on: Sat Feb 27 12:11:03 PST 1999
MI part done as proposed, but passing struct proc * instead of a pmap pointer.
MIPS done as proposed (same interface change of course).
PPC done by Tsubai.
ARM32 will be done by Mark, but not necessary for gdb, only for procfs.
PC532 might be affected, too.

State-Changed-From-To: analyzed->closed 
State-Changed-By: is 
State-Changed-When: Wed May 19 02:26:32 PDT 1999 
State-Changed-Why:  
This has been fixed, and is ina a main release now. 
State-Changed-From-To: closed->analyzed 
State-Changed-By: is 
State-Changed-When: Mon May 24 07:40:49 PDT 1999 
State-Changed-Why:  
Browsing through my old mail, I found that gwr thinks this code still has 
problems on a VAC sun3. 


Responsible-Changed-From-To: is->port-sun3-maintainer 
Responsible-Changed-By: is 
Responsible-Changed-When: Mon May 24 07:40:49 PDT 1999 
Responsible-Changed-Why:  
The sun3 port maintainer needs to finish this. 
State-Changed-From-To: analyzed->closed 
State-Changed-By: chs 
State-Changed-When: Sat Nov 30 12:03:08 PST 2002 
State-Changed-Why:  
the sun3 cache is unified, so no flushing is needed. 
>Unformatted:

NetBSD Home
NetBSD PR Database Search

(Contact us) $NetBSD: query-full-pr,v 1.39 2013/11/01 18:47:49 spz Exp $
$NetBSD: gnats_config.sh,v 1.8 2006/05/07 09:23:38 tsutsui Exp $
Copyright © 1994-2007 The NetBSD Foundation, Inc. ALL RIGHTS RESERVED.