Specifications
This is the Title of the Book, eMatter Edition
Copyright © 2005 O’Reilly & Associates, Inc. All rights reserved.
434
|
Chapter 15: Memory Mapping and DMA
crw-r--r-- 1 root root 10, 175 Sep 15 07:40 agpgart
morgana% ./mapper /dev/scullp 8192 200
mapped "/dev/scullp" from 8192 (0x00002000) to 8392 (0x000020c8)
d0h1494
brw-rw---- 1 root floppy 2, 92 Sep 15 07:40 fd0h1660
brw-rw---- 1 root floppy 2, 20 Sep 15 07:40 fd0h360
brw-rw---- 1 root floppy 2, 12 Sep 15 07:40 fd0H360
Remapping Kernel Virtual Addresses
Although it’s rarely necessary, it’s interesting to see how a driver can map a kernel
virtual address to user space using mmap. A true kernel virtual address, remember, is
an address returned by a function such as vmalloc—that is, a virtual address mapped
in the kernel page tables. The code in this section is taken from scullv, which is the
module that works like scullp but allocates its storage through vmalloc.
Most of the scullv implementation is like the one we’ve just seen for scullp, except
that there is no need to check the
order parameter that controls memory allocation.
The reason for this is that vmalloc allocates its pages one at a time, because single-
page allocations are far more likely to succeed than multipage allocations. There-
fore, the allocation order problem doesn’t apply to vmalloced space.
Beyond that, there is only one difference between the nopage implementations used by
scullp and scullv. Remember that scullp, once it found the page of interest, would obtain
the corresponding
struct page pointer with virt_to_page. That function does not work
with kernel virtual addresses, however. Instead, you must use vmalloc_to_page. So the
final part of the scullv version of nopage looks like:
/*
* After scullv lookup, "page" is now the address of the page
* needed by the current process. Since it's a vmalloc address,
* turn it into a struct page.
*/
page = vmalloc_to_page(pageptr);
/* got it, now increment the count */
get_page(page);
if (type)
*type = VM_FAULT_MINOR;
out:
up(&dev->sem);
return page;
Based on this discussion, you might also want to map addresses returned by ioremap
to user space. That would be a mistake, however; addresses from ioremap are special
and cannot be treated like normal kernel virtual addresses. Instead, you should use
remap_pfn_range to remap I/O memory areas into user space.
,ch15.13676 Page 434 Friday, January 21, 2005 11:04 AM