static void rtblget(struct apic *apic, int sel, uint32_t * hi, uint32_t * lo) { sel = Ioredtbl + 2 * sel; write_mmreg32(apic->addr + Ioregsel, sel + 1); *hi = read_mmreg32(apic->addr + Iowin); write_mmreg32(apic->addr + Ioregsel, sel); *lo = read_mmreg32(apic->addr + Iowin); }
/* * Sets the LAPIC timer to go off after a certain number of ticks. The primary * clock freq is actually the bus clock, which we figure out during timer_init * Unmasking is implied. Ref SDM, 3A, 9.6.4 */ void __lapic_set_timer(uint32_t ticks, uint8_t vec, bool periodic, uint8_t div) { // clears bottom bit and then set divider write_mmreg32(LAPIC_TIMER_DIVIDE, (read_mmreg32(LAPIC_TIMER_DIVIDE) &~0xf) | (div & 0xf)); // set LVT with interrupt handling information write_mmreg32(LAPIC_LVT_TIMER, vec | (periodic << 17)); write_mmreg32(LAPIC_TIMER_INIT, ticks); // For debugging when we expand this //cprintf("LAPIC LVT Timer: 0x%08x\n", read_mmreg32(LAPIC_LVT_TIMER)); //cprintf("LAPIC Init Count: 0x%08x\n", read_mmreg32(LAPIC_TIMER_INIT)); //cprintf("LAPIC Current Count: 0x%08x\n", read_mmreg32(LAPIC_TIMER_CURRENT)); }
// timer init calibrates both tsc timer and lapic timer using PIT void timer_init(void){ uint64_t tscval[2]; long timercount[2]; pit_set_timer(0xffff, TIMER_RATEGEN); // assume tsc exist tscval[0] = read_tsc(); udelay_pit(1000000); tscval[1] = read_tsc(); system_timing.tsc_freq = SINIT(tscval[1] - tscval[0]); cprintf("TSC Frequency: %llu\n", system_timing.tsc_freq); __lapic_set_timer(0xffffffff, LAPIC_TIMER_DEFAULT_VECTOR, FALSE, LAPIC_TIMER_DEFAULT_DIVISOR); // Mask the LAPIC Timer, so we never receive this interrupt (minor race) mask_lapic_lvt(LAPIC_LVT_TIMER); timercount[0] = read_mmreg32(LAPIC_TIMER_CURRENT); udelay_pit(1000000); timercount[1] = read_mmreg32(LAPIC_TIMER_CURRENT); system_timing.bus_freq = SINIT((timercount[0] - timercount[1])*128); cprintf("Bus Frequency: %llu\n", system_timing.bus_freq); }