/**
* 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++)
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.
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 -
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)