Qemu PIT Broken?
Posted: Tue Mar 20, 2012 11:52 pm
Is it me, or is Qemu's PIT very dodgy? I'm trying to use the PIT to create consistent delays for MP startup, but it seems that Qemu does not handle the PIT very well at all.
I'm testing it like so:
The problem is that the rate at which Qemu generates the interrupts is very inconsistent. When I run the above code, I get ~20 interrupts a second, which is same is what I get without changing the reload value (which I assume is set to 65535\65536 by the BIOS) which is what you would expect by default, but not with a reload value of just 5.
Other values I've tested:
Low: 0x10 High: 0x00
I get a steady stream of interrupts, about very roughly 4096 every ~10 seconds
Low: 0xF0 High: 0x00
I get about twice as many interrupts as above
Low: 0xF0 High: 0xF0
I'm back to the ~20 interrupts a second routine.
I understand that Qemu cant emulate the PIT to a degree anywhere close to what the real deal can, but obviously this isn't right. Am I doing something wrong? Everything seems to work just fine in Virtualbox (changing the (ticks % 16) to a much higher value or nothing is ever really seen with low reloads, as one would expect).
I've used the old binaries included with Qemu Manager 7 and recent ones found below with the same results.
http://lassauge.free.fr/qemu/
(I tried to compile the git repo, but it's giving me grief on Cygwin).
I'm testing it like so:
Code: Select all
PRIVATE u64 ticks = 0;
void pit_tick()
{
ticks++;
if (!(ticks % 16))
{
kprintf_cls();
kprintf("Ticks: %X", ticks);
}
outb(MASTER_PIC_COMMAND, 0x20);
}
PRIVATE void pit_init()
{
/* First setup the PIC */
outb(MASTER_PIC_COMMAND, ICW1_INIT + ICW1_ICW4);
outb(SLAVE_PIC_COMMAND, ICW1_INIT + ICW1_ICW4);
outb(MASTER_PIC_DATA, 0x20);
outb(SLAVE_PIC_DATA, 0x28);
outb(MASTER_PIC_DATA, 4);
outb(SLAVE_PIC_DATA, 2);
outb(MASTER_PIC_DATA, ICW4_8086);
outb(SLAVE_PIC_DATA, ICW4_8086);
/* Mask all interrupts besides IRQ 0 (the PIT) */
outb(MASTER_PIC_DATA, 0xFE);
outb(SLAVE_PIC_DATA, 0xFF);
outb(PIT_COMMAND, 0x34); // Channel 0, Mode 2, Lo\Hi bytes access mode
outb(PIT0_DATA, 0x05);
outb(PIT0_DATA, 0x00);
set_isr(32, (unsigned long)pit_tick, 0x8, 0x8E00);
enable_interrupts();
for(;;);
}
The problem is that the rate at which Qemu generates the interrupts is very inconsistent. When I run the above code, I get ~20 interrupts a second, which is same is what I get without changing the reload value (which I assume is set to 65535\65536 by the BIOS) which is what you would expect by default, but not with a reload value of just 5.
Other values I've tested:
Low: 0x10 High: 0x00
I get a steady stream of interrupts, about very roughly 4096 every ~10 seconds
Low: 0xF0 High: 0x00
I get about twice as many interrupts as above
Low: 0xF0 High: 0xF0
I'm back to the ~20 interrupts a second routine.
I understand that Qemu cant emulate the PIT to a degree anywhere close to what the real deal can, but obviously this isn't right. Am I doing something wrong? Everything seems to work just fine in Virtualbox (changing the (ticks % 16) to a much higher value or nothing is ever really seen with low reloads, as one would expect).
I've used the old binaries included with Qemu Manager 7 and recent ones found below with the same results.
http://lassauge.free.fr/qemu/
(I tried to compile the git repo, but it's giving me grief on Cygwin).