这是 Linux 内核启动阶段非常经典的一行:
calibrating delay loop(skipped), value calculated using timer frequency.. 2.00 BogoMIPS (lpj=4000)你问的是它的原理,下面我把它拆成三步讲清楚:
① BogoMIPS 是什么 → ② 正常情况下怎么算 → ③ 你这里 "skipped / calculated using timer frequency" 是什么原理
一、BogoMIPS 是什么?(一句话)
BogoMIPS = CPU 在一个 jiffy(1/HZ 秒)内能执行多少个“空循环”迭代
Bogo = bogus(假、无意义)
不是性能基准
用途:为内核里
udelay()/mdelay()提供忙等延时校准
void udelay(unsigned long usecs);内核必须知道:
“我这个 CPU,空转多少次要 ≈ 1μs”
这就是lpj(loops per jiffy)的作用。
二、正常情况:calibrating delay loop ...
正常情况下内核会做运行时校准:
步骤概概
内核知道1 jiffy = 1/HZ 秒(如 HZ=250 → 4ms)
启动一个固定指令序列的空循环
用TSC / arch timer / cycle counter 精确测量:
循环多少次 ≈ 1 jiffy
得到
lpj(loops per jiffy)计算:
BogoMIPS = lpj × HZ / 500000
示例:
lpj = 4 000 000
HZ = 250
BogoMIPS = 4 000 000 × 250 / 500 000 =2000
三、你这行的含义:(skipped), value calculated using timer frequency
calibrating delay loop(skipped), value calculated using timer frequency.. 2.00 BogoMIPS (lpj=4000)✅ 发生了什么?
内核没有做运行时循环校准,而是:
用已知 CPU / timer 频率直接计算 lpj
这是CONFIG_CPU_FREQ / device tree / KVM / QEMU / 模拟器 常见行为。
🔧 计算原理(简化)
如果内核知道:
CPU/Timer 频率 =
FHz假设每个 delay loop ≈
N个 cycles(架构常量)
那么:
lpj ≈ F × (1 / HZ) / N或从 DT / KVM host 传入:
lpj = (timer_freq / HZ) * loop_cycles_per_tick你看到:
lpj=4000BogoMIPS=2.00
说明:
lpj × HZ / 500000 = 2.00 → HZ=100 → lpj=4000 ✅这通常出现在:
✅ QEMU / KVM(虚拟 CPU,不跑真实校准)
✅ 设备树给出
clock-frequency✅
CONFIG_PRECISE_DELAY_CALIBRATION=n✅
lpj=被 bootargs 指定(或继承自古固件)
四、为什么内核允许“跳过”校准?
因为:
在虚拟机 / 模拟器:
循环时间不稳定
TSC / cycle counter 可能虚拟
在固定 SoC:
CPU 频率已知
算出来的 lpj 足够准 for
udelay()
👉 只要udelay()延时大致正确,不需要真跑校准循环
五、什么时候要担心?
✅不用管,如果:
你是 QEMU / FPGA / 固定频率 SoC
lpj与预期同量级驱动
udelay()看起来差不多准
⚠️要注意,如果:
实际 CPU freq 与 DT 中
clock-frequency不符udelay(100)明显偏快/偏慢(I2C、SPI 时序怪异)可强制指定:
lpj=xxxxxxx或开启运行中校准(关闭 skip)
六、一句话总结
calibrating delay loop skipped, value calculated using timer frequency表示:
内核没有跑空循环来测 CPU 速度
而是根据已知 timer/cpu 频率直接计算 lpj
得到的 BogoMIPS 仅供
udelay()使用,不是性能指标