Помогите с функциями 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);
Однако, когда я инсталлирую этот модуль, ядро вылетает и жалуется, что не может обработать пейджинговый запрос @ address 00000000fee00300. Глядя в / proc / iomem, я вижу, что этот адрес находится в диапазоне, помеченном как "зарезервированный"
fee00000-fee00fff : reserved
Я также попытался использовать функции в:
static inline void __default_local_send_IPI_allbutself(int vector)
но ядро по-прежнему выдает сообщения "невозможно обработать запрос на пейджинг" и вылетает. У кого-нибудь есть предложения? Почему этот диапазон памяти помечен как "зарезервированный" и не помечен как используемый локальным APIC? Заранее спасибо.
1 ответ
Адрес APIC - это адрес физической памяти, но вы пытаетесь получить к нему доступ как линейный адрес памяти - вот почему ваш первый подход не работает. Память помечена как "зарезервированная" именно потому, что она принадлежит APIC, а не реальной памяти.
Вы должны использовать внутренние функции ядра. Для этого необходимо включить <asm/apic.h>
и использовать:
apic->send_IPI_allbutself(vector);