Thursday, October 9, 2014

Access the redirection table entry in IO APIC

http://wiki.osdev.org/IOAPIC
http://wiki.osdev.org/APIC

These two URLs provides detailed the explanation about IOAPIC, but the read/write code do not work on my CentOS machine. The IO APIC base is 0xfec00000 on my machine (index 0xfec00000; port 0xfec00010). It is a memory maped IO memory.

I use the code in both user-level program and a kernel module. The code raises an segmentation fault. After looking at the dmesg, I notice that it is because page table does not know how to translate the virtual address (i.e., 0xfec00000).

Then I use the ioremap() in the kernel module, it works.

#include <linux/module.h>
#include <linux/init.h>

#include <asm/io.h>


MODULE_LICENSE("Dual BSD/GPL");



static int hello_init(void)
{
    // IO APIC base is 0xfec00000
    // IO APIC index: 0xfec00000
    // IO APIC data: 0xfec00010
    // The redicection table of the keyboard is at index 0x12
    // please see southbridge manual for redirection table
    // the original value of the redirection table entry is 0x939
    // We change it to 0xa39, which enables SMI triggering
    //
    // if you want to compile this kernel moudule,
    // please also change the Makefile to hello6.o
    //
    // just run the script enable_kb_SMI.sh to enable the SMI
    // triggering
    //
    unsigned int IRQ1_entry;
    void * IOAPIC_BASE = ioremap(0xfec00000, 32);
    iowrite8(0x12, IOAPIC_BASE);
    IRQ1_entry = ioread32((unsigned char*)IOAPIC_BASE + 0x10);
    printk("IRQ1 Entry Value is: %x\n", IRQ1_entry);
     
    iowrite8(0x12, IOAPIC_BASE);
    iowrite32(0xA39, (unsigned char*)IOAPIC_BASE + 0x10);
  
    printk("Successfully enable keyboard SMI triggering\n");
    return 0;
}

static void hello_exit(void)
{
    printk("Goodbye, crule world\n");
}

module_init(hello_init);
module_exit(hello_exit);

No comments: