Subject: kern/6152: UVM breaks gdb breakpoints on m680[46]0 and potentially mips
To: None <gnats-bugs@gnats.netbsd.org>
From: None <mhitch@montana.edu>
List: netbsd-bugs
Date: 09/13/1998 11:11:43
>Number:         6152
>Category:       kern
>Synopsis:       UVM breaks gdb breakpoints on m680[46]0 and potentially mips
>Confidential:   no
>Severity:       critical
>Priority:       high
>Responsible:    kern-bug-people (Kernel Bug People)
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Sun Sep 13 10:20:00 1998
>Last-Modified:
>Originator:     Michael L. Hitch
>Organization:
	Montana State University - Bozeman
>Release:        September 5, 1998 -current
>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.
>Audit-Trail:
>Unformatted: