One: Kmap () and Kunmap () functions
Permanent kernel mapping allows the kernel to establish long-term mappings of high-end page frames to the kernel address space. He uses a dedicated page table in the main kernel page table whose page table addresses are stored in pkmap_page_table, and the page table contains 512 or 1024 items.
Therefore, the kernel accesses up to 2M or 4 m of high-end memory at a time (the address range is between 4g-8m and 4g-4m, which is called the "kernel permanent mapping Space" or "permanent kernel mapping Space").
The Kmap () and Kunmap () functions cannot be used with interrupt handlers because they may sleep.
Pkmap_count is an array of integers with a capacity of last_pkmap, where each element corresponds to a persistent mapping page.
Macro definition and key variable definition:
Pkmap_page_table: High-end Memory main kernel page table, an address for a dedicated page table lock for permanent kernel mappings
Last_pkmap: Table entries included in the above page table (512 or 1024)
Pkmap_base: The start address of the linear address mapped by the page table
Pkmap_count: Provides an array of counters for page table entries
Page_address_htable: A hash table that records the relationship between a high-end page box and a linear address of a permanent kernel map
Page_address_map: A data structure that contains a pointer to a page descriptor and a linear address assigned to a page box;
A page box provides the current mapping, which is included in the page_address_htable hansh table
The kernel primarily uses the following data structures to establish the association of the physical page pages with their location in the virtual memory area
[CPP]View Plaincopy
- struct Page_address_map { //page address mapping
- struct page *page; description Structure of//page
- void *virtual; virtual address of//page
- struct List_head list; //Link to the page table pool global linked list page_address_pool or page_address_htable[hash_ptr (Page,pa_hash_order) through the list field].LH
- };
- 1 void *kmap (struct page* page)
- 2 {
- 3 if (! Pagehighmem (page))//Determine if it is high-end memory
- 4 return page_address (page);
- 5 return Kmap_high (page);
- 6}
- 7
- 8 void *kmap_high (struct page *page)
- 9 {
- Ten unsigned long vaddr;
- Spin_lock (&kmap_lock); //Spin lock
- Vaddr = (unsigned long) page_address (page);
- if (! VADDR) //If the page corresponds to a valid address in the middle of the virtual memory, then the map_new_virtual () function is called to map it,
- vaddr = map_new_virtual (page);
- pkmap_count[(vaddr-pkmap_base) >> page_shift]++; //pkamp_count array contains last_pkamp counters
- Spin_unlock (&kmap_lock);
- vaddr return (void *);
- 18}
Two: Kmap_atomic () temporary memory function
The Kmap_atomic () function is primarily used to establish temporary memory mappings, which cannot be used for code that may sleep.
[Linux Memory] persistent memory mapping Kmap