Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

memory management: Add virtual heap memory allocators #7276

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
133 changes: 113 additions & 20 deletions zephyr/include/sof/lib/regions_mm.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: BSD-3-Clause */
/*
* Copyright(c) 2022 Intel Corporation. All rights reserved.
* Copyright(c) 2022 - 2023 Intel Corporation. All rights reserved.
*
* Author: Jakub Dabek <jakub.dabek@intel.com>
*/
Expand All @@ -10,31 +10,124 @@

#include <adsp_memory.h>
#include <adsp_memory_regions.h>
#include <ipc/topology.h>
#include <rtos/alloc.h>
#include <sof/list.h>
#include <zephyr/drivers/mm/system_mm.h>
#include <zephyr/sys/mem_blocks.h>
#include <zephyr/init.h>
#include <ipc/topology.h>
#include <zephyr/sys/mem_blocks.h>

/* Dependency on ipc/topology.h created due to memory capability definitions
* that are defined there
*/

/* API is NOT re-entry safe.
* This is due to our assumption that only management code will ever handle
* memory operations on heaps themselves.
*/

/* Defines maximum amount of memory block allocators in one heap
* since minimum realistic block should be cache line size
* and block sizes in allocator must be powers of 2
* so logically it gives limited block sizes
* eg allocator of block size 64 128 256 512 2048 4096 1024 8192
* would end up in 8 allocators.
* It is expected that allocations bigger than that would
* either be spanned on specifically configured heap or have
* individual configs with bigger block sizes.
*/
#define MAX_MEMORY_ALLOCATORS_COUNT 8

/* vmh_get_default_heap_config() function will try to split the region
* down the given count. Only applicable when API client did not
* use its config.
*/
#define DEFAULT_CONFIG_ALOCATORS_COUNT 5

/** @struct vmh_heap
*
* @brief This structure holds all information about virtual memory heap
* it aggregates information about its allocations and
* physical mappings.
*
* @var node generic list member used for list operations
* @var virtual_region pointer to virtual region information, it holds its
* attributes size and beginning ptr provided by zephyr.
* @var physical_blocks_allocators[] a table of block allocators
* each representing a virtual regions part in blocks of a given size
* governed by sys_mem_blocks API.
* @var allocation_sizes[] a table of bit arrays representing sizes of allocations
* made in physical_blocks_allocators directly related to physical_blocks_allocators
* @var core_id id of the core that heap was created on
* @var allocating_continuously configuration value deciding if heap allocations
* will be contiguous or single block.
*/
struct vmh_heap {
struct list_item node;
const struct sys_mm_drv_region *virtual_region;
struct sys_mem_blocks *physical_blocks_allocators[MAX_MEMORY_ALLOCATORS_COUNT];
struct sys_bitarray *allocation_sizes[MAX_MEMORY_ALLOCATORS_COUNT];
int core_id;
bool allocating_continuously;
};

/** @struct vmh_block_bundle_descriptor
*
* @brief This is a struct describing one bundle of blocks
* used as base for allocators blocks.
*
* @var block_size size of memory block.
* @var number_of_blocks number of memory blocks.
*/
struct vmh_block_bundle_descriptor {
size_t block_size;
size_t number_of_blocks;
};

/*
* Struct containing information on virtual memory heap.
* Information about allocated physical blocks is stored in
* physical_blocks_allocators variable and uses zephyr memblocks api.
*/
struct virtual_memory_heap {
/* zephyr provided virtual region */
struct sys_mm_drv_region *virtual_region;
/* physical pages allocators represented in memblocks */
struct sys_multi_mem_blocks physical_blocks_allocators;
/* SOF memory capability */
uint32_t memory_caps;
* Maybe this heap config should have small bundles first going up to max
* size or there should be a sorting mechanism for those ?
* Should we assume that bundles are given from smallest to biggest ?
*/

/** @struct vmh_heap_config
*
* @brief This is a struct that aggregates vmh_block_bundle_descriptor to
* create one cfg that can be passed to heap initiation.
* Provided config size must be physical page aligned so it
* will not overlap in physical space with other heaps during mapping.
* So every block has to have its overall size aligned to CONFIG_MM_DRV_PAGE_SIZE
*
* @vmh_block_bundle_descriptor[] aggregation of bundle descriptors.
*/
struct vmh_heap_config {
struct vmh_block_bundle_descriptor block_bundles_table[MAX_MEMORY_ALLOCATORS_COUNT];
};

/* Available externaly array containing all information on virtual heaps
* Used to control physical allocations and overall virtual to physicall
* mapping on sof side (zephyr handles the actual assigning physical memory
* sof only requests it).
struct vmh_heap *vmh_init_heap(const struct vmh_heap_config *cfg,
int memory_region_attribute, int core_id, bool allocating_continuously);
void *vmh_alloc(struct vmh_heap *heap, uint32_t alloc_size);
int vmh_free_heap(struct vmh_heap *heap);
int vmh_free(struct vmh_heap *heap, void *ptr);
struct vmh_heap *vmh_reconfigure_heap(struct vmh_heap *heap,
struct vmh_heap_config *cfg, int core_id, bool allocating_continuously);
void vmh_get_default_heap_config(const struct sys_mm_drv_region *region,
struct vmh_heap_config *cfg);
struct vmh_heap *vmh_get_heap_by_attribute(uint32_t attr, uint32_t core_id);
/**
* @brief Checks if ptr is in range of given memory range
*
* @param ptr checked ptr
* @param range_start start of checked memory range
* @param range_size size of checked memory range.
*
* @retval false if no overlap detected.
* @retval true if any overlap detected.
*/
extern struct virtual_memory_heap
vm_heaps[CONFIG_MP_MAX_NUM_CPUS + VIRTUAL_REGION_COUNT];
static inline bool vmh_is_ptr_in_memory_range(uintptr_t ptr, uintptr_t range_start,
size_t range_size)
{
return ptr >= range_start && ptr < range_start + range_size;
}

#endif /* ZEPHYR_LIB_REGIONS_MM_H_ */
Loading