Skip to contentSkip to conversation

IA64 watchpoint traps not reported in system calls

Linux-ia64 Robert Faught 2 participants 2 messages Jan 16, 2003

lore
Share & tools
lore
#0 lore raw

A watchpoint set using an IA64 debug data register is ignored when the location is accessed by a system call such as read.

It would be very good to have the data watch triggered from inside the kernel reported to the user (or more likely the users debugger), since if youre trying to find out what is stomping one of your variables you expect setting a watchpoint on it to tell you, whether or not the stomping is happening as a result of passing bad arguments to a system call.

The test below shows the problem using the gdb debugger. It is not a gdb problem. Our debugger shows the same behavior.

- Rob Faught

This is a simple test case and a gdb session:
--------
/* Watchpoint test program. */

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

/**********************************************************************/ /* Reads zeroes into a buf. */

void read_zero_into (void *buf, int len)

{
    int fd = open ("/dev/zero", O_RDONLY);
    read (fd, buf, len);
    close (fd);
}

void nop ()
{
}

/**********************************************************************/ /* Globals reference tests. */

volatile int gi = -1; /* Ensure writes happen by tagging it volatile */

void globals_test()

{
    nop();
    gi = 26;
    nop();

    read_zero_into ((void *)&gi, sizeof(gi)); /* Hit the watchpoint from

the kernel */

    nop();
    gi = 41; 		/* Should stop */
    nop();
}

int main()

{
    globals_test();
    exit (0);
}

-------

[ourmachine:328] uname -a
Linux ourmachine 2.4.17-4hpmckinleysmp #1 SMP Mon May 6 15:26:29 MDT 2002 ia64 unknown

[ourmachine:329] gcc -g -o watch watch.c

[ourmachine:330] gdb watch
GNU gdb Red Hat Linux (5.1-1)
Copyright 2001 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details. This GDB was configured as "ia64-redhat-linux"...
(gdb) watch gi
Hardware watchpoint 1: gi
(gdb) run
Starting program: /nfs/fs/u3/home/rtf/watch
Hardware watchpoint 1: gi
Hardware watchpoint 1: gi
Hardware watchpoint 1: gi

Old value = -1
New value = 26
globals_test () at watch.c:31
31

    nop();

(gdb) list 26,39
26

27
void globals_test()
28
{
29

    nop();
30
    gi = 26;
31
    nop();

32

33
read_zero_into ((void *)&gi, sizeof(gi)); /* Hit the watchpoint from
the kernel */
34

35

    nop();
36
    gi = 41; 		/* Should stop */
37
    nop();

38
}
39

(gdb) cont
Continuing.
Hardware watchpoint 1: gi

Old value = 26
New value = 41
globals_test () at watch.c:37
37

    nop();

(gdb) q
The program is running. Exit anyway? (y or n) y
---------------------------------
Lines 30 and 36 cause traps but the read called from line 33 does not.

#1 lore raw
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line · Robert Faught

Robert> A watchpoint set using an IA64 debug data register is Robert> ignored when the location is accessed by a system call such Robert> as read.

Yes, that's the expected behavior: watch points are programmed to trigger only when running at the user-level (privilege level 3).

Robert> It would be very good to have the data watch triggered from Robert> inside the kernel reported to the user (or more likely the Robert> users debugger), since if youre trying to find out what is Robert> stomping one of your variables you expect setting a Robert> watchpoint on it to tell you, whether or not the stomping is Robert> happening as a result of passing bad arguments to a system Robert> call.

I see your point, but don't see any easy solution: I think it's way too dangerous to allow them to trigger at privilege level 0 (because of speculation and because of the risk of spurious matches when running with address translation disabled; it definitely would also require special handling for fsyscalls, because we currently rely on watchpoints not triggering at privilege level 0).

The cost of elevating the privilege level during user-memory accesses would be prohibitive.

We could use faulting "probe" instructions in the kernel as an alternative, but doing so would also slow down the user-access routines so much that it would be unacceptable (especially since _every_ byte would have to be "probe"d to make watchpoints work all the time).

Unless someone has another idea, I suspect this is a limitation we'll have to live with. It doesn't strike me as a huge issue: it's not unlike shared memory, which can change "underneath" you as well (without a watchpoint catching it, I mean).

	--david