[start_kernel() --> page_address_init()]
page_address_init() do nothing when all RAM can be mapped directly, otherwise, do following operations:
highmem.c:
static struct page_address_map page_address_maps[LAST_PKMAP];
void __init page_address_init(void)
{
int i;
INIT_LIST_HEAD(&page_address_pool);
for (i = 0; i < ARRAY_SIZE(page_address_maps); i++)
list_add(&page_address_maps[i].list, &page_address_pool);
for (i = 0; i < ARRAY_SIZE(page_address_htable); i++) {
INIT_LIST_HEAD(&page_address_htable[i].lh);
spin_lock_init(&page_address_htable[i].lock);
}
spin_lock_init(&pool_lock);
}
|
page_address_pool is a global variable defined in highmem.c
/*
* page_address_map freelist, allocated from page_address_maps.
*/
static struct list_head page_address_pool; /* freelist */
static spinlock_t pool_lock; /* protects page_address_pool */
|
page_address_htable[] is also a global variable defined in highmem.c
/*
* Hash table bucket
*/
static struct page_address_slot {
struct list_head lh; /* List of page_address_maps */
spinlock_t lock; /* Protect this bucket's list */
} ____cacheline_aligned_in_smp page_address_htable[1<<PA_HASH_ORDER];
|
There is a very important data structure:
struct page_address_map, this structure's main purpose is to maintain the association of struct page and its virtual memory. However, this will be wasteful if the page has a linear association with its virtual memory. This becomes necessary when the addressing is hashed.
/*
* Describes one page->virtual association
*/
struct page_address_map {
struct page *page;
void *virtual;
struct list_head list;
};
|
Summary:1. The main purpose of page_address_init() is to initiate global variable
page_address_pool, which is used to support high memory that cannot be directly mapped.
page_address_pool is a list header pointing to lots of
struct page_address_map connected each other using list.
2.
page_address_htable[] is used to hold the list of entry that hash to the same bucket. page_address_init() initiates it.
阅读(3093) | 评论(1) | 转发(1) |