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!
APIC Timer leads to lots of prerequisites?
- eryjus
- 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?
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
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
- Combuster
- 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?
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.
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.
Re: APIC Timer leads to lots of prerequisites?
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.
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.
Re: APIC Timer leads to lots of prerequisites?
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.
Re: APIC Timer leads to lots of prerequisites?
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.
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 ?
- eryjus
- 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?
Well.....
Here was my smoking gun (I specified "-d in_asm,cpu,int" in the qemu parameters):
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.
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!Combuster wrote:Start by finding out why SS contains an invalid value since *you* put it in there.
I didn't sign up for easy. That's why we pick writing an OS as a hobby, right?bewing wrote:nobody ever promised you that OS development was going to be easy
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
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
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