Creating a vmarea

Before a new virtual memory area can be created, it is necessary to find a suitable location for it. A linked list with instances of vm_area manages the sections already created in the vmalloc area. The global variable vmlist defined in mm/vmalloc is the list head.

mm/vmalloc.c struct vm_struct *vmlist;

The kernel provides the get_vm_area helper function in mm/vmalloc; it acts as a parameter-preparation front end for_get_vm_area. In turn, the latter function is a frontend for_get_vm_area_node that does the actual work. On the basis of the size information for the area, the function tries to find a suitable place in the virtual vmalloc space.

As a safety gap of 1 page (guard page) is inserted between each vmalloc area, the kernel first increases the size specification by the appropriate amount.

mm/vmalloc.c struct vm_struct *_get_vm_area_node(unsigned long size, unsigned long flags, unsigned long start, unsigned long end, int node)

size = PAGE_ALIGN(size);

* We always allocate a guard page.

The start and end parameters are set to vmalloc_start and vmalloc_end, respectively, by the calling functions.

A loop then iterates over all elements of the vmlist list to find a suitable entry. mm/vmalloc.c for (p = kvmlist; (tmp = *p) != NULL ;p = &tmp->next) { if ((unsigned long)tmp->addr < addr) {

if((unsigned long)tmp->addr + tmp->size >= addr) addr = ALIGN(tmp->size +

(unsigned long)tmp->addr, align);

continue;

if (size + addr <= (unsigned long)tmp->addr) goto found;

addr = ALIGN(tmp->size + (unsigned long)tmp->addr, align);

The kernel finds a suitable position if size+addr is less than the start address of the area just examined (held in tmp->addr). The new list element is then initialized with the appropriate values and is added to the vmlist linked list.

mm/vmalloc.c found:

area->flags = flags; area->addr = (void *)addr; area->size = size; area->pages = NULL; area->nr_pages = 0; area->phys_addr = 0;

return area;

A null pointer is returned to indicate failure if no suitable memory area is found. The remove_vm_area function removes an existing area from the vmalloc address space. <vmalloc.h>

struct vm_struct *remove_vm_area(void *addr);

The function expects as a parameter the virtual start address of the area to be removed. To find the area, the kernel must successively scan the list elements of vmlist until it finds a match. The corresponding vm_area instance can then be removed from the list.

Continue reading here: Allocating a Memory Area

Was this article helpful?

0 0