How to read/write LAPIC Registers from Kernel Module?


I'm trying to disable all Interrupts. Most of them are easy, but I have problems with the Non-Maskable Interrupts (NMIs). To disable them, I want to manipulate the LVT Registers in the Local APIC. Currently I am testing inside a Kernel Module, cause that's the Environment, the final code should run.

How can I read/write to the memory-mapped registers of the APIC?

I've already read many articles and everyone suggested this procedure. I also tried to directly access the *mapped pointer, which resolves in the same result.

Instead of the foo() Function I implemented a lookup for the correct address. But according to the Intel manual and my personal inspections, the APIC always get's mapped to the physical address 0xFEE00000, which is interesting, cause I also tried the program on a Virtual Machine with 2 GB RAM.

phys_addr_t apic_base_phys = foo(); // fee00000
void __iomem *mapped = ioremap(apic_base_phys + 0x20, 0x4);

if(mapped == NULL){
    printk(KERN_INFO "nullpointer\n");
} else {
    uint32_t value = ioread32(mapped);
    printk(KERN_INFO "Value: %x\n", value); // 0xffffffff



[ 1329.743182] apic_base_phys: fee00000
[ 1329.743198] Value: ffffffff

Address 0xFEE00020 should output the Local APIC ID, which probably not is 0xFFFFFFFF.
I also tried to read 0xFEE00030 which should output the LAPIC Version.

asked on Stack Overflow Apr 16, 2019 by MatzeWi

1 Answer


Got the solution by myself: On my System runs the newer x2APIC. This uses a different transfer mode.

This can be disabled by adding nox2apic to the boot options.

answered on Stack Overflow Apr 17, 2019 by MatzeWi

User contributions licensed under CC BY-SA 3.0