APIC timer not working

Vaibhav Jain vjoss197 at gmail.com
Mon Jun 25 00:00:13 EDT 2012


I am trying to write my own kernel but I am facing problems with timer
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.
I am using bochs as emulator. I have made some changes but all in vain.
Here is what I have done :

-  compiled bochs with cpu_leve 6 to get the APIC enabled.

-  I have checked that APIC is present and is enabled (code at the end)

-  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.

- Added a page table entry for the APIC base - 0xFEE00000 which has the
Cache Disable bit set.
  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)

- Added code from the wiki - http://wiki.osdev.org/APIC_timer to initialize
APIC timer but it did not work.The timer interrupt didn't get triggered.

- Now I have reduced the code from the wiki to only a few lines (code
below) but the interrupt is just not getting generated.
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.
Please let me know if I am doing something wrong. I am unable to figure out

*Code for APIC timer :*

uint32 apic = 0xFEE00000;
uint32 APIC_SPURIOUS   = 0x0F0;
uint32 APIC_SW_ENABLE   = 0x100;
uint32 APIC_DFR   = 0x0E0;
uint32 APIC_TASKPRIOR   = 0x80;
uint32 APIC_TMRDIV   = 0x3E0;
uint32 APIC_LVT_TMR   = 0x320;
uint32 TMR_PERIODIC   = 0x20000;
uint32 APIC_TMRINITCNT   = 0x380;
void apic_timer_init(){

    *    //software enable apic timer
*   *(uint32*)(apic+APIC_SPURIOUS)=0xFF|APIC_SW_ENABLE;

   *    //set DFR to flat mode
*   *(uint32*)(apic+APIC_DFR)=0xFFFFFFFF;

     *  //set task priority to 0 to allow all
*   *(uint32*)(apic+APIC_TASKPRIOR) = 0;

    *   //set divider to 16
*   *(uint32*)(apic+APIC_TMRDIV)=0x03;

*   //map APIC timer to an interrupt enable it in periodic mode
*   *(uint32*)(apic+APIC_LVT_TMR)=32|TMR_PERIODIC;

 *  //initialize intial count
*   *(uint32*)(apic+APIC_TMRINITCNT)=0x10000;


*Code for checking if APIC is present:*
//check if APIC is present using CPUID
uint32 cpuHasAPIC()
  uint32 eax , edx;
  eax = 0x1;
  uint32 CPU_FLAG_APIC = 0x200;
  asm volatile("cpuid": "=d"(edx) :"a"(eax));
  return edx &  CPU_FLAG_APIC;

*Code for checking if APIC is enabled and for getting APIC Base address :*

void checkAPICStatus()
  uint32 APIC_ENABLE_FLAG = 0x800;
  uint32 APIC_BASE_FLAG = 0xFFFFF000;
  uint32 ecx = 0x1B;                                    * //<<<<<<<<<<<<<<
*  uint32 eax, edx;
  asm volatile("rdmsr":"=a"(eax), "=d"(edx):"c"(ecx));
  uint32 apic_enabled = eax & APIC_ENABLE_FLAG;

    print_str("\nAPIC IS ENABLED!!");
    print_str("\nAPIC IS DISABLED");

*// Get APIC BASE address
*  uint32 apic_base = eax & APIC_BASE_FLAG;

* // print APIC Base address*
  print_str("\n APIC BASE ADDRESS IS ");

- Thanks
Vaibhav Jain
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.kernelnewbies.org/pipermail/kernelnewbies/attachments/20120624/df294f43/attachment.html 

More information about the Kernelnewbies mailing list