A Dynamic Visualization of Core-2 Duo Interrupts Allan B. Cruse

advertisement
A Dynamic Visualization of
Core-2 Duo Interrupts
Allan B. Cruse
University of San Francisco
17 September 2009
Organization of this Talk
• This talk is about “using the computer to study the computer”
Its General Thesis
Its Specific Application
Dynamic Visualization
Core-2 Duo Interrupts
• The focus here will be on using a recent version of the Linux
operating system on your personal computer, where you can
use “free” utilities -- and can exercise a few “root” privileges
‘Dynamic Visualization’
• This refers to a type of computer program
which can show us some volatile aspects
of a machine’s inner workings in real time
• Without the ability to “see” these activities
we are left simply to try and imagine what
they are like -- never quite feeling certain
• Such visualizations often reveal aspects
which our textbooks forgot to mention!
UNIX’s ‘top’ utility
This program lets a user see some volatile information from inside the kernel;
however, it’s not really being displayed in real time since it only gets updated
about once every 3 seconds – still it does help us to understand ‘timesharing’.
The software ‘architecture’
kernel space
user space
(unrestricted privileges)
(restricted privileges)
shared function
libraries
(e.g., ‘printf()’)
Linux
operating system
syscall
ret
sysret
in
out
call
application program
(e.g., ‘top’)
hardware devices
The software ‘architecture’
kernel space
user space
(unrestricted privileges)
(restricted privileges)
shared function
libraries
(e.g., ‘printf()’)
Linux
operating system
syscall
ret
sysret
LKM
in
out
call
application program
(e.g., ‘top’)
hardware devices
LKM = Linux Kernel Module
Formatting screen-output
• The Linux operating system is written in C
-- plus some “inline” assembly language,
and a large portion of the shared libraries
and standard system utilities are in C/C++
• Using functions like ‘printf()’ you can very
quickly write C/C++ code that will output
data values in a humanly-readable form
• There’s similar kernel-function: ‘printk()’
The ‘teletype’ model
• But the usual way C/C++ programs output
text to consoles (or to desktop windows) is
unsuitable for doing dynamic visualizations
• It’s based on a software emulation of early
teletype terminals, where a new character
gets added at the end of earlier text, until
the screen fills and is then scrolled upward
• A cursor blinks where the next text will go
Non-canonical I/O
• Our ‘dynamic’ visualizations will require us
to employ ‘full-screen’ terminal-output and
‘un-buffered’ terminal-input, with no ‘echo’
of keystrokes, and with no flashing cursor
or upward-scrolling screen
Hello, world
_
ANSI ‘escape’ codes
• There are standard control-codes we can
use in ‘printf()’ statements to achieve our
‘draw anywhere’ and ‘hide cursor’ goals:
printf( “\e[H\e[J” );
printf( “\e[?25l” );
// erase the entire display
// make the cursor disappear
// draw a textstring at the center of the 80-by-25 screen
int
row = 12, column = 40;
printf( “\e[%d;%dH%s”, row, column, “Hello” );
fflush( stdout );
// flush the output buffer
‘struct termios’
• We can use the ‘tcgetattr()’ and ‘tcsetattr()’
library functions to install changes to the
data that controls our terminal’s behavior
user space
kernel space
tcgetattr()
struct termios
tcsetattr()
struct termios
struct termios
Our ‘visualization’ application
• It consists of two ‘pieces’ of code:
– a user-program, written in C++
– a kernel-module, written in C
// activity.cpp
#include <stdio.h>
#include <termios.h>
int main( void )
{
// activity.c
#include <linux/module.h>
#include <linux/proc_fs.h>
#include <asm/uaccess.h>
int init_module( void )
{
}
}
void cleanup_module( void )
{
}
compiled using g++
compiled using mmake
What are ‘interrupts’?
• Normally a CPU inside our computer is
fetching and executing our sequence of
program-instructions from a contiguous
region of the system’s main memory
• But occasionally some peripheral device
undergoes a change in its state, and our
system needs to take note of it promptly
• An ‘interrupt’ is the signaling of that event
to the CPU so it’s dealt with appropriately
System-component overview
Core-2 Duo
CPU 0
Graphics
CPU 1
MCH
USB Hub
Ethernet
Real-Time Clock
Audio
Camera
Printer
MCH = Memory Controller Hub
DRAM
Disk Drives
ICH
CD/DVD
Keyboard
Mouse
ICH = I/O Controller Hub
Some examples
• The system needs to take note promptly when:
–
–
–
–
–
–
–
your keyboard has a key that’s been pressed
your mouse has been moved, or ‘clicked’
your network controller has received a packet
your internal clock’s time has been advanced
your disk controller has finished saving a file
your printer’s running low on paper or toner
your application’s ‘time-slice’ has expired
• Each of these needs a different CPU response
Interrupt ‘handlers’
• Your operating system includes all of the
code-fragments for responding to any of
the events that could ‘interrupt’ the CPU
• They’re called ‘Interrupt Service Routines’,
and the addresses of their entry-points are
stored within an array, known as the IDT,
whose location and size are held in a CPU
register that’s dedicated to that purpose
ISRs, IDT and the IDTR
Main Memory
Central
Processing
Unit
isr_kbd: ... iret
isr_prn: ... iret
isr_rtc: ... iret
EFLAGS
Interrupt Service Routines
(aka ‘interrupt handlers’)
isr_dvd: ... iret
...
EIP
ESP
EBP
EAX
EBX
Interrupt Descriptor Table
...
IDTR
‘Gate’ descriptors
• The Interrupt Descriptor Table (IDT) has
room for up to 256 entries (called ‘gates’):
32-bits
offset[31..16]
code-segment selector
type and
access
attributes
reserved
(=0)
bytes 7,6,5,4
offset[15..0]
bytes 3,2,1,0
The peculiar arrangement of this information, in which the 32-bit offset’s value
is split into a pair of non-adjacent 16-bit fields, is due to the history of Intel’s
earlier processor-architecture and its commitment to ‘backward compatibility’
Some questions…
• A typical PC doesn’t have 256 peripherals
attached to it! So, is the IDT-array larger
than is really necessary?
• The interruption-requests coming from the
various devices will be occurring at times
that application-programs cannot predict!
So how often will this be happening, and
how likely is it to ‘degrade’ performance?
Let’s take a look
• Our ‘dynamic visualization’ will let us view
all the various interrupt occurrences -- as
they are happening (i.e., in ‘real time’)
This is a static screenshot of our interrupt activity ‘visualization’
Our source-code (6 pages)
activity.c
activity.cpp
Our SMP version
The ‘enhanced’ version of our visualization shows separate interrupt-counters
for each of the two ‘logical’ processors inside our Core-2 Duo Linux platform
APIC components
Core-2 Duo
Graphics
CPU 0
CPU 1
Local-APIC
Local-APIC
MCH
USB Hub
Real-Time Clock
Printer
DRAM
Ethernet
ICH
Audio
Camera
Each CPU contains its
own Local-APIC with a
‘processor-ID’ register
Disk Drives
CD/DVD
I/O-APIC
Keyboard
Mouse
The I/O Controller Hub contains the so-called I/O-APIC whose registers
control routing of Interrupt Request signals (IRQs) to specific interrupts
(INTs) on one or more of the logical CPUs that are present in a system
Linux’s interrupt assignments
The kernel developers frequently make changes to their interrupt routing
for uniprocessor versus multiprocessor platforms, or 32-bit versus 64-bit
0
0x00
0x10
0x20
0x30
0x40
0x50
0x60
0x70
0x80
0x90
0xA0
0xB0
0xC0
0xD0
0xE0
0xF0
1
2
3
4
5
6
7
8
9
A
B
C
D
E
F
Reserved by Intel
Not in use with SMP
Legacy PIC interrupts
Assigned for use by
IO-APIC interrupts
or ‘Message-Signaled’
interrupts (or unused)
Local-APIC interrupts
…but usage is usually documented in Linux’s <asm/irq_vectors.h> kernel header
Writing LKM code
• The first two chapters of this O’Reilly book
teaches how to write Linux kernel modules
• You can use kernel ‘helper’ functions -–
–
–
–
to allocate kernel memory: kmalloc()
to create ‘pseudo’ files: create_proc_entry()
to execute code on another CPU: smp_call_function()
to insert “inline” assembly language statements: asm()
Our module’s organization
*oldidt
Our module’s ‘global’ data
*newidt
...
n_interrupts[ 256 ]
original_isr[ 256 ]
several module helper-functions…
my_open()
Our module’s ‘payload’
of file-operation methods
my_read()
my_write()
The pseudo-file’s struct
of method-pointers
Our module’s two required
administrative functions
my_fops{ }
init_module()
cleanup_module()
includes 256
ISR “hooks”
written in
in assembly
language
We ‘hook’ every ISR
• We build a new Interrupt Descriptor Table
whose entries point to our own set of very
short interrupt-handler routines: each will
simply increment a counter, then transfer
control to the usual Linux interrupt-handler
• This is NOT a new idea! It’s been used in
PCs for at least thirty years, although only
one or two interrupts got ‘hooked’ typically
How ‘hooking’ works
Our substitute ISR will increment the count of its previous interrupts…
original IDT
n_interrupts[ … ]
original ISR
isr:
...
iret
substitute IDT
substitute ISR
isr:
...
ret
IDTR
…then the substitute ISR puts the address of the original ISR on top of its stack,
so that it can transfer control there merely by executing a ‘ret’ instruction
…so, use a ‘repeat-macro’ ☻
We really didn’t want
to type in the code
for over two-hundred
separate assembly
language routines…
.text
.type
.align
isr_entry:
n = 0
.rept
pushl
jmp
.align
n = n+1
.endr
ahead:
push
mov
push
push
isr_entry, @function
16
256
$n
ahead
16
%ebp
%esp, %ebp
%eax
%ebx
mov
incl
mov
mov
4(%ebp), %ebx
n_interrupts(, %ebx, 4)
original_isr(, %ebx, 4), %eax
%eax, 4(%ebp)
pop
pop
pop
ret
%ebx
%eax
%ebp
Compiling and Installing
• Compiling a kernel module for Linux 2.6.x
is inherently complicated, so we wrote a
utility (‘mmake.cpp’) that does it easily:
$ ./mmake activity.c
• To install the compiled ‘kernel object’ in a
running kernel is a step that normally will
require ‘root’ privileges:
# /sbin/insmod activity.ko
Some exercises to try
• Can you modify our LKMs (‘activity.c’ and
‘smpwatch.c’) to use with a 64-bit kernel?
• Can you see what changes will be needed
if you want a ‘dynamic visualization’ of all
the interrupts on a multiprocessor platform
with more than two CPUs? (Core-2 Quad)
• Can you imagine other kinds of ‘dynamic
visualizations’ that would be enlightening?
Website resources
• You can download the source-code for all
the demos discussed during this talk from
this website:
<http://cs.usfca.edu/~cruse>
• You can obtain the newest versions of the
Linux kernel source-code from this site:
<http://www.kernel.org>
Download