Помощ за функциите на APIC в Linux

Опитвам се да си играя с локалните APIC функции в ядрото на Linux 2.6.32.40, но имам някои проблеми. Искам да опитам да изпратя немаскируеми прекъсвания (NMI) до всички процесори в моята система (използвам Intel i7 Q740). Първо прочетох документацията в Ръководството на разработчиците на софтуер на Intel, том 3, свързана с APIC функциите. Той гласи, че прекъсванията могат да бъдат излъчвани към всички процесори чрез използването на регистъра на командите за прекъсване (ICR), разположен на адрес 0xFEE00300. Затова написах модул на ядрото със следната функция init, за да се опитам да запиша в този регистър:

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

MODULE_LICENSE("GPL");

#define SUCCESS 0
#define ICR_ADDRESS 0xFEE00300
#define ICR_PROGRAM 0x000C4C89

static int icr_init(void){

    int * ICR = (int *)ICR_ADDRESS;

    printk(KERN_ALERT "Programing ICR\n");

    *ICR = ICR_PROGRAM;

    return SUCCESS;
}

static void icr_exit(void){
    printk(KERN_ALERT "Removing ICR Programing module removed");
}

module_init(icr_init);
module_exit(icr_exit);

Въпреки това, когато insmod този модул, ядрото се срива и се оплаква, че не може да обработи заявката за пейджинг @ адрес 00000000fee00300. Гледайки под /proc/iomem, виждам, че този адрес е в диапазон, маркиран като "резервиран"

fee00000-fee00fff : reserved

Също така се опитах да използвам функциите под:

static inline void __default_local_send_IPI_allbutself(int vector)

но ядрото все още изхвърля съобщения "не може да обработи заявка за пейджинг" и се срива. Някой има ли предложения? Защо този диапазон от памет е маркиран като „запазен“, а не е маркиран като използван от локалния APIC? Благодаря предварително.


person John    schedule 08.08.2011    source източник


Отговори (1)


APIC адресът е адрес на физическа памет, но вие се опитвате да получите достъп до него като линеен адрес на паметта - затова първият ви подход не работи. Паметта е маркирана като "запазена" точно защото принадлежи на APIC, а не на реална памет.

Трябва да използвате вътрешните функции на ядрото. За да направите това, трябва да включите <asm/apic.h> и да използвате:

apic->send_IPI_allbutself(vector);
person caf    schedule 11.08.2011
comment
Имам същия проблем с тази функция, както и с: static inline void __default_local_send_IPI_allbutself(int vector) Получавам съобщение на ядрото: ГРЕШКА: не мога да обработя заявка за пейджинг на ядрото при FFFFFFFFFF5fb300 - person John; 12.08.2011
comment
Всъщност разреших проблема. Проблемът възникна от липсата на информация от моя страна. Изпълнявах този код в domain0 на Xen хипервизор. Xen блокираше записите в системната памет (тъпа грешка от моя страна). - person John; 12.08.2011
comment
@John: Вашият първи подход все още щеше да се провали на гол метал. - person caf; 12.08.2011