CS 452/652 Spring 2025 - Lecture 9
Events, Clock, Idle
June 3, 2025 prev next
BCM - Broadcom BCM2711 data sheet
GIC - ARM Generic Interrupt Controller
Interrupt Controller
System at Boot Time
- GIC distribution and signalling enabled (GICD_CTLR, GICC_CTLR)
- all interrupts disabled at GIC
- interrupt routing ?
- interrupts masked in EL1 (via boot.S)
System Timer Interrupts
- Initialization
- Timer has 4 interrupt signals, corresponding to C0-C3
- C0 and C2 reserved by VC, so use C1 and/or C3
- BCM Chap 6 says system timer interrupts are first 4 VC (video core) interrupts
- Interrupt IDs for video core start at 96, so
- C1 interrupt has InterruptID 97
- C3 interrupt has InterruptID 99
- route the interrupt to IRQ on CPU 0
- use
GICD_ITARGETSRn
- each register defines targets for 4 interrupts
- 1024 interrupts, 8 bits = 8 cores
- make sure IRQ handler is set up in your kernel's exception vector
- enable the interrupt
- use
GICD_ISENABLERn
- 4-byte registers, with 1 bit per InterruptID
- 1024 interrupts, 1 bit
- use
GICD_ICENABLERn
to disable interrupt
- write values into system timer C1/C3 to trigger interrupt assertion at correct time
- might have to clear interrupt via CS status register (see below)
- enable IRQ handling in CPU via pstate
Timer Interrupt Handling
- save running task state
- read
GICC_IAR
- returns interruptID (should be 97/99)!
- sets interrupt state to Active in GIC
- if system timer interrupt
- update Cn compare register - overflow?
- clear interrupt via CS status register
- write InterruptID to
GICC_EOIR
- marks interrupt as not active in GIC
- perform interrupt handling work
- unblock task(s) waiting for event
- loop: read GICC_IAR again?
- schedule next task
- resume task
- note: system timer interrupts cannot be explicitly disabled at device
AwaitEvent
- synchronization: user tasks ↔ device
- AwaitEvent() argument and return code → design decision
- eventIds are defined by the kernel, known to the application
- return code - event-specific interpretation
- example: subtype, count, data
- micro-kernel: put as much functionality as possible in user-level tasks
- AwaitEvent() blocks calling task
- matchmaking task ↔ event
- 0, 1, N tasks waiting? store in queue (cf. SRR)?
- N tasks wait for event? complexity? unblock one or all?
- 0 tasks wait for interrupt? buffer in kernel?
- multiple same interrupts without waiting task indicate performance problem
- use task prioritity to make sure that hardware interrupts are handled promptly
- intention of AwaitEvent() is to expose device interrupts to the application
- program periodic interrupt in kernel
- can be decoupled: 1ms timer interrupt vs. 10ms clock tick
Clock Server
- API:
Time(int tid)
- current time (in ticks)
Delay(tid, ticks)
- delay, relative to current time
DelayUntil(tid, ticks)
- delay, to absolute time
- DelayUntil = Time + Delay, but at server
- convenience for real-time loop
- these are Send() wrappers; tid is tid of a Clock server
- Time measured in "ticks"
Server Implementaion
- AwaitEvent() might block; server pattern?
- if server calls AwaitEvent(), it cannot Receive() new requests (e.g., Time())
- delegate event blocking to special task: Notifier pattern
Clock Notifier
for (;;) {
AwaitEvent();
Send(); // send tick to clock server
}
Clock Server
for (;;) {
Receive();
process(); // manage tasks
Reply(); // if applicable
}
- needs to manage list of suspended tasks
Idle/Halt
K3 overview
- Note: system with 1ms clock tick is fine as well
