#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.
+ * This routine extracts a frequency property 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)
+EFI_get_frequency(const char *prop)
{
uint64_t frequency = 0;
DTEntry entry;
unsigned int size;
if (DTLookupEntry(0, "/efi/platform", &entry) != kSuccess) {
- kprintf("EFI_FSB_frequency: didn't find /efi/platform\n");
+ kprintf("EFI_get_frequency: didn't find /efi/platform\n");
return 0;
}
- if (DTGetProperty(entry,FSB_Frequency_prop,&value,&size) != kSuccess) {
- kprintf("EFI_FSB_frequency: property %s not found\n",
- FSB_Frequency_prop);
+ if (DTGetProperty(entry,prop,&value,&size) != kSuccess) {
+ kprintf("EFI_get_frequency: property %s not found\n", prop);
return 0;
}
if (size == sizeof(uint64_t)) {
frequency = *(uint64_t *) value;
- kprintf("EFI_FSB_frequency: read %s value: %llu\n",
- FSB_Frequency_prop, frequency);
- if (!(90*Mega < frequency && frequency < 10*Giga)) {
- kprintf("EFI_FSB_frequency: value out of range\n");
- frequency = 0;
- }
- } else {
- kprintf("EFI_FSB_frequency: unexpected size %d\n", size);
+ kprintf("EFI_get_frequency: read %s value: %llu\n",
+ prop, frequency);
}
/*
* While we're here, see if EFI published an initial TSC value.
*/
- if (DTGetProperty(entry,TSC_at_boot_prop,&value,&size) == kSuccess) {
+ if (DTGetProperty(entry,"InitialTSC",&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);
+ kprintf("EFI_get_frequency: read InitialTSC: %llu\n",
+ tsc_at_boot);
}
}
}
}
- /*
- * Get the FSB frequency and conversion factors from EFI.
- */
- busFreq = EFI_FSB_frequency();
-
switch (cpuid_cpufamily()) {
default: {
uint64_t msr_flex_ratio;
tscGranularity = flex_ratio;
}
+ busFreq = EFI_get_frequency("FSBFrequency");
/* If EFI isn't configured correctly, use a constant
* value. See 6036811.
*/
prfsts = rdmsr64(IA32_PERF_STS);
tscGranularity = (uint32_t)bitfield(prfsts, 44, 40);
N_by_2_bus_ratio = (prfsts & bit(46)) != 0;
+
+ busFreq = EFI_get_frequency("FSBFrequency");
}
}
(uint32_t)(busFCvtt2n >> 32), (uint32_t)busFCvtt2n,
(uint32_t)(busFCvtn2t >> 32), (uint32_t)busFCvtn2t);
- /*
- * Get the TSC increment. The TSC is incremented by this
- * on every bus tick. Calculate the TSC conversion factors
- * 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. If we cannot
- * determine the TSC conversion, assume it ticks at the bus frequency.
- */
- if (tscGranularity == 0)
+ if (tscFreq == busFreq) {
+ bus2tsc = 1;
tscGranularity = 1;
+ tscFCvtn2t = busFCvtn2t;
+ tscFCvtt2n = busFCvtt2n;
+ } else {
+ /*
+ * Get the TSC increment. The TSC is incremented by this
+ * on every bus tick. Calculate the TSC conversion factors
+ * 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.
+ */
+ if (N_by_2_bus_ratio)
+ tscFCvtt2n = busFCvtt2n * 2 / (1 + 2*tscGranularity);
+ else
+ tscFCvtt2n = busFCvtt2n / tscGranularity;
- if (N_by_2_bus_ratio)
- tscFCvtt2n = busFCvtt2n * 2 / (1 + 2*tscGranularity);
- else
- tscFCvtt2n = busFCvtt2n / tscGranularity;
+ tscFreq = ((1 * Giga) << 32) / tscFCvtt2n;
+ tscFCvtn2t = 0xFFFFFFFFFFFFFFFFULL / tscFCvtt2n;
- tscFreq = ((1 * Giga) << 32) / tscFCvtt2n;
- tscFCvtn2t = 0xFFFFFFFFFFFFFFFFULL / tscFCvtt2n;
+ /*
+ * Calculate conversion from BUS to TSC
+ */
+ bus2tsc = tmrCvt(busFCvtt2n, tscFCvtn2t);
+ }
kprintf(" TSC: Frequency = %6d.%06dMHz, "
"cvtt2n = %08X.%08X, cvtn2t = %08X.%08X, gran = %lld%s\n",
(uint32_t)(tscFCvtt2n >> 32), (uint32_t)tscFCvtt2n,
(uint32_t)(tscFCvtn2t >> 32), (uint32_t)tscFCvtn2t,
tscGranularity, N_by_2_bus_ratio ? " (N/2)" : "");
-
- /*
- * Calculate conversion from BUS to TSC
- */
- bus2tsc = tmrCvt(busFCvtt2n, tscFCvtn2t);
}
void