]> rtime.felk.cvut.cz Git - jailhouse.git/blobdiff - hypervisor/paging.c
Merge remote-tracking branch 'kiszka/master'
[jailhouse.git] / hypervisor / paging.c
index 1fd74029a2046c46d88c7ee7af830acf552cf8ec..1f228878b6f48ca11d8e52f248f6678c0f12de39 100644 (file)
@@ -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)