# Interrupts & Exceptions

Required reading: xv6 `trapasm.S`, `trap.c`, `syscall.c`, `usys.S`.
You will need to consult IA32 System Programming Guide chapter 5 (skip 5.7.1, 5.8.2, 5.12.2).

## Overview

Big picture: kernel is trusted third-party that runs the machine. Only the kernel can execute privileged instructions (e.g., changing MMU state). The processor enforces this protection through the ring bits in the code segment. If a user application needs to carry out a privileged operation or other kernel-only service, it must ask the kernel nicely. How can a user program change to the kernel address space? How can the kernel transfer to a user address space? What happens when a device attached to the computer needs attention? These are the topics for today's lecture.

There are three kinds of events that must be handled by the kernel, not user programs: (1) a system call invoked by a user program, (2) an illegal instruction or other kind of bad processor state (memory fault, etc.). and (3) an interrupt from a hardware device.

Although these three events are different, they all use the same mechanism to transfer control to the kernel. This mechanism consists of three steps that execute as one atomic unit. (a) change the processor to kernel mode; (b) save the old processor somewhere (usually the kernel stack); and (c) change the processor state to the values set up as the “official kernel entry values.” The exact implementation of this mechanism differs from processor to processor, but the idea is the same.

We'll work through examples of these today in lecture. You'll see all three in great detail in the labs as well.

A note on terminology: sometimes we'll use interrupt (or trap) to mean both interrupts and exceptions.

## Setting up traps on the x86

See handout Table 5-1, Figure 5-1, Figure 5-2.

xv6 Sheet 07: `struct gatedesc` and `SETGATE`.

xv6 Sheet 28: `tvinit` and `idtinit`. Note setting of gate for `T_SYSCALL`

xv6 Sheet 29: `vectors.pl` (also see generated `vectors.S`).

## System calls

xv6 Sheet 16: `init.c` calls `open("console")`. How is that implemented?

xv6 `usys.S` (not in book). (No saving of registers. Why?)

Breakpoint `0x1b:"open"`, step past `int` instruction into kernel.

See handout Figure 9-4 [sic].

xv6 Sheet 28: in `vectors.S` briefly, then in `alltraps`. Step through to `call trap`, examine registers and stack. How will the kernel find the argument to `open`?

xv6 Sheet 29: `trap`, on to `syscall`.

xv6 Sheet 31: `syscall` looks at `eax`, calls `sys_open`.

(Briefly) xv6 Sheet 52: `sys_open` uses `argstr` and `argint` to get its arguments. How do they work?

xv6 Sheet 30: `fetchint`, `fetcharg`, `argint`, `argptr`, `argstr`.

What happens if a user program divides by zero or accesses unmapped memory? Exception. Same path as system call until `trap`.

What happens if kernel divides by zero or accesses unmapped memory?

## Interrupts

Like system calls, except: devices generate them at any time, there are no arguments in CPU registers, nothing to return to, usually can't ignore them.

How do they get generated? Device essentially phones up the interrupt controller and asks to talk to the CPU. Interrupt controller then buzzes the CPU and tells it, “keyboard on line 1.” Interrupt controller is essentially the CPU's secretary administrative assistant, managing the phone lines on the CPU's behalf.

Have to set up interrupt controller.

(Briefly) xv6 Sheet 63: `pic_init` sets up the interrupt controller, `irq_enable` tells the interrupt controller to let the given interrupt through.

(Briefly) xv6 Sheet 68: `pit8253_init` sets up the clock chip, telling it to interrupt on `IRQ_TIMER` 100 times/second. `console_init` sets up the keyboard, enabling `IRQ_KBD`.

In Bochs, set breakpoint at 0x8:"vector0" and continue, loading kernel. Step through clock interrupt, look at stack, registers.

Was the processor executing in kernel or user mode at the time of the clock interrupt? Why? (Have any user-space instructions executed at all?)

Can the kernel get an interrupt at any time? Why or why not? `cli` and `sti`, `irq_enable`.