From 1de87953e6a297bca44a59e03b4d6ca2bb41370b Mon Sep 17 00:00:00 2001 From: buxiasen Date: Fri, 9 May 2025 19:21:31 +0800 Subject: [PATCH] mm/gran: add gran_alloc_align API for arm-v7a, possible region with 4K and need align with 16K. Signed-off-by: buxiasen --- include/nuttx/mm/gran.h | 23 +++++++++++++++++++ include/nuttx/pgalloc.h | 19 ++++++++++++++++ mm/mm_gran/mm_granalloc.c | 47 +++++++++++++++++++++++++++++++++++++++ mm/mm_gran/mm_pgalloc.c | 24 ++++++++++++++++++++ 4 files changed, 113 insertions(+) diff --git a/include/nuttx/mm/gran.h b/include/nuttx/mm/gran.h index cca0908326..01d8b0141e 100644 --- a/include/nuttx/mm/gran.h +++ b/include/nuttx/mm/gran.h @@ -200,6 +200,29 @@ FAR void *gran_reserve(GRAN_HANDLE handle, uintptr_t start, size_t size); FAR void *gran_alloc(GRAN_HANDLE handle, size_t size); +/**************************************************************************** + * Name: gran_alloc_align + * + * Description: + * Allocate memory from the granule heap. + * + * NOTE: The current implementation also restricts the maximum allocation + * size to 32 granules. That restriction could be eliminated with some + * additional coding effort. + * + * Input Parameters: + * handle - The handle previously returned by gran_initialize + * size - The size of the memory region to allocate. + * align - The size of the memory region to align. + * + * Returned Value: + * On success, a non-NULL pointer to the allocated memory is returned; + * NULL is returned on failure. + * + ****************************************************************************/ + +FAR void *gran_alloc_align(GRAN_HANDLE handle, size_t size, size_t align); + /**************************************************************************** * Name: gran_free * diff --git a/include/nuttx/pgalloc.h b/include/nuttx/pgalloc.h index 02f92601c7..33f6a937b4 100644 --- a/include/nuttx/pgalloc.h +++ b/include/nuttx/pgalloc.h @@ -166,6 +166,25 @@ void mm_pgreserve(uintptr_t start, size_t size); uintptr_t mm_pgalloc(unsigned int npages); +/**************************************************************************** + * Name: mm_pgalloc_align + * + * Description: + * Allocate page memory from the page memory pool. + * + * Input Parameters: + * npages - The number of pages to allocate, each of size CONFIG_MM_PGSIZE. + * align - The number of pages to align, each of size CONFIG_MM_PGSIZE. + * + * Returned Value: + * On success, a non-zero, physical address of the allocated page memory + * is returned. Zero is returned on failure. NOTE: This is an unmapped + * physical address and cannot be used until it is appropriately mapped. + * + ****************************************************************************/ + +uintptr_t mm_pgalloc_align(unsigned int npages, unsigned int align); + /**************************************************************************** * Name: mm_pgfree * diff --git a/mm/mm_gran/mm_granalloc.c b/mm/mm_gran/mm_granalloc.c index e44b92be9b..9e6ce64172 100644 --- a/mm/mm_gran/mm_granalloc.c +++ b/mm/mm_gran/mm_granalloc.c @@ -81,4 +81,51 @@ FAR void *gran_alloc(GRAN_HANDLE handle, size_t size) return (FAR void *)retp; } +FAR void *gran_alloc_align(GRAN_HANDLE handle, size_t size, size_t align) +{ + FAR gran_t *gran = (FAR gran_t *)handle; + uintptr_t retp; + size_t nalign; + size_t ngran; + size_t naligned_up; + int posi; + int ret; + + DEBUGASSERT(gran); + nalign = NGRANULE(gran, align); + ngran = NGRANULE(gran, size); + + naligned_up = ngran + (nalign - 1); + if (!naligned_up || naligned_up > gran->ngranules) + { + return NULL; + } + + ret = gran_enter_critical(gran); + if (ret < 0) + { + return NULL; + } + + posi = gran_search(gran, naligned_up); + if (posi >= 0) + { + posi = (posi + nalign - 1) & ~(nalign - 1); + gran_set(gran, posi, ngran); + } + + gran_leave_critical(gran); + if (posi < 0) + { + return NULL; + } + + retp = gran->heapstart + (posi << gran->log2gran); + graninfo("heap=%"PRIxPTR" posi=%d retp=%"PRIxPTR" size=%zu n=%zu\n", + gran->heapstart, posi, retp, size, ngran); + DEBUGASSERT(retp >= gran->heapstart); + DEBUGASSERT(retp < gran->heapstart + GRANBYTE(gran)); + return (FAR void *)retp; +} + #endif /* CONFIG_GRAN */ diff --git a/mm/mm_gran/mm_pgalloc.c b/mm/mm_gran/mm_pgalloc.c index 46e6c27312..2abc8c06eb 100644 --- a/mm/mm_gran/mm_pgalloc.c +++ b/mm/mm_gran/mm_pgalloc.c @@ -150,6 +150,30 @@ uintptr_t mm_pgalloc(unsigned int npages) return (uintptr_t)gran_alloc(g_pgalloc, (size_t)npages << MM_PGSHIFT); } +/**************************************************************************** + * Name: mm_pgalloc_align + * + * Description: + * Allocate page memory from the page memory pool. + * + * Input Parameters: + * npages - The number of pages to allocate, each of size CONFIG_MM_PGSIZE. + * align - The number of pages to align, each of size CONFIG_MM_PGSIZE. + * + * Returned Value: + * On success, a non-zero, physical address of the allocated page memory + * is returned. Zero is returned on failure. NOTE: This is an unmapped + * physical address and cannot be used until it is appropriately mapped. + * + ****************************************************************************/ + +uintptr_t mm_pgalloc_align(unsigned int npages, unsigned int align) +{ + size_t alloc_size = (size_t)npages << MM_PGSHIFT; + size_t align_size = (size_t)align << MM_PGSHIFT; + return (uintptr_t)gran_alloc_align(g_pgalloc, alloc_size, align_size); +} + /**************************************************************************** * Name: mm_pgfree *