# Copyright (c) 2021 Intel Corporation
#
# SPDX-License-Identifier: Apache-2.0

menu "Heap and Memory Allocation"

config SYS_HEAP_VALIDATE
	bool "Internal heap validity checking"
	help
	  The sys_heap implementation is instrumented for extensive
	  internal validation.  Leave this off by default, unless
	  modifying the heap code or (maybe) when running in
	  environments that require sensitive detection of memory
	  corruption.

	  Use for testing and validation only.

config SYS_HEAP_STRESS
	bool "General purpose heap stress test"
	help
	  Stresses the heap.

	  Use for testing and validation only.

config SYS_HEAP_INFO
	bool "Heap internal structure information"
	help
	  Enables support for printing heap internal structure
	  information to the console.

	  Use for debugging only.

config SYS_HEAP_ALLOC_LOOPS
	int "Number of tries in the inner heap allocation loop"
	default 3
	help
	  The sys_heap allocator bounds the number of tries from the
	  smallest chunk level (the one that might not fit the
	  requested allocation) to maintain constant time performance.
	  Setting this to a high level will cause the heap to return
	  more successful allocations in situations of high
	  fragmentation, at the cost of potentially significant
	  (linear time) searching of the free list.  The default is
	  three, which results in an allocator with good statistical
	  properties ("most" allocations that fit will succeed) but
	  keeps the maximum runtime at a tight bound so that the heap
	  is useful in locked or ISR contexts.

config SYS_HEAP_RUNTIME_STATS
	bool "System heap runtime statistics"
	help
	  Gather system heap runtime statistics.

config SYS_HEAP_ARRAY_SIZE
	int "Size of array to store heap pointers"
	default 0
	help
	  The size of the internal array to store heap pointers. The array
	  is filled with a heap pointer on every sys_heap_init() call.
	  One can then iterate through the array to get all heaps statistics
	  and to sum up the total memory allocated for all heaps.

	  The default array size is zero, which disables the feature.
	  To enable the feature, assign a value greater than zero.

config SYS_HEAP_LISTENER
	bool "sys_heap event notifications"
	select HEAP_LISTENER
	help
	  This allows application to listen for sys_heap events,
	  such as memory allocation and de-allocation.

config HEAP_LISTENER
	bool
	help
	  Hidden option to enable API for registering and notifying
	  listeners of certain events related to a heap usage,
	  such as the heap resize.

choice SYS_HEAP_HARDENING
	prompt "Heap hardening level"
	default SYS_HEAP_HARDENING_MODERATE if ASSERT
	default SYS_HEAP_HARDENING_BASIC
	help
	  Controls the level of runtime validation performed by the
	  sys_heap allocator. Higher levels detect more classes of
	  heap corruption but add increasing overhead. Each level
	  includes all checks from lower levels.

config SYS_HEAP_HARDENING_NONE
	bool "None"
	help
	  Disable all heap validation checks for maximum performance.
	  Use this for production builds where heap usage is well
	  tested and every cycle counts.

config SYS_HEAP_HARDENING_BASIC
	bool "Basic"
	help
	  Cheap double-free and buffer overflow detection in
	  sys_heap_free(). This adds a few field reads on the free
	  path with negligible runtime cost. Suitable for production
	  builds that want a safety net.

config SYS_HEAP_HARDENING_MODERATE
	bool "Moderate"
	help
	  In addition to basic checks, validate free list pointer
	  consistency in free list operations and bidirectional
	  neighbor size consistency in sys_heap_free(). This adds
	  a few more field reads on the alloc and free paths. This
	  is quite effective at detecting most accidental corruptions
	  and is a good default for development and production
	  systems that need extra robustness.

config SYS_HEAP_HARDENING_FULL
	bool "Full"
	select SYS_HEAP_CANARIES
	help
	  In addition to moderate checks, enable per-chunk trailer
	  canaries. The canary is validated on free, realloc, and
	  size queries. This adds 8 bytes of memory overhead per
	  allocation and a canary computation on alloc and free.
	  Useful for hardening against deliberate memory corruption
	  attacks as well as for chasing bugs during development.

config SYS_HEAP_HARDENING_EXTREME
	bool "Extreme"
	select SYS_HEAP_CANARIES
	select SYS_HEAP_VALIDATE
	help
	  In addition to full checks, run a complete heap structure
	  validation after every allocation and free operation.
	  This walks every chunk on each operation, making it
	  extremely expensive (linear in the number of allocations).
	  Detects external corruption of the heap before the allocator
	  acts on it.

	  The overhead of this level is disproportionate to the
	  protection it provides over "Full". It is unsuitable for
	  production use and intended solely for debugging.

endchoice

config SYS_HEAP_HARDENING_LEVEL
	int
	default 0 if SYS_HEAP_HARDENING_NONE
	default 1 if SYS_HEAP_HARDENING_BASIC
	default 2 if SYS_HEAP_HARDENING_MODERATE
	default 3 if SYS_HEAP_HARDENING_FULL
	default 4 if SYS_HEAP_HARDENING_EXTREME

config SYS_HEAP_CANARIES
	bool

config SYS_HEAP_CANARIES_RANDOM
	bool "Use random base for heap canaries"
	depends on SYS_HEAP_CANARIES
	depends on ENTROPY_GENERATOR || TEST_RANDOM_GENERATOR
	default y
	help
	  Use a random base value for heap canary computation,
	  making canaries unpredictable across power cycles.
	  Without this, canaries are still effective at detecting
	  accidental corruption but are predictable.

config SYS_HEAP_SANITIZER_HOOKS
	bool
	help
	  Hidden symbol selected by any sys_heap sanitizer backend. When set,
	  heap.c emits the generic poison/unpoison hook calls
	  (heap_sanitizer_on_init / _alloc / _free) at the public-API boundary. The
	  active backend implements those three entry points. Keeping the call
	  sites gated on this single symbol means heap.c carries no
	  backend-specific conditionals.

config SYS_HEAP_SANITIZER_ASAN
	bool "Full Address Sanitizer (ASAN) heap poisoning (native_sim)"
	depends on ASAN && ARCH_POSIX
	depends on SYS_HEAP_BIG_ONLY || (64BIT && !SYS_HEAP_SMALL_ONLY)
	select SYS_HEAP_SANITIZER_HOOKS
	help
	  Enables integration with the toolchain's Address Sanitizer (ASAN)
	  runtime to implement memory poisoning for the sys_heap allocator.

	  The whole heap buffer is poisoned at initialization; an allocation
	  unpoisons the user region it returns and a free re-poisons it. This
	  lets ASAN report accesses to freed, never-allocated and out-of-bounds
	  heap memory with a full backtrace and shadow dump.

	  When enabled, the following classes of memory error are detected:
	  - Use-after-free: accessing memory after it has been freed
	  - Unallocated access: accessing memory that was never allocated
	  - Buffer overruns: writing beyond the requested allocation size

	  This feature is only available on native simulator based platforms
	  where ASAN is supported. It works with any toolchain that provides
	  the ASAN runtime and the manual poisoning API, e.g. GCC (libasan) or
	  Clang/LLVM (compiler-rt).

	  The big-heap chunk format is required so the user pointer and the end
	  of the usable region are 8-byte aligned, matching ASAN's shadow
	  granularity. On 64-bit this is implied; on 32-bit SYS_HEAP_BIG_ONLY
	  must be chosen explicitly, which means the small-heap chunk format is
	  not exercised under this configuration.

	  Use for debugging and validation only.

config SYS_HEAP_KASAN
	bool "Lightweight heap write sanitizer"
	depends on !ASAN
	select SYS_HEAP_SANITIZER_HOOKS
	help
	  Lightweight write sanitizer for sys_heap.  Uses
	  -fsanitize=kernel-address compiler instrumentation combined with
	  a per-heap shadow bitarray (one bit per granule) to detect buffer
	  overflows, underflows, and use-after-free on write accesses.

	  Ships its own lightweight sanitizer runtime (__asan_store*
	  callbacks); does not depend on an external ASAN library and
	  supports debugging on real embedded targets.

	  Currently only supported for kernel-mode heaps.
	  Requires GCC or Clang with -fsanitize=kernel-address support.
	  Cannot be combined with CONFIG_ASAN.

	  This option does not enable system-wide instrumentation.  Source
	  files must be explicitly opted in: use
	  zephyr_target_enable_heap_kasan() to instrument all sources of a
	  CMake target, or zephyr_heap_kasan_enable_directory() to instrument
	  sources under a specific directory.
	  Heap tracking is opt-in; each heap must be registered to enable
	  detection.  For the common libc malloc heap and the kernel system
	  heap, enable CONFIG_SYS_HEAP_KASAN_MALLOC and
	  CONFIG_SYS_HEAP_KASAN_SYSTEM respectively.  Custom k_heap or
	  sys_heap instances must be registered explicitly with
	  K_HEAP_KASAN_ENABLE() or SYS_HEAP_KASAN_ENABLE().

config SYS_HEAP_KASAN_MAX_HEAPS
	int "Maximum number of KASAN-tracked heaps"
	depends on SYS_HEAP_KASAN
	default 8
	help
	  Maximum number of heaps on which heap KASAN can be enabled
	  simultaneously.

choice SYS_HEAP_KASAN_GRANULE_CHOICE
	prompt "Shadow granule size"
	depends on SYS_HEAP_KASAN
	default SYS_HEAP_KASAN_GRANULE_4
	help
	  Bytes of heap memory represented by one shadow bit.  Smaller values
	  improve precision at proportionally higher shadow memory cost.

config SYS_HEAP_KASAN_GRANULE_1
	bool "1 byte (1:8 shadow ratio)"
	help
	  Byte-precise detection.  Shadow size = heap_size / 8.

config SYS_HEAP_KASAN_GRANULE_4
	bool "4 bytes (1:32 shadow ratio)"
	help
	  One shadow bit per 4-byte granule.  Sub-granule tail overwrites
	  (e.g., alloc(1) then write p[1]-p[3]) go undetected; they remain
	  within the granule and do not reach sys_heap metadata or adjacent
	  chunks.
	  Shadow size = heap_size / 32.

config SYS_HEAP_KASAN_GRANULE_8
	bool "8 bytes (1:64 shadow ratio)"
	help
	  One shadow bit per 8-byte granule.  Sub-granule tail overwrites
	  are not detected.  Only reliable when all allocations are
	  8-byte aligned.  Shadow size = heap_size / 64.

endchoice

config SYS_HEAP_KASAN_GRANULE
	int
	depends on SYS_HEAP_KASAN
	default 1 if SYS_HEAP_KASAN_GRANULE_1
	default 4 if SYS_HEAP_KASAN_GRANULE_4
	default 8 if SYS_HEAP_KASAN_GRANULE_8

config SYS_HEAP_KASAN_EXTENSIONS
	bool "Interceptors for POSIX/GNU string extensions"
	depends on SYS_HEAP_KASAN
	default y if PICOLIBC || NEWLIB_LIBC || NATIVE_LIBC || POSIX_API
	help
	  Add KASAN write-checking wrappers for POSIX and GNU extension
	  functions. Requires the C library to declare them.

config SYS_HEAP_KASAN_MALLOC
	bool "Track libc malloc heap with KASAN"
	depends on SYS_HEAP_KASAN && COMMON_LIBC_MALLOC && COMMON_LIBC_MALLOC_ARENA_SIZE > 0
	depends on !NATIVE_LIBC
	help
	  Enable heap KASAN on the common libc malloc heap.  The shadow
	  buffer is statically sized from CONFIG_COMMON_LIBC_MALLOC_ARENA_SIZE
	  at build time.

config SYS_HEAP_KASAN_SYSTEM
	bool "Track system heap with KASAN"
	depends on SYS_HEAP_KASAN && KERNEL_MEM_POOL
	help
	  Enable heap KASAN on the kernel system heap (used by
	  k_malloc / k_free).

module = SYS_HEAP
module-str = sys_heap
source "subsys/logging/Kconfig.template.log_config"

DT_CHOSEN_Z_SRAM = zephyr,sram
DT_SRAM_SIZE = $(dt_chosen_reg_size_int,$(DT_CHOSEN_Z_SRAM),0,K)

choice
	prompt "Supported heap sizes"
	depends on !64BIT
	default SYS_HEAP_SMALL_ONLY if ((SRAM_DEPRECATED_KCONFIG_SET && SRAM_SIZE <= 256) || \
		(!SRAM_DEPRECATED_KCONFIG_SET && $(DT_SRAM_SIZE) <= 256))
	default SYS_HEAP_AUTO
	help
	  Heaps using reduced-size chunk headers can accommodate so called
	  "small" heaps with a total size of 262136 bytes or less.

	  Heaps using full-size chunk headers can have a total size up to
	  16383 megabytes. The overhead is of course bigger.

	  On 32-bit system the tradeoff is selectable between:

	  - "small" heaps with low memory and runtime overhead;

	  - "big" heaps with bigger memory overhead even for small heaps;

	  - "auto" providing optimal memory overhead in all cases but with
	    a higher runtime overhead and somewhat bigger code footprint.

	  On 64-bit systems the "big" chunk header size conveniently provides
	  the needed alignment on returned memory allocations. Small chunk
	  headers would require alignment padding up to the big header size
	  anyway so "big" heap is the only option in that case.

config SYS_HEAP_SMALL_ONLY
	bool "Support for small heaps only"
	help
	  Select this to optimize the code and memory usage if all your
	  heaps are 262136 bytes or less.

config SYS_HEAP_BIG_ONLY
	bool "Support for big heaps only"
	help
	  Select this to optimize the code for big heaps only. This can
	  accommodate any heap size but memory usage won't be as
	  efficient with small sized heaps.

config SYS_HEAP_AUTO
	bool "Support for both small and big heaps at run time"
	help
	  This option optimizes memory usage for each heap according to
	  their size albeit with some overhead in code size and execution.

endchoice

config MULTI_HEAP
	bool "Multi-heap manager"
	help
	  Allows multiple sys_heap regions to be unified under a single
	  allocation API.  Sometimes apps need the ability to share multiple
	  discontiguous regions in a single "heap", or
	  to have memory of different "types" be allocated heuristically based
	  on usage (e.g. cacheability, latency, power...).  This allows a
	  user-specified function to select the underlying memory to use for
	  each application.

config SHARED_MULTI_HEAP
	bool "Shared multi-heap manager"
	select MULTI_HEAP
	help
	  Enable support for a shared multi-heap manager that uses the
	  multi-heap allocator to manage a set of reserved memory regions with
	  different capabilities / attributes (cacheable, non-cacheable,
	  etc...) defined in the DT.

endmenu
