Как зарегистрировать обработчик прерываний для сгенерированного x2APIC IPI? - PullRequest
0 голосов
/ 08 июня 2019

Я включил x2APIC в ОС хоста и хочу сгенерировать IPI на самом уровне хоста (а не внутри ВМ).

Чтобы проверить, включен ли x2APIC или нет, я запускаю следующую команду:

sudo rdmsr 0x1b // IA32_APIC_BASE MSR to check the x2APIC status

А согласно Intel SDM бит 10 показывает состояние x2APIC. Результат для вышеуказанной команды - fee00d00 и d-1101. Итак, оба бита 10 и 11 включены, что означает, что LAPIC может работать как в режиме APIC, так и в режиме x2APIC.

После включения этого я пытаюсь написать обработчик прерываний, чтобы я мог обрабатывать IPI, генерируемый lapic.

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

MODULE_LICENSE("GPL");
MODULE_AUTHOR("A-B");
MODULE_DESCRIPTION("A simple example Linux module.");
MODULE_VERSION("0.01");

#define IRQ_x2APIC 0xf0  //Taken from the reserved linux list

#define APIC_EOI_MSR 0x80B
#define EOI_ACK 0x0

#define wrmsrl(msr, val) \
    write_msr((msr), (u32)((u64)(val)), (u32)((u64)(val) >> 32))


static inline void write_msr(unsigned int msr, unsigned low, unsigned high)
{
   asm volatile("wrmsr" : : "c" (msr), "a"(low), "d" (high) : "memory");
}


static irqreturn_t handler_irq(int irq, void *dev_id)
{
    printk("irq %d\n", irq);
    wrmsrl(APIC_EOI_MSR, EOI_ACK);
    return IRQ_HANDLED;
}

static void register_handler(unsigned int irq) {
    const char *devname = "x2apic_irq";
    int ret = request_irq(irq, (irq_handler_t )handler_irq, IRQF_TRIGGER_RISING |  IRQF_TRIGGER_FALLING | IRQF_PERCPU, devname, NULL);
    if (ret < 0) {
        printk(KERN_ALERT "request_irq failed with %d\n", ret);
    }
}

static int __init lkm_example_init(void) {
    free_irq(IRQ_x2APIC, NULL);
    register_handler(IRQ_x2APIC);
    return 0;
}

static void __exit lkm_example_exit(void) {
    free_irq(IRQ_x2APIC, NULL);
    printk(KERN_INFO "Goodbye, World!\n");
}

module_init(lkm_example_init);
module_exit(lkm_example_exit);

После загрузки этого модуля с помощью insmod я надеюсь увидеть запись в /proc/interrupts, но при запуске команды dmesg я получаю сообщение об ошибке request_irq failed with -22 (недопустимые аргументы).

Не могли бы вы указать, что не так с модулем? Или что еще мне нужно сделать, чтобы зарегистрировать обработчик прерываний?

...