X-Git-Url: http://rtime.felk.cvut.cz/gitweb/jailhouse.git/blobdiff_plain/4e0ea74420900c7a66d265117b09fddbc3aaa754..f053c948f5b6fe7b9ec5cf6533e177fd42113ba3:/hypervisor/paging.c diff --git a/hypervisor/paging.c b/hypervisor/paging.c index 1fd7402..1f22887 100644 --- a/hypervisor/paging.c +++ b/hypervisor/paging.c @@ -89,32 +89,44 @@ static unsigned long find_next_free_page(struct page_pool *pool, /** * Allocate consecutive pages from the specified pool. - * @param pool Page pool to allocate from. - * @param num Number of pages. + * @param pool Page pool to allocate from. + * @param num Number of pages. + * @param align_mask Choose start so that start_page_no & align_mask == 0. * * @return Pointer to first page or NULL if allocation failed. * * @see page_free */ -void *page_alloc(struct page_pool *pool, unsigned int num) +static void *page_alloc_internal(struct page_pool *pool, unsigned int num, + unsigned long align_mask) { - unsigned long start, last, next; + /* The pool itself might not be aligned as required. */ + unsigned long aligned_start = + ((unsigned long)pool->base_address >> PAGE_SHIFT) & align_mask; + unsigned long next = aligned_start; + unsigned long start, last; unsigned int allocated; - start = find_next_free_page(pool, 0); - if (start == INVALID_PAGE_NR) +restart: + /* Forward the search start to the next aligned page. */ + if ((next - aligned_start) & align_mask) + next += num - ((next - aligned_start) & align_mask); + + start = next = find_next_free_page(pool, next); + if (start == INVALID_PAGE_NR || num == 0) return NULL; -restart: + /* Enforce alignment (none of align_mask is 0). */ + if ((start - aligned_start) & align_mask) + goto restart; + for (allocated = 1, last = start; allocated < num; allocated++, last = next) { next = find_next_free_page(pool, last + 1); if (next == INVALID_PAGE_NR) return NULL; - if (next != last + 1) { - start = next; - goto restart; - } + if (next != last + 1) + goto restart; /* not consecutive */ } for (allocated = 0; allocated < num; allocated++) @@ -125,6 +137,34 @@ restart: return pool->base_address + start * PAGE_SIZE; } +/** + * Allocate consecutive pages from the specified pool. + * @param pool Page pool to allocate from. + * @param num Number of pages. + * + * @return Pointer to first page or NULL if allocation failed. + * + * @see page_free + */ +void *page_alloc(struct page_pool *pool, unsigned int num) +{ + return page_alloc_internal(pool, num, 0); +} + +/** + * Allocate aligned consecutive pages from the specified pool. + * @param pool Page pool to allocate from. + * @param num Number of pages. Num needs to be a power of 2. + * + * @return Pointer to first page or NULL if allocation failed. + * + * @see page_free + */ +void *page_alloc_aligned(struct page_pool *pool, unsigned int num) +{ + return page_alloc_internal(pool, num, num - 1); +} + /** * Release pages to the specified pool. * @param pool Page pool to release to. @@ -468,8 +508,6 @@ int paging_init(void) per_cpu_pages = hypervisor_header.max_cpus * sizeof(struct per_cpu) / PAGE_SIZE; - system_config = (struct jailhouse_system *) - (__page_pool + per_cpu_pages * PAGE_SIZE); config_pages = PAGES(jailhouse_system_config_size(system_config)); page_offset = JAILHOUSE_BASE - @@ -513,16 +551,16 @@ int paging_init(void) if (err) return err; - if (system_config->debug_uart.flags & JAILHOUSE_MEM_IO) { - vaddr = (unsigned long)hypervisor_header.debug_uart_base; - /* check if UART overlaps remapping region */ - if (vaddr + system_config->debug_uart.size >= REMAP_BASE && + if (system_config->debug_console.flags & JAILHOUSE_MEM_IO) { + vaddr = (unsigned long)hypervisor_header.debug_console_base; + /* check if console overlaps remapping region */ + if (vaddr + system_config->debug_console.size >= REMAP_BASE && vaddr < REMAP_BASE + remap_pool.pages * PAGE_SIZE) return trace_error(-EINVAL); err = paging_create(&hv_paging_structs, - system_config->debug_uart.phys_start, - system_config->debug_uart.size, vaddr, + system_config->debug_console.phys_start, + system_config->debug_console.size, vaddr, PAGE_DEFAULT_FLAGS | PAGE_FLAG_DEVICE, PAGING_NON_COHERENT); if (err)