Linux kernel source scenario analysis-address mapping for external device storage spaces

Source: Internet
Author: User

With the development of computer technology, it is found that the simple I/O mapping method can not meet the requirements. This method is only suitable for the early computer technology, when a peripheral is usually only a few registers, through these registers can complete the external operation of all. And now the situation is not the same. For example, on a PC you can plug in an image card with 2MB of memory, or even a piece of ROM with executable code. So to map the memory on the peripheral card to the memory space is actually a means of virtual space. In the Linux kernel, such mappings are created by the function Ioremap ().


For the management of memory pages, usually we first allocate a virtual space in the virtual space, and then allocate the corresponding physical memory page for this interval and establish the mapping. And such mappings are not built at once, and can be set up incrementally when accessing these virtual pages to cause page anomalies.

However, Ioremap () is different, first we have a physical storage interval, whose address is the memory on the peripheral card appears on the bus address (not the storage unit on the external multiplication local physical address). In a Linux system, theCPU cannot access the storage space by physical address, but must use the virtual address, so it must "reverse" the physical address to find a piece of virtual space and establish a mapping . Second, such a requirement only occurs in the operation of the external device, and this is the kernel, so the corresponding virtual space is in the system space (3GB or more).


Let's look at Ioremap first, the code is as follows:

extern inline void * IOREMAP (unsigned long offset, unsigned long size) {return __ioremap (offset, size, 0);}

__ioremap, the code is as follows:

void * __IOREMAP (unsigned long phys_addr, unsigned long size, unsigned long flags) {void * addr;struct vm_struct * area;uns igned long offset, last_addr;/* Don ' t allow wraparound or zero size */last_addr = phys_addr + size-1;if (!size | | last_a DDR < PHYS_ADDR) return null;/* * Don ' t remap the low Pci/isa area, it's always mapped. */if (phys_addr >= 0xa0000 && last_addr < 0x100000) return Phys_to_virt (PHYS_ADDR);/* * Don ' t allow anybody t o Remap normal RAM that we ' re using. */if (Phys_addr < Virt_to_phys (high_memory)) {char *t_addr, *t_end;struct page *page;t_addr = __va (phys_addr); t_end = t   _addr + (size-1); for (page = Virt_to_page (t_addr); page <= virt_to_page (t_end); page++) if (!        Pagereserved (page)) return NULL;} We assume that the condition is met, execute it here/* * Mappings has to be page-aligned */offset = phys_addr & ~page_mask;phys_addr &= page_mask;//Object Address size = Page_align (last_addr)-phys_addr; From the starting physical address to the end of the total number of bytes */* Ok, go for it. */area = Get_vm_area (Size, vm_iOREMAP);//Vmlist_lock Find the appropriate virtual address and insert Vm_struct vmlist_lockif (!area) return null;addr = area->addr;//virtual address if (REMAP_ Area_pages (vmalloc_vmaddr (addr), phys_addr, size, flags)) {//Establish mappings between virtual and physical addresses Vfree (addr); return NULL;} return (void *) (offset + (char *) addr);//returns the virtual address plus the 12-bit offset of the physical page}

Get_vm_area, locate the appropriate virtual address in Vmlist_lock and insert the vm_struct into the Vmlist_lock code as follows:

struct vm_struct * Get_vm_area (unsigned long size, unsigned long flags) {unsigned long addr;struct vm_struct **p, *tmp, *ar Ea;area = (struct vm_struct *) kmalloc (sizeof (*area), gfp_kernel); if (!area) return null;size + = PAGE_SIZE;ADDR = vmalloc_s Tart;write_lock (&vmlist_lock); for (P = &vmlist; (TMP = *p); p = &tmp->next) {//Vmlist_lock find the appropriate virtual address if (size + addr) < addr) {write_unlock (&vmlist_lock); Kfree (area) ; return NULL;} if (size + addr < (unsigned long) tmp->addr) break;addr = tmp->size + (unsigned long) tmp->addr;if (Addr > V Malloc_end-size) {write_unlock (&vmlist_lock); Kfree (area); return NULL;}} Area->flags = FLAGS;AREA->ADDR = (void *) addr;//virtual Address area->size = size;//size Area->next = *p;//will Vm_ struct Insert vmlist_lock*p = Area;write_unlock (&vmlist_lock); return area;}

Among them, thevm_struct structure is as follows:

struct Vm_struct {unsigned long flags;void * addr;unsigned long size;struct vm_struct * next;};

struct vm_struct * vmlist;

Go back to __ioremap, start executing remap_area_pages, establish a mapping between the virtual address and the physical address, the code is as follows:

static int remap_area_pages (unsigned long address, unsigned long phys_addr, unsigned long size, unsigned long flags)//ADDR ESS is the virtual address, PHYS_ADDR is the physical address {pgd_t * dir;unsigned long end = Address + size;phys_addr-= address;//minus address, and later added Addressdir = Pgd_offset (&init_mm, address);//point to Page directory entry Flush_cache_all (); if (address >= end) BUG ();d o {pmd_t *PMD;PMD = Pmd_ Alloc_kernel (dir, address);//relay or point to page directory entry if (!PMD) return-enomem;if (REMAP_AREA_PMD (PMD, Address, end-address, Phys_ Addr + address, flags))//end-address for size, phys_addr + address is Physical address return-enomem;address = (address + pgdir_size) & Pgdi r_mask;dir++;//refers to the next page directory entry} while (address && address < end); Flush_tlb_all (); return 0;}

REMAP_AREA_PMD, the code is as follows:

static inline int REMAP_AREA_PMD (pmd_t * PMD, unsigned long address, unsigned long size,unsigned long phys_addr, unsigned Long flags) {unsigned long end;address &= ~pgdir_mask;end = address + size;if (end > Pgdir_size) end = Pgdir_size;phy S_ADDR-= address;if (address >= end) BUG ();d o {pte_t * pte = Pte_alloc_kernel (PMD, address);//point to Page Table entry if (!PTE) return-en Omem;remap_area_pte (Pte, Address, end-address, address + phys_addr, flags);//end-address for size, phys_addr + Address is physical addresses = (address + pmd_size) & pmd_mask;pmd++;//refers to the next page directory entry} while (address && address < end) ; return 0;}


Remap_area_pte, the code is as follows:

static inline void Remap_area_pte (pte_t * pte, unsigned long address, unsigned long size,unsigned long phys_addr, unsigned Long flags) {unsigned long end;address &= ~pmd_mask;end = address + size;if (end > Pmd_size) end = Pmd_size;if (addr ESS >= end) BUG ();d o {if (!pte_none (*pte)) {PRINTK ("Remap_area_pte:page already exists\n"); BUG ();} Set_pte (Pte, Mk_pte_phys (PHYS_ADDR, __pgprot (_page_present | _page_rw | _page_dirty | _page_accessed | flags)));// The page table entry points to the corresponding page, and the page's properties are set to _page_present,_page_rw,_page_dirty,_page_accessedaddress + = page_size;phys_addr + = PAGE_SIZE; pte++;//refers to the next page table entry} while (address && address < end);}

Back to__ioremap, the last return is the virtual address plus the physical page after the 12-bit offset to the final virtual address, the previous mapping (page directory entries and page table entries), so that the virtual address can be accessed to the physical address of the first line of code.


Because the kernel mm_struct structure init_mm is separate, init_mm is not reachable from the task structure of any one process. Therefore, KSWAPD can not see the init_mm in the virtual range, these sections of the page will naturally not be swapped out and resident memory.


Linux kernel source scenario analysis-address mapping for external device storage spaces

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.