LINUX.ORG.RU

kernel BUG at mm/memory.c при вызове remap_pfn_range()


0

1

Здравствуйте!
Пытаюсь заставить работать на новом ядре драйвер и тестовую программу к нему, которые были написаны лет пять назад для этого же железа, но для старого ядра. В те времена все работало отлично.
Компьютер одноплатный. Загрузочная карта памяти содержит linux с ядром 3.10.12 и файлом initrd.img, сделанным так, чтобы постоянная файловая система не монтировалась, а работа велась в initrd, который крутится в оперативной памяти. Ядро было довольно сильно урезано, для экономии памяти.
Драйвер создан для сигнального процессора, который связан с одноплатным компьютером через PCI шину (и компьютер и плата содержащая процессор вставляются в PCI слоты в одной стойке). Драйвер успешно распознает процессор и загружается в систему.
Этот драйвер позволяет загружать данные с хоста (одноплатного компьютера) прямо в память сигнального процессора. Тестовая программа собственно это и делает.
В коде драйвера, в структуре file_operations, определена функция .mmap, которая, насколько я понимаю, производит отображение памяти процессора в пространство ядра. Функция mmap заключается в вызове функции remap_pfn_range(). Именно на вызове этой функции вылетает следующая ошибка и вся система перестает работать (здесь linkdrv это драйвер, а BoardTest это тестовая программа):

--------[ cut here ]--------
kernel BUG at mm/memory.c :2377! 
invalid opcode: 0000 [#1] SMP DEBUG_PAGEALLOC
Modules linked in: linkdrv(0)
CPU: 1 PID: 851 Comm: BoardTest Tainted: G   0 3.10.12 #10
Hardware name:      /F15, BIOS F15r1-Q.11 10/17/2006 
task: f6581950 ti: f5c5c000 task.ti: f5c5c000 
EIP: 0060:[<c10aeac4>] EFLAGS: 00010246 CPU: 1 
EIP is at remap_pfn_range+0x75/0x191
ЕАХ: 00000000 EBX: b72f5000 ECX: b72f5000 EDX: 00000000 
ESI: f6616c08 EDI: 00040000 EBP: f5c5ded8 ESP: f5c5de9c
 DS: 007b ES: 007b FS: 00d8 GS: 0033 SS: 0068 
CR0: 80050033 CR2: b760а890 CR3: 35c2f000 CR4: 000007d0 
DR0: 00000000 DR1: 00000000 DR2: 00000000 DR3: 00000000 
DR6: ffff0ff0 DR7: 00000400 
Stack:
 f5c5ded8 с10b2b9с f67d3540 00000200 f65175ac 00000003 
 00000000 b72f5000 00000000 f5c5ded0 f678ce00 f6616c08 
 f8028123 00000000 00000027 f6616c08 b74f5000 f5c5df24 
Call Trace:
 [<c10b2b9c>] ? vma_merge+0x148/0xlc5
 [<f80281Z3>] Mmар+0х4а/0х51 [linkdrv]
 [<c10b3fl6>] mmap_region+0x20d/0x3c8
 [<c10b4330>] do_mmap_pgoff+0x25f/0x2d5
 [<c10a9a3c>] vw_mmap_pgoff+0x54/0x7d
 [<c10b2d96>] SyS_mmap_pgoff+0xllf/0x159
 [<c14a2558>] syscall_call+0x7/0xb 
Code: 04 75 ec 89 7e 4c ff 75 ec 89 f9 8d 55 0c 89 f0 53 e8 88 36
EIP: [<c10aeac4>] remap_pfn_range+0x75/0x191  SS:ESP 0068:f5c5de9c 
---[ end trace b23282ceb98d656f ]---
Я нашел только один аналогичный случай на stackoverflow, но там проблема состояла в отображении большого объема памяти (1Гб и более). Здесь же такой проблемы не стоит. На всякий случай я все равно сделал так как советовали там в ответе (включив в ядре опцию CONFIG_TRANSPARENT_HUGEPAGE), но это разумеется не помогло. Пробовал так же использовать ядро с defconfig, но результат оставался тем же.

Подскажите пожалуйста, в чем может быть причина этой ошибки и в чем она вообще заключается? Насколько я понимаю, проблема больше в ядре(ведь драйвер раньше работал). Возможно нужно что-то изменить в конфигах? Если так, то что именно?

Заранее спасибо за любую помощь!



Последнее исправление: just_a_student (всего исправлений: 1)
Ответ на: комментарий от punya

Не, к сожалению не помогло. Там он решил проблему тем, что вставил remap_pfn_range() в функцию .mmap, а в моем случае она и так там находится

just_a_student
() автор топика

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

Заранее спасибо за любую помощь!

Проблема в том, что пять лет назад этот драйвер был написан из рук вон плохо, и то что он работал, это просто вопрос случая и везения.

Ядро нельзя писать методом «сейчас добавлю строчку кода, и все будет ништяк».

Лучшая помощь самому себе — прочитаная и проанализированная книга, а также код интерфейсов, которые ты используешь.

ttnl ★★★★★
()

В коде драйвера, в структуре file_operations, определена функция .mmap, которая, насколько я понимаю, производит отображение памяти процессора в пространство ядра.

Нет, неправильно понимаешь - она отображает физические адреса в пространстве пользователя. В общем не видя кода этой вашей mmap тут не о чем говорить.

anonymous
()
Ответ на: комментарий от anonymous

код у mmap следующий:

int Mmap(struct file* file, struct vm_area_struct* vma)
{
	
	struct inode* inode = file->f_dentry->d_inode;
	struct LinkDev* link = &linkdev[iminor(inode)];
	unsigned address = __pa(link->bufAddr[index]);
	unsigned size = link->bufSize[index];

	return remap_pfn_range(vma, vma->vm_start, (address >> PAGE_SHIFT), size, vma->vm_page_prot);
}

just_a_student
() автор топика
Ответ на: комментарий от anonymous

virt_to_phys(your_buff_addr) >> PAGE_SHIFT

Никакой разницы с тем что там написано не будет

http://lxr.free-electrons.com/source/arch/x86/include/asm/io.h?v=3.10#L111

Без понимания что там вендузятник наваял в этом драйвере не обойтись - явно напортачено с буферами.

anonymous
()
Ответ на: комментарий от anonymous

В remap_pfn_range() всего один BUG_ON(addr >= end). Есть проверки и в inline функциях, но они сильно выше по коду. Думаю, у него просто size нулевой.

ttnl ★★★★★
()
Ответ на: комментарий от ttnl

Спасибо! Сделал отладочный вывод: и вправду нулевой... Буду разбираться! Теперь хоть знаю в чем

just_a_student
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.