Title: What Linux does with IDE
1What Linux does with IDE?
- Introduction to Pentium features for trapping
reads/writes to memory-locations and i/o-ports
2Breakpoint Address Registers
DR0
DR1
DR2
DR3
3Special MOV instructions
- Use mov DRn, genreg to write into DRn
- Use mov genreg, DRn to read from DRn
- These instructions are privileged (i.e., can
only be executed by code running in ring0)
4Debug Control Register (DR7)
15
0
0
0
G D
0
0
1
G E
L E
G 3
L 3
G 2
L 2
G 1
L 1
G 0
L 0
Least significant word
31
16
LEN 3
R/W 3
LEN 2
R/W 2
LEN 1
R/W 1
LEN 0
R/W 0
Most significant word
5What kinds of breakpoints?
LEN
R/W
LEN 00 one byte 01 two bytes 10
undefined 11 four bytes
R/W 00 break on instruction fetch only 01
break on data writes only 10 break on in/out
to port-address 11 break on data reads or
writes (but not on instruction fetches)
Provided the DE-bit (bit 3) is set to 1 in
Control Register CR4
6Control Register 4
- The Pentium uses Control Register 4 to activate
certain extended features of the processor, while
still allowing for backward compatibility with
systems software that was written for earlier x86
processors - An example Debug Extensions (DE-bit)
31
3
0
other feature bits
D E
CR4
7Debug Status Register (DR6)
15
0
B D
0
1
1
1
1
1
1
1
B 3
B 2
B 1
B S
B T
1
B 0
Least significant word
31
16
unused ( all bits here are set to 1 )
Most significant word
8Where to set a breakpoint
- Suppose you want to trigger a debug fault
whenever Linux tries to write/read the IDE
Command/Status Register (ioport 0x1F7) - Your debug exception-handler can use the saved
CSEIP values on its stack to check whether an
out or in was just executed - Machine-code 0xEC for in dx, al , or
0xEE for out al, dx - Could set a breakpoint at address EIP-1
9Detecting a breakpoint
- Your debug exception-handler reads DR6 to check
for occurrences of breakpoints - mov eax, DR6 get debug status
- bt eax, 0 breakpoint 0?
- jnc notBP0 no, another cause
- test for other causes
- notBP0
10The asm construct
- An introduction to the GNU C/C compilers
obscure syntax for doing inline assembly language
11The asm construct
- When using C/C for systems programs, we
sometimes need to employ processor-specific
instructions (e.g., to access CPU registers or
the current stack area) - Because our high-level languages strive for
portability across different hardware
platforms, these languages dont provide direct
access to CPU registers or stack
12gcc/g extensions
- The GNU compilers support an extension to the
language which allows us to insert assembler code
into our instruction-stream - Operands in registers or global variables can
directly appear in assembly language, like this
(as can immediate operands) - int count 4 // global variable
- asm( movl count , eax )
- asm( imull 5, eax, ecx )
13Local variables
- Variables defined as local to a function are more
awkward to reference by name with the asm
construct, because they reside on the stack and
require the generation of offsets from the ebp
register-contents - A special syntax is available for handling such
situations in a manner that gcc/g can decipher
14Template
- The general construct-format is as follows
- asm( instruction-template
- output-operand
- input-operand
- clobber-list )
15Example from hdtraps.c
- void trap_handler( unsigned long tos )
-
- unsigned long db_status
- // other instructions can go here
- asm( movl dr6, eax )
- asm( movl eax, 0 m (db_status) )
- // other instructions can go here
-
16In-class exercise
- Modify the hdtraps.c module so that the output
from /proc/hdtraps is improved (i.e., more
understandable to humans) - Instead of eax00530150 opnEC show 0x50
inb( 0x01F7 ) - Instead of eax007402EA opnEE show outb(
0xEA, 0x01F7 )