Page 1 of 1
IOAPIC refusing my data
Posted: Sun Oct 02, 2016 6:20 am
by poby
I'm having a problem getting my IOAPIC to accept the data I'm feeding it. I created the following functions:
Code: Select all
; -----------------------------------------------------------------------------
; IN : r8= ioapic address, EBX = index register
; OUT: ECX = return value
ioapic_read:
mov [r8], ebx
mov ecx, [r8 + 0x10]
ret
; -----------------------------------------------------------------------------
; IN : r8= ioapic address, EBX = index register, ECX = value
; OUT: -
ioapic_write:
mov [r8], ebx
mov [r8 + 0x10], ecx
ret
I set r8 to 0xFEC00000 (value extracted from ACPI enumeration)
The following example illustrates my issue:
Code: Select all
mov r8, [IOAPICAddress]
mov ecx, 0x20
mov ebx, 0x10
call ioapic_write
mov ecx, 0x21
mov ebx, 0x12
call ioapic_write
mov ebx, 0x10
call ioapic_read
; ecx should equal 0x20 but it equals 0x21
I have identity mapping set up and can't find anything remiss in that so I believe the 0xFEC00000 address is being correctly mapped. It seems to ignore whatever register I select with ebx, and just gives me back the last data I wrote. What am I missing?
Running under virtualbox. Extremely frustrating. Out of ideas.
Re: IOAPIC refusing my data
Posted: Sun Oct 02, 2016 6:28 am
by BrightLight
You're trying to set register 0x10 to 1. This would make IRQ 0 use interrupt vector 1. That violates the IOAPIC limits. You can't use interrupt vectors less than 32 and greater than 254 (not sure about the second part, someone could correct me here.)
Re: IOAPIC refusing my data
Posted: Sun Oct 02, 2016 6:32 am
by poby
Ok it was a poor example but it doesn't matter what values I use. I ignores the index and just gives me back the last value I wrote.
I will edit the post to use valid values.
Re: IOAPIC refusing my data
Posted: Sun Oct 02, 2016 6:34 am
by BrightLight
Try adding a "pause" instruction after selecting the index register as well as after writing to the data register.
Re: IOAPIC refusing my data
Posted: Sun Oct 02, 2016 6:38 am
by poby
Thanks for the suggestion. Tried it. No change
Is there some other configuration of the ioapic I need to do first before writing to the registers? Do I need to explicitly enable it or something?
Re: IOAPIC refusing my data
Posted: Sun Oct 02, 2016 8:00 am
by SpyderTL
Silly question, but you DO have IOAPIC enabled in VirtualBox, correct?
Re: IOAPIC refusing my data
Posted: Sun Oct 02, 2016 9:31 am
by BrightLight
SpyderTL wrote:Silly question, but you DO have IOAPIC enabled in VirtualBox, correct?
I'll assume he does; because he mentions that he got the value 0xFEC00000 from ACPI.
Re: IOAPIC refusing my data
Posted: Sun Oct 02, 2016 3:50 pm
by poby
It occurs to me this could be a caching issue. So I've changed my paging routine to use 0x9B instead of 0x83, which hopefully will disable caching. Is there somewhere else I need to change? It's still not working.
yeah ioapic is enabled in virtualbox.
Re: IOAPIC refusing my data
Posted: Mon Oct 03, 2016 3:45 am
by Brendan
Hi,
poby wrote:It occurs to me this could be a caching issue. So I've changed my paging routine to use 0x9B instead of 0x83, which hopefully will disable caching. Is there somewhere else I need to change? It's still not working.
yeah ioapic is enabled in virtualbox.
If it is a caching issue, then the firmware has failed to configure MTRRs properly (against both Intel's recommendations and common sense).
Far more likely is that you've made a simple mistake in your paging structures somewhere and you're actually writing to normal RAM. This should be relatively simple to test (e.g. write the bytes 0x00 to 0xFF at addresses 0xFEC00000 to 0xFEC000FF , then read them back). You can even throw a few "WBINVD" instructions in there if you want.
Cheers,
Brendan
Re: IOAPIC refusing my data
Posted: Mon Oct 03, 2016 7:02 am
by poby
Brendan wrote:Hi,
Far more likely is that you've made a simple mistake in your paging structures somewhere and you're actually writing to normal RAM. This should be relatively simple to test (e.g. write the bytes 0x00 to 0xFF at addresses 0xFEC00000 to 0xFEC000FF , then read them back). You can even throw a few "WBINVD" instructions in there if you want.
Brendan
Yeah I've pretty much confirmed now it's a paging issue. Haven't nailed it down yet but I think at least one of my page tables are getting overwritten as the physical address 0xFEC00000 translates to appears to be a big zero.
It's taken me down a lot of rabbit holes chasing red herrings that had nothing to do with it. But, I have learnt a lot in the process so not a total loss
Re: IOAPIC refusing my data
Posted: Mon Oct 03, 2016 2:43 pm
by poby
My identity paging, works on demand such that a page fault will generate the correct physical page in the tables. I'm able to get it working if I do a dummy read or write (so the page gets loaded), well before the MMIO access.
e.g.
This WORKS!
Code: Select all
mov eax, [IOAPICAddress]
mov dword[rax], 0
mov r8, rax
.
.
.
call ioapic_read
This DOESN'T!
Code: Select all
mov eax, [IOAPICAddress]
mov r8, rax
mov dword[rax], 0
.
.
.
call ioapic_read
I suspect a pipelining/serializing issue but I would really love to learn both why I need to page fault the address into the tables before using it in an MMIO register, and why I need to do it far enough in advance. In the latter case, how to fix it so it is serialized such so I don't need to worry about it.
Re: IOAPIC refusing my data
Posted: Mon Oct 03, 2016 3:27 pm
by hgoel
After changing things in the page tables, are you performing a tlb invalidation? Using either invlpg or writing to cr3 ?
Re: IOAPIC refusing my data
Posted: Mon Oct 03, 2016 3:29 pm
by poby
hgoel wrote:After changing things in the page tables, are you performing a tlb invalidation? Using either invlpg or writing to cr3 ?
I tried this but it didn't make any difference. AFAIK, TLB invalidation isn't necessary when the change is only to add a missing page. i.e. The page isn't cached in the TLB anyway so no reason to invalidate
Re: IOAPIC refusing my data
Posted: Tue Oct 04, 2016 9:54 pm
by MichaelPetch
This was finally resolved in this
Stackoverflow question/answer. It was discovered that the page fault handler was not properly restoring all the registers it used, and thus caused unexpected behaviour.
Re: IOAPIC refusing my data
Posted: Wed Oct 05, 2016 11:33 am
by stdcall
This is a nice catch indeed.