]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blobdiff - arch/x86/kernel/tsc.c
x86/cpu: Sanitize FAM6_ATOM naming
[mirror_ubuntu-bionic-kernel.git] / arch / x86 / kernel / tsc.c
index ad2b925a808e7327dec37ae03c60ea2901d48352..7d5f9910c39d55e34eaee85402bd2a6a95ab9056 100644 (file)
@@ -25,6 +25,7 @@
 #include <asm/geode.h>
 #include <asm/apic.h>
 #include <asm/intel-family.h>
+#include <asm/i8259.h>
 
 unsigned int __read_mostly cpu_khz;    /* TSC clocks / usec, not used here */
 EXPORT_SYMBOL(cpu_khz);
@@ -112,7 +113,7 @@ static void cyc2ns_data_init(struct cyc2ns_data *data)
        data->cyc2ns_offset = 0;
 }
 
-static void cyc2ns_init(int cpu)
+static void __init cyc2ns_init(int cpu)
 {
        struct cyc2ns *c2n = &per_cpu(cyc2ns, cpu);
 
@@ -316,7 +317,7 @@ static unsigned long calc_hpet_ref(u64 deltatsc, u64 hpet1, u64 hpet2)
        hpet2 -= hpet1;
        tmp = ((u64)hpet2 * hpet_readl(HPET_PERIOD));
        do_div(tmp, 1000000);
-       do_div(deltatsc, tmp);
+       deltatsc = div64_u64(deltatsc, tmp);
 
        return (unsigned long) deltatsc;
 }
@@ -363,6 +364,20 @@ static unsigned long pit_calibrate_tsc(u32 latch, unsigned long ms, int loopmin)
        unsigned long tscmin, tscmax;
        int pitcnt;
 
+       if (!has_legacy_pic()) {
+               /*
+                * Relies on tsc_early_delay_calibrate() to have given us semi
+                * usable udelay(), wait for the same 50ms we would have with
+                * the PIT loop below.
+                */
+               udelay(10 * USEC_PER_MSEC);
+               udelay(10 * USEC_PER_MSEC);
+               udelay(10 * USEC_PER_MSEC);
+               udelay(10 * USEC_PER_MSEC);
+               udelay(10 * USEC_PER_MSEC);
+               return ULONG_MAX;
+       }
+
        /* Set the Gate high, disable speaker */
        outb((inb(0x61) & ~0x02) | 0x01, 0x61);
 
@@ -487,6 +502,9 @@ static unsigned long quick_pit_calibrate(void)
        u64 tsc, delta;
        unsigned long d1, d2;
 
+       if (!has_legacy_pic())
+               return 0;
+
        /* Set the Gate high, disable speaker */
        outb((inb(0x61) & ~0x02) | 0x01, 0x61);
 
@@ -602,8 +620,7 @@ unsigned long native_calibrate_tsc(void)
                case INTEL_FAM6_KABYLAKE_DESKTOP:
                        crystal_khz = 24000;    /* 24.0 MHz */
                        break;
-               case INTEL_FAM6_SKYLAKE_X:
-               case INTEL_FAM6_ATOM_DENVERTON:
+               case INTEL_FAM6_ATOM_GOLDMONT_X:
                        crystal_khz = 25000;    /* 25.0 MHz */
                        break;
                case INTEL_FAM6_ATOM_GOLDMONT:
@@ -612,6 +629,8 @@ unsigned long native_calibrate_tsc(void)
                }
        }
 
+       if (crystal_khz == 0)
+               return 0;
        /*
         * TSC frequency determined by CPUID is a "hardware reported"
         * frequency and is the most accurate one so far we have. This
@@ -812,13 +831,13 @@ unsigned long native_calibrate_cpu(void)
        return tsc_pit_min;
 }
 
-int recalibrate_cpu_khz(void)
+void recalibrate_cpu_khz(void)
 {
 #ifndef CONFIG_SMP
        unsigned long cpu_khz_old = cpu_khz;
 
        if (!boot_cpu_has(X86_FEATURE_TSC))
-               return -ENODEV;
+               return;
 
        cpu_khz = x86_platform.calibrate_cpu();
        tsc_khz = x86_platform.calibrate_tsc();
@@ -828,10 +847,6 @@ int recalibrate_cpu_khz(void)
                cpu_khz = tsc_khz;
        cpu_data(0).loops_per_jiffy = cpufreq_scale(cpu_data(0).loops_per_jiffy,
                                                    cpu_khz_old, cpu_khz);
-
-       return 0;
-#else
-       return -ENODEV;
 #endif
 }
 
@@ -959,17 +974,21 @@ core_initcall(cpufreq_register_tsc_scaling);
 /*
  * If ART is present detect the numerator:denominator to convert to TSC
  */
-static void detect_art(void)
+static void __init detect_art(void)
 {
        unsigned int unused[2];
 
        if (boot_cpu_data.cpuid_level < ART_CPUID_LEAF)
                return;
 
-       /* Don't enable ART in a VM, non-stop TSC and TSC_ADJUST required */
+       /*
+        * Don't enable ART in a VM, non-stop TSC and TSC_ADJUST required,
+        * and the TSC counter resets must not occur asynchronously.
+        */
        if (boot_cpu_has(X86_FEATURE_HYPERVISOR) ||
            !boot_cpu_has(X86_FEATURE_NONSTOP_TSC) ||
-           !boot_cpu_has(X86_FEATURE_TSC_ADJUST))
+           !boot_cpu_has(X86_FEATURE_TSC_ADJUST) ||
+           tsc_async_resets)
                return;
 
        cpuid(ART_CPUID_LEAF, &art_to_tsc_denominator,
@@ -1263,6 +1282,25 @@ static int __init init_tsc_clocksource(void)
  */
 device_initcall(init_tsc_clocksource);
 
+void __init tsc_early_delay_calibrate(void)
+{
+       unsigned long lpj;
+
+       if (!boot_cpu_has(X86_FEATURE_TSC))
+               return;
+
+       cpu_khz = x86_platform.calibrate_cpu();
+       tsc_khz = x86_platform.calibrate_tsc();
+
+       tsc_khz = tsc_khz ? : cpu_khz;
+       if (!tsc_khz)
+               return;
+
+       lpj = tsc_khz * 1000;
+       do_div(lpj, HZ);
+       loops_per_jiffy = lpj;
+}
+
 void __init tsc_init(void)
 {
        u64 lpj, cyc;
@@ -1296,6 +1334,12 @@ void __init tsc_init(void)
                (unsigned long)cpu_khz / 1000,
                (unsigned long)cpu_khz % 1000);
 
+       if (cpu_khz != tsc_khz) {
+               pr_info("Detected %lu.%03lu MHz TSC",
+                       (unsigned long)tsc_khz / 1000,
+                       (unsigned long)tsc_khz % 1000);
+       }
+
        /* Sanitize TSC ADJUST before cyc2ns gets initialized */
        tsc_store_and_check_tsc_adjust(true);