]> xenbits.xensource.com Git - xen.git/commitdiff
x86/time: reduce rounding errors in calculations
authorJan Beulich <jbeulich@suse.com>
Mon, 16 Mar 2020 16:31:35 +0000 (17:31 +0100)
committerJan Beulich <jbeulich@suse.com>
Mon, 16 Mar 2020 16:31:35 +0000 (17:31 +0100)
Plain (unsigned) integer division simply truncates the results. The
overall errors are smaller though if we use proper rounding. (Extend
this to the purely cosmetic aspect of time.c's freq_string(), which
before this change I've frequently observed to report e.g. NN.999MHz
HPET clock speeds.)

While adding the rounding logic, also switch to using an unsigned
constant for the other, original half of bus_cycle's calculation.

Signed-off-by: Jan Beulich <jbeulich@suse.com>
Acked-by: Andrew Cooper <andrew.cooper3@citrix.com>
xen/arch/x86/apic.c
xen/arch/x86/hpet.c
xen/arch/x86/time.c

index dbea826d48713d1b768ecbd2065a60c24d14b19f..ab30de939c3d7c7c5452c591489746bb23bd41bf 100644 (file)
@@ -1260,8 +1260,10 @@ static int __init calibrate_APIC_clock(void)
 
     /* set up multipliers for accurate timer code */
     bus_freq   = result*HZ;
-    bus_cycle  = (u32) (1000000000000LL/bus_freq); /* in pico seconds */
+    bus_cycle  = 1000000000000UL / bus_freq; /* in pico seconds */
+    bus_cycle += (1000000000000UL % bus_freq) * 2 > bus_freq;
     bus_scale  = (1000*262144)/bus_cycle;
+    bus_scale += ((1000 * 262144) % bus_cycle) * 2 > bus_cycle;
 
     apic_printk(APIC_VERBOSE, "..... bus_scale = %#x\n", bus_scale);
     /* reset APIC to zero timeout value */
index ae99993d90c6cb2dd80bb4f81917bb100372da79..86929b9ba19d6b61bb02e9b976d9d22ee5b46e26 100644 (file)
@@ -799,9 +799,9 @@ u64 __init hpet_setup(void)
     hpet_resume(hpet_boot_cfg);
 
     hpet_rate = 1000000000000000ULL; /* 10^15 */
-    (void)do_div(hpet_rate, hpet_period);
+    last = do_div(hpet_rate, hpet_period);
 
-    return hpet_rate;
+    return hpet_rate + (last * 2 > hpet_period);
 }
 
 void hpet_resume(u32 *boot_cfg)
index bb1b97787fc7c61a805037ac9c99fb935f8e3bba..2d4430b283c9c8e1143995226eba88538047a3a1 100644 (file)
@@ -275,7 +275,10 @@ static char *freq_string(u64 freq)
 {
     static char s[20];
     unsigned int x, y;
-    y = (unsigned int)do_div(freq, 1000000) / 1000;
+
+    if ( do_div(freq, 1000) > 500 )
+        ++freq;
+    y = (unsigned int)do_div(freq, 1000);
     x = (unsigned int)freq;
     snprintf(s, sizeof(s), "%u.%03uMHz", x, y);
     return s;