[PATCH] x86/apic: fix frequency in apic=verbose log output

From: Julian Stecklina
Date: Sat Oct 30 2021 - 10:22:19 EST


From: Julian Stecklina <julian.stecklina@xxxxxxxxxxxxxxxxxxxxx>

When apic=verbose is specified, the LAPIC timer calibration prints its
results to the console. While debugging virtualization code, we
noticed that the CPU and bus frequencies are printed incorrectly.

Specifically, for a 1.7 GHz CPU with 1 GHz bus frequency and HZ=1000,
the log includes a superfluous 0 after the period:

..... calibration result: 999978
..... CPU clock speed is 1696.0783 MHz.
..... host bus clock speed is 999.0978 MHz.

Looking at the code, this only worked as intended for HZ=100. After
the fix, we now see the correct frequency in the log:

..... calibration result: 999828
..... CPU clock speed is 1696.507 MHz.
..... host bus clock speed is 999.828 MHz.

There is no functional change to the LAPIC calibration here, beyond
the printf changes.

Suggested-by: Markus Napierkowski <markus.napierkowski@xxxxxxxxxxxxxxxxxxxxx>
Signed-off-by: Julian Stecklina <julian.stecklina@xxxxxxxxxxxxxxxxxxxxx>
---
arch/x86/kernel/apic/apic.c | 14 ++++++++------
1 file changed, 8 insertions(+), 6 deletions(-)

diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c
index b70344bf6600..925becaac12a 100644
--- a/arch/x86/kernel/apic/apic.c
+++ b/arch/x86/kernel/apic/apic.c
@@ -198,6 +198,7 @@ static struct resource lapic_resource = {
.flags = IORESOURCE_MEM | IORESOURCE_BUSY,
};

+/* Measured in ticks per HZ. */
unsigned int lapic_timer_period = 0;

static void apic_pm_activate(void);
@@ -835,6 +836,7 @@ static int __init calibrate_APIC_clock(void)
unsigned long jif_start;
unsigned long deltaj;
long delta, deltatsc;
+ long tsc_khz, bus_khz;
int pm_referenced = 0;

if (boot_cpu_has(X86_FEATURE_TSC_DEADLINE_TIMER))
@@ -937,16 +939,16 @@ static int __init calibrate_APIC_clock(void)
lapic_timer_period);

if (boot_cpu_has(X86_FEATURE_TSC)) {
+ tsc_khz = (deltatsc * HZ) / (1000 * LAPIC_CAL_LOOPS);
apic_printk(APIC_VERBOSE, "..... CPU clock speed is "
- "%ld.%04ld MHz.\n",
- (deltatsc / LAPIC_CAL_LOOPS) / (1000000 / HZ),
- (deltatsc / LAPIC_CAL_LOOPS) % (1000000 / HZ));
+ "%ld.%03ld MHz.\n",
+ tsc_khz / 1000, tsc_khz % 1000);
}

+ bus_khz = (long)lapic_timer_period * HZ / 1000;
apic_printk(APIC_VERBOSE, "..... host bus clock speed is "
- "%u.%04u MHz.\n",
- lapic_timer_period / (1000000 / HZ),
- lapic_timer_period % (1000000 / HZ));
+ "%ld.%03ld MHz.\n",
+ bus_khz / 1000, bus_khz % 1000);

/*
* Do a sanity check on the APIC calibration result
--
2.31.1