Principles of Computers 20th Lecture Pavel Ježek, Ph.D. pavel.jezek@d3s.mff.cuni.cz
Software Interrupts CPU arch. Interrupts supported by CPU ISA instruction in assembler In machine code Instruction behavior 6502 1 vector (16 bit address of handler) at $FFFE - $FFFF BRK $00 JSR ($FFFE) 8086/88 256 vectors with fixed base address: $0000:$0000 (1 vector = 16+16 bits = segment:offset) INT $xx (x = 0 … 255) $CD $xx CALL [xx * 4] >= 80286 256 vectors: base address given by IDTR register CALL [IDTR + xx * 4]
Selected Faults/Traps/Exceptions of x86 ISA CPU Exception Interrupt vector (all push IP of faulting instruction) Invalid opcode 6 Divide by zero (DIV0) Alignment check 17 ($11)
absolute address = BAD absolute address = BAD absolute address = BAD Data/constants section absolute address = BAD var A = @B var B = @proc1 Code (Text) section absolute address = BAD absolute address = BAD call $xxxxxxxx absolute address = BAD call [$xxxxxxxx] call $xxxxxxxx relative address = OK absolute address = BAD call +-xxxxxxxx Executable file header: Entrypoint
absolute address = BAD absolute address = BAD absolute address = BAD Data/constants section absolute address = BAD var A = @B var B = @proc1 Code (Text) section absolute address = BAD absolute address = BAD call $xxxxxxxx absolute address = BAD call [$xxxxxxxx] call $xxxxxxxx relative address = OK absolute address = BAD call +-xxxxxxxx Executable file header: Entrypoint Base address to load to
List of offsets from beginning of the executable file – each offset points to an address that needs to be corrected. Relocation table: Data/constants section var A = @B var B = @proc1 Code (Text) section call $xxxxxxxx call [$xxxxxxxx] call $xxxxxxxx relative address = OK call +-xxxxxxxx Executable file header: Entrypoint Base address to load to Offset to start of relocation table
von Neumann Architecture and Devices CPU 32-bit physical address space comm. protocol: 32-bit address space operating memory (DRAM) 1 GB memory bus $FFFFFFFF = 232-1 $FFFFFFFF = 232-1 4 GB 4 GB device A $40000000 = 230 $40000000 = 230 addr 1 1 B register 1 GB $3FFFFFFF = 230-1 $3FFFFFFF = 230-1 1 GB 2 B register bus 1 $00000000 = 0 $00000000 = 0 device B addr 8 1 B register device C = bus 1 to bus 2 bridge bus 2 addr 7 1 B register 1 B register addr 13 addr 1 device D device E 1 B register 1 B register
Memory Controller CPU memory controller (refresh) 1 GB DRAM module 32-bit physical address space memory controller (refresh) comm. protocol: 32-bit address space 1 GB DRAM module memory bus memory bus $FFFFFFFF = 232-1 $FFFFFFFF = 232-1 4 GB 4 GB device A $40000000 = 230 $40000000 = 230 addr 1 1 B register 1 GB $3FFFFFFF = 230-1 $3FFFFFFF = 230-1 1 GB 2 B register bus 1 $00000000 = 0 $00000000 = 0 device B addr 8 1 B register device C = bus 1 to bus 2 bridge bus 2 addr 7 1 B register 1 B register addr 13 addr 1 device D device E 1 B register 1 B register
Memory Controller – Support for Multiple Memory Modules CPU 32-bit physical address space memory controller (refresh) comm. protocol: 32-bit address space 1 GB DRAM module memory bus memory bus $FFFFFFFF = 232-1 $FFFFFFFF = 232-1 4 GB 4 GB memory bus $60000000 device A 512 MB $5FFFFFFF $40000000 = 230 addr 1 1 B register 1 GB $3FFFFFFF = 230-1 $40000000 = 230 comm. protocol: 32-bit address space $3FFFFFFF = 230-1 1 GB 2 B register bus 1 $00000000 = 0 $00000000 = 0 $FFFFFFFF = 232-1 512 MB DRAM module 4 GB device B addr 8 1 B register device C = bus 1 to bus 2 bridge bus 2 addr 7 1 B register $20000000 = 229 1 B register addr 13 addr 1 $1FFFFFFF = 229-1 512 MB device D device E $00000000 = 0 1 B register 1 B register
Memory Controller – Different Address Space Sizes CPU 8 GB $1FFFFFFFF = 233-1 33-bit physical address space memory controller (refresh) comm. protocol: 32-bit address space 1 GB DRAM module memory bus memory bus $FFFFFFFF = 232-1 4 GB memory bus device A $40000000 = 230 addr 1 1 B register comm. protocol: 32-bit address space $3FFFFFFF = 230-1 1 GB 2 B register $060000000 bus 1 512 MB $05FFFFFFF $00000000 = 0 1 GB $03FFFFFFF = 230-1 $040000000 = 230 $FFFFFFFF = 232-1 512 MB DRAM module 4 GB device B addr 8 $000000000 = 0 1 B register device C = bus 1 to bus 2 bridge bus 2 addr 7 1 B register $20000000 = 229 $1FFFFFFF = 229-1 512 MB 1 B register addr 13 addr 1 device D device E $00000000 = 0 1 B register 1 B register
Memory Controller – Detecting Sizes of Connected Modules? SPD Bus = I2C CPU 8 GB $1FFFFFFFF = 233-1 33-bit physical address space memory controller (refresh) comm. protocol: 32-bit address space 1 GB DRAM module memory bus memory bus I2C EEPROM $FFFFFFFF = 232-1 I2C master 4 GB memory bus device A $40000000 = 230 addr 1 1 B register comm. protocol: 32-bit address space $3FFFFFFF = 230-1 1 GB 2 B register $060000000 bus 1 512 MB $05FFFFFFF $00000000 = 0 1 GB $03FFFFFFF = 230-1 $040000000 = 230 $FFFFFFFF = 232-1 512 MB DRAM module 4 GB device B addr 8 $000000000 = 0 1 B register I2C EEPROM device C = bus 1 to bus 2 bridge bus 2 addr 7 1 B register $20000000 = 229 $1FFFFFFF = 229-1 512 MB 1 B register addr 13 addr 1 device D device E $00000000 = 0 1 B register 1 B register
Assigning I2C Addresses
System Bus CPU memory controller (refresh) 1 GB DRAM module 512 MB 32-bit physical address space memory controller (refresh) comm. protocol: 32-bit address space 1 GB DRAM module memory bus memory bus comm. protocol: 32-bit address space 512 MB DRAM module device A addr 1 1 B register 2 B register system bus $FFFFFFFF = 232-1 4 GB device B addr 8 1 B register device C = bus 2 controller (HBA) bus 2 $60000000 512 MB $5FFFFFFF addr 7 1 GB $3FFFFFFF = 230-1 1 B register addr 13 addr 1 device D device E $00000000 = 0 1 B register 1 B register 1 B register
System Bus – PCI Express Memory Write Packet (MWr) Code executed by CPU: MOV EAX, 12345678h ; load constant MOV [3F6BFC10h], EAX ; store EAX content CPU 32-bit physical address space addr 0 memory controller (refresh) comm. protocol: 32-bit address space 1 GB DRAM module MWr memory bus MWr Routing by memory address space address, NOT by device address! addr $100 memory bus comm. protocol: 32-bit address space 512 MB DRAM module device A addr 1 1 B register 2 B register system bus $FFFFFFFF = 232-1 4 GB device B addr 8 1 B register device C = bus 2 controller (HBA) bus 2 $60000000 512 MB $5FFFFFFF addr 7 1 GB $3FFFFFFF = 230-1 1 B register addr 13 addr 1 device D device E $00000000 = 0 1 B register 1 B register 1 B register
System Bus – PCI Express Memory Read Packet (MRd) + Completion with data (CplD) Code executed by CPU: MOV EAX, [3F6BFC10h] ; load into EAX ; EAX register now contains value $12345678 CPU 32-bit physical address space MRd addr 0 memory controller (refresh) comm. protocol: 32-bit address space 1 GB DRAM module CplD memory bus MRd addr $100 memory bus comm. protocol: 32-bit address space 512 MB DRAM module device A CplD addr 1 1 B register 2 B register system bus $FFFFFFFF = 232-1 4 GB device B addr 8 1 B register device C = bus 2 controller (HBA) bus 2 $60000000 512 MB $5FFFFFFF addr 7 1 GB $3FFFFFFF = 230-1 1 B register addr 13 addr 1 device D device E $00000000 = 0 1 B register 1 B register 1 B register
System Bus – PCI Express – How To Access Other Devices? Code executed by CPU: MOV EAX, 12345678h ; load constant MOV [3F6BFC10h], EAX ; store EAX content CPU 32-bit physical address space addr 0 memory controller (refresh) comm. protocol: 32-bit address space 1 GB DRAM module memory bus MWr addr $100 memory bus comm. protocol: 32-bit address space 512 MB DRAM module Write to device 1 device A addr 1 1 B register 2 B register Code executed by CPU: ??? system bus $FFFFFFFF = 232-1 4 GB device B addr 8 1 B register device C = bus 2 controller (HBA) bus 2 $60000000 512 MB $5FFFFFFF addr 7 1 GB $3FFFFFFF = 230-1 1 B register addr 13 addr 1 device D device E $00000000 = 0 1 B register 1 B register 1 B register
System Bus – Memory Mapped I/O Code executed by CPU: MOV EAX, 12345678h ; load constant MOV [3F6BFC10h], EAX ; store EAX content CPU 32-bit physical address space Code executed by CPU: ??? addr 0 memory controller (refresh) comm. protocol: 32-bit address space 1 GB DRAM module memory bus MWr addr $100 memory bus comm. protocol: 32-bit address space 512 MB DRAM module device A zoomed view: addr 1 1 B register Y MWr 2 B register X reg Y system bus $90000002 reg X $FFFFFFFF = 232-1 4 GB device B $90000000 addr 8 1 B register device C = bus 2 controller (HBA) bus 2 $60000000 512 MB $5FFFFFFF addr 7 1 GB $3FFFFFFF = 230-1 1 B register addr 13 addr 1 device D device E $00000000 = 0 1 B register 1 B register 1 B register
Memory Mapped I/O (write 5 to register Y of device A) Code executed by CPU: MOV EAX, 12345678h ; load constant MOV [3F6BFC10h], EAX ; store EAX content CPU 32-bit physical address space Code executed by CPU: MOV AL, 05h ; load 8-bit constant MOV [90000002h], AL ; 8-bit store addr 0 memory controller (refresh) comm. protocol: 32-bit address space 1 GB DRAM module memory bus MWr addr $100 memory bus comm. protocol: 32-bit address space 512 MB DRAM module device A zoomed view: addr 1 1 B register Y MWr 2 B register X reg Y system bus $90000002 reg X $FFFFFFFF = 232-1 4 GB device B $90000000 addr 8 1 B register device C = bus 2 controller (HBA) bus 2 $60000000 512 MB $5FFFFFFF addr 7 1 GB $3FFFFFFF = 230-1 1 B register addr 13 addr 1 device D device E $00000000 = 0 1 B register 1 B register 1 B register
Point-to-point connections only Real PCI Express Bus Has a Tree Topology (with point-to-point links only) Point-to-point connections only
PCI Express Connector Includes SMBus Signals (SCL and SDA) I2C (SMBus) Controller Point-to-point connections only SMBus (I2C)
Back To Simplified View: Concept of an HBA (Host Bus Adapter) Code executed by CPU: MOV EAX, 12345678h ; load constant MOV [3F6BFC10h], EAX ; store EAX content CPU 32-bit physical address space Code executed by CPU: MOV AL, 05h ; load 8-bit constant MOV [90000002h], AL ; 8-bit store addr 0 memory controller (refresh) comm. protocol: 32-bit address space 1 GB DRAM module memory bus MWr addr $100 memory bus comm. protocol: 32-bit address space 512 MB DRAM module device A zoomed view: addr 1 1 B register Y MWr 2 B register X reg Y system bus $90000002 reg X $FFFFFFFF = 232-1 4 GB device B $90000000 addr 8 1 B register device C = bus 2 controller (HBA) bus 2 $60000000 512 MB $5FFFFFFF addr 7 1 GB $3FFFFFFF = 230-1 1 B register addr 13 addr 1 device D device E $00000000 = 0 1 B register 1 B register 1 B register
System Bus’ HBA Example
Sending 1 Byte Via Philips PCA9564 I2C HBA W I2CCON ← (STA=1|STO=0|CR0-CR2=clock rate) R I2CCON → wait for SI=1 (controller waits for I2C idle state) R I2CSTA → $08=start transmitted W I2CCON ← (STA=0,STO=0) W I2CDAT ← (slave addr|R/W=0=write) R I2CCON → wait for SI=1 R I2CSTA → $18=ACK received=slave listening → $20=NACK received=slave not present → $38=arbitration lost W I2CDAT ← data byte to send R I2CSTA → $28=ACK received → $30=NACK received W I2CCON ← (STA=0,STO=1) Registers I2CCON = Control (R/W) bit STA: 1 = send Start condition bit STO: 1 = send Stop condition bit SI = Serial Interrupt: 1 = Status register changed (SCL line is held LOW → I2C transmission is suspended) I2CDAT = Data (R/W) I2CSTA = Status (R/O)
Sending 1 Byte Via Philips PCA9564 I2C HBA W I2CCON ← (STA=1|STO=0|CR0-CR2=clock rate) R I2CCON → wait for SI=1 (controller waits for I2C idle state) R I2CSTA → $08=start transmitted W I2CCON ← (STA=0,STO=0) W I2CDAT ← (slave addr|R/W=0=write) R I2CCON → wait for SI=1 R I2CSTA → $18=ACK received=slave listening → $20=NACK received=slave not present → $38=arbitration lost W I2CDAT ← data byte to send R I2CSTA → $28=ACK received → $30=NACK received W I2CCON ← (STA=0,STO=1) Registers I2CCON = Control (R/W) bit STA: 1 = send Start condition bit STO: 1 = send Stop condition bit SI = Serial Interrupt: 1 = Status register changed (SCL line is held LOW → I2C transmission is suspended) I2CDAT = Data (R/W) I2CSTA = Status (R/O) If everything is ideal: 1 transaction on I2C bus = 11 transactions on system bus (or more, if not ideal)
Sending 1 Byte Via Philips PCA9564 I2C HBA W I2CCON ← (STA=1|STO=0|CR0-CR2=clock rate) R I2CCON → wait for SI=1 (controller waits for I2C idle state) R I2CSTA → $08=start transmitted W I2CCON ← (STA=0,STO=0) W I2CDAT ← (slave addr|R/W=0=write) R I2CCON → wait for SI=1 R I2CSTA → $18=ACK received=slave listening → $20=NACK received=slave not present → $38=arbitration lost W I2CDAT ← data byte to send R I2CSTA → $28=ACK received → $30=NACK received W I2CCON ← (STA=0,STO=1) Registers I2CCON = Control (R/W) bit STA: 1 = send Start condition bit STO: 1 = send Stop condition bit SI = Serial Interrupt: 1 = Status register changed (SCL line is held LOW → I2C transmission is suspended) I2CDAT = Data (R/W) I2CSTA = Status (R/O) Device polling – wastes CPU time :( If everything is ideal: 1 transaction on I2C bus = 11 transactions on system bus (or more, if not ideal)
“Traditional” IRQ Lines CPU IRQ 0 addr 0 memory controller (refresh) comm. protocol: 32-bit address space 1 GB DRAM module memory bus MWr addr $100 memory bus comm. protocol: 32-bit address space 512 MB DRAM module device A addr 1 1 B register Y MWr interrupt 2 B register X system bus device B addr 8 interrupt 1 B register device C = bus 2 controller (HBA) bus 2 addr 7 1 B register addr 13 addr 1 device D device E 1 B register 1 B register 1 B register
PCI Express: Message Packet Type: Assert_INTx/Deassert_INTx Messages CPU addr 0 memory controller (refresh) comm. protocol: 32-bit address space 1 GB DRAM module memory bus addr $100 memory bus comm. protocol: 32-bit address space 512 MB DRAM module device A addr 1 1 B register Y 2 B register X system bus Virtual IRQ line state 1 device B addr 8 Assert_INTA 1 B register Assert_INTA Deassert_INTA device C = bus 2 controller (HBA) bus 2 addr 7 1 B register addr 13 addr 1 device D device E 1 B register 1 B register 1 B register
Hardware Interrupt Handler Execution Instructions executed by CPU LOAD R1 ADD R1,3 MUL R1,10 STORE R1 LOAD R1 AND R1,1 STORE R1 Virtual IRQ line state 1
Hardware Interrupt Handler Execution Instructions executed by CPU LOAD R1 ADD R1,3 MUL R1,10 STORE R1 LOAD R1 AND R1,1 STORE R1 Virtual IRQ line state 1 Instructions executed by CPU LOAD R1 ADD R1,3 MUL R1,10 CPU calls interrupt handler instruction 1 of IRQ handler inst 2 Virtual IRQ line state 1 Assert_INTA Deassert_INTA
Hardware Interrupt Handler Execution Instructions executed by CPU LOAD R1 ADD R1,3 MUL R1,10 STORE R1 LOAD R1 AND R1,1 STORE R1 Virtual IRQ line state 1 Instructions executed by CPU LOAD R1 ADD R1,3 MUL R1,10 CPU calls interrupt handler instruction 1 of IRQ handler inst 2 Virtual IRQ line state 1 Save blue code’s registers to call stack Assert_INTA Deassert_INTA
Hardware Interrupt Handler Execution Instructions executed by CPU LOAD R1 ADD R1,3 MUL R1,10 STORE R1 LOAD R1 AND R1,1 STORE R1 Virtual IRQ line state 1 Instructions executed by CPU LOAD R1 ADD R1,3 MUL R1,10 CPU calls interrupt handler instruction 1 of IRQ handler inst 2 Virtual IRQ line state 1 Assert_INTA
Hardware Interrupt Handler Execution Instructions executed by CPU LOAD R1 ADD R1,3 MUL R1,10 STORE R1 LOAD R1 AND R1,1 STORE R1 Virtual IRQ line state 1 Instructions executed by CPU LOAD R1 ADD R1,3 MUL R1,10 CPU calls interrupt handler instruction 1 of IRQ handler CPU calls Virtual IRQ line state 1 Unbounded recursion Assert_INTA
Sending 1 Byte Via Philips PCA9564 I2C HBA W I2CCON ← (STA=1|STO=0|CR0-CR2=clock rate) R I2CCON → wait for SI=1 (controller waits for I2C idle state) R I2CSTA → $08=start transmitted W I2CCON ← (STA=0,STO=0) W I2CDAT ← (slave addr|R/W=0=write) R I2CCON → wait for SI=1 R I2CSTA → $18=ACK received=slave listening → $20=NACK received=slave not present → $38=arbitration lost W I2CDAT ← data byte to send R I2CSTA → $28=ACK received → $30=NACK received W I2CCON ← (STA=0,STO=1) Registers I2CCON = Control (R/W) bit STA: 1 = send Start condition bit STO: 1 = send Stop condition bit SI = Serial Interrupt: 1 = Status register changed (SCL line is held LOW → I2C transmission is suspended) I2CDAT = Data (R/W) I2CSTA = Status (R/O) If everything is ideal: 1 transaction on I2C bus = 11 transactions on system bus (or more, if not ideal)
Sending 1 Byte Using Interrupts procedure SendByte(…); begin W I2CCON ← (STA=1|STO=0|CR0-CR2=clock rate) set interrupt X handler = @SendAddress end; procedure SendAddress(…); begin R I2CSTA → $08=start transmitted W I2CCON ← (STA=0,STO=0) W I2CDAT ← (slave addr|R/W=0=write) set interrupt X handler = @SendData procedure SendData(…); begin R I2CSTA → $18=ACK received=slave listening → $20=NACK received=slave not present → $38=arbitration lost W I2CDAT ← data byte to send set interrupt X handler = @SendStop procedure SendStop(…); begin R I2CSTA → $28=ACK received → $30=NACK received W I2CCON ← (STA=0,STO=1) set interrupt X handler = default Registers I2CCON = Control (R/W) bit STA: 1 = send Start condition bit STO: 1 = send Stop condition bit SI = Serial Interrupt: 1 = Status register changed (SCL line is held LOW → I2C transmission is suspended) I2CDAT = Data (R/W) I2CSTA = Status (R/O)
Sending 1 Byte Using Interrupts procedure SendByte(…); begin W I2CCON ← (STA=1|STO=0|CR0-CR2=clock rate) set interrupt X handler = @SendAddress end; procedure SendAddress(…); begin R I2CSTA → $08=start transmitted W I2CCON ← (STA=0,STO=0) W I2CDAT ← (slave addr|R/W=0=write) set interrupt X handler = @SendData procedure SendData(…); begin R I2CSTA → $18=ACK received=slave listening → $20=NACK received=slave not present → $38=arbitration lost W I2CDAT ← data byte to send set interrupt X handler = @SendStop procedure SendStop(…); begin R I2CSTA → $28=ACK received → $30=NACK received W I2CCON ← (STA=0,STO=1) set interrupt X handler = default Registers I2CCON = Control (R/W) bit STA: 1 = send Start condition bit STO: 1 = send Stop condition bit SI = Serial Interrupt: 1 = Status register changed (SCL line is held LOW → I2C transmission is suspended) I2CDAT = Data (R/W) I2CSTA = Status (R/O) RACE CONDITION!
Sending 1 Byte Using Interrupts procedure SendByte(…); begin W I2CCON ← (STA=1|STO=0|CR0-CR2=clock rate) set interrupt X handler = @SendAddress end; procedure SendAddress(…); begin R I2CSTA → $08=start transmitted W I2CCON ← (STA=0,STO=0) W I2CDAT ← (slave addr|R/W=0=write) set interrupt X handler = @SendData procedure SendData(…); begin R I2CSTA → $18=ACK received=slave listening → $20=NACK received=slave not present → $38=arbitration lost W I2CDAT ← data byte to send set interrupt X handler = @SendStop procedure SendStop(…); begin R I2CSTA → $28=ACK received → $30=NACK received W I2CCON ← (STA=0,STO=1) set interrupt X handler = default Registers I2CCON = Control (R/W) bit STA: 1 = send Start condition bit STO: 1 = send Stop condition bit SI = Serial Interrupt: 1 = Status register changed (SCL line is held LOW → I2C transmission is suspended) I2CDAT = Data (R/W) I2CSTA = Status (R/O) RACE CONDITION! If controller is fast and interrupt arrives here, we will send the same data byte for the second time!
Sending 1 Byte Using Interrupts procedure SendByte(…); begin W I2CCON ← (STA=1|STO=0|CR0-CR2=clock rate) set interrupt X handler = @SendAddress end; procedure SendAddress(…); begin R I2CSTA → $08=start transmitted W I2CCON ← (STA=0,STO=0) W I2CDAT ← (slave addr|R/W=0=write) set interrupt X handler = @SendData procedure SendData(…); begin R I2CSTA → $18=ACK received=slave listening → $20=NACK received=slave not present → $38=arbitration lost STI W I2CDAT ← data byte to send set interrupt X handler = @SendStop procedure SendStop(…); begin R I2CSTA → $28=ACK received → $30=NACK received W I2CCON ← (STA=0,STO=1) set interrupt X handler = default Registers I2CCON = Control (R/W) bit STA: 1 = send Start condition bit STO: 1 = send Stop condition bit SI = Serial Interrupt: 1 = Status register changed (SCL line is held LOW → I2C transmission is suspended) I2CDAT = Data (R/W) I2CSTA = Status (R/O) RACE CONDITION! Solution 1: Do NOT re-enable interrupts too soon!
Sending 1 Byte Using Interrupts procedure SendByte(…); begin set interrupt X handler = @SendAddress W I2CCON ← (STA=1|STO=0|CR0-CR2=clock rate) end; procedure SendAddress(…); begin R I2CSTA → $08=start transmitted W I2CCON ← (STA=0,STO=0) set interrupt X handler = @SendData W I2CDAT ← (slave addr|R/W=0=write) procedure SendData(…); begin R I2CSTA → $18=ACK received=slave listening → $20=NACK received=slave not present → $38=arbitration lost set interrupt X handler = @SendStop W I2CDAT ← data byte to send procedure SendStop(…); begin R I2CSTA → $28=ACK received → $30=NACK received set interrupt X handler = default W I2CCON ← (STA=0,STO=1) Registers I2CCON = Control (R/W) bit STA: 1 = send Start condition bit STO: 1 = send Stop condition bit SI = Serial Interrupt: 1 = Status register changed (SCL line is held LOW → I2C transmission is suspended) I2CDAT = Data (R/W) I2CSTA = Status (R/O) Solution 2: Reverse order of installing new interrupt handler and starting new command execution in the controller!