Calibrate Delay Avoidance Specification

Introduction
This page specifies a facility to avoid the delay associated with the Linux kernel function calibrate_delay.

The calibrate_delay routine is intended to calculate at boot time an appropriate value for loops_per_jiffy, on an arbitrary platform. The value of loops_per_jiffy is used to execute "busywait" (non-yielding) delays inside the Linux kernel.

The duration of calibrate_delay is independent of the CPU architecture or processor speed. Rather, the delay is dependent on the length of a "jiffy" and the number of iterations of the internal loops required to perform the calibration. A jiffy is the time period defined by the HZ variable in the Linux kernel. For the 2.4 Linux kernel, a jiffy is 10 milliseconds. Each iteration of the calibration algorithm takes about 1 jiffy, and there are, on average, about 20-25 iterations. Thus, the time to execute calibrate_delay takes between 200 to 250 milliseconds on most platforms.

Rationale
The calibrate_delay function in the Linux kernel can be one of the single most time-consuming events during system startup. For a 2.4 version Linux kernel, the calibrate_delay operation accounts for about 200 to 250 milliseconds of delay during kernel startup.

The value of loops_per_jiffy is primarily dependent on processor speed, and its initial value at boot time is expected to be constant for each boot of Linux on the same hardware. Because of this attribute, it is possible in most embedded situations to calculate the initial value in advance for a particular platform. This value can then be specified at compile time in the kernel, or provided to the kernel at boot time from an external source. This avoids the delay associated with dynamically calculating the value, by the kernel, on every system boot.

Specifications

 * 1) A configuration option for the Linux kernel SHALL be provided which controls whether the value of loops_per_jiffy is statically compiled into the kernel or not. This option MUST be named CONFIG_USE_PRESET_LPJ.
 * 2) With the kernel compiled with the CONFIG_USE_PRESET_LPJ option set, the system MUST avoid the delay associated with calculating loops_per_jiffy at runtime (with the exception of a "validation" error, mentioned below).
 * 3) If the option CONFIG_USE_PRESET_LPJ is set, but the value of loops_per_jiffy is not specified at compile time, then the kernel compile SHOULD fail.
 * 4) A kernel MAY provide support for accepting the value of loops_per_jiffy at boot time.
 * 5) If the kernel supports accepting the loops_per_jiffy value at boot time, then when loops_per_jiffy is so specified the kernel SHOULD avoid the delay associated with calculating loops_per_jiffy.
 * 6) If the kernel supports accepting the loops_per_jiffy value on the kernel command line, the syntax for this option MUST be: "lpj= ". The value for the option MUST be interpreted in loops_per_jiffy units.
 * 7) If the kernel supports accepting the loops_per_jiffy value at boot time, then the value provided at boot time should be used instead of any compiled-in (statically defined) value.
 * 8) When the kernel does not dynamically calculate the value of loops_per_jiffy itself, it MAY validate the value of loops_per_jiffy at bootup time. If validation is performed, and the value of loops_per_jiffy is found to be incorrect (to within a predetermined margin of error not specified here), the kernel SHOULD perform a normal delay calibration operation.

Notes (informational and non-normative)

 * Validating loops_per_jiffy means measuring that the value is accurate (within a certain tolerance) for creating a delay of 1 jiffy on the target platform. 2. It is expected that the cost to validate a preset value for loops_per_jiffy is about 1 jiffy. 3. Note that this specification avoids indicating how the value of loops_per_jiffy is specified at compile time. It could be done via another configuration option (intentionally not named here) or as a constant in the kernel source code. 4. An example of accepting the value of loops_per_jiffy at boot time would be a implementation where the firmware passed the value to the kernel on the kernel command line. 5. It is preferred that the feature to support acceptance of loops_per_jiffy at boot time not be a compile-time option.  That is, if the feature is present it should always be available, independent of the setting of CONFIG_USE_PRESET_LPJ. 6. It is expected that power management schemes that change the CPU frequency dynamically will be enabled after the calibrate_delay function completes. This means that the CPU frequency used for the initial calibration operation (or for which a preset value for loops_per_jiffy is provided at compilation or boot time) is the default bootup CPU frequency for the platform.

Power management systems which subsequently change CPU frequency may need to adjust the value of loops_per_jiffy with changes in the CPU frequency to keep internal kernel timing delays accurate.


 * Accepting the lpj= argument at the kernel command line is one possible way to comply with requirement 4 of the specification. Other ways are to use persistent memory populated by firmware or having the firmware pass the value to the kernel using a tagged sequence.

Remaining Issues
- need to specify the manifest constant for ATAG_PRESET_LPJ?