PCI PIC IRQs
PCI PIC IRQs
Hello!
Im using Virtualbox on my Windows Host to code my own Operating System.
Im testing it on many different virtual machines and I've got a problem with it on Virtualbox.
The problem:
My OS is using different PCI devices.
I used the status code of the PCI devices to make sure the interrupt was triggered from this particular device in my interrupt handler incase the BIOS maps the IRQs to the same offset (0xA/0xB..)
Virtualbox BIOS is nice and maps all 3 devices to 3 different IRQs so no IRQ sharing is happening.
The problem is, I still have to check whether a device has triggered that particular IRQ or not.
I made sure my code is correct by testing it on QEMU and VMWare, both set the 3rd bit (0x8) as expected but Virtualbox doesnt, which results in unhandled IRQs.
Thanks for your time and thanks in advance!
Im using Virtualbox on my Windows Host to code my own Operating System.
Im testing it on many different virtual machines and I've got a problem with it on Virtualbox.
The problem:
My OS is using different PCI devices.
I used the status code of the PCI devices to make sure the interrupt was triggered from this particular device in my interrupt handler incase the BIOS maps the IRQs to the same offset (0xA/0xB..)
Virtualbox BIOS is nice and maps all 3 devices to 3 different IRQs so no IRQ sharing is happening.
The problem is, I still have to check whether a device has triggered that particular IRQ or not.
I made sure my code is correct by testing it on QEMU and VMWare, both set the 3rd bit (0x8) as expected but Virtualbox doesnt, which results in unhandled IRQs.
Thanks for your time and thanks in advance!
Last edited by Ch40zz on 5. Mar 2016, 01:02, edited 1 time in total.
-
- Site Moderator
- Posts: 39134
- Joined: 4. Sep 2008, 17:09
- Primary OS: MS Windows 10
- VBox Version: PUEL
- Guest OSses: Mostly XP
Re: PCI PIC IRQs
What does this question have to do with "Windows Hosts"? Moving it to "Other Guests".
-
- Oracle Corporation
- Posts: 2973
- Joined: 19. Dec 2007, 15:45
- Primary OS: MS Windows 7
- VBox Version: PUEL
- Guest OSses: Any and all
- Contact:
Re: PCI PIC IRQs
What's an "IRQ offset"? What's "3rd flag"?
FYI, "this code works on qemu and VMware" is very far from "this code is correct". Try it on real hardware to get some idea whether it actually works or not. It's possible to write quite broken code that still runs in VMs.
FYI, "this code works on qemu and VMware" is very far from "this code is correct". Try it on real hardware to get some idea whether it actually works or not. It's possible to write quite broken code that still runs in VMs.
Re: PCI PIC IRQs
Well, thanks for the replies.
Im 100% sure it works because Im just reading a 2 byte value, and everything else is correct (all the other data I read from PCI devices, on all vms).
With IRQ offset I meant the offset from a remapped base IRQ (in my case 0x20) because I remapped the IRQs above exceptions.
3rd flag was a typo, I meant third bit, which is the Interrupt Status.
Im 100% sure it works because Im just reading a 2 byte value, and everything else is correct (all the other data I read from PCI devices, on all vms).
With IRQ offset I meant the offset from a remapped base IRQ (in my case 0x20) because I remapped the IRQs above exceptions.
3rd flag was a typo, I meant third bit, which is the Interrupt Status.
-
- Oracle Corporation
- Posts: 2973
- Joined: 19. Dec 2007, 15:45
- Primary OS: MS Windows 7
- VBox Version: PUEL
- Guest OSses: Any and all
- Contact:
Re: PCI PIC IRQs
Okay, so if you're so convinced your code is correct, what exactly is the VirtualBox bug? And for bonus points, why does Windows/Linux/Solaris/etc. not have a problem with it... If you could point to the code in VirtualBox that you believe is wrong, that would be wonderful.
You seem to be assuming that it must be obvious to everyone what you're talking about. Well, it's not. If you could show some actual code, that would probably clarify things considerably.
I'm not saying you're wrong, I just don't understand what it is you're trying to say. I am however going to make a bold guess that someone calling themselves 'Chaozz' in 1337-speak does not have a whole lot of experience with reporting software problems.
You seem to be assuming that it must be obvious to everyone what you're talking about. Well, it's not. If you could show some actual code, that would probably clarify things considerably.
I'm not saying you're wrong, I just don't understand what it is you're trying to say. I am however going to make a bold guess that someone calling themselves 'Chaozz' in 1337-speak does not have a whole lot of experience with reporting software problems.
Re: PCI PIC IRQs
Well theres not too much to add but I will summarize it again to make it more clear.
The computer has got a PIC which notifies me when an interrupt occurs.
PCI devices can get 4 different IRQs assigned, depending on the BIOS.
Those PCI devices have a special structure:
In my PCI driver Im reading this data to parse it with my device drivers.
When an interrupt occurs, the 3rd bit in the status register will normally be set for the device which triggered it (word@0x6).
In Virtualbox this bit is never set, even when this device just triggered an interrupt.
So why this doesnt effect other OS'?
Because modern OS' use ACPI and AML to get this information which is just insane for a hobby OS.
Heres a little code that Im using in the interrupt handler for each device:
And the actual readfunction:
As you can see, when the third bit is not set (aka no interrupt occured for this device) I will simply return from the handler.
The handler is called for all devices which were registered to the occured IRQ.
The computer has got a PIC which notifies me when an interrupt occurs.
PCI devices can get 4 different IRQs assigned, depending on the BIOS.
Those PCI devices have a special structure:
In my PCI driver Im reading this data to parse it with my device drivers.
When an interrupt occurs, the 3rd bit in the status register will normally be set for the device which triggered it (word@0x6).
In Virtualbox this bit is never set, even when this device just triggered an interrupt.
So why this doesnt effect other OS'?
Because modern OS' use ACPI and AML to get this information which is just insane for a hobby OS.
Heres a little code that Im using in the interrupt handler for each device:
Code: Select all
uint16_t status = pci_read_word(device.bus, device.slot, device.function, 6);
if(!(status & (1 << 3)))
return false;
Code: Select all
uint16_t pci_read_word(uint8_t bus, uint8_t slot, uint8_t func, uint8_t offset)
{
uint32_t address = (uint32_t)(((uint32_t)lbus << 16) | ((uint32_t)lslot << 11) | ((uint32_t)lfunc << 8) | ((uint32_t)offset & 0xFC) | 0x80000000);
outl(0xCF8, address);
return (uint16_t)((inl(0xCFC) >> ((offset & 2) * 8)) & 0xFFFF);
}
The handler is called for all devices which were registered to the occured IRQ.
Last edited by mpack on 5. Mar 2016, 11:58, edited 1 time in total.
Reason: Replace partial image link with URL.
Reason: Replace partial image link with URL.
-
- Oracle Corporation
- Posts: 2973
- Joined: 19. Dec 2007, 15:45
- Primary OS: MS Windows 7
- VBox Version: PUEL
- Guest OSses: Any and all
- Contact:
Re: PCI PIC IRQs
OK, now I understand what you're talking about. Thanks for clearing it up. You're reading the status register in the device's PCI configuration space. That's very interesting.
This has zilch to do with ACPI. You can disable ACPI in VirtualBox and observe that Windows, Linux, etc. will happily keep working. The reason of course is that they never look at the PCI status register to check for pending interrupts. And the reason no OS looks at those bits is that this bit was not defined at all up to and including PCI specification 2.2. So... for any device confirming to PCI 2.2 or older, this approach has zero chance of working.
The other problem is that even when a device supports PCI 2.3 or newer, the interrupt status bit is read-only. So it needs to be cleared somewhere else, in some device-specific register... which probably also provides the pending interrupt information. So poking around the status register in the config space is a waste of time even when the status bit is actually there.
This has zilch to do with ACPI. You can disable ACPI in VirtualBox and observe that Windows, Linux, etc. will happily keep working. The reason of course is that they never look at the PCI status register to check for pending interrupts. And the reason no OS looks at those bits is that this bit was not defined at all up to and including PCI specification 2.2. So... for any device confirming to PCI 2.2 or older, this approach has zero chance of working.
The other problem is that even when a device supports PCI 2.3 or newer, the interrupt status bit is read-only. So it needs to be cleared somewhere else, in some device-specific register... which probably also provides the pending interrupt information. So poking around the status register in the config space is a waste of time even when the status bit is actually there.
Re: PCI PIC IRQs
Thanks for the answer.
How should I determinate which device triggered which IRQ then?
Osdev had an article about it and stated that I have to use the APIC combined with ACPI incase the BIOS remapped the IRQs.
EDIT: It looks like all new OS' are using the IO-APIC.
When I disable it in Virtualbox Windows and Linux just crash, so I will look into that.
Thanks for the answer
How should I determinate which device triggered which IRQ then?
Osdev had an article about it and stated that I have to use the APIC combined with ACPI incase the BIOS remapped the IRQs.
EDIT: It looks like all new OS' are using the IO-APIC.
When I disable it in Virtualbox Windows and Linux just crash, so I will look into that.
Thanks for the answer
-
- Oracle Corporation
- Posts: 2973
- Joined: 19. Dec 2007, 15:45
- Primary OS: MS Windows 7
- VBox Version: PUEL
- Guest OSses: Any and all
- Contact:
Re: PCI PIC IRQs
You need some device-specific code (i.e. a driver) which understands a given device's registers and can determine whether an interrupt is pending and handle it. If you ask me about a specific device I can tell you how to check for pending interrupts.Ch40zz wrote:How should I determinate which device triggered which IRQ then?
That very much depends on which version of Windows/Linux you're talking about. Some require an I/O APIC, some don't (generally 64-bit versions require I/O APIC and 32-bit don't). And some can handle changes after installation and some can't (XP is especially bad).When I disable it in Virtualbox Windows and Linux just crash, so I will look into that.
Re: PCI PIC IRQs
Thanks alot!
Im using The AC97 soundcard and the AMD PCnet fast III (Am79C973).
How can I identify which IRQ came from which of those 2 devices?
Couldn't find any info about that specific question anywhere
Im using The AC97 soundcard and the AMD PCnet fast III (Am79C973).
How can I identify which IRQ came from which of those 2 devices?
Couldn't find any info about that specific question anywhere
-
- Oracle Corporation
- Posts: 2973
- Joined: 19. Dec 2007, 15:45
- Primary OS: MS Windows 7
- VBox Version: PUEL
- Guest OSses: Any and all
- Contact:
Re: PCI PIC IRQs
You must not have been looking very hard For the Intel AC'97 controller, you need the Intel ICH 2 or so datasheet. For the PCnet, you need the Am79C973 datasheet.
For Intel AC'97, the GLOB_STA register (NABMBAR + 30h) contains interrupt status bits. The interrupts must be cleared by writing the corresponding x_SR register (NABMBAR + 06h/16h/26h).
For the PCnet, register CSR0 bit 7 (INTR) is the aggregate interrupt flag. To clear it, all individual pending interrupt sources must be checked/cleared (listed in the documentation). Those bits are in CSR0 and CSR7.
For Intel AC'97, the GLOB_STA register (NABMBAR + 30h) contains interrupt status bits. The interrupts must be cleared by writing the corresponding x_SR register (NABMBAR + 06h/16h/26h).
For the PCnet, register CSR0 bit 7 (INTR) is the aggregate interrupt flag. To clear it, all individual pending interrupt sources must be checked/cleared (listed in the documentation). Those bits are in CSR0 and CSR7.
Re: PCI PIC IRQs
Oh Im totally dumbmichaln wrote:You must not have been looking very hard For the Intel AC'97 controller, you need the Intel ICH 2 or so datasheet. For the PCnet, you need the Am79C973 datasheet.
For Intel AC'97, the GLOB_STA register (NABMBAR + 30h) contains interrupt status bits. The interrupts must be cleared by writing the corresponding x_SR register (NABMBAR + 06h/16h/26h).
For the PCnet, register CSR0 bit 7 (INTR) is the aggregate interrupt flag. To clear it, all individual pending interrupt sources must be checked/cleared (listed in the documentation). Those bits are in CSR0 and CSR7.
I thought theres another global way for those devices, but actually Im using BOTH of the mentioned ways already.
Just have to add 2 lines and it works perfectly, thanks alot!
-
- Oracle Corporation
- Posts: 2973
- Joined: 19. Dec 2007, 15:45
- Primary OS: MS Windows 7
- VBox Version: PUEL
- Guest OSses: Any and all
- Contact:
Re: PCI PIC IRQs
Glad to hear that.
Note that the AMD PCnet-FAST III is actually a PCI 2.2 compliant device. If the PCnet's PCI status register really reports interrupts in qemu and/or VMware, they're doing it wrong because the datasheet clearly says bit 3 is hardwired to zero and has no function.
The same is actually true of the ICH AC'97 PCI status register. Bit 3 is documented by Intel as having no function. So... that's why you can't use it for anything
Note that the AMD PCnet-FAST III is actually a PCI 2.2 compliant device. If the PCnet's PCI status register really reports interrupts in qemu and/or VMware, they're doing it wrong because the datasheet clearly says bit 3 is hardwired to zero and has no function.
The same is actually true of the ICH AC'97 PCI status register. Bit 3 is documented by Intel as having no function. So... that's why you can't use it for anything
Re: PCI PIC IRQs
Makes sense, just weird they both failed to implement it as real hardware behaves..michaln wrote:Glad to hear that.
Note that the AMD PCnet-FAST III is actually a PCI 2.2 compliant device. If the PCnet's PCI status register really reports interrupts in qemu and/or VMware, they're doing it wrong because the datasheet clearly says bit 3 is hardwired to zero and has no function.
The same is actually true of the ICH AC'97 PCI status register. Bit 3 is documented by Intel as having no function. So... that's why you can't use it for anything
Thanks for the help, learned another lesson when reading data sheets