[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: CONFIG_HIGHMEM + kmap()



Hi folks,

Figured it out, I think. The top 128MB of kernel virtual
space is reserved, and never gets mapped into the PAGE_OFFSET
mapping. It's used for compile-time fixed virtual mappings
(including, it seems, kmap() mappings, which aren't really
"fixed") and vmalloc(). Physical pages that would otherwise
land in that part of kernel VM get moved up into the HIGHMEM
zone (or rather, the high zone lower bound moves down to
absorb them). So my point (4) below is just irrelevant; there
are no mappings to worry about for the kmapped vaddrs. Only
the kernel can or needs to call kmap(); user pagetables can
map HIGHMEM pages directly, no problem.

This code seems somewhat fragile to me.
We just trust people to not call __get_free_pages() with
GFP_HIGHMEM; if they did, it looks to me like bad things
would/could happen, since a high page can be allocated,
kmapped, kunmapped, and freed without page->virtual being
reset; so a __gfp() with GFP_HIGHMEM could return an old
bogus kmap vaddr if called at the wrong time. Everyone who
calls alloc_pages() with GFP_HIGHMEM must kmap() the page,
use it, and kunmap() it, preferably right away (although
it is possible to schedule() while you've got a kmapped
page). I assume there's some mechanism for preventing
vmalloc() from walking on the fixmaps and kmaps, but I
haven't noticed it yet.

"Joseph A. Knapka" wrote:
>
> Hi everyone,
>
> I'm trying to understand exactly how CONFIG_HIGHMEM and kmap()
> work. (I'm working on documenting the MM system in detail;
> I'll make it available once it's a little more complete.)
>
> Anyway, it looks to me like the following things are true:
>
> (1) At boot time, the kernel maps as much physical RAM as
> possible to the range PAGE_OFFSET...4GB in swapper_pg_dir
> (I'm only concerned with x86 at the moment, BTW);
>
> (2) If CONFIG_HIGHMEM is true, then the kmap() pagetables
> get initialized with vaddrs starting at PKMAP_BASE, which
> is PAGE_OFFSET < PKMAP_BASE < 4GB.
>
> (3) kmap() maps high pages into the PKMAP_BASE...4GB range
> as necessary when someone (kernel or user process?) needs
> them. (Looks to me like only the kernel can do it; that is,
> since PKMAP > PAGE_OFFSET, all kmapped() pages are going
> to be shared by all processes, and will only be available
> in kernel mode.)
>
> (4) No attempt is made to keep track of the pages that
> get unmapped from swapper_pg_dir when the kernel does
> a kmap(), and in fact the page->virtual pointer for
> a low page being (virtually) replaced by a kmapped page
> is not updated when a high page is mapped by kmap (!)
>
> Are all of the above points true? If so, I'm confused,
> because (4) just seems wrong. So I must not be
> understanding the code properly...

-- Joe Knapka

-- Joe Knapka
-
Kernelnewbies: Help each other learn about the Linux kernel.
Archive:       http://mail.nl.linux.org/
IRC Channel:   irc.openprojects.net / #kernelnewbies
Web Page:      http://www.surriel.com/kernelnewbies.shtml