Thursday, January 10, 2008

More on HPET..

Welcome back!

If you are all waiting for what the reply from kernelnewbies was , there was no reply infact! This post is about the HPET research i carried out with the specs in hand and looking at the source code.

The line hpet0: at MMIO 0xfed00000, IRQs 2, 8, 0, make me realize that something was fishy, so I decided to look into the area where the IRQs were actually assigned, and I found it in arch/x86/kernel/hpet.c.

In that piece of code, a register field names TN_INT_ROUTE_CNF was being read from the per timer Configuration and Capabilities register. I quickly turned pages in the specs to see what it does, and It read that

" Default is 00h Software writes to this field to select which interrupt in the I/O (x) will be used for this timer’s interrupt. If the value is not supported by this prarticular timer, then the value read back will not match what is written. The software must only write valid values."


So, I got the reason why the value of 0 IRQ was being given to timer 2. Well, if it's zero be default, who changes it was the question. Ideally the BIOS assigns IRQs to various PCI devices. So, could it be a BIOS bug ? No, because many posts on LKML with dmesg, showed the same line which I got.

I decided to try one more thing. Why not mmap /dev/hpet and look at the registers ? I did so, and got a dump of its 1K register space and began examining it. I turn to the 'Timer N Configuration and Capabilities register' in the spec, and began looking at the first field,

" Tn_INT_ROUTE_CAP - Timer n Interrupt Routing Capability: (where n is the timer number: 00 to 31) This 32-bit read-only field indicates to which interrupts in the I/O (x) APIC this timer’s interrupt can be routed. This is used in conjunction with the Tn_INT_ROUTE_CNF field. Each bit in this field corresponds to a particular interrupt. For example, if this timer’s interrupt can be mapped to interrupts 16, 18, 20, 22, or 24, then bits 16, 18, 20, 22, and 24 in this field will be set to 1. All other bits will be 0. "

Wow!! was my reaction. So using this bitmap field, I could assign interrupts to timers! I wrote a dirty and quick patch, and ran the userspace program and to my astonishment, it worked like a charm!

This is about making the userspace API work. The kernelspace API is a bit different, in that it does not use ioctls, but has a struct hpet_task object and stuff. Its simple to use. So my next job is to make the kernelspace API to work..

Will post again on that.. stay tuned folks!

Tuesday, January 8, 2008

HPET support for qemu

For those who don't know what HPET is check out the specifications at the Intel site and continue reading.

It was only yesterday I decided to work on adding HPET support to qemu. I talked to Amit Shah(the only employee of Qumranet in India), for ideas on this and how to go about it.

He told me to start off by making qemu access the HPET in userspace and then extend it to make it visible on the guest. Emulation of a HPET in cases where there is no real hardware, comes at a later stage. I am lucky to have a new Core 2 Duo 945 chipset machine which has HPET which fortunately became 'visible' only after I flashed my BIOS!. But my excitation quickly died down when I began trying to run the userspace program (Documentation/hpet.txt). It would not run. It was failing at the Interrupt Enable (HPET_IE_ON) ioctl command.

As usual, i decided to find a solution to this problem by googling for HPET. But even after searching for a long time, I could not find even a single place where i could get help, so i decided to write this blog, so that I will be the first one to have a nice resource on HPET!

Deciding to track down this problem, I started looking at the kernel sources. I began by adding printks in drivers/char/hpet.c. Grepping through the kernel logs showed me that my HPET had 3 timer blocks which used interrupts 2, 8 and 0. My printks told me that when I opened /dev/hpet, I got assigned a timer block which had interrupt 0, and hence the routine hpet_ioctl_ieon would not continue using it and it fails.

I think this happens because of improper ACPI tables which report the IRQ of the third HEPT timer block as 0. I have posted a query on kernelnewbies and now awaiting a reply..

Will continue this once i get this reply! Stay tuned..