L13 [Interrupts, Traps, and Exceptions] - Skyline-9/CS2110-Notes GitHub Wiki
L13 [Interrupts, Traps, and Exceptions]
Operating System Machine Layer
Operating Systems are about sharing resources and protecting users from themselves and others
- Certain oeprations require specialized knowledge and protection
- Specific knowledge of I/O device registeres and the sequence of the operations needed to use them
- I/O and memory resources shared among multiple users/programs; a mistake could affect lots of other users/processes!
Not every programmers knows (or wants to know) this level of detail, so we abstract them in an Operating System Machine Layer
We provide service routines or system calls (as part fo operating system) to safely and conveniently perform low-level, privileged operations
What are Program Discontinuities
- Interrupts
An I/O device is reporting a completion or an error
- TRAPs
The program is calling a privilged operating system subroutine (e.g. Read a line from a file)
- Exceptions
Something unaticipated has happened
- Hardware error in the CPU or memory
- Program error (e.g. illegal opcode, divide by zero)
We handle all of these in similar ways
- Save the state of the CPU
- Raise the CPu privilege level
- Call an operating system routine
- Restore the state of the CPU and the privilege level
- Resume the executing program where it left off
Properties
- Synchronous with the program (TRAPs and some exceptions) or asynchronous (interrupts and other exceptions)
- Anticipated by the programmer (TRAPs) or unanticipated (interrupts and exceptions)
What are interrupts?
Modifications to the hardware of the datapath and I/O system and additional software to allow an external device to cause the CPU to stop current execution and execute a "service" routine and then resume execution of the original program. Hence, an interrupt.
Interrupts are significantly more efficient than polling and very useful when there may be concurrency issues.
An interrupt is an unscripted subroutine call triggered by an external event
Device Status Register
When a device goes "ready" and its IE bit is set, it will generate an interrupt signal.
Priority encoder outputs the highest priority with an interrupt signal
- If priority > priority in PL register, comparator asserts the INT signal to the microsequencer
- New priority is stored in PL
- The interrupting device ID is stored in the INTV register (circuit not shown)
Detecting Inputs
When the I/O device is allowed to signal an interrupt, the INT control signal to the microcode FSM is asserted.
- The first state in the FETCH cycle tests to see if INT is asserted
- If it is, microcode transfers to state 49 and sets up a call to the interrupt service routine
Where to save processor state?
Restrictions: can't use general purpose registers (programmer can't prepare by saving critical registers) and can't use memory allocated by service routine (must save state before invoking routine, so the hardware wouldn't know where; interrupts can also get nested)
Use the existing supervisor stack!
- Top fo the stack is already known in R6
- Push state to save, pop to restore
Supervisor Stack for Completeness
- INT are handled on the supervisor-mode stack to protect them from user mode programs
- R6 points to the supervisor mode stack when the PSR is set to Supervisor mode (bit 15) and to the user-mode stack when it's not
- When swapping between modes
- Supervisor Stack Pointer (SSP) is saved in Saved.SSP
- User Stack Pointer (USP) is saved in Saved.USP
- Interrupt in user mode will switch to Supervisor mode, save R6 to Saved.USP, and load R6 from Saved.SSP
What is the Processor State?
- Processor Status Register
Privilege [15], Priority Level [10:8], Condition Codes [2:0]
This register doesn't really exist, but the hardware pushes the values on teh stack using the following format
- Program Counter
- General Purpose Registers
Privilege (P) has only two values 0 and 1 but a lot of synonyms
- 1 is user mode or unprivileged mode
- 0 is system, supervisor, kernel, or privileged mode
Handling Interrupt
- Set Table to x01, Vector to INTV (i.e., interrupting device ID)
- If PSR[15] == 1 (user state), Saved.USP = R6, R6 = Saved.SSP.
- Push PSR and PC-1 to Supervisor Stack.
- Set PSR[15] = 0 (supervisor mode).
- Set PSR[10:8] = priority of interrupt being serviced.
- Set MAR = Table’Vector, where Vector = 8-bit interrupt vector provided by interrupting device (e.g., keyboard = x80).
- Load memory location (M[Table’Vector]) into MDR.
- Set PC = MDR; now first instruction of ISR will be fetched next.
- Go back to the first state of FETCH (state 18)
Returning from Interrupt
Special instruction RTI restores state
- Pop RC from supervisor stack (
PC = M[R6]; R6 = R6 + 1
) - Pop PSR from supervisor stack (
PSR = M[R6]; R6 = R6 + 1
) - If PSR[15] = 1, Saved.SSP = R6, R6 = Saved.USP
RTI is a privileged instruction and can only be executed in Supervisor Mode. If executed in User Mode, it throws an exception.
Operating Systems
How are we going to ask the OS to do things for us? We could do a subroutine call, but we don't know where the procedure will be stored in memory.
Thus, we use a special instruction TRAP
TRAP
- Uses trap vector table
- Can call from anywhere
- TV table is loaded by OS
- Normally calls system functions
- I/O, resource sharing, etc.
- Written very carefully!
- If in user state, switch to supervisor state to allow privileged action
LC-3 TRAP Mechanism
- Set of service routines
Service routines start at arbitrary addresses within the OS (convention is that system code lives between x0200 and x3000)
Supports up to 256 service routines
- Using a table of starting addresses
- Stored at
x0000
throughx00FF
in memory - Called System Control Block in some architectures
- Initialized by OS
- TRAP instruction
- Used by program to transfer control to OS routine
8-bit
trap vector names one of the256
service routines- Saves PSR and PC on via the R6 stack and gains privilege just like INT
TRAP Vector
- Identifies address of the system call to invoke
8-bit
index into the Trap Vector Table- Zero-extended into 16-bit memory address
Think of TRAP as a special indirect JSR with a choice of memory location from 0
through 255
(i.e. let’s call that trapvect).
Common LC-3 Trap Numbers
Vector | Routine |
---|---|
x23 | IN - prompt and read a chracter from the keyboard |
x21 | OUT - output a character to the monitor (R0) |
x25 | HALT - halt the program |
x20 | GETC - read a character from keyboard (R0) |
x22 | PUTS - output a string, 1 char per word ending with x0000, address in R0 |
2x24 | PUTSP - Output a string, 2 characters per word ending with a word of x0000, address in R0 |
Exceptions
- Synchronous exceptions in the LC-3
- Divide by zero (no divide in LC-3)
- Illegal instruction (opcode=D)
- Privileged instruction (RTI in user mode)
- Address Violation (ACV)
- Asynchronous exceptions (not implemented on LC-3)
- Processor error
- Memory error