IO APIC and GPF exception

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
User avatar
CorruptedByCPU
Member
Member
Posts: 79
Joined: Tue Feb 11, 2014 4:59 pm

IO APIC and GPF exception

Post by CorruptedByCPU »

Hey!

I configured LAPIC, IO APIC, IDT, RTC and Keyboard.

Up to now everything seems to working great but... only when there is only one I/O Redirection Table entry :(

IO APIC configuration (nasm style):

Code: Select all

	mov	rdi,	qword [kernel_ioapic_base_address]

	; keyboard
	mov	dword [edi + 0x0000],	0x12	; IRQ1 low
	mov	dword [edi + 0x0010],	0x20 + 0x01	; IDT descriptor/vector 33
	mov	dword [edi + 0x0000],	0x13	; IRQ1 high
	mov	dword [edi + 0x0010],	0x00

	; rtc
	mov	dword [edi + 0x0000],	0x20	; IRQ8 low
	mov	dword [edi + 0x0010],	0x20 + 0x08	; IDT descriptor/vector 40
	mov	dword [edi + 0x0000],	0x21	; IRQ8 high
	mov	dword [edi + 0x0010],	0x00

	; PIC interrupts are masked

	; all above has the same configuration
	;	delivery mode (fixed)
	;	destination mode (physical destination)
	;	delivery status (relaxed)
	;	pin polarity (active high)
	;	trigger mode (edge)
	;	mask (interrupt enabled)
	;	destination (apic id 0, so only BSP core will receive this interrupts at now)
LAPIC configuration (nasm style):

Code: Select all

	mov	rsi,	qword [kernel_lapic_table_address]

	; task priority
	mov	dword [rsi + 0x0080],	0x00000000

	; flat mode
	mov	dword [rsi + 0x00E0],	0xFFFFFFFF

	; target cpu
	mov	dword [rsi + 0x00D0],	0x01000000

	; enable lapic, spurious vector
	mov	eax,	dword [rsi + 0x00F0]
	or	eax,	100000000b | 011111111b
	mov	dword [rsi + 0x00F0],	eax

	; unmask interrupts
	mov	eax,	dword [rsi + 0x0320]
	and	eax,	~0x00010000
	mov	dword [rsi + 0x0320],	eax
If both entrys are enabled in IO APIC, it is possible to catch General Protection Fault exception :/ and I don't know where to look at :(
https://blackdev.org/ - system programming, my own 64 bit kernel and software.
User avatar
CorruptedByCPU
Member
Member
Posts: 79
Joined: Tue Feb 11, 2014 4:59 pm

Re: IO APIC and GPF exception

Post by CorruptedByCPU »

Ok, I found the answer :D so the respond will be with new post.

The culprit was Spurious Interrupt, because I didn't make IDT entry at descriptor 255 (which was configured in LAPIC).

Right now, this is the code for Spurious Interrupt

Code: Select all

kernel_idt_spurious_interrupt:
	xchg	bx,bx	; debug
	nop
	nop
	nop
	nop
	iretq
How should the procedure for handling this interrupt look like?
https://blackdev.org/ - system programming, my own 64 bit kernel and software.
Korona
Member
Member
Posts: 1000
Joined: Thu May 17, 2007 1:27 pm
Contact:

Re: IO APIC and GPF exception

Post by Korona »

Do you really encounter the spurious IRQ (double check that indeed comes from that source)? Is this on real HW or on qemu (or some other VM)? If spurious IRQs happen frequently (e.g. on every boot) that suggests that something might be wrong with your hardware configuration.
managarm: Microkernel-based OS capable of running a Wayland desktop (Discord: https://discord.gg/7WB6Ur3). My OS-dev projects: [mlibc: Portable C library for managarm, qword, Linux, Sigma, ...] [LAI: AML interpreter] [xbstrap: Build system for OS distributions].
User avatar
CorruptedByCPU
Member
Member
Posts: 79
Joined: Tue Feb 11, 2014 4:59 pm

Re: IO APIC and GPF exception

Post by CorruptedByCPU »

Yes, I'm sure of that. This interrupt exist only in Bochs environment, Qemu was fine (I dont use real hardware).

After a deeper analysis, I come to the conclusion that this may be a PIT controller that I do not use.

Thus unhandled interrupt could trigger "spurious interrupt". The frequency of occurrence is very close to 18 Hz :)
https://blackdev.org/ - system programming, my own 64 bit kernel and software.
Korona
Member
Member
Posts: 1000
Joined: Thu May 17, 2007 1:27 pm
Contact:

Re: IO APIC and GPF exception

Post by Korona »

That sounds very suspicious. Spurious IRQs happen when an IRQ cannot be delivered correctly. For example, (to my understanding) this happens if the I/O APIC tells the CPU to raise an IRQ but is unable to deliver the vector number due to noise on the wires. Normal devices like the PIT should never be able to cause spurious IRQs (reliably).

Before concluding that the PIT really causes a spurious IRQ, you should make sure that: (i) the IRQ is really maked in the (legacy) XT-PIC, (ii) the IRQ is masked in the I/O APIC and (iii) it's not just caused by a possible default (or BIOS-configured) value of 0xFF in the I/O APIC's vector register.

To further diagnose the issue: did you call the AML _PIC method?

If you are sure that this is really a spurious IRQ, it probably makes sense to file a bug report to Bochs.
managarm: Microkernel-based OS capable of running a Wayland desktop (Discord: https://discord.gg/7WB6Ur3). My OS-dev projects: [mlibc: Portable C library for managarm, qword, Linux, Sigma, ...] [LAI: AML interpreter] [xbstrap: Build system for OS distributions].
User avatar
CorruptedByCPU
Member
Member
Posts: 79
Joined: Tue Feb 11, 2014 4:59 pm

Re: IO APIC and GPF exception

Post by CorruptedByCPU »

Hmm, I redirected interrupts to higher ones (0x20..0x2F) on PIC controller and masked all of them.
but,
after I mounted interrupt procedure for PIT to IO APIC register no 0x14, the spurious interrupt dissapeared :)
To further diagnose the issue: did you call the AML _PIC method?
No, I thought that masking the interrupts on the PIC controller would solve the problem.
Is it difficult to use AML? I'm asking because I only work in assembler language and creating my own interpreter is not going to my mind.
https://blackdev.org/ - system programming, my own 64 bit kernel and software.
nullplan
Member
Member
Posts: 1801
Joined: Wed Aug 30, 2017 8:24 am

Re: IO APIC and GPF exception

Post by nullplan »

akasei wrote:Is it difficult to use AML? I'm asking because I only work in assembler language and creating my own interpreter is not going to my mind.
Your options are to make or use an AML interpreter to do these things, or to dump the AML code for all the mainboards you wish to support, and use a mainboard driver for each one.

If you wish to pursue the former route, I suggest taking a look at ACPICA. Though it is written in C, you can easily fulfill its interface needs even from assembly. I mean, it only needs a few functions.

If you wish to pursue the latter route, I again suggest taking a look at ACPICA. The package comes with tools you can execute under Linux, and you can use the output to reverse-engineer the AML of a given mainboard (it obviously must be executed on the target mainboard). Then you don't have to "execute the PIC method", but rather can do "the equivalent of executing the PIC method". On my laptop, for example, the PIC method does this:

Code: Select all

    Method (_PIC, 1, NotSerialized)  // _PIC: Interrupt Model
    {
        GPIC = Arg0
        PICM = Arg0
    }
Remember, you are supposed to call this with 1 for APIC. OK, so what are these two identifiers? GPIC is a field in an OperationRegion:

Code: Select all

    OperationRegion (GNVS, SystemMemory, 0x9CFBCC18, 0x0383)
    Field (GNVS, AnyAcc, Lock, Preserve)
    {
        [...]
        Offset (0x7C), 
        GPIC,   8, 
        [...]
    }
So that means, if I am not mistaken, that in order to use the APIC, I am supposed to set the qword at 0x9cfbcc18+0x7c to 1, using locking. But I'd have to read up on what that means specifically.

PICM is just a name, basically an internal variable. It is referenced in all the _PRT methods. So I can now execute these methods under the assumption that PICM = 1. So for instance:

Code: Select all

            Method (_PRT, 0, NotSerialized)  // _PRT: PCI Routing Table
            {
                If (PICM)
                {
                    Return (AR00 ())
                }

                Return (PR00 ())
            }
Means I have to look up the routing information for that particular device in AR00. And that rabbit hole just keeps going.
Carpe diem!
Korona
Member
Member
Posts: 1000
Joined: Thu May 17, 2007 1:27 pm
Contact:

Re: IO APIC and GPF exception

Post by Korona »

So the APIC issue was that you did not initialize the vector? Yes, if you do not modify it, it will be left in whatever state the BIOS set up, which may be not what you want. Thus, it makes sense to mask all I/O APIC vectors before you start using it.

---

Regarding _PIC: what nullplan posted is entirely correct. Let me just add that for Intel mainboards, the registers affected by _PIC are actually documented. Luckily, there is no need to disassemble the AML, you can find their descriptions in the ICH/PCH data sheets.

Also, you could always use Omar's LAI library (library / usage example) to execute the AML. Disclaimer: I contributed a lot to that project ;D.
managarm: Microkernel-based OS capable of running a Wayland desktop (Discord: https://discord.gg/7WB6Ur3). My OS-dev projects: [mlibc: Portable C library for managarm, qword, Linux, Sigma, ...] [LAI: AML interpreter] [xbstrap: Build system for OS distributions].
Post Reply