2013-05-16 3 views
1

Я создаю систему FPGA System-on-Chip, где я меняю конфигурацию оборудования во время выполнения с помощью модуля ядра. Они используют Linux 2.6 и процессор LEON3 (SPARC). Некоторые битфайлы работают нормально, но для некоторых битфайлов я получаю «ядро незаконной инструкции» или «не удается обработать запрос подкачки ядра на виртуальном адресе x». Я уверен, что мое оборудование правильно, поскольку я тестировал его с помощью альтернативного метода, а аппаратное обеспечение, которое я меняю, не имеет ничего общего с процессором. Я предполагаю, что это ошибка программного обеспечения/модуля. Это происходит после моей 14-й записи в метод записи модуля ядра. Я не уверен, с чего начать для отладки. Любая помощь будет оценена по достоинству.Ядро Нелегальная инструкция при записи в модуль ядра

# cat x > /dev/y 
Unable to handle kernel paging request at virtual address 00001000 
tsk->{mm,active_mm}->context = 00000045 
tsk->{mm,active_mm}->pgd = fc013400 
       \|/ ____ \|/ 
       "@'/ ,. \`@" 
       /_| \__/ |_\ 
       \__U_/ 
cat(86): Oops [#1] 
PSR: f30000c7 PC: f0089e90 NPC: f0089e94 Y: 00000000 Not tainted 
PC: <vfs_write+0xb8/0x148> 
%G: 80080000 00001000 00000001 fd000100 00000dae f09c4370 fbca0000 0000fffb 
%O: 00001000 00000003 00001000 fe60e5dc fe60e430 fe60e420 fbca1e80 f0089e80 
RPC: <vfs_write+0xa8/0x148> 
%L: fbdcad40 00000000 fbca1e78 00000004 fbc0e940 00000000 fbdd2000 f0035784 
%I: 00001000 efe07b50 00001000 fbca1f40 00000000 00000000 000007af 000007af 
Disabling lock debugging due to kernel taint 
Caller[000007af]: 0x7af 
Instruction DUMP: d204200c f602600c c416e072 <84088001> 03000010 80a08001 02 
800018 b2102002 c404201c 
Killed 
# 

Kernel метод модуль записи:

ssize_t icap_write(struct file *filp, char *buf, size_t count, loff_t *f_pos) { 
unsigned long words, data, *pdata, mem_loc_temp; 

pdata = (unsigned long *)buf; 
mem_loc_temp = icap_mem_loc;//reset mem_loc_temp 

while((pdata < (buf + count)) && (mem_loc_temp < icap_mem_loc+4096)){ 
     leon_store_reg(mem_loc_temp,*pdata); 
     pdata++; 
     mem_loc_temp+=4; 
    } 
} 

Я думаю, что это моя проблема. pdata выходит за пределы. Является ли это жизнеспособный исправить, чтобы изменить его: -------------- обновленный код -------------

unsigned long *pdata; 
static int __init icap_init(void) { 
... 
pdata = (unsigned long *)kmalloc(mem_size*sizeof(char), GFP_KERNEL); 
... 
} 

ssize_t icap_write(struct file *filp, const char *buf, 
        size_t count, loff_t *f_pos) { 

int i, cycles, spins; 
ssize_t result; 

if(count%4 != 0){ 
    printk(KERN_INFO "ERROR: count = %d is not a multiple of 4. count mod 4 = %u\n Assuming 0 padding for last word. Configuration may not have completed as expected.",count, count%4); 
    //return count; 
} 

result = copy_from_user(pdata, buf, count); 
if (result) { 
    printk(KERN_INFO "copy_from_user failed, returned: %d\n.", result); 
    return -EINVAL; 
} 
spins = 0; 
while((leon_load_reg(ctrl_mem_loc+8) & 0x10) == 0){//check done 
    spins++;//spin on NOT done 
} 
if (spins > 0) 
    printk(KERN_INFO "%d spins\n", spins); 

leon_store_reg(ctrl_mem_loc+8, 0);//deassert start 

if(count == 4096){ 
    cycles=min((unsigned long)1024, (unsigned long)mem_size/4); 
}else if((count > 0) && (count < 4096)){ 
    cycles=min(((unsigned long)count+3)/4, (unsigned long)mem_size/4); 
}else{ 
    printk(KERN_INFO "ERROR: count > 4096\n"); 
    cycles = 0; 
} 

for(i = 0; i < cycles; i++){ 
    leon_store_reg(icap_mem_loc+4*i, pdata[i]); 
} 

leon_store_reg(ctrl_mem_loc, cycles);//set number of samples 
leon_store_reg(ctrl_mem_loc+8, 0x1);//set start high 

return count; 
} 
+0

Вы уверены, что ваше исправление работает? Поскольку он, похоже, делает то же самое, что и оригинал для меня, - напишите в -1 записи, затем напишите последнюю запись ... –

+0

Добавлен больше кода, чтобы сделать его понятным. Мое пространство памяти составляет 4096 байт, и я ожидаю, что buf будет иметь 4096 байт и будет считаться 4096. Может быть, мне нужно просто сделать это жестко, чтобы избежать путаницы, поскольку это не будет использоваться повторно или что-то еще. – Stuart

+0

'4K' - это страница ядра. Вы не должны использовать 'copy_from_user'. –

ответ

1

You может потребоваться добавить код для нас, чтобы помочь вам лучше.

Мое первое предположение: у вас есть где-то переписывать массив в коде и что, когда вы нажимаете на 14-ю запись, она поражает то, что требуется системе и вызывает исключение. Если возможно, проследите свою программу по мере ее записи, чтобы увидеть, написана ли она там, где она должна. Различные файлы будут находиться в разных местах в памяти, и если эти области не являются критическими для системы, это может объяснить, почему они не сбой, и это происходит.

Одна интересная вещь из вашего дампе:

Unable to handle kernel paging request at virtual address 00001000

Это 4096 в десятичной системе - так же, как смещение в вашем цикле. Так что, возможно, там что-то происходит, но ваш код, похоже, не исправляет его и может ухудшить его, поскольку в вашем цикле while есть два условия.

Дополнение кода измененными

Кастинг pdata к unsigned long * не может быть безопасным, если указатель базы не long выровнены. Не уверен, что ваша система разрешает доступ к неограниченной памяти или нет, поэтому будьте осторожны.

icap_mem_loc - неизвестный тип, но, по-видимому, представляет собой интегральное значение? если да, то обращение с целыми значениями и указателями требует будущих проблем.

Вы сравниваете длинный указатель без знака с неподписанным указателем на символ в цикле while - может быть безопасным, но остерегайтесь арифметики указателя здесь.

Вы компилируете этот код с включенными предупреждениями? если нет, сделайте это, так как я уверен, что он будет орать над вышеупомянутыми проблемами ...

Что произойдет, если icap_mem_loc NULL или 0? если это условие ошибки, вам нужно обработать его - запрос на ваш запрос указывает, что это плохое состояние, и у вас нет ASSERT или если условия для этого.

И, наконец, mem_loc_temp+=4; Это 4 - Вы уверены, что long: 4 байт в вашей системе. Должно быть sizeof() 'd или еще лучше, вместо этого нужно сконфигурировать const, чтобы избавиться от двусмысленности.

Не пытайтесь атаковать вас здесь, но указывая на каждую потенциальную точку отказа, которую я вижу, чтобы мы могли решить эту проблему.

+0

Я изменил вопрос. Я думаю, что нашел проблему, но буду благодарен за отзывы. – Stuart

+0

Комментарий выше - не думайте, что это ... –

+0

Не беспокойтесь, я очень ценю помощь. Теперь я избавился от большинства предупреждений. Я уверен, что система не допускает несвязанный доступ. 'icap_mem_loc' является int и устанавливается статически. Я исправил 'buf + count', переведя его в' unsigned long', который проверяется на размер в методе инициализации. – Stuart

Смежные вопросы