Exceptions and Interrupts How does Linux handle service- the peripheral devices?

advertisement
Exceptions and Interrupts
How does Linux handle servicerequests from the cpu and from
the peripheral devices?
The ‘fetch-execute’ cycle
Normal programming assumes this ‘cycle’:
• 1) Fetch the next instruction from ram
• 2) Interpret the instruction just fetched
• 3) Execute this instruction as decoded
• 4) Advance the cpu instruction-pointer
• 5) Go back to step 1
But ‘departures’ may occur
• Circumstances may arise under which it
would be inappropriate for the cpu to
proceed with this fetch-execute cycle
• Examples:
• An ‘external device’ may ask for service
• An interpreted instruction may be ‘illegal’
• An instruction ‘trap’ may have been set
Faults
• If the cpu detects that an instruction it has
just decoded would be illegal to execute, it
cannot proceed with the fetch-execute cycle
• This type of situation is known as a ‘fault’
• It is detected BEFORE incrementing the IP
• The cpu will react by: 1) saving some info
on its stack, then 2) switching control to a
special fault-handling routine
Fault-Handling
•
•
•
•
•
•
•
The causes of ‘faults’ may often be fixed
A few examples:
1) Writing to a ‘read-only’ segment
2) Reading from a ‘not present’ segment
3) Executing an out-of-bounds instruction
4) Executing a ‘privileged’ instruction
If the problem can be remedied, the cpu
can resume executing from where it left off
Traps
• The cpu may have been programmed to
automatically switch control to a ‘debugger’
Program after it has executed an instruction
• This type of situation is known as a ‘trap’
• It is activated AFTER incrementing the IP
• It is accomplished by setting the TF flag
• Just as with faults, the cpu will react:
save return-info, and jump to trap-handler
Faults versus Traps
Both ‘faults’ and ‘traps’ occur at points within
a computer program which are ‘predictible’
(i.e., triggered by pre-planned instructions),
so they are ‘in sync’ with the program (and
thus are called ‘synchronous’ interruptions
in the normal fetch-execute cycle)
The cpu responds in a similar way to faults
and to traps – yet what gets saved differs!
Faults vs Traps (continued)
• With a ‘fault’:
the saved address is for the instruction
that was the cause of the fault – so that
instruction will get re-fetched after the
cause of the problem has been fixed
• With a ‘trap’:
the saved address is for the instruction
following the one which triggered the trap
Synchronous vs Asynchronous
• Devices which are ‘external’ to the cpu
may under go certain changes-of-state
that the system needs to take notice of
• These changes occur independently of
what the cpu is doing, and so cannot be
predicted from reading a program’s code
• They are ‘asynchronous’ to the program,
and are known as ‘interrupts’
Interrupt Handling
• As with faults and traps, the cpu responds
to interrupt-requests by saving some info
on the stack and then jumping to a special
‘interrupt-handler’ routine designed to take
appropriate action for the particular device
which caused the interrupt to occur
The ‘Interrupt Controller’
• Special hardware is responsible for telling
the cpu when an external device wants to
‘interrupt’ the current program
• This hardware is the ‘Interrupt Controller’
• It needs to let the cpu know which among
several devices is the one needing attention
• It also needs to prioritize multiple requests
Cascaded 8259 PICs
CPU
INTR
INTA
Master
PIC
IRQ0
IRQ1
IRQ2
IRQ3
IRQ4
IRQ5
IRQ6
IRQ7
Slave
PIC
PC Design (for single-processor systems)
IRQ8
IRQ9
IRQ10
IRQ11
IRQ12
IRQ13
IRQ14
IRQ15
Two Crucial Data Tables
• The Global Descriptor Table (GDT)
defines memory segments, and
enforces their access-privileges
(by using ‘segment descriptors’)
• The Interrupt Descriptor Table (IDT)
defines entry-points for the code-routines
which handle ‘interrupts’ and ‘exceptions’
How does CPU find GDT/IDT?
• Two dedicated registers: GDTR and IDTR
• Both have identical 48-bit format:
Segment Base Address
47
Segment Limit
16 15
0
Kernel must setup these registers during system startup (set-and-forget)
Privileged instructions: LGDT and LIDT used to set these register-values
Unprivileged instructions: SGDT and SIDT used for reading register-values
Segment-Descriptor Format
63
56
39
Limit
[19..16]
Base[31…24]
Access
attributes
Base[ 15 … 0 ]
31
32
Base[23…16]
Limit[ 15 ... 0 ]
16 15
Quadword (64-bits)
0
Gate-Descriptor Format
63
32
Entrypoint Offset[ 31…16 ]
Code-segment Selector
Gate type
code
(Reserved)
Entrypoint Offset[ 15…0 ]
0
31
Quadword (64-bits)
Intel-Reserved ID-Numbers
• Of the 256 possible interrupt ID-numbers,
Intel reserves the first 32 for ‘exceptions’
• Operating systems such as Linux are free
to use the remaing 224 available interrupt
ID-numbers for their own purposes (e.g.,
for service-requests from external devices,
or for other purposes such as system-calls
Some Intel-defined exceptions
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
0: divide-overflow fault
1: debug traps and faults
2: non-maskable interrupts
3: debug breakpoint trap
4: INTO detected overflow
5: BOUND range exceeded
6: Undefined Opcode
7: Coprocessor Not Available
8: Double-Fault
9: (reserved)
10: Invalid Task-State Segment
11: Segment-Not-Present fault
12: Stack fault
13: General Protection Exception
14: Page-Fault Exception
15: (reserved)
Error-Codes
• A few of the Intel-defined exceptions also
push a diagnostic ‘error-code’ onto the cpu
stack (in addition to pushing the EFLAGS,
CS and EIP register-values); the ‘handler’
must discard that error-code before it can
execute the ‘iret’ instruction to resume the
program that got interrupted (Exceptions
8 and 10 through 14 generate error-codes)
Using our ‘physmem’ driver
We can look at the kernel’s GDT/IDT tables
1) We can find them (using ‘sgdt’ and ‘sidt’)
2) We can ‘read’ them by using ‘physmem’
Demo program on course website:
showidt.cpp
It prints out the 256 IDT Gate-Descriptors
In-Class Exercise
• Write a similar program (showgdt.cpp)
• Two ‘big’ issues:
size of GDT isn’t known in advance
(whereas the IDT is of a known size)
labeling for GDT entries is by offset
(whereas the IDT entries use index)
• There could be some ‘other’ issues as well
Some Questions
• How many “non-null” descriptors in GDT?
(There’s always at least one that’s “null”)
• What kinds of descriptors does Linux use?
Sizes? Access-rights? Code/Data? TSS?
Download