Помощь с функциями APIC в Linux

Я пытаюсь поиграть с локальными функциями APIC в ядре Linux 2.6.32.40, но у меня возникают некоторые проблемы. Я хочу попытаться отправить немаскируемые прерывания (NMI) на все процессоры в моей системе (я использую Intel i7 Q740). Сначала я прочитал документацию в Руководстве разработчика программного обеспечения Intel, том 3, относящуюся к функциям APIC. В нем говорится, что прерывания могут передаваться всем процессорам посредством использования регистра команд прерывания (ICR), расположенного по адресу 0xFEE00300. Поэтому я написал модуль ядра со следующей функцией инициализации, чтобы попытаться записать в этот регистр:

#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);

Однако, когда я вставляю этот модуль, ядро ​​​​вылетает и жалуется на то, что не может обработать запрос на подкачку по адресу 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) Я получаю сообщение ядра: BUG: невозможно обработать запрос подкачки ядра в FFFFFFFFFF5fb300 - person John; 12.08.2011
comment
Собственно, я решил вопрос. Проблема возникла из-за отсутствия информации с моей стороны. Я запускал этот код в domain0 гипервизора Xen. Xen блокировал запись в системную память (глупая ошибка с моей стороны). - person John; 12.08.2011
comment
@John: Ваш первый подход все равно потерпел бы неудачу на голом железе. - person caf; 12.08.2011