Page_address () function analysis -- how to obtain a virtual address through page

Source: Internet
Author: User

On the X86 platform, the memory is divided into low-end memory and high-end memory, so the corresponding virtual address of page search in the two regions is different.

1. Definition of page_address () function on x86


In include/Linux/mm. h, there are three macro definitions for the page_address () function, mainly dependent on different platforms:

First, let's take a look at the definition of several macros:
Config_highmem: as the name suggests, whether high-end memory is supported. You can view the config file. Generally, if the memory exceeds MB, It is configured to support high-end memory.
Want_page_virtual: The X86 platform is not defined.
Therefore, the following hashed_page_virtual is defined on the i386 platform that supports high-end memory.
 

#if defined(CONFIG_HIGHMEM) && !defined(WANT_PAGE_VIRTUAL)
#define HASHED_PAGE_VIRTUAL
#endif




1. // This is false. page_address () is not defined here on i386.


    #if defined(WANT_PAGE_VIRTUAL)

    #define page_address(page) ((page)->virtual)

    #define set_page_address(page, address) \\
    do { \\
    (page)->virtual = (address); \\
    } while(0)
    #define page_address_init() do { } while(0)
    #endif



2. // on the i386 platform without config_highmem configured, page_address is defined here

#if !defined(HASHED_PAGE_VIRTUAL) && !defined(WANT_PAGE_VIRTUAL)

    #define page_address(page) lowmem_page_address(page)

    #define set_page_address(page, address) do { } while(0)

    #define page_address_init() do { } while(0)

    #endif


3. // Therefore, page_address () is defined here on the i386 platform that supports high-end memory.

#if defined(HASHED_PAGE_VIRTUAL)

    void *page_address(struct page *page);

    void set_page_address(struct page *page, void *virtual);

    void page_address_init(void);

    #endif

II.Implementation of page_address () corresponding to page in low-end memory
Page_address () is equivalentlowmem_page_address():

#define page_address(page) lowmem_page_address(page)


static __always_inline void *lowmem_page_address(struct page *page)
{
return __va(page_to_pfn(page) << PAGE_SHIFT);
}

#define page_to_pfn(page) ((unsigned long)((page) - mem_map) + \
                                 ARCH_PFN_OFFSET)

 

#define __va(x) ((void *)((unsigned long)(x) + PAGE_OFFSET))


We know that the physical address space smaller than 896 m (low-end memory) and the linear address space 3g--3g + 896m are mapped one by one, so we only need to know the physical address corresponding to the page, the linear address space (PA + page_offset) corresponding to the page is displayed ).
So how do I find the physical address corresponding to a page? We know that the physical memory is divided into many pages by size (1 <page_shift), each of which corresponds to a struct page * Page Structure, these page description structures are stored in an array called mem_map, which is stored strictly in the order of physical memory, that is, the first page description structure of the physical system, as the first element of the mem_map array, and so on. Therefore, the physical address of the page can be obtained by multiplying the location of the page in the array mem_map by the page size. The above code is based on this principle:
The page_to_pfn (PAGE) function is used to obtain the position of each page in mem_map, and the left-shift page_shift function is multiplied by the page size. This gives you the physical address of the page. Add page_offset (3G) to the physical address to obtain the linear address of the page.

In the low-end memory (less than 896 MB), the virtual address obtained through the page (struct page * Page) is converted in this way.

3. Implementation of page_address () corresponding to pages in high-end memory:

On the i386 platform with config_highmem configured, page_address is implemented in mm/highmem. C:


/**
* page_address - get the mapped virtual address of a page
* @page: &struct page to get the virtual address of
*
* Returns the page\‘s virtual address.
*/
void *page_address(struct page *page)
{

unsigned long flags;
void *ret;
struct page_address_slot *pas;

If (! Pagehighmem (page) // determines whether it belongs to high-end memory. If not, it is low.
End-to-End
Stored, you can directly find
    return lowmem_page_address(page);

PAS = page_slot (PAGE); // see the following analysis. Pas points to the table header of the page_address_map structure corresponding to the page.

ret = NULL;
spin_lock_irqsave(&pas->lock, flags);
if (!list_empty(&pas->lh)) {
struct page_address_map *pam;

list_for_each_entry(pam, &pas->lh, list) {
if (pam->page == page) {
ret = pam->virtual;
goto done;}
}}
done:
spin_unlock_irqrestore(&pas->lock, flags);
return ret;

}


In high-end memory, a structure called page_address_map is introduced because the linear address cannot be obtained directly by adding page_offset to the physical address just like in low-end memory, this structure stores each page (only in high-end memory) and the corresponding virtual address. All mappings in high-end memory are linked through the linked list, this structure is created during high-end memory ing and added to the linked list.

/*
* Describes one page-> virtual Association
*/
Struct page_address_map {
Struct page * page; // page
Void * virtual; // virtual address
Struct list_head list; // point to the next Structure
};


If the memory is much larger than 896 MB, there will be more pages in the high-end memory (memory-896 MB)/4 K pages, assuming the page size is 4 K ), if you use only one linked list, it takes a long time to search. Therefore, the hash algorithm is introduced here. Multiple linked lists are used, and each page uses a certain hash algorithm, corresponding to a linked list, there are always enough 128 linked lists:

/*
* Hash table Bucket
*/
Static struct page_address_slot {
Struct list_head LH; // list of page_address_maps points to

// Page_address_map Structure linked list
Spinlock_t lock;/* protect this bucket \'s list */
} Page_address_htable [1 <pa_hash_order];

Pa_hash_order = 7, so a total of 1 <7 (128) linked list, each page corresponds to a page_address_htable linked list after the hash algorithm, then, traverse the linked list to find the corresponding page and virtual address.
The following code corresponds to a page_address_htable linked list after page uses the hash algorithm:

static struct page_address_slot *page_slot(struct page *page)
{
return &page_address_htable[hash_ptr(page, PA_HASH_ORDER)];
}


The hash_ptr (Val, BITs) function is a simple hash algorithm on a 32-bit machine, that is, to multiply Val by a golden value golden_ratio_prime_32, In the result (32-bit) take the high bits bit (here 7 digits) as the index of the hash table

static inline u32 hash_32(u32 val, unsigned int bits)
{
/* On some cpus multiply is faster, on others gcc will do shifts */
u32 hash = val * GOLDEN_RATIO_PRIME_32;

/* High bits are more random, so use them. */
return hash >> (32 - bits);
}



In this way, after the PAS = page_slot (PAGE) is executed, the PAS points to the header of the linked table where the page_address_map structure corresponding to the page is located.
Then traverse the linked list to find the corresponding linear address (if any). Otherwise, null is returned.

list_for_each_entry(pam, &pas->lh, list) {
   if (pam->page == page) {
      ret = pam->virtual;
      goto done;
   }
}

 

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.