[lkml]   [2003]   [Nov]   [15]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
Messages in this thread
SubjectMysterious driver-related oops in vm system

I've been trying to debug a nasty driver related oops
in the VM system on 2.4 kernels, and have reduced the
problem to a relatively simple test case that seems to cause an
oops on most Linux kernels. The oops occurs when the
test program calls exit(). It requires more than one execution
of the test program to cause an oops. Not all kernels generate
the oops, but there doesn't seem to be any particular pattern.

I have seen the problem on a variety of 2.4 kernels (2.4.18-2.4.22)
including both i586 and x86-64 platforms.

The oops is in mm/page_alloc.c, __free_pages_ok()
if (BAD_RANGE(zone,buddy2))

crashes here -> list_del(&buddy1->list);
mask <<= 1;
index >>= 1;

sample call trace: __free_pte zap_pte_range do_page_fault
zap_page_range exit_mmap mmput do_exit schedule do_group_exit

The crash is in the inline expansion of __list_del (linux/list.h):

static inline void __list_del(struct list_head *prev, struct list_head
next->prev = prev;
prev->next = next;

which is called by list_del: (linux/list.h)

static inline void list_del(struct list_head *entry)
__list_del(entry->prev, entry->next);
entry->next = (void *) 0;
entry->prev = (void *) 0;

And the crash is because both entry->prev and entry->next are NULL.

The problem seems to be related to the munmapping of a shared memory
segment. Modifying the test program to explicitly munmap() before
calling exit() causes instead a hang at the munmap() call.
This is particularly intriguing, since the driver does not implement
munmap() itself, but rather relies on the kernel default behavior.
The driver is memory mapping space originally allocated with

As far as I can tell, the driver implements mmap() and nopage()

Here is mmap:

static int das4020_mmap( struct file *filePtr, struct vm_area_struct
*vma )
int board = 0;
int chan = 0;
int size = vma->vm_end - vma->vm_start;
unsigned int minor = MINOR(filePtr->f_dentry->d_inode->i_rdev);

board = BOARD(minor); /* get which board */
chan = (minor & 0xf); /* get which channel */

if (chan >= 0 && chan < AD_CHANNELS) {

if(vma->vm_pgoff != 0) { // You have to map the entire buffer.

if (size > BoardData[board].dma_phy_size) { // You cannot
request more than the max buffer

vma->vm_ops = &das4020_vops;
vma->vm_flags |= VM_RESERVED;
vma->vm_private_data = (void *) minor;
return 0;

And here is nopage():

static struct page *das4020_nopage(struct vm_area_struct *vma, unsigned
long address, int write_access)
struct page *page = NOPAGE_SIGBUS; // page to be mapped
unsigned char *v_addr = NULL; // kernel virtual address to
be mapped to user space
unsigned int minor = (unsigned int) vma->vm_private_data;
int board = 0;
int chan = 0;
unsigned long offset; // offset to test for valid address

board = BOARD(minor);
chan = (minor & 0xf);

offset = (address - vma->vm_start) + vma->vm_pgoff * PAGE_SIZE;
if (offset >= BoardData[board].dma_phy_size) {

v_addr = BoardData[board].dma_virt_addr + (address - vma->vm_start);
page = virt_to_page(v_addr);
get_page (page);
return (page);

It was suggested last night that perhaps the VM_RESERVED flag was the
problem. Removing this flag does not change the behavior.

The test case can be downloaded from:
The test case does not require specialized hardware.

A Makefile is included with instructions for demonstrating the kernel
oops. Some kernels do not seem to show the symptoms, while others do.
A list of tests and results is included in the makefile.

Thanks for your help in tracking down this bug.

Steve Holland 11/14/03

sdh4 AT cornell D nospam O nospam T edu

To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to
More majordomo info at
Please read the FAQ at

 \ /
  Last update: 2005-03-22 13:58    [W:0.035 / U:0.648 seconds]
©2003-2018 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site