358 | Timer: HPET and Clock Interrupts
Key Insight: The operating system’s sense of time doesn’t come from “watching a clock” — it’s “punched out” by interrupts. Each clock tick tells the kernel that another jiffy has passed — and then it decides who gets to run next.
1. Three Clock Hardware Components
The x86 platform has three kinds of clock hardware, in historical order:
1.1 RTC (Real Time Clock)
The oldest, slowest, used to maintain time even when powered off.
- Independently powered (coin cell battery), doesn’t lose time even during power outages
- Can only be set to slow frequencies (max 8192Hz)
- Now only used to record wall-clock time (year/month/day/hour/minute/second)
1.2 PIT (Programmable Interval Timer)
8253/8254 chip, the standard timer of the IBM PC era.
- Can only set 3 independent counters
- Maximum frequency approximately 1.193MHz (clock crystal 14.31818MHz / 12 divider)
- Linux used it early on to generate the system clock interrupt (IRQ 0)
- Now replaced by HPET and APIC
1.3 HPET (High Precision Event Timer)
The standard clock for modern PCs, standard equipment after 2007.
- At least 10MHz clock base (100ns precision)
- Up to 32 comparators, each can independently trigger different interrupts
- Supports 64-bit counter, never overflows (vs PIT’s 16-bit counter)
- Can program multiple timers at once, no polling required
HPET Structure:
┌─────────────────────────────────────┐
│ Main Counter (64-bit, 10MHz+) │ Unified clock source
└─────────────────────────────────────┘
├── Comparator 0 → IRQ 2 (or mapped to APIC)
├── Comparator 1 → IRQ 3
├── Comparator 2 → IRQ 4
└── ...Up to 32 comparators2. Clock Interrupts and jiffies
The Linux kernel has a global variable jiffies:
volatile unsigned long jiffies;
// Records the number of interrupts since system boot
// Automatically incremented by 1 on each timer tickIf HZ = 100 (common configuration), jiffies increases by 100 per second, i.e., each jiffy = 10ms.
jiffies growth process:
0 → 1 → 2 → ... → 99 → 100 → ...
|____|← 1 jiffy = 10ms →|Choosing HZ:
- HZ=100: Desktop systems (responds every 10ms)
- HZ=1000: Server/real-time systems (1ms granularity, but higher CPU overhead)
- HZ=300: Traditional in some Unix systems
// HZ definition in the kernel (arch/x86/include/asm/param.h)
#ifdef CONFIG_HZ
# define HZ CONFIG_HZ
#else
# define HZ 100
#endif
// Reading jiffies
#define get_jiffies() (jiffies)
// Converting from jiffies to seconds/milliseconds
int seconds = jiffies / HZ;
int ms = (jiffies * 1000) / HZ;3. Complete Path of a Clock Interrupt
Hardware Layer (HPET → CPU)
HPET Comparator 0 triggers (reaches the set period value)
↓
APIC receives IRQ 0 (clock interrupt)
↓
CPU executes APIC interrupt vector (usually 0xEC = 236)
↓
CPU jumps to IDT[236] (trap gate)
↓
Enters kernel timer interrupt handlerKernel Layer (IRQ 0 handler)
// arch/x86/entry/entry_64.S
IRQ_DOMAIN[236]:
irq_entries_start:
pushq $~0 ... [truncated]
Comments