<div>Hi,</div><div> </div><div>I am trying to write my own kernel but I am facing problems with timer interrupt.</div><div>I have been using PIC and PIT to generate timer interrupts and it has been working fine but now I want to switch to local APIC timer.</div>
<div>I am using bochs as emulator. I have made some changes but all in vain.</div><div>Here is what I have done :</div><div> </div><div style="text-align:left">- compiled bochs with cpu_leve 6 to get the APIC enabled.</div>
<div style="text-align:left"><br>- I have checked that APIC is present and is enabled (code at the end)</div><div style="text-align:left"> </div><div style="text-align:left">- I have added code for disabling PIC. Now my code first remaps IRQs in PIC and then disables the PIC. If I don't remap the IRQs I sometimes get a double fault. </div>
<div style="text-align:left"> </div><div style="text-align:left">- Added a page table entry for the APIC base - 0xFEE00000 which has the Cache Disable bit set. </div><div style="text-align:left"> I haven't mapped it to a physical page. I have checked that the apic base address is correct by reading the APIC BASE MSR. (code at the end)</div>
<div style="text-align:left"> </div><div style="text-align:left">- Added code from the wiki - <a href="http://wiki.osdev.org/APIC_timer">http://wiki.osdev.org/APIC_timer</a> to initialize APIC timer but it did not work.The timer interrupt didn't get triggered.</div>
<div style="text-align:left"> </div><div style="text-align:left">- Now I have reduced the code from the wiki to only a few lines (code below) but the interrupt is just not getting generated. <br>I checked bit 32 of the Interrupt Request register (0xFEE00390) and found it to be Set. But the interrupt handler is not getting called. The IDT and all the interrupt handlers are in place. If I switch back to the old code using PIC and PIT it works fine.</div>
<div style="text-align:left">Please let me know if I am doing something wrong. I am unable to figure out anything.</div><div style="text-align:left"> </div><div style="text-align:left"><font style="background-color:rgb(255,255,255)"><strong>Code for APIC timer :</strong></font> </div>
<div style="text-align:left"> </div><div style="text-align:left">uint32 apic = 0xFEE00000;</div><div style="text-align:left">uint32 APIC_SPURIOUS = 0x0F0;<br>uint32 APIC_SW_ENABLE = 0x100;<br>uint32 APIC_DFR = 0x0E0;<br>
uint32 APIC_TASKPRIOR = 0x80;<br>uint32 APIC_TMRDIV = 0x3E0;</div><div style="text-align:left">uint32 APIC_LVT_TMR = 0x320;<br>uint32 TMR_PERIODIC = 0x20000;<br>uint32 APIC_TMRINITCNT = 0x380;</div><div style="text-align:left">
void apic_timer_init(){ <br> <br> <em> //software enable apic timer <br></em> *(uint32*)(apic+APIC_SPURIOUS)=0xFF|APIC_SW_ENABLE;<br> <br> <em> //set DFR to flat mode<br></em> *(uint32*)(apic+APIC_DFR)=0xFFFFFFFF;<br>
<br> <em> //set task priority to 0 to allow all <br></em> *(uint32*)(apic+APIC_TASKPRIOR) = 0;<br> <br> <em> //set divider to 16<br></em> *(uint32*)(apic+APIC_TMRDIV)=0x03;<br> <br><em> //map APIC timer to an interrupt enable it in periodic mode<br>
</em> *(uint32*)(apic+APIC_LVT_TMR)=32|TMR_PERIODIC;</div><div style="text-align:left"> </div><div style="text-align:left"> <em> //initialize intial count<br></em> *(uint32*)(apic+APIC_TMRINITCNT)=0x10000;<br> <br>
}</div><div style="text-align:left"> </div><div style="text-align:left"> </div><div style="text-align:left"><strong>Code for checking if APIC is present:</strong></div><div style="text-align:left"><strong></strong> </div>
<div style="text-align:left">//check if APIC is present using CPUID<br>uint32 cpuHasAPIC()<br>{<br> uint32 eax , edx;<br> eax = 0x1;<br> uint32 CPU_FLAG_APIC = 0x200;<br> asm volatile("cpuid": "=d"(edx) :"a"(eax));<br>
return edx & CPU_FLAG_APIC;<br>}</div><div style="text-align:left"> </div><div style="text-align:left"><strong></strong> </div><div style="text-align:left"><strong></strong> </div><div style="text-align:left"><strong>Code for checking if APIC is enabled and for getting APIC Base address :</strong></div>
<div style="text-align:left"><strong></strong> </div><div style="text-align:left"> </div><div style="text-align:left">void checkAPICStatus()<br>{<br> uint32 APIC_ENABLE_FLAG = 0x800;<br> uint32 APIC_BASE_FLAG = 0xFFFFF000;<br>
uint32 ecx = 0x1B; <em> //<<<<<<<<<<<<<< APIC BASE MSR <br></em> uint32 eax, edx;<br> asm volatile("rdmsr":"=a"(eax), "=d"(edx):"c"(ecx));</div>
<div style="text-align:left"> uint32 apic_enabled = eax & APIC_ENABLE_FLAG;<br> <br>if(apic_enabled)<br> {<br> print_str("\nAPIC IS ENABLED!!");<br> }else<br> {<br> print_str("\nAPIC IS DISABLED");<br>
}</div><div style="text-align:left"> </div><div style="text-align:left"><em>// Get APIC BASE address<br></em> uint32 apic_base = eax & APIC_BASE_FLAG;</div><div style="text-align:left"> </div><div style="text-align:left">
<em> // print APIC Base address</em><br> print_str("\n APIC BASE ADDRESS IS ");<br> print_hex(apic_base);<br>}<br></div><div style="text-align:left"> </div><div style="text-align:left">- Thanks</div><div style="text-align:left">
Vaibhav Jain</div>