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

Bash
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 comparators

2. Clock Interrupts and jiffies

The Linux kernel has a global variable jiffies:

C
volatile unsigned long jiffies;
// Records the number of interrupts since system boot
// Automatically incremented by 1 on each timer tick

If HZ = 100 (common configuration), jiffies increases by 100 per second, i.e., each jiffy = 10ms.

Bash
jiffies growth process:
012 → ... → 99100 → ...
|____|← 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

C
// 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)

Bash
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 handler

Kernel Layer (IRQ 0 handler)

C

// arch/x86/entry/entry_64.S
IRQ_DOMAIN[236]:
    irq_entries_start:
        pushq    $~0      ... [truncated]
Last modified: 2024年3月24日

Author

Comments

Write a Reply or Comment

Your email address will not be published.