getting cpu bus speed for apic timer
Posted: Wed Oct 21, 2015 10:56 pm
Hi, Does a value of 218mhz seem right as the outcome of using the pit to time and find the number of ticks elapsed in an apic timer? Seems kind of low to me. Running on real hardware.
Here is my pit timing code:
and here is the actual speed finding code
Here is my pit timing code:
Code: Select all
// pit trigger speed in hz
#define CYCLE ((uint64_tp)1193182)
static uint32_tp pit_hz = 200;
static uint32_tp pit_divisor = CYCLE / pit_hz;
// count of ticks since start where there are pit_hz ticks per second.
static volatile uint64_tp pit_ticks = 0;
// IRQ handler
void smos_pit_tick(registers_tp *regs_)
{
++pit_ticks;
}
void pit()
{
ASM("cli");
// do note, while this is registered, its the only irq we'll handle
// (besides PF and GPF)
smos_register_int_handler(32, smos_pit_tick);
// chan 0, lo/hibyte rate generator
smos_outb(0x43, FROM_BINARY(0, 0, 1, 1, 0, 1, 0, 0));
smos_outb(0x40, pit_divisor & 0xff);
smos_outb(0x40, (pit_divisor >> 8) & 0xff);
clear_irq_mask(0);
ASM("sti");
}
void pit_done()
{
ASM("cli");
smos_register_int_handler(32, 0);
set_irq_mask(0);
// TODO: actually stop the pit
}
Code: Select all
#define APIC_SPURIOUS 0xf0
#define APIC_LVT_TMR 0x320
#define APIC_TMRDIV 0x3e0
#define APIC_TMRINITCNT 0x380
#define APIC_DISABLE 0x10000
#define APIC_TMRCURRCNT 0x390
#define APIC_SW_ENABLE 0x100
typedef uint8_tp *addr_tp;
void set_dword_at(addr_tp addr_, uint32_tp val_) { *((uint32_tp *)addr_) = val_; }
func()
{
// where the registers are in regular virtual space (mapped earlier)
addr_tp apic = (addr_tp)smos.apic_registers_base;
// set spurious irq.. My int handler just returns if this triggers.
set_dword_at(apic + APIC_SPURIOUS, 39 + APIC_SW_ENABLE);
set_dword_at(apic + APIC_LVT_TMR, 32); // timer irq to use (?)
set_dword_at(apic + APIC_TMRDIV, 0x03); // divide ratio is 16.
uint32_tp target = pit_hz / 4; // we wait 250ms
pit(); // start the timer
// start the apic counting down.
set_dword_at(apic + APIC_TMRINITCNT, 0xffffffff);
while (pit_ticks < target) ASM("hlt"); // wait til 250ms has elapsed
pit_done(); // stop pit
set_dword_at(apic + APIC_LVT_TMR, APIC_DISABLE); // disable apic
uint32_tp count = get_dword_at(apic + APIC_TMRCURRCNT);
uint32_tp diff = (0xffffffff - count); // number of ticks that occurred in 250ms
// * 16 because we used a divisor of 16
// * 4 because we only waited 250ms.
uint64_tp cpu_bus_hz = (uint64_tp)diff * 16 * 4;
kprintf("speed %u mhz\n", cpu_bus_hz / 1024 / 1024); // this outputs approx 218
}