Creating a Mapping

The kmap function must be used to create a mapping by means of a page pointer.24 It is only a front end to establish whether the desired page really is in highmem. If not, the address yielded by page_address is returned as the result. Otherwise, the kernel delegates work to kmap_high, which is defined as follows:

mm/highmem.c void fastcall *kmap_high(struct page *page) {

unsigned long vaddr;

vaddr = (unsigned long)page_address(page); if (!vaddr)

vaddr = map_new_virtual(page); pkmap_count[PKMAP_NR(vaddr)]++; return (void*) vaddr;

24This function resides not only in arch/x86/mm/highmem_32.c but also in include/asm-ppc/highmem.h and include/asm-sparc/highmem.h with practically the same definition.

The page_address function discussed above first checks whether the page is already mapped. If it does not return a valid address, the page must be mapped using map_new_virtual. The function performs the following main steps:

1. The pkmap_count array is scanned backward from the last used position (held in the global variable last_pkmap_nr) until a free position is found. If no position is free, the function sleeps until another part of the kernel performs an unmapping.

When the maximum index of pkmap_count is reached, the search begins at position 0. In this case, the flush_all_zero_pkmaps function is also invoked to flush the caches (you will see this shortly).

2. The page tables of the kernel are modified so that the page is mapped at the desired position. However, the TLB is not updated.

3. The usage counter for the new position is set to 1. As stated above, this means that the page is reserved but cannot be used because the TLB entries are not current.

4. set_page_address adds the page to the data structures of the persistent kernel mappings.

The function returns the virtual address of the newly mapped page as its result.

On architectures that do not require high-memory pages (or if config_highmem is not set), a generic version of kmap is used to return only the page address without changing anything in virtual memory.

<highmem.h>

static inline void *kmap(struct page *page) {

might_sleep();

return page_address(page);

Continue reading here: This mechanism can never reduce the counter value to less than 1 this means that the associated page is not freed This is because of the additional usage counter increment required to ensure correct handling of the CPU cache as discussed above

Was this article helpful?

0 0