Has 4 privilege levels: to protect data and prevent user from executing privileged instruction (modify control registers or change how the processor is running)
PL0: most privileged, OS kernel
PL1: OS service
PL2: OS service
PL3: least privileged application
For project 2~4, PL0 is kernel, PL3 is user. Interrupts, exception usually transfer from PL3 to PL0 (sometimes PL0 to PL0 page fault). Running user code means getting from PL0 to PL3
Memory segment: a range of the same variety of memory
process may use many separate segments
each Windows DLL is multiple segment
x86-32 has mandatory segments: each has privilege levels
stack
code
data
Segment Related Stuff:
Segment
Segment registers (2 bytes): %CS(code) %SS (stack) %DS (data) %ES, %FS, %GS (additional)
%CS:%EIP: all instruction fetches%SS:%ESP: push, pop instructions, dealing with stack%DS:%EAX: default for data access MOVL (%EAX), %EBX (you could do MOVL (%ES:%EAX), %EBX to use other segments)Segment selector: bit pattern inside Segment register
Segment descriptor: defines a region of virtual memory by specifying a base address and a size, and various flags
Segment table: implemented by OS
When the processor fetches an instruction, it asks for an address of the form CS:EIP. So if %EIP is 0x100, this indicates the 256'th byte of the CS segment.


When calculating instruction pointer address:
read %CS to find out which table we are looking at
read %CS to find out which entry in the table we are looking at
read Segment descriptor for base address and limit
check if %EIP is within the limit
calculate final address using %EIP and base address by adding together
then it goes to page table to check corresponding physical memory
When doing
PUSH, POP, MOVL, the instruction specifies which segment register to use (%SSforPUSH, POP,%DSforMOVL). Note that the base address for all segments can be the same, and the limit can all be infinity. Which renders the while segment thing useless, except for making hardware happy so that they have different access permission (you can not have one segment that has all read, write, execute permission). So it's main job isn't address space translation, but permission separation. In modern CPU and OS, this segment table does not exist.
For this semester, we have 4 segments:
need one for readable/executable code
need another for readable/writable data
So we need 2 for kernel and 2 for user (different privilege level)
See: Here for more details.
Segments need not to be fully backed by physical memory, and can overlap
Kind of instruction
regular work: sequential execution
branch: jump around
"surprises": run a different body of code
Synchronous "surprises": cannot be deferred
because it is due to specific instruction
with reason being pre-condition not met
Asynchronous "surprises" can be deferred (I/O)
What happens:
retry the surprising instruction (exception)
kill program (exception)
run next instruction (trap, interrupt)
Exception: PARTICULAR instruction violate pre-condition
Trap: PARTICULAR instruction ask system for help
Interrupt: an I/O device needs attention
device get kernel's attention by raising a hardware interrupt as well
When exception
record info about which instruction broke
why it broke
locate "exception handler"
exception handler device: fix/kill/crash
Programmable Interrupt Controller (PIC)



Interrupt Management:
disable_interrupts(): defer interrupts from ALL devices.
enable_interrupts(): re-enable listening to interrupts.
you have have fine grain management to specify which interrupt (timer/printer) to enable/disable
Interrupt Discriptor Table (IDT): maps interrupt/exception/trap (one table for all) to a function pointer and some flags
often abused to store other things as well
0 -> divide by zero
14 -> page fault
0-31: processor exceptions
32 -> timer interrupt (interrupt request queue 0 (IRQ0))
31-255: correspond to hardware/software events
More info on section 5.12 of
intel-sys.pdf

inb(port), outb(port, data): controlled by I/O ports (cursor)
Memory mapped IO: communication via virtual memory (video memory for screen display)
I/O ports:
8 bit (1 byte) ports: which is problematic because values are usually greater than 1 byte (e.g. 2 byte)
"registers" / property
Sample interaction for transmitting 2 bytes:
outb(command_port, SELECT_R12_LOWER);
outb(data_port, 32);
outb(command_port, SELECT_R12_UPPER);
outb(data_port, 0);
P1 Makefile: build floppy disk images
Simics boots and runs simics60 in build directory
Uses xchg %bx, %bx as breakpoint for debugging
scriptable using python
Table of Content