Data Structures

As discussed in Section 3.4.2, the IA-32 kernel reserves a region that follows on from the vmalloc area and extends from pkmap_base to fixaddr_start. This area is used for persistent mappings. The schemes used by different architectures are similar.

pkmap_count (defined in mm/highmem.m) is an integer array with LAST_PKMAP positions that contain an entry for each page that can be persistently mapped. It is, in fact, a usage counter for the mapped pages with slightly unusual semantics. The number of users in the kernel is not counted, but the number of users plus 1. If the value of the counter is 2, the mapped page is used at just one point in the kernel. The counter value 5 indicates that there are four users. Expressed more generally, the counter value n stands for n — 1 users in the kernel.

As with classic usage counters, 0 means that the associated page is not in use. Counter value 1 has a special meaning. The page associated with the position has already been mapped but cannot be used because the TLB of the CPU has not been updated and access would either fail or be directed to an incorrect address.

The kernel makes use of the following data structure to create the association between the page instances of the physical pages and their position in the virtual memory area:

mm/highmem.c struct page_address_map { struct page *page; void *virtual; struct list_head list;

This structure is used to create the page—>virtual mapping (hence the name of the structure). page holds a pointer to the page instance in the global mem_map array, and virtual specifies the allocated position in the kernel virtual address space.

For ease of organization, the mappings are kept in a hash table where the list element is used to set up an overflow list to handle hash collisions.

The hash table is implemented by means of the page_address_htable array, not discussed further here. The hash function is page_slot from mm/highmen.c, which determines the page address on the basis of the page instance. page_address is the front-end function to determine the address of a given page instance using the data structures just described:

mm/highmem.c void *page_address(struct page *page) Figure 3-41 outlines the interplay between the above data structures.

^ struct page_address_map —► page_address_map->virtual ■ page_address_map->page

Virtual address space 1 2

LAST_ PKMAP

LAST_ PKMAP

LAST_ PKMAP

pkmap_count

Virtual address space 1 2

LAST_ PKMAP

page_address_htable

Figure 3-41: Data structures for managing persistent mappings.

pkmap_count page_address_htable

Figure 3-41: Data structures for managing persistent mappings.

Continue reading here: Creating a Mapping

Was this article helpful?

0 0