[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) {
    return NOPAGE_SIGBUS;

    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.026 / U:29.752 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site