174 lines
		
	
	
	
		
			4.8 KiB
		
	
	
	
		
			HTML
		
	
	
	
	
	
			
		
		
	
	
			174 lines
		
	
	
	
		
			4.8 KiB
		
	
	
	
		
			HTML
		
	
	
	
	
	
<html>
 | 
						|
<head><title>Lecture 6: Interrupts & Exceptions</title></head>
 | 
						|
<body>
 | 
						|
 | 
						|
<h1>Interrupts & Exceptions</h1>
 | 
						|
 | 
						|
<p>
 | 
						|
Required reading: xv6 <code>trapasm.S</code>, <code>trap.c</code>, <code>syscall.c</code>, <code>usys.S</code>.
 | 
						|
<br>
 | 
						|
You will need to consult
 | 
						|
<a href="../readings/ia32/IA32-3.pdf">IA32 System
 | 
						|
Programming Guide</a> chapter 5 (skip 5.7.1, 5.8.2, 5.12.2).
 | 
						|
 | 
						|
<h2>Overview</h2>
 | 
						|
 | 
						|
<p>
 | 
						|
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.
 | 
						|
 | 
						|
<p>
 | 
						|
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.
 | 
						|
 | 
						|
<p>
 | 
						|
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.
 | 
						|
 | 
						|
<p>
 | 
						|
We'll work through examples of these today in lecture.
 | 
						|
You'll see all three in great detail in the labs as well.
 | 
						|
 | 
						|
<p>
 | 
						|
A note on terminology: sometimes we'll
 | 
						|
use interrupt (or trap) to mean both interrupts and exceptions.
 | 
						|
 | 
						|
<h2>
 | 
						|
Setting up traps on the x86
 | 
						|
</h2>
 | 
						|
 | 
						|
<p>
 | 
						|
See handout Table 5-1, Figure 5-1, Figure 5-2.
 | 
						|
 | 
						|
<p>
 | 
						|
xv6 Sheet 07: <code>struct gatedesc</code> and <code>SETGATE</code>.
 | 
						|
 | 
						|
<p>
 | 
						|
xv6 Sheet 28: <code>tvinit</code> and <code>idtinit</code>.
 | 
						|
Note setting of gate for <code>T_SYSCALL</code>
 | 
						|
 | 
						|
<p>
 | 
						|
xv6 Sheet 29: <code>vectors.pl</code> (also see generated <code>vectors.S</code>).
 | 
						|
 | 
						|
<h2>
 | 
						|
System calls
 | 
						|
</h2>
 | 
						|
 | 
						|
<p>
 | 
						|
xv6 Sheet 16: <code>init.c</code> calls <code>open("console")</code>.
 | 
						|
How is that implemented?
 | 
						|
 | 
						|
<p>
 | 
						|
xv6 <code>usys.S</code> (not in book).
 | 
						|
(No saving of registers.  Why?)
 | 
						|
 | 
						|
<p>
 | 
						|
Breakpoint <code>0x1b:"open"</code>,
 | 
						|
step past <code>int</code> instruction into kernel.
 | 
						|
 | 
						|
<p>
 | 
						|
See handout Figure 9-4 [sic].
 | 
						|
 | 
						|
<p>
 | 
						|
xv6 Sheet 28: in <code>vectors.S</code> briefly, then in <code>alltraps</code>.
 | 
						|
Step through to <code>call trap</code>, examine registers and stack.
 | 
						|
How will the kernel find the argument to <code>open</code>?
 | 
						|
 | 
						|
<p>
 | 
						|
xv6 Sheet 29: <code>trap</code>, on to <code>syscall</code>.
 | 
						|
 | 
						|
<p>
 | 
						|
xv6 Sheet 31: <code>syscall</code> looks at <code>eax</code>,
 | 
						|
calls <code>sys_open</code>.
 | 
						|
 | 
						|
<p>
 | 
						|
(Briefly)
 | 
						|
xv6 Sheet 52: <code>sys_open</code> uses <code>argstr</code> and <code>argint</code>
 | 
						|
to get its arguments.  How do they work?
 | 
						|
 | 
						|
<p>
 | 
						|
xv6 Sheet 30: <code>fetchint</code>, <code>fetcharg</code>, <code>argint</code>,
 | 
						|
<code>argptr</code>, <code>argstr</code>.
 | 
						|
 | 
						|
<p>
 | 
						|
What happens if a user program divides by zero
 | 
						|
or accesses unmapped memory?
 | 
						|
Exception.  Same path as system call until <code>trap</code>.
 | 
						|
 | 
						|
<p>
 | 
						|
What happens if kernel divides by zero or accesses unmapped memory?
 | 
						|
 | 
						|
<h2>
 | 
						|
Interrupts
 | 
						|
</h2>
 | 
						|
 | 
						|
<p>
 | 
						|
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.
 | 
						|
 | 
						|
<p>
 | 
						|
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
 | 
						|
<strike>secretary</strike> administrative assistant,
 | 
						|
managing the phone lines on the CPU's behalf.
 | 
						|
 | 
						|
<p>
 | 
						|
Have to set up interrupt controller.
 | 
						|
 | 
						|
<p>
 | 
						|
(Briefly) xv6 Sheet 63: <code>pic_init</code> sets up the interrupt controller,
 | 
						|
<code>irq_enable</code> tells the interrupt controller to let the given
 | 
						|
interrupt through. 
 | 
						|
 | 
						|
<p>
 | 
						|
(Briefly) xv6 Sheet 68: <code>pit8253_init</code> sets up the clock chip,
 | 
						|
telling it to interrupt on <code>IRQ_TIMER</code> 100 times/second.
 | 
						|
<code>console_init</code> sets up the keyboard, enabling <code>IRQ_KBD</code>.
 | 
						|
 | 
						|
<p>
 | 
						|
In Bochs, set breakpoint at 0x8:"vector0"
 | 
						|
and continue, loading kernel.
 | 
						|
Step through clock interrupt, look at 
 | 
						|
stack, registers.
 | 
						|
 | 
						|
<p>
 | 
						|
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?)
 | 
						|
 | 
						|
<p>
 | 
						|
Can the kernel get an interrupt at any time?
 | 
						|
Why or why not?  <code>cli</code> and <code>sti</code>,
 | 
						|
<code>irq_enable</code>.
 | 
						|
 | 
						|
</body>
 | 
						|
</html>
 |