APIC Timer leads to lots of prerequisites?

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
eryjus
Member
Member
Posts: 286
Joined: Fri Oct 21, 2011 9:47 pm
Libera.chat IRC: eryjus
Location: Tustin, CA USA

APIC Timer leads to lots of prerequisites?

Post by eryjus »

Hi,

I have worked on some basic concepts for my OS and have been reasonably successful but I took a step back to make sure I was taking a more holistic approach. I am having some trouble getting my APIC timer working and thought I better reach out for help. As I continue to research, I find myself falling into a bottomless pit.

Since I want my OS to be able to use multi-cores and/or multi-processors, I understand that I need to make use of the APIC. The APIC will be necessary for coordinating between the processors. In implementing use of the APIC, the 8259 PIC must be disabled. In disabling the 8259, I am forced to use the APIC timer. I did query CPUID to make sure I have an APIC available before I start and went through the exercise to calibrate the APIC timer.

When I enable interrupts, I am getting an immediate Interrupt 0 (no division by 0, though, and I have put in the proper checks to prevent it), followed by an Interrupt 8 (double fault) and then repeating Interrupt 13s (GPF). I have some odd anomalies in the SS selector when I dump the registers on Interrupt 0, but I am thinking that it is a symptom rather than the problem. I am expecting an Interrupt 32 (for my APIC timer), but I do not get any triggers on Interrupt 32.

What is noteworthy is that in debugging, I am seeing that the Interrupt 0 is actually in response to a IRQ. As hinted above, I have set my APIC timer interrupt vector to 32 in periodic mode. I have tried to send the APIC an EOI before enabling interrupts, but that had no effect.

With all that said, my research points me to the need to setup the IOAPIC before I enable interrupts (details are a still little hazy on having to do this for the APIC timer...). In order to begin setting up the IOAPIC, I need to parse the MADT from ACPI in order to get some basic information required. In order to find the information for the ACPI, I need to get the address from memory (which I assume [for now] I take the starting address for the block reported), following the multiboot specification and what is reported by INT15. I cannot query INT15 myself as I am already in protected mode and I'm not really interested or prepared to switch back to real mode.

I cannot help the feeling that I have fallen down a rabbit hole I didn't intend and I am missing something far more fundamental. I can easily fall back to the 8259 PIC, but that will not deliver the ultimate multi-processor functionality I am looking for.

I have read everything I can find on APIC timer not working. At the point I setup the APIC timer, I have setup a GDT, IDT, the Heap is created and Paging is enabled (with 0xfee00000 identity mapped).

Thanks in advance for any assistance and/or advice you are willing to provide. If you would like to see code, please let me know.


Thank you!
Adam

The name is fitting: Century Hobby OS -- At this rate, it's gonna take me that long!
Read about my mistakes and missteps with this iteration: Journal

"Sometimes things just don't make sense until you figure them out." -- Phil Stahlheber
User avatar
Combuster
Member
Member
Posts: 9301
Joined: Wed Oct 18, 2006 3:45 am
Libera.chat IRC: [com]buster
Location: On the balcony, where I can actually keep 1½m distance
Contact:

Re: APIC Timer leads to lots of prerequisites?

Post by Combuster »

Exceptions are not caused by the APIC - it will only send interrupt numbers.

Instead your system structures are broken in some way. Start by finding out why SS contains an invalid value since *you* put it in there.
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
Cognition
Member
Member
Posts: 191
Joined: Tue Apr 15, 2008 6:37 pm
Location: Gotham, Batmanistan

Re: APIC Timer leads to lots of prerequisites?

Post by Cognition »

Seems like you have most of it down. As Combuster said most of the errors you're getting with the IDT indicating some problems there on your part. Either with the structure of your IDT and handling code and perhaps the masking of the PIC. Finding and parsing the ACPI table for the MADT and the IOAPIC information shouldn't be terribly difficult if you already have paging and heap management under control. Worrying about the memory map probably isn't too necessary either at this point either, the ACPI reclaim space exists so that it can be freed after all of ACPI is initialized (a much more involved process). For now you should be able to trust the RSDP and checksums to validate the tables.

There's a few extra things I didn't see listed, but that you will need to be aware of if you're using the IOAPIC too. On some systems IRQ to global system interrupt mappings are not the same. The MADT you'll be parsing for the IOAPIC may also contain interrupt source override structures, which will tell the mapping from IRQ to global system interrupt along with the some trigger and polarity information. You need to keep track of this information when routing interrupts for the system to function properly.

On a more positive note the same MADT structure is responsible for enumerating other logical processors at boot time so you'll have a lot of that work done once you have proper parsing code in place. Honestly if you have a heap and paging this all shouldn't be too painful, there's going to be a good amount of reading specifications and testing code. But the actual amount of work involved is pretty minor compared to many other drivers and features your OS will have.
Reserved for OEM use.
User avatar
bewing
Member
Member
Posts: 1401
Joined: Wed Feb 07, 2007 1:45 pm
Location: Eugene, OR, US

Re: APIC Timer leads to lots of prerequisites?

Post by bewing »

Yes, progressing from running on a single core to running on multicore involves parsing and dealing with all the stuff you listed. Sorry, but that's just how it is and nobody ever promised you that OS development was going to be easy -- especially on such an ad hoc piece of silicon as an Intel CPU. But the rabbit hole is not infinitely deep. Finding and parsing the ACPI info is indeed the starting point. And your INT 0x15 issue is why everyone needs a decent bootloader to preload and pass the best possible memory info into your OS.
gerryg400
Member
Member
Posts: 1801
Joined: Thu Mar 25, 2010 11:26 pm
Location: Melbourne, Australia

Re: APIC Timer leads to lots of prerequisites?

Post by gerryg400 »

I suspect the interrupt 0 that you see is a timer interrupt from the 8259. The bios typically sets up this interrupt.

On most PCs you cannot actually disable the 8259. You need to initiialise the 8259 as you would if you were going to use it and then mask all the interrupts by writing 0xff to the mask register.
If a trainstation is where trains stop, what is a workstation ?
User avatar
eryjus
Member
Member
Posts: 286
Joined: Fri Oct 21, 2011 9:47 pm
Libera.chat IRC: eryjus
Location: Tustin, CA USA

Re: APIC Timer leads to lots of prerequisites?

Post by eryjus »

Well..... :oops:
Combuster wrote:Start by finding out why SS contains an invalid value since *you* put it in there.
Combuster, you are right, I did it to myself. I neglected to distinguish between IRQ0 and ISR0 in my code. So, even though IRQ0 was generating interrupt 32, my handler was incorrectly redirecting it to ISR0. I was not able to determine why the funny SS value was showing up, but will continue to look. But, let me say, I appreciate you!
bewing wrote:nobody ever promised you that OS development was going to be easy
I didn't sign up for easy. That's why we pick writing an OS as a hobby, right?

Here was my smoking gun (I specified "-d in_asm,cpu,int" in the qemu parameters):

Code: Select all

IN: 
0x0010c801:  sti    

EAX=00000000 EBX=00002000 ECX=00000018 EDX=00000780
ESI=0010efa5 EDI=000b8fa0 EBP=0011a7c0 ESP=0011a7a4
EIP=0010c801 EFL=00000006 [-----P-] CPL=0 II=0 A20=1 SMM=0 HLT=0
ES =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
CS =0008 00000000 ffffffff 00cf9a00 DPL=0 CS32 [-R-]
SS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
DS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
FS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
GS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
LDT=0000 00000000 00000000 00008200 DPL=0 LDT
TR =0008 00000580 00000067 00008900 DPL=0 TSS32-avl
GDT=     001167a0 00000027
IDT=     00115f80 000007ff
CR0=80000011 CR2=00000000 CR3=0013d000 CR4=00000000
DR0=00000000 DR1=00000000 DR2=00000000 DR3=00000000 
DR6=ffff0ff0 DR7=00000400
CCS=00000004 CCD=0011a79c CCO=EFLAGS  
EFER=0000000000000000
EAX=00000000 EBX=00002000 ECX=00000018 EDX=00000780
ESI=0010efa5 EDI=000b8fa0 EBP=0011a7c0 ESP=0011a7a4
EIP=0010c802 EFL=00000206 [-----P-] CPL=0 II=1 A20=1 SMM=0 HLT=0
ES =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
CS =0008 00000000 ffffffff 00cf9a00 DPL=0 CS32 [-R-]
SS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
DS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
FS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
GS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
LDT=0000 00000000 00000000 00008200 DPL=0 LDT
TR =0008 00000580 00000067 00008900 DPL=0 TSS32-avl
GDT=     001167a0 00000027
IDT=     00115f80 000007ff
CR0=80000011 CR2=00000000 CR3=0013d000 CR4=00000000
DR0=00000000 DR1=00000000 DR2=00000000 DR3=00000000 
DR6=ffff0ff0 DR7=00000400
CCS=00000004 CCD=0011a79c CCO=EFLAGS  
EFER=0000000000000000
----------------
IN: 
0x0010c802:  ret    

Servicing hardware INT=0x20
     8: v=20 e=0000 i=0 cpl=0 IP=0008:00108940 pc=00108940 SP=0010:0011a7a8 EAX=00000000
EAX=00000000 EBX=00002000 ECX=00000018 EDX=00000780
ESI=0010efa5 EDI=000b8fa0 EBP=0011a7c0 ESP=0011a7a8
EIP=00108940 EFL=00000202 [-------] CPL=0 II=0 A20=1 SMM=0 HLT=0
ES =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
CS =0008 00000000 ffffffff 00cf9a00 DPL=0 CS32 [-R-]
SS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
DS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
FS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
GS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
LDT=0000 00000000 00000000 00008200 DPL=0 LDT
TR =0008 00000580 00000067 00008900 DPL=0 TSS32-avl
GDT=     001167a0 00000027
IDT=     00115f80 000007ff
CR0=80000011 CR2=00000000 CR3=0013d000 CR4=00000000
DR0=00000000 DR1=00000000 DR2=00000000 DR3=00000000 
DR6=ffff0ff0 DR7=00000400
CCS=00000004 CCD=0011a79c CCO=EFLAGS  
EFER=0000000000000000
EAX=00000000 EBX=00002000 ECX=00000018 EDX=00000780
ESI=0010efa5 EDI=000b8fa0 EBP=0011a7c0 ESP=0011a79c
EIP=001001a4 EFL=00000006 [-----P-] CPL=0 II=0 A20=1 SMM=0 HLT=0
ES =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
CS =0008 00000000 ffffffff 00cf9a00 DPL=0 CS32 [-R-]
SS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
DS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
FS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
GS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
LDT=0000 00000000 00000000 00008200 DPL=0 LDT
TR =0008 00000580 00000067 00008900 DPL=0 TSS32-avl
GDT=     001167a0 00000027
IDT=     00115f80 000007ff
CR0=80000011 CR2=00000000 CR3=0013d000 CR4=00000000
DR0=00000000 DR1=00000000 DR2=00000000 DR3=00000000 
DR6=ffff0ff0 DR7=00000400
CCS=00000004 CCD=0011a79c CCO=EFLAGS  
EFER=0000000000000000
Ultimately, my thinking in the original post was not correct: I do NOT have to implement all these extra things yet in order to get the APIC timer to work. They can come a little later.

Thanks for your replies.
Adam

The name is fitting: Century Hobby OS -- At this rate, it's gonna take me that long!
Read about my mistakes and missteps with this iteration: Journal

"Sometimes things just don't make sense until you figure them out." -- Phil Stahlheber
Post Reply