[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [PATCH v3 6/9] xen/common: add cache coloring allocator for domains
On 22.10.2022 17:51, Carlo Nonato wrote: > --- a/xen/arch/arm/p2m.c > +++ b/xen/arch/arm/p2m.c > @@ -661,7 +661,12 @@ static int p2m_create_table(struct p2m_domain *p2m, > lpae_t *entry) > > ASSERT(!p2m_is_valid(*entry)); > > - page = alloc_domheap_page(NULL, 0); > + /* If cache coloring is enabled, p2m tables are allocated using the > domain > + * coloring configuration to prevent cache interference. */ > + if ( IS_ENABLED(CONFIG_CACHE_COLORING) ) > + page = alloc_domheap_page(p2m->domain, MEMF_no_refcount); Are you sure you don't mean MEMF_no_owner (which implies MEMF_no_refcount) here? And then ... > + else > + page = alloc_domheap_page(NULL, 0); ... is it really necessary to keep the two cases separate? Also nit: Comment style. > --- a/xen/common/page_alloc.c > +++ b/xen/common/page_alloc.c > @@ -150,6 +150,9 @@ > #define p2m_pod_offline_or_broken_hit(pg) 0 > #define p2m_pod_offline_or_broken_replace(pg) BUG_ON(pg != NULL) > #endif > +#ifdef CONFIG_HAS_CACHE_COLORING > +#include <asm/coloring.h> > +#endif > > #ifndef PGC_static > #define PGC_static 0 > @@ -231,6 +234,14 @@ static bool __read_mostly scrub_debug; > #define scrub_debug false > #endif > > +/* Memory required for buddy allocator to work with colored one */ > +#ifdef CONFIG_BUDDY_ALLOCATOR_SIZE > +static unsigned long __initdata buddy_alloc_size = > + CONFIG_BUDDY_ALLOCATOR_SIZE << 20; > +#else > + static unsigned long __initdata buddy_alloc_size = 0; Nit: Bogus indentation. I wonder anyway whether if wouldn't better be static unsigned long __initdata buddy_alloc_size = #ifdef CONFIG_BUDDY_ALLOCATOR_SIZE CONFIG_BUDDY_ALLOCATOR_SIZE << 20; #else 0; #endif or static unsigned long __initdata buddy_alloc_size #ifdef CONFIG_BUDDY_ALLOCATOR_SIZE = CONFIG_BUDDY_ALLOCATOR_SIZE << 20 #endif ; > +static void free_color_heap_page(struct page_info *pg) > +{ > + struct page_info *pos; > + unsigned int color = page_to_color(pg); > + colored_pages_t *head = color_heap(color); > + > + spin_lock(&heap_lock); > + > + pg->count_info = PGC_state_free | PGC_colored; > + page_set_owner(pg, NULL); > + free_colored_pages[color]++; > + > + page_list_for_each( pos, head ) > + { > + if ( page_to_maddr(pos) < page_to_maddr(pg) ) > + break; > + } I continue to view such loops as problematic. With them in place I don't think this feature can move to being (security) supported, so I think this and similar places want annotating with a FIXME or alike comment. > + page_list_add_next(pg, pos, head); > > + spin_unlock(&heap_lock); > +} > + > +static struct page_info *alloc_color_heap_page(unsigned int memflags, > + const unsigned int *colors, > + unsigned int num_colors) > +{ > + struct page_info *pg = NULL; > + unsigned int i, color; > + bool need_tlbflush = false; > + uint32_t tlbflush_timestamp = 0; > + > + spin_lock(&heap_lock); > + > + for ( i = 0; i < num_colors; i++ ) > + { > + struct page_info *tmp; > + > + if ( page_list_empty(color_heap(colors[i])) ) > + continue; > + > + tmp = page_list_first(color_heap(colors[i])); > + if ( !pg || page_to_maddr(tmp) > page_to_maddr(pg) ) > + pg = tmp; > + } > + > + if ( !pg ) > + { > + spin_unlock(&heap_lock); > + return NULL; > + } > + > + pg->count_info = PGC_state_inuse | PGC_colored; > + > + if ( !(memflags & MEMF_no_tlbflush) ) > + accumulate_tlbflush(&need_tlbflush, pg, &tlbflush_timestamp); > + > + init_free_page_fields(pg); > + flush_page_to_ram(mfn_x(page_to_mfn(pg)), > + !(memflags & MEMF_no_icache_flush)); > + > + color = page_to_color(pg); You don't really need to retrieve the color here, do you? You could as well latch it in the loop above. > +static void dump_color_heap(void) > +{ > + unsigned int color; > + > + printk("Dumping coloring heap info\n"); > + for ( color = 0; color < get_max_colors(); color++ ) > + printk("Color heap[%u]: %lu pages\n", color, > free_colored_pages[color]); > +} > + > +integer_param("buddy-alloc-size", buddy_alloc_size); This would preferably live next to the variable it controls, e.g. (taking the earlier comment into account) static unsigned long __initdata buddy_alloc_size = #ifdef CONFIG_CACHE_COLORING CONFIG_BUDDY_ALLOCATOR_SIZE << 20; integer_param("buddy-alloc-size", buddy_alloc_size); #else 0; #endif (Assuming buddy_alloc_size is indeed used anywhere outside any #ifdef CONFIG_CACHE_COLORING in the first place.) > @@ -1926,24 +2106,49 @@ static unsigned long avail_heap_pages( > void __init end_boot_allocator(void) > { > unsigned int i; > + unsigned long buddy_pages; > > - /* Pages that are free now go to the domain sub-allocator. */ > - for ( i = 0; i < nr_bootmem_regions; i++ ) > + buddy_pages = PFN_DOWN(buddy_alloc_size); Any reason this can't be the initializer of the variable? > + if ( !IS_ENABLED(CONFIG_CACHE_COLORING) ) > { > - struct bootmem_region *r = &bootmem_region_list[i]; > - if ( (r->s < r->e) && > - (phys_to_nid(pfn_to_paddr(r->s)) == cpu_to_node(0)) ) > + /* Pages that are free now go to the domain sub-allocator. */ > + for ( i = 0; i < nr_bootmem_regions; i++ ) > { > - init_heap_pages(mfn_to_page(_mfn(r->s)), r->e - r->s); > - r->e = r->s; > - break; > + struct bootmem_region *r = &bootmem_region_list[i]; > + if ( (r->s < r->e) && Even if you're only re-indenting the original code (which personally I'd prefer if it was avoided), please add the missing blank line between declaration and statement here. > + (phys_to_nid(pfn_to_paddr(r->s)) == cpu_to_node(0)) ) > + { > + init_heap_pages(mfn_to_page(_mfn(r->s)), r->e - r->s); > + r->e = r->s; > + break; > + } > } > } > + > for ( i = nr_bootmem_regions; i-- > 0; ) > { > - struct bootmem_region *r = &bootmem_region_list[i]; > + struct bootmem_region *r; > + > + if ( IS_ENABLED(CONFIG_CACHE_COLORING) ) > + r = &bootmem_region_list[nr_bootmem_regions - i - 1]; If you want to handle things low-to-high, why don't you alter the earlier loop rather than skipping (and re-indenting) it? However, considering that in alloc_color_heap_page() you prefer pages at higher addresses, I continue to find it odd that here you want to process low address pages first. > + else > + r = &bootmem_region_list[i]; > + > + if ( buddy_pages && (r->s < r->e) ) > + { > + unsigned long pages = MIN(r->e - r->s, buddy_pages); > + init_heap_pages(mfn_to_page(_mfn(r->s)), pages); Nit: Blank line between declaration(s) and statement(s) please. Also: Any reason the type-safe min() cannot be used here? > --- a/xen/include/xen/mm.h > +++ b/xen/include/xen/mm.h > @@ -297,6 +297,37 @@ page_list_add_tail(struct page_info *page, struct > page_list_head *head) > } > head->tail = page; > } > +static inline void > +_page_list_add(struct page_info *new, struct page_info *prev, > + struct page_info *next) > +{ > + new->list.prev = page_to_pdx(prev); > + new->list.next = page_to_pdx(next); > + prev->list.next = page_to_pdx(new); > + next->list.prev = page_to_pdx(new); Nit: Several hard tabs here, and ... > +} > +static inline void > +page_list_add_next(struct page_info *new, struct page_info *prev, > + struct page_list_head *head) > +{ > + struct page_info *next = page_list_next(prev, head); ... one more here (and at least one more further down). Afaict you're passing a NULL "pos" in here from free_color_heap_page() if the list was previously empty and page lists aren't simply "normal" (xen/list.h) lists. I don't consider it valid to call page_list_next() with a NULL first argument, even if it looks as if this would work right now as long as the list is empty (but I think we'd see a NULL prev here also if all other pages looked at by free_color_heap_page() are at lower addresses). So perhaps ... > + if ( !next ) > + page_list_add_tail(new, head); > + else > + _page_list_add(new, prev, next); if ( !prev ) page_list_add_tail(new, head); else _page_list_add(new, prev, page_list_next(prev, head)); ? > +} > +static inline void > +page_list_add_prev(struct page_info *new, struct page_info *next, > + struct page_list_head *head) > +{ > + struct page_info *prev = page_list_prev(next, head); > + > + if ( !prev ) > + page_list_add(new, head); > + else > + _page_list_add(new, prev, next); > +} This function looks to not be used anywhere. Jan
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |