#include <config.h>
#include <machine/io.h>
#include <arch/kernel/apic.h>
#include <arch/model/statedata.h>
#include <arch/linker.h>
#include <plat/machine/pic.h>
#include <plat/machine/ioapic.h>
#include <plat/machine.h>
#include <plat/machine/intel-vtd.h>
BOOT_CODE bool_t platAddDevices(void)
{
if (PADDR_USER_DEVICE_TOP > 0xFFFFFFF8) {
if (!add_allocated_p_region( (p_region_t) {
(word_t)0xFFFFFFF8, (word_t)0xFFFFFFF8 + 8
})) {
return false;
}
}
return true;
}
void resetTimer(void)
{
}
#define TSC_FREQ_RETRIES 10
BOOT_CODE static inline uint32_t
measure_tsc_khz(void)
{
for (int i = 0; i < TSC_FREQ_RETRIES; i++) {
uint64_t old_ticks = x86_rdtsc();
pit_wait_wraparound();
uint64_t new_ticks = x86_rdtsc();
uint64_t diff = new_ticks - old_ticks;
if ((uint32_t)diff == diff && new_ticks > old_ticks) {
return (uint32_t)diff / PIT_WRAPAROUND_MS;
}
printf("warning: TSC frequency too high (%d retries remaining)\n",
TSC_FREQ_RETRIES - i - 1);
}
fail("TSC frequency too high");
return 0;
}
BOOT_CODE uint32_t
tsc_init(void)
{
x86_cpu_identity_t *model_info = x86_cpuid_get_model_info();
uint32_t valid_models[] = {
NEHALEM_1_MODEL_ID, NEHALEM_2_MODEL_ID, NEHALEM_3_MODEL_ID,
SANDY_BRIDGE_1_MODEL_ID, SANDY_BRIDGE_2_MODEL_ID,
HASWELL_1_MODEL_ID, HASWELL_2_MODEL_ID, HASWELL_3_MODEL_ID, HASWELL_4_MODEL_ID,
IVY_BRIDGE_1_MODEL_ID, IVY_BRIDGE_2_MODEL_ID, IVY_BRIDGE_3_MODEL_ID,
BROADWELL_2_MODEL_ID, BROADWELL_3_MODEL_ID, BROADWELL_4_MODEL_ID, BROADWELL_5_MODEL_ID,
SKYLAKE_1_MODEL_ID, SKYLAKE_2_MODEL_ID
};
if (model_info->family == IA32_PREFETCHER_COMPATIBLE_FAMILIES_ID) {
for (int i = 0; i < ARRAY_SIZE(valid_models); i++) {
if (model_info->model == valid_models[i]) {
rdmsr_safe_result_t info = x86_rdmsr_safe(IA32_PLATFORM_INFO_MSR);
if (info.success) {
uint32_t ratio = (((uint32_t) info.value) & 0xFF00) >> 8u;
if (ratio != 0) {
if (model_info->model == NEHALEM_1_MODEL_ID ||
model_info->model == NEHALEM_2_MODEL_ID ||
model_info->model == NEHALEM_3_MODEL_ID) {
return ratio * 13333u / 100u;
} else {
return ratio * 100u;
}
}
}
break;
}
}
}
pit_init();
pit_wait_wraparound();
uint32_t tsc_khz = measure_tsc_khz();
return tsc_khz / 1000u;
}