]> xenbits.xensource.com Git - people/sstabellini/xen-unstable.git/.git/commitdiff
xen,common: move colored allocator into page_alloc
authorLuca Miccio <206497@studenti.unimore.it>
Mon, 6 Jan 2020 17:35:09 +0000 (18:35 +0100)
committerLuca Miccio <206497@studenti.unimore.it>
Tue, 7 Jan 2020 09:50:41 +0000 (10:50 +0100)
Colored allocator is supposed to be like a "side allocator" because the
standard buddy allocator is needed for Xen heap. Until there is no
support to Xen heap coloring the two allocators have to coexist. Current
implementation assumes that colored allocator is architecture dependent
but it is false. In fact, only color definition depends on the hardware
but the overall data structure and its management are hardware agnostic.
There is no reason to split implementations so move the colored allocator
code to page_alloc. This helps to keep everything organized.

Signed-off-by: Luca Miccio <206497@studenti.unimore.it>
xen/arch/arm/Makefile
xen/arch/arm/color_alloc.c [deleted file]
xen/arch/arm/coloring.c
xen/common/page_alloc.c
xen/include/xen/mm.h

index 23dbf66cd5d82f8d187951ac5de5eec098eb1de0..e1e67323ec9e2c0ef8eb5e56f9fb124c90c380c0 100644 (file)
@@ -63,7 +63,6 @@ obj-y += vsmc.o
 obj-y += vpsci.o
 obj-y += vuart.o
 obj-$(CONFIG_COLORING) += coloring.o
-obj-$(CONFIG_COLORING) += color_alloc.o
 
 #obj-bin-y += ....o
 
diff --git a/xen/arch/arm/color_alloc.c b/xen/arch/arm/color_alloc.c
deleted file mode 100644 (file)
index 219300a..0000000
+++ /dev/null
@@ -1,275 +0,0 @@
-/*
- * xen/arch/arm/color_alloc.c
- *
- * Colored allocator
- *
- * Copyright (C) 2019 Xilinx Inc.
- *
- * Authors:
- *  Luca Miccio <lucmiccio@gmail.com> (Università di Modena e Reggio Emilia)
- *  Marco Solieri <ms@xt3.it> (Università di Modena e Reggio Emilia)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-#include <asm/coloring.h>
-#include <asm/page.h>
-#include <xen/keyhandler.h>
-
-/*
- * Pages are stored by their color in separated lists. Each list defines a color
- * and it is initialized during end_boot_allocator, where each page's color
- * is calculated and the page itself is put in the correct list.
- * After initialization we have N list where N is the number of maximum
- * available colors on the platform.
- * All the lists' heads are stored as element in an array with size N-1 using
- * the following schema:
- * array[X] = head of color X, where X goes from 0 to N-1
- */
-typedef struct page_list_head color_list;
-static color_list *color_heap;
-static long total_avail_col_pages;
-static u64 col_num_max;
-static bool color_init_state = true;
-
-static DEFINE_SPINLOCK(heap_lock);
-
-#define page_to_head(pg) (&color_heap[color_from_page(pg)])
-#define color_to_head(col) (&color_heap[col])
-
-/* Add page in list in order depending on its physical address. */
-static void page_list_add_order(struct page_info *pg, struct list_head *head)
-{
-    struct page_info *pos;
-
-    /* Add first page after head */
-    if ( page_list_empty(head) )
-    {
-        page_list_add(pg, head);
-        return;
-    }
-
-    /* Add non-first page in list in ascending order */
-    page_list_for_each_reverse(pos, head)
-    {
-        /* Get pg position */
-        if ( page_to_maddr(pos) <= page_to_maddr(pg) )
-        {
-            /* Insert pg between pos and pos->list.next */
-            page_list_add(pg, &pos->list);
-            break;
-        }
-
-        /*
-         * If pos is the first element it means that pg <= pos so we have
-         * to insert pg after head.
-         */
-        if ( page_list_first(head) == pos )
-        {
-            page_list_add(pg, head);
-            break;
-        }
-    }
-}
-
-/* Alloc one page based on domain color configuration */
-static struct page_info *alloc_col_heap_page(
-    unsigned int memflags, struct domain *d)
-{
-    struct page_info *pg, *tmp;
-    bool need_tlbflush = false;
-    uint32_t cur_color;
-    uint32_t tlbflush_timestamp = 0;
-    uint32_t *colors = 0;
-    int max_colors;
-    int i;
-
-    colors = d->colors;
-    max_colors = d->max_colors;
-
-    spin_lock(&heap_lock);
-
-    tmp = pg = NULL;
-
-    /* Check for the first pg on non-empty list */
-    for ( i = 0; i < max_colors; i++ )
-    {
-        if ( !page_list_empty(color_to_head(colors[i])) )
-        {
-            tmp = pg = page_list_last(color_to_head(colors[i]));
-            cur_color = d->colors[i];
-            break;
-        }
-    }
-
-    /* If all lists are empty, no requests can be satisfied */
-    if ( !pg )
-    {
-        spin_unlock(&heap_lock);
-        return NULL;
-    }
-
-    /* Get the highest page from the lists compliant to the domain color(s) */
-    for ( i += 1; i < max_colors; i++ )
-    {
-        if ( page_list_empty(color_to_head(colors[i])) )
-        {
-            C_DEBUG("List empty\n");
-            continue;
-        }
-        tmp = page_list_last(color_to_head(colors[i]));
-        if ( page_to_maddr(tmp) > page_to_maddr(pg) )
-        {
-            pg = tmp;
-            cur_color = colors[i];
-        }
-    }
-
-    if ( !pg )
-    {
-        spin_unlock(&heap_lock);
-        return NULL;
-    }
-
-    pg->count_info = PGC_state_inuse;
-
-    if ( !(memflags & MEMF_no_tlbflush) )
-        accumulate_tlbflush(&need_tlbflush, pg,
-                            &tlbflush_timestamp);
-
-    /* Initialise fields which have other uses for free pages. */
-    pg->u.inuse.type_info = 0;
-    page_set_owner(pg, NULL);
-
-    flush_page_to_ram(mfn_x(page_to_mfn(pg)),
-                      !(memflags & MEMF_no_icache_flush));
-
-    page_list_del(pg, page_to_head(pg));
-    total_avail_col_pages--;
-
-    spin_unlock(&heap_lock);
-
-    if ( need_tlbflush )
-        filtered_flush_tlb_mask(tlbflush_timestamp);
-
-    return pg;
-}
-
-struct page_info *alloc_col_domheap_page(
-    struct domain *d, unsigned int memflags)
-{
-    struct page_info *pg;
-
-    ASSERT(!in_irq());
-
-    /* Get page based on color selection */
-    pg = alloc_col_heap_page(memflags, d);
-
-    if ( !pg )
-    {
-        C_DEBUG("ERROR: Colored Page is null\n");
-        return NULL;
-    }
-
-    /* Assign page to domain */
-    if ( d && !(memflags & MEMF_no_owner) &&
-        assign_pages(d, pg, 0, memflags) )
-    {
-        free_col_heap_page(pg);
-        return NULL;
-    }
-
-    return pg;
-}
-
-void free_col_heap_page(struct page_info *pg)
-{
-    /* This page is not a guest frame any more. */
-    pg->count_info = PGC_state_free;
-
-    page_set_owner(pg, NULL);
-    total_avail_col_pages++;
-    page_list_add_order( pg, page_to_head(pg) );
-}
-
-bool init_col_heap_pages(struct page_info *pg, unsigned long nr_pages)
-{
-    int i;
-
-    if ( color_init_state )
-    {
-        col_num_max = get_max_colors();
-        color_heap = xmalloc_array(color_list, col_num_max);
-        BUG_ON(!color_heap);
-
-        for ( i = 0; i < col_num_max; i++ )
-        {
-            C_DEBUG("Init list for color: %u\n", i);
-            INIT_PAGE_LIST_HEAD(&color_heap[i]);
-        }
-
-        color_init_state = false;
-    }
-
-    C_DEBUG("Init color heap pages with %lu pages for a given size of 0x%lx\n",
-            nr_pages, nr_pages * PAGE_SIZE);
-    C_DEBUG("Paging starting from: 0x%lx\n", page_to_maddr(pg));
-    total_avail_col_pages += nr_pages;
-
-    for ( i = 0; i < nr_pages; i++ )
-    {
-        pg->colored = true;
-        page_list_add_order(pg, page_to_head(pg));
-        pg++;
-    }
-
-    return true;
-}
-
-static void dump_col_heap(unsigned char key)
-{
-    struct page_info *pg;
-    unsigned long size;
-    unsigned int i;
-
-    printk("Colored heap info\n");
-    for ( i = 0; i < col_num_max; i++ )
-    {
-        printk("Heap[%u]: ", i);
-        size = 0;
-        page_list_for_each( pg, color_to_head(i) )
-        {
-            BUG_ON(!(color_from_page(pg) == i));
-            size++;
-        }
-        printk("%lu pages -> %lukB free\n", size, size << (PAGE_SHIFT - 10));
-    }
-
-    printk("Total number of pages: %lu\n", total_avail_col_pages);
-}
-
-static __init int register_heap_trigger(void)
-{
-    register_keyhandler('c', dump_col_heap, "dump coloring heap info", 1);
-    return 0;
-}
-__initcall(register_heap_trigger);
-
-/*
- * Local variables:
- * mode: C
- * c-file-style: "BSD"
- * c-basic-offset: 4
- * tab-width: 4
- * indent-tabs-mode: nil
- * End:
- */
index 35af5b3aa1e9c7ac154c8ee5fa3e5ae0f4466a8f..ec397d2b6780c247d5fa4fd78a7d60fc5b02abba 100644 (file)
@@ -35,9 +35,6 @@
 /* Current maximum useful colors */
 #define MAX_XEN_COLOR   128
 
-/* Minimum size required for buddy allocator to work with colored one */
-unsigned long buddy_required_size __read_mostly = MB(64);
-
 /* Number of color(s) assigned to Xen */
 static uint64_t xen_col_num;
 /* Coloring configuration of Xen as bitmask */
@@ -383,14 +380,6 @@ static int __init parse_way_size(const char *s)
 }
 custom_param("way_size", parse_way_size);
 
-static int __init parse_buddy_required_size(const char *s)
-{
-    buddy_required_size = simple_strtoull(s, &s, 0);
-
-    return *s ? -EINVAL : 0;
-}
-custom_param("buddy_size", parse_buddy_required_size);
-
 static int __init parse_dom0_colors(const char *s)
 {
     return parse_color_config(s, &dom0_colors_mask, &dom0_colors_num);
index f628a12c35d574d11e71203cf95dadafc927db86..528e83aead3230be44c2380620f8a53ba7200230 100644 (file)
 #define p2m_pod_offline_or_broken_hit(pg) 0
 #define p2m_pod_offline_or_broken_replace(pg) BUG_ON(pg != NULL)
 #endif
+#ifdef CONFIG_COLORING
+#include <asm/coloring.h>
+#endif
 
 /*
  * Comma-separated list of hexadecimal page numbers containing bad bytes.
@@ -222,6 +225,13 @@ static bool __read_mostly scrub_debug;
 #define scrub_debug    false
 #endif
 
+#ifdef CONFIG_COLORING
+/* Minimum size required for buddy allocator to work with colored one */
+unsigned long buddy_required_size __read_mostly = MB(64);
+#else
+unsigned long buddy_required_size __read_mostly = 0;
+#endif
+
 /*
  * Bit width of the DMA heap -- used to override NUMA-node-first.
  * allocation strategy, which can otherwise exhaust low memory.
@@ -1846,12 +1856,6 @@ static unsigned long avail_heap_pages(
     return free_pages;
 }
 
-#if CONFIG_COLORING
-extern unsigned long buddy_required_size;
-#else
-static unsigned long buddy_required_size = 0;
-#endif
-
 void __init end_boot_allocator(void)
 {
     unsigned int i;
@@ -1884,23 +1888,23 @@ void __init end_boot_allocator(void)
         {
             unsigned long nr_pages = 0;
 
-            printk(XENLOG_INFO "Allocating 0x%lx for buddy allocator starting from: 0x%lx\n",
-                buddy_required_size, pfn_to_paddr(r->s));
+            //printk(XENLOG_INFO "Allocating 0x%lx for buddy allocator starting from: 0x%lx\n",
+            //    buddy_required_size, pfn_to_paddr(r->s));
             init_heap_pages(mfn_to_page(_mfn(r->s)),
                 (buddy_required_size >> PAGE_SHIFT));
 
             r->s += (buddy_required_size >> PAGE_SHIFT);
             nr_pages = (r->e - r->s);
-            printk(XENLOG_INFO "COLORED: Init heap pages from 0x%lx with size: 0x%lx\n",
-                pfn_to_paddr(r->s), nr_pages*PAGE_SIZE);
+            //printk(XENLOG_INFO "COLORED: Init heap pages from 0x%lx with size: 0x%lx\n",
+            //    pfn_to_paddr(r->s), nr_pages*PAGE_SIZE);
             if( !init_col_heap_pages(mfn_to_page(_mfn(r->s)), nr_pages) )
                 init_heap_pages(mfn_to_page(_mfn(r->s)), nr_pages);
             buddy_required_size = 0;
         }
         else
         {
-            printk(XENLOG_INFO "COLORED: Init heap pages from 0x%lx with size: 0x%lx\n",
-                pfn_to_paddr(r->s),(r->e - r->s)*PAGE_SIZE);
+            //printk(XENLOG_INFO "COLORED: Init heap pages from 0x%lx with size: 0x%lx\n",
+            //    pfn_to_paddr(r->s),(r->e - r->s)*PAGE_SIZE);
             if( !init_col_heap_pages(mfn_to_page(_mfn(r->s)), r->e - r->s) )
                 init_heap_pages(mfn_to_page(_mfn(r->s)), r->e - r->s);
         }
@@ -2267,7 +2271,266 @@ void free_xenheap_pages(void *v, unsigned int order)
 
 #endif  /* CONFIG_SEPARATE_XENHEAP */
 
+/*************************
+ * COLORED SIDE-ALLOCATOR
+ */
+
+#ifdef CONFIG_COLORING
+/*
+ * Pages are stored by their color in separated lists. Each list defines a color
+ * and it is initialized during end_boot_allocator, where each page's color
+ * is calculated and the page itself is put in the correct list.
+ * After initialization we have N list where N is the number of maximum
+ * available colors on the platform.
+ * All the lists' heads are stored as element in an array with size N-1 using
+ * the following schema:
+ * array[X] = head of color X, where X goes from 0 to N-1
+ */
+typedef struct page_list_head color_list;
+static color_list *color_heap;
+static long total_avail_col_pages;
+static u64 col_num_max;
+static bool color_init_state = true;
+
+#define page_to_head(pg) (&color_heap[color_from_page(pg)])
+#define color_to_head(col) (&color_heap[col])
+
+/* Add page in list in order depending on its physical address. */
+static void page_list_add_order(struct page_info *pg, struct list_head *head)
+{
+    struct page_info *pos;
+
+    /* Add first page after head */
+    if ( page_list_empty(head) )
+    {
+        page_list_add(pg, head);
+        return;
+    }
+
+    /* Add non-first page in list in ascending order */
+    page_list_for_each_reverse(pos, head)
+    {
+        /* Get pg position */
+        if ( page_to_maddr(pos) <= page_to_maddr(pg) )
+        {
+            /* Insert pg between pos and pos->list.next */
+            page_list_add(pg, &pos->list);
+            break;
+        }
+
+        /*
+         * If pos is the first element it means that pg <= pos so we have
+         * to insert pg after head.
+         */
+        if ( page_list_first(head) == pos )
+        {
+            page_list_add(pg, head);
+            break;
+        }
+    }
+}
+
+/* Alloc one page based on domain color configuration */
+static struct page_info *alloc_col_heap_page(
+    unsigned int memflags, struct domain *d)
+{
+    struct page_info *pg, *tmp;
+    bool need_tlbflush = false;
+    uint32_t cur_color;
+    uint32_t tlbflush_timestamp = 0;
+    uint32_t *colors = 0;
+    int max_colors;
+    int i;
+
+    colors = d->colors;
+    max_colors = d->max_colors;
+
+    spin_lock(&heap_lock);
+
+    tmp = pg = NULL;
+
+    /* Check for the first pg on non-empty list */
+    for ( i = 0; i < max_colors; i++ )
+    {
+        if ( !page_list_empty(color_to_head(colors[i])) )
+        {
+            tmp = pg = page_list_last(color_to_head(colors[i]));
+            cur_color = d->colors[i];
+            break;
+        }
+    }
+
+    /* If all lists are empty, no requests can be satisfied */
+    if ( !pg )
+    {
+        spin_unlock(&heap_lock);
+        return NULL;
+    }
+
+    /* Get the highest page from the lists compliant to the domain color(s) */
+    for ( i += 1; i < max_colors; i++ )
+    {
+        if ( page_list_empty(color_to_head(colors[i])) )
+        {
+            printk(XENLOG_INFO "List empty\n");
+            continue;
+        }
+        tmp = page_list_last(color_to_head(colors[i]));
+        if ( page_to_maddr(tmp) > page_to_maddr(pg) )
+        {
+            pg = tmp;
+            cur_color = colors[i];
+        }
+    }
+
+    if ( !pg )
+    {
+        spin_unlock(&heap_lock);
+        return NULL;
+    }
+
+    pg->count_info = PGC_state_inuse;
+
+    if ( !(memflags & MEMF_no_tlbflush) )
+        accumulate_tlbflush(&need_tlbflush, pg,
+                            &tlbflush_timestamp);
 
+    /* Initialise fields which have other uses for free pages. */
+    pg->u.inuse.type_info = 0;
+    page_set_owner(pg, NULL);
+
+    flush_page_to_ram(mfn_x(page_to_mfn(pg)),
+                      !(memflags & MEMF_no_icache_flush));
+
+    page_list_del(pg, page_to_head(pg));
+    total_avail_col_pages--;
+
+    spin_unlock(&heap_lock);
+
+    if ( need_tlbflush )
+        filtered_flush_tlb_mask(tlbflush_timestamp);
+
+    return pg;
+}
+
+struct page_info *alloc_col_domheap_page(
+    struct domain *d, unsigned int memflags)
+{
+    struct page_info *pg;
+
+    ASSERT(!in_irq());
+
+    /* Get page based on color selection */
+    pg = alloc_col_heap_page(memflags, d);
+
+    if ( !pg )
+    {
+        printk(XENLOG_INFO "ERROR: Colored Page is null\n");
+        return NULL;
+    }
+
+    /* Assign page to domain */
+    if ( d && !(memflags & MEMF_no_owner) &&
+        assign_pages(d, pg, 0, memflags) )
+    {
+        free_col_heap_page(pg);
+        return NULL;
+    }
+
+    return pg;
+}
+
+void free_col_heap_page(struct page_info *pg)
+{
+    /* This page is not a guest frame any more. */
+    pg->count_info = PGC_state_free;
+
+    page_set_owner(pg, NULL);
+    total_avail_col_pages++;
+    page_list_add_order( pg, page_to_head(pg) );
+}
+
+bool init_col_heap_pages(struct page_info *pg, unsigned long nr_pages)
+{
+    int i;
+
+    if ( color_init_state )
+    {
+        col_num_max = get_max_colors();
+        color_heap = xmalloc_array(color_list, col_num_max);
+        BUG_ON(!color_heap);
+
+        for ( i = 0; i < col_num_max; i++ )
+        {
+            printk(XENLOG_INFO "Init list for color: %u\n", i);
+            INIT_PAGE_LIST_HEAD(&color_heap[i]);
+        }
+
+        color_init_state = false;
+    }
+
+    printk(XENLOG_INFO "Init color heap pages with %lu pages for a given size of 0x%lx\n",
+            nr_pages, nr_pages * PAGE_SIZE);
+    printk(XENLOG_INFO "Paging starting from: 0x%lx\n", page_to_maddr(pg));
+    total_avail_col_pages += nr_pages;
+
+    for ( i = 0; i < nr_pages; i++ )
+    {
+        pg->colored = true;
+        page_list_add_order(pg, page_to_head(pg));
+        pg++;
+    }
+
+    return true;
+}
+
+static void dump_col_heap(unsigned char key)
+{
+    struct page_info *pg;
+    unsigned long size;
+    unsigned int i;
+
+    printk("Colored heap info\n");
+    for ( i = 0; i < col_num_max; i++ )
+    {
+        printk("Heap[%u]: ", i);
+        size = 0;
+        page_list_for_each( pg, color_to_head(i) )
+        {
+            BUG_ON(!(color_from_page(pg) == i));
+            size++;
+        }
+        printk("%lu pages -> %lukB free\n", size, size << (PAGE_SHIFT - 10));
+    }
+
+    printk("Total number of pages: %lu\n", total_avail_col_pages);
+}
+
+static int __init parse_buddy_required_size(const char *s)
+{
+    buddy_required_size = simple_strtoull(s, &s, 0);
+
+    return *s ? -EINVAL : 0;
+}
+custom_param("buddy_size", parse_buddy_required_size);
+#else /* !CONFIG_COLORING */
+inline bool init_col_heap_pages(
+       struct page_info *pg, unsigned long nr_pages)
+{
+       return false;
+}
+
+inline struct page_info *alloc_col_domheap_page(
+       struct domain *d, unsigned int memflags)
+{
+       return NULL;
+}
+
+inline void free_col_heap_page(struct page_info *pg)
+{
+       return;
+}
+#endif /* CONFIG_COLORING */
 
 /*************************
  * DOMAIN-HEAP SUB-ALLOCATOR
@@ -2288,7 +2551,6 @@ void init_domheap_pages(paddr_t ps, paddr_t pe)
     init_heap_pages(mfn_to_page(smfn), mfn_x(emfn) - mfn_x(smfn));
 }
 
-
 int assign_pages(
     struct domain *d,
     struct page_info *pg,
@@ -2580,6 +2842,9 @@ static void dump_heap(unsigned char key)
 static __init int register_heap_trigger(void)
 {
     register_keyhandler('H', dump_heap, "dump heap info", 1);
+#ifdef CONFIG_COLORING
+    register_keyhandler('c', dump_col_heap, "dump coloring heap info", 1);
+#endif
     return 0;
 }
 __initcall(register_heap_trigger);
index ebe0d356beebcb98db2c3bfea38fc01448727af8..2d8c45ee9a16f84b6798d64a084369d875b1fd7d 100644 (file)
@@ -211,29 +211,10 @@ int offline_page(mfn_t mfn, int broken, uint32_t *status);
 int query_page_offline(mfn_t mfn, uint32_t *status);
 
 /* Colored suballocator. */
-#ifdef CONFIG_COLORING
 bool init_col_heap_pages(struct page_info *pg, unsigned long nr_pages);
 struct page_info *alloc_col_domheap_page(
-       struct domain *d, unsigned int memflags);
+    struct domain *d, unsigned int memflags);
 void free_col_heap_page(struct page_info *pg);
-#else
-static inline bool init_col_heap_pages(
-       struct page_info *pg, unsigned long nr_pages)
-{
-       return false;
-}
-
-static inline struct page_info *alloc_col_domheap_page(
-       struct domain *d, unsigned int memflags)
-{
-       return NULL;
-}
-
-static inline void free_col_heap_page(struct page_info *pg)
-{
-       return;
-}
-#endif
 
 void heap_init_late(void);