diff --git a/arch/x86/kernel/include/arch-memory.h b/arch/x86/kernel/include/arch-memory.h index a1c9196c..65ca4710 100644 --- a/arch/x86/kernel/include/arch-memory.h +++ b/arch/x86/kernel/include/arch-memory.h @@ -16,10 +16,12 @@ #define PAGE_SHIFT 12 #define PAGE_SIZE (1UL << PAGE_SHIFT) #define PAGE_MASK (~((unsigned long)PAGE_SIZE - 1)) +#define PAGE_P2ALIGN 0 #define LARGE_PAGE_SHIFT 21 #define LARGE_PAGE_SIZE (1UL << LARGE_PAGE_SHIFT) #define LARGE_PAGE_MASK (~((unsigned long)LARGE_PAGE_SIZE - 1)) +#define LARGE_PAGE_P2ALIGN (LARGE_PAGE_SHIFT - PAGE_SHIFT) #define USER_END 0x0000800000000000UL #define MAP_ST_START 0xffff800000000000UL diff --git a/arch/x86/kernel/memory.c b/arch/x86/kernel/memory.c index 50419478..6c71effd 100644 --- a/arch/x86/kernel/memory.c +++ b/arch/x86/kernel/memory.c @@ -35,7 +35,7 @@ void *early_alloc_page(void) void *arch_alloc_page(enum ihk_mc_ap_flag flag) { if (pa_ops) - return pa_ops->alloc_page(1, flag); + return pa_ops->alloc_page(1, PAGE_P2ALIGN, flag); else return early_alloc_page(); } @@ -45,14 +45,19 @@ void arch_free_page(void *ptr) pa_ops->free_page(ptr, 1); } -void *ihk_mc_alloc_pages(int npages, enum ihk_mc_ap_flag flag) +void *ihk_mc_alloc_aligned_pages(int npages, int p2align, enum ihk_mc_ap_flag flag) { if (pa_ops) - return pa_ops->alloc_page(npages, flag); + return pa_ops->alloc_page(npages, p2align, flag); else return NULL; } +void *ihk_mc_alloc_pages(int npages, enum ihk_mc_ap_flag flag) +{ + return ihk_mc_alloc_aligned_pages(npages, PAGE_P2ALIGN, flag); +} + void ihk_mc_free_pages(void *p, int npages) { if (pa_ops) diff --git a/kernel/mem.c b/kernel/mem.c index 5dc7bf06..8a7949ff 100644 --- a/kernel/mem.c +++ b/kernel/mem.c @@ -42,9 +42,9 @@ static void reserve_pages(unsigned long start, unsigned long end, int type) ihk_pagealloc_reserve(pa_allocator, start, end); } -void *allocate_pages(int npages, enum ihk_mc_ap_flag flag) +void *allocate_aligned_pages(int npages, int p2align, enum ihk_mc_ap_flag flag) { - unsigned long pa = ihk_pagealloc_alloc(pa_allocator, npages); + unsigned long pa = ihk_pagealloc_alloc(pa_allocator, npages, p2align); /* all_pagealloc_alloc returns zero when error occured, and callee (in mcos/kernel/process.c) so propagate it */ if(pa) @@ -54,13 +54,18 @@ void *allocate_pages(int npages, enum ihk_mc_ap_flag flag) return NULL; } +void *allocate_pages(int npages, enum ihk_mc_ap_flag flag) +{ + return allocate_aligned_pages(npages, PAGE_P2ALIGN, flag); +} + void free_pages(void *va, int npages) { ihk_pagealloc_free(pa_allocator, virt_to_phys(va), npages); } static struct ihk_mc_pa_ops allocator = { - .alloc_page = allocate_pages, + .alloc_page = allocate_aligned_pages, .free_page = free_pages, }; @@ -176,12 +181,15 @@ static void page_allocator_init(void) unsigned long page_map_pa, pages; void *page_map; unsigned int i; + uint64_t start; + uint64_t end; - pa_start = ihk_mc_get_memory_address(IHK_MC_GMA_AVAIL_START, 0); - pa_end = ihk_mc_get_memory_address(IHK_MC_GMA_AVAIL_END, 0); + start = ihk_mc_get_memory_address(IHK_MC_GMA_AVAIL_START, 0); + end = ihk_mc_get_memory_address(IHK_MC_GMA_AVAIL_END, 0); - pa_start &= PAGE_MASK; - pa_end = (pa_end + PAGE_SIZE - 1) & PAGE_MASK; + start &= PAGE_MASK; + pa_start = start & LARGE_PAGE_MASK; + pa_end = (end + PAGE_SIZE - 1) & PAGE_MASK; #ifndef ATTACHED_MIC page_map_pa = ihk_mc_get_memory_address(IHK_MC_GMA_HEAP_START, 0); @@ -198,6 +206,9 @@ static void page_allocator_init(void) PAGE_SIZE, page_map, &pages); reserve_pages(page_map_pa, page_map_pa + pages * PAGE_SIZE, 0); + if (pa_start < start) { + reserve_pages(pa_start, start, 0); + } /* BIOS reserved ranges */ for (i = 1; i <= ihk_mc_get_memory_address(IHK_MC_NR_RESERVED_AREAS, 0); @@ -249,7 +260,7 @@ void *ihk_mc_map_virtual(unsigned long phys, int npages, offset = (phys & (PAGE_SIZE - 1)); phys = phys & PAGE_MASK; - p = (void *)ihk_pagealloc_alloc(vmap_allocator, npages); + p = (void *)ihk_pagealloc_alloc(vmap_allocator, npages, PAGE_P2ALIGN); if (!p) { return NULL; } diff --git a/lib/include/ihk/mm.h b/lib/include/ihk/mm.h index 76de6e68..14e547d6 100644 --- a/lib/include/ihk/mm.h +++ b/lib/include/ihk/mm.h @@ -50,7 +50,7 @@ void ihk_mc_reserve_arch_pages(unsigned long start, unsigned long end, void (*cb)(unsigned long, unsigned long, int)); struct ihk_mc_pa_ops { - void *(*alloc_page)(int, enum ihk_mc_ap_flag); + void *(*alloc_page)(int, int, enum ihk_mc_ap_flag); void (*free_page)(void *, int); void *(*alloc)(int, enum ihk_mc_ap_flag); @@ -74,6 +74,7 @@ void ihk_mc_map_micpa(unsigned long host_pa, unsigned long* mic_pa); int ihk_mc_free_micpa(unsigned long mic_pa); void ihk_mc_clean_micpa(void); +void *ihk_mc_alloc_aligned_pages(int npages, int p2align, enum ihk_mc_ap_flag flag); void *ihk_mc_alloc_pages(int npages, enum ihk_mc_ap_flag flag); void ihk_mc_free_pages(void *p, int npages); void *ihk_mc_allocate(int size, enum ihk_mc_ap_flag flag); diff --git a/lib/include/ihk/page_alloc.h b/lib/include/ihk/page_alloc.h index 0f17aa8a..4cc2d67c 100644 --- a/lib/include/ihk/page_alloc.h +++ b/lib/include/ihk/page_alloc.h @@ -20,7 +20,7 @@ void *__ihk_pagealloc_init(unsigned long start, unsigned long size, void *ihk_pagealloc_init(unsigned long start, unsigned long size, unsigned long unit); void ihk_pagealloc_destroy(void *__desc); -unsigned long ihk_pagealloc_alloc(void *__desc, int npages); +unsigned long ihk_pagealloc_alloc(void *__desc, int npages, int p2align); void ihk_pagealloc_reserve(void *desc, unsigned long start, unsigned long end); void ihk_pagealloc_free(void *__desc, unsigned long address, int npages); unsigned long ihk_pagealloc_count(void *__desc); diff --git a/lib/page_alloc.c b/lib/page_alloc.c index 9c2c2109..e1fdffd0 100644 --- a/lib/page_alloc.c +++ b/lib/page_alloc.c @@ -88,13 +88,14 @@ void ihk_pagealloc_destroy(void *__desc) } static unsigned long __ihk_pagealloc_large(struct ihk_page_allocator_desc *desc, - int npages) + int npages, int p2align) { unsigned long flags; unsigned int i, j, mi; int nblocks; int nfrags; unsigned long mask; + int mialign; nblocks = (npages / 64); mask = -1; @@ -103,13 +104,14 @@ static unsigned long __ihk_pagealloc_large(struct ihk_page_allocator_desc *desc, ++nblocks; mask = (1UL << nfrags) - 1; } + mialign = (p2align <= 6)? 1: (1 << (p2align - 6)); flags = ihk_mc_spinlock_lock(&desc->lock); for (i = 0, mi = desc->last; i < desc->count; i++, mi++) { if (mi >= desc->count) { mi = 0; } - if (mi + nblocks >= desc->count) { + if ((mi + nblocks >= desc->count) || (mi % mialign)) { continue; } for (j = mi; j < mi + nblocks - 1; j++) { @@ -131,18 +133,20 @@ static unsigned long __ihk_pagealloc_large(struct ihk_page_allocator_desc *desc, return 0; } -unsigned long ihk_pagealloc_alloc(void *__desc, int npages) +unsigned long ihk_pagealloc_alloc(void *__desc, int npages, int p2align) { struct ihk_page_allocator_desc *desc = __desc; unsigned int i, mi; int j; unsigned long v, mask, flags; + int jalign; - if (npages >= 32) { - return __ihk_pagealloc_large(desc, npages); + if ((npages >= 32) || (p2align >= 5)) { + return __ihk_pagealloc_large(desc, npages, p2align); } mask = (1UL << npages) - 1; + jalign = (p2align <= 0)? 1: (1 << p2align); flags = ihk_mc_spinlock_lock(&desc->lock); for (i = 0, mi = desc->last; i < desc->count; i++, mi++) { @@ -155,6 +159,9 @@ unsigned long ihk_pagealloc_alloc(void *__desc, int npages) continue; for (j = 0; j <= 64 - npages; j++) { + if (j % jalign) { + continue; + } if (!(v & (mask << j))) { /* free */ desc->map[mi] |= (mask << j);