X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/b0d623f7f2ae71ed96e60569f61f9a9a27016e80..15129b1c8dbb3650c63b70adb1cad9af601c6c17:/osfmk/i386/tsc.c diff --git a/osfmk/i386/tsc.c b/osfmk/i386/tsc.c index 6744a9097..f79a8fcb2 100644 --- a/osfmk/i386/tsc.c +++ b/osfmk/i386/tsc.c @@ -36,7 +36,6 @@ */ #include -#include #include @@ -51,7 +50,6 @@ #include #include #include /* for kernel_map */ -#include #include #include #include @@ -78,6 +76,7 @@ uint32_t flex_ratio = 0; uint32_t flex_ratio_min = 0; uint32_t flex_ratio_max = 0; +uint64_t tsc_at_boot = 0; #define bit(n) (1ULL << (n)) #define bitmask(h,l) ((bit(h)|(bit(h)-1)) & ~(bit(l)-1)) @@ -93,8 +92,10 @@ uint32_t flex_ratio_max = 0; #define CPU_FAMILY_PENTIUM_M (0x6) static const char FSB_Frequency_prop[] = "FSBFrequency"; +static const char TSC_at_boot_prop[] = "InitialTSC"; /* * This routine extracts the bus frequency in Hz from the device tree. + * Also reads any initial TSC value at boot from the device tree. */ static uint64_t EFI_FSB_frequency(void) @@ -124,6 +125,18 @@ EFI_FSB_frequency(void) } else { kprintf("EFI_FSB_frequency: unexpected size %d\n", size); } + + /* + * While we're here, see if EFI published an initial TSC value. + */ + if (DTGetProperty(entry,TSC_at_boot_prop,&value,&size) == kSuccess) { + if (size == sizeof(uint64_t)) { + tsc_at_boot = *(uint64_t *) value; + kprintf("EFI_FSB_frequency: read %s value: %llu\n", + TSC_at_boot_prop, tsc_at_boot); + } + } + return frequency; } @@ -134,22 +147,44 @@ EFI_FSB_frequency(void) void tsc_init(void) { - uint64_t busFCvtInt = 0; boolean_t N_by_2_bus_ratio = FALSE; + if (cpuid_vmm_present()) { + kprintf("VMM vendor %u TSC frequency %u KHz bus frequency %u KHz\n", + cpuid_vmm_info()->cpuid_vmm_family, + cpuid_vmm_info()->cpuid_vmm_tsc_frequency, + cpuid_vmm_info()->cpuid_vmm_bus_frequency); + + if (cpuid_vmm_info()->cpuid_vmm_tsc_frequency && + cpuid_vmm_info()->cpuid_vmm_bus_frequency) { + + busFreq = (uint64_t)cpuid_vmm_info()->cpuid_vmm_bus_frequency * kilo; + busFCvtt2n = ((1 * Giga) << 32) / busFreq; + busFCvtn2t = 0xFFFFFFFFFFFFFFFFULL / busFCvtt2n; + + tscFreq = (uint64_t)cpuid_vmm_info()->cpuid_vmm_tsc_frequency * kilo; + tscFCvtt2n = ((1 * Giga) << 32) / tscFreq; + tscFCvtn2t = 0xFFFFFFFFFFFFFFFFULL / tscFCvtt2n; + + tscGranularity = tscFreq / busFreq; + + bus2tsc = tmrCvt(busFCvtt2n, tscFCvtn2t); + + return; + } + } + /* * Get the FSB frequency and conversion factors from EFI. */ busFreq = EFI_FSB_frequency(); - if (cpuid_info()->cpuid_family != CPU_FAMILY_PENTIUM_M) { - panic("tsc_init: unknown CPU family: 0x%X\n", - cpuid_info()->cpuid_family); - } - - switch (cpuid_info()->cpuid_model) { - case CPUID_MODEL_NEHALEM: { - uint64_t cpu_mhz; + switch (cpuid_cpufamily()) { + case CPUFAMILY_INTEL_HASWELL: + case CPUFAMILY_INTEL_IVYBRIDGE: + case CPUFAMILY_INTEL_SANDYBRIDGE: + case CPUFAMILY_INTEL_WESTMERE: + case CPUFAMILY_INTEL_NEHALEM: { uint64_t msr_flex_ratio; uint64_t msr_platform_info; @@ -173,8 +208,6 @@ tsc_init(void) if (busFreq == 0) busFreq = BASE_NHM_CLOCK_SOURCE; - cpu_mhz = tscGranularity * BASE_NHM_CLOCK_SOURCE; - break; } default: { @@ -189,19 +222,16 @@ tsc_init(void) if (busFreq != 0) { busFCvtt2n = ((1 * Giga) << 32) / busFreq; busFCvtn2t = 0xFFFFFFFFFFFFFFFFULL / busFCvtt2n; - busFCvtInt = tmrCvt(1 * Peta, 0xFFFFFFFFFFFFFFFFULL / busFreq); } else { panic("tsc_init: EFI not supported!\n"); } - kprintf(" BUS: Frequency = %6d.%04dMHz, " - "cvtt2n = %08X.%08X, cvtn2t = %08X.%08X, " - "cvtInt = %08X.%08X\n", + kprintf(" BUS: Frequency = %6d.%06dMHz, " + "cvtt2n = %08X.%08X, cvtn2t = %08X.%08X\n", (uint32_t)(busFreq / Mega), (uint32_t)(busFreq % Mega), (uint32_t)(busFCvtt2n >> 32), (uint32_t)busFCvtt2n, - (uint32_t)(busFCvtn2t >> 32), (uint32_t)busFCvtn2t, - (uint32_t)(busFCvtInt >> 32), (uint32_t)busFCvtInt); + (uint32_t)(busFCvtn2t >> 32), (uint32_t)busFCvtn2t); /* * Get the TSC increment. The TSC is incremented by this @@ -209,8 +239,12 @@ tsc_init(void) * to and from nano-seconds. * The tsc granularity is also called the "bus ratio". If the N/2 bit * is set this indicates the bus ration is 0.5 more than this - i.e. - * that the true bus ratio is (2*tscGranularity + 1)/2. + * that the true bus ratio is (2*tscGranularity + 1)/2. If we cannot + * determine the TSC conversion, assume it ticks at the bus frequency. */ + if (tscGranularity == 0) + tscGranularity = 1; + if (N_by_2_bus_ratio) tscFCvtt2n = busFCvtt2n * 2 / (1 + 2*tscGranularity); else @@ -219,7 +253,7 @@ tsc_init(void) tscFreq = ((1 * Giga) << 32) / tscFCvtt2n; tscFCvtn2t = 0xFFFFFFFFFFFFFFFFULL / tscFCvtt2n; - kprintf(" TSC: Frequency = %6d.%04dMHz, " + kprintf(" TSC: Frequency = %6d.%06dMHz, " "cvtt2n = %08X.%08X, cvtn2t = %08X.%08X, gran = %lld%s\n", (uint32_t)(tscFreq / Mega), (uint32_t)(tscFreq % Mega),