Skip to content
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
8 changes: 8 additions & 0 deletions arch/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ config ARM64
select ARCH_HAS_DIRECTED_IPIS
select ARCH_HAS_DEMAND_PAGING
select ARCH_HAS_DEMAND_MAPPING
select ARCH_SUPPORTS_EVICTION_TRACKING
select EVICTION_TRACKING if DEMAND_PAGING
help
ARM64 (AArch64) architecture

Expand Down Expand Up @@ -694,6 +696,12 @@ config ARCH_SUPPORTS_ROM_START
config ARCH_SUPPORTS_EMPTY_IRQ_SPURIOUS
bool

config ARCH_SUPPORTS_EVICTION_TRACKING
bool
help
Architecture code supports page tracking for eviction algorithms
when demand paging is enabled.

config ARCH_HAS_EXTRA_EXCEPTION_INFO
bool

Expand Down
8 changes: 6 additions & 2 deletions doc/kernel/memory_management/demand_paging.rst
Original file line number Diff line number Diff line change
Expand Up @@ -156,8 +156,12 @@ Two eviction algorithms are currently available:
to the NRU code but also considerably more efficient. This is recommended for
production use.

To implement a new eviction algorithm, the five functions mentioned
above must be implemented.
To implement a new eviction algorithm, :c:func:`k_mem_paging_eviction_init()`
and :c:func:`k_mem_paging_eviction_select()` must be implemented.
If :kconfig:option:`CONFIG_EVICTION_TRACKING` is enabled for an algorithm,
these additional functions must also be implemented,
:c:func:`k_mem_paging_eviction_add()`, :c:func:`k_mem_paging_eviction_remove()`,
:c:func:`k_mem_paging_eviction_accessed()`.

Backing Store
*************
Expand Down
21 changes: 21 additions & 0 deletions include/zephyr/kernel/mm/demand_paging.h
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,8 @@ __syscall void k_mem_paging_histogram_backing_store_page_out_get(
* @{
*/

#if defined(CONFIG_EVICTION_TRACKING) || defined(__DOXYGEN__)

/**
* Submit a page frame for eviction candidate tracking
*
Expand Down Expand Up @@ -261,6 +263,25 @@ void k_mem_paging_eviction_remove(struct k_mem_page_frame *pf);
*/
void k_mem_paging_eviction_accessed(uintptr_t phys);

#else /* CONFIG_EVICTION_TRACKING || __DOXYGEN__ */

static inline void k_mem_paging_eviction_add(struct k_mem_page_frame *pf)
{
ARG_UNUSED(pf);
}

static inline void k_mem_paging_eviction_remove(struct k_mem_page_frame *pf)
{
ARG_UNUSED(pf);
}

static inline void k_mem_paging_eviction_accessed(uintptr_t phys)
{
ARG_UNUSED(phys);
}

#endif /* CONFIG_EVICTION_TRACKING || __DOXYGEN__ */

/**
* Select a page frame for eviction
*
Expand Down
35 changes: 24 additions & 11 deletions kernel/mmu.c
Original file line number Diff line number Diff line change
Expand Up @@ -556,7 +556,7 @@
}
frame_mapped_set(pf, addr);
#ifdef CONFIG_DEMAND_PAGING
if (!lock) {
if (IS_ENABLED(CONFIG_EVICTION_TRACKING) && (!lock)) {
k_mem_paging_eviction_add(pf);
}
#endif
Expand Down Expand Up @@ -784,7 +784,8 @@

arch_mem_unmap(pos, CONFIG_MMU_PAGE_SIZE);
#ifdef CONFIG_DEMAND_PAGING
if (!k_mem_page_frame_is_pinned(pf)) {
if (IS_ENABLED(CONFIG_EVICTION_TRACKING) &&
(!k_mem_page_frame_is_pinned(pf))) {
k_mem_paging_eviction_remove(pf);
}
#endif
Expand Down Expand Up @@ -1041,7 +1042,8 @@
} else {
k_mem_page_frame_clear(pf, K_MEM_PAGE_FRAME_PINNED);
#ifdef CONFIG_DEMAND_PAGING
if (k_mem_page_frame_is_evictable(pf)) {
if (IS_ENABLED(CONFIG_EVICTION_TRACKING) &&
k_mem_page_frame_is_evictable(pf)) {
k_mem_paging_eviction_add(pf);
}
#endif
Expand Down Expand Up @@ -1147,10 +1149,13 @@
#endif /* CONFIG_DEMAND_PAGING_TIMING_HISTOGRAM */
k_mem_paging_backing_store_init();
k_mem_paging_eviction_init();
/* start tracking evictable page installed above if any */
K_MEM_PAGE_FRAME_FOREACH(phys, pf) {
if (k_mem_page_frame_is_evictable(pf)) {
k_mem_paging_eviction_add(pf);

if (IS_ENABLED(CONFIG_EVICTION_TRACKING)) {
/* start tracking evictable page installed above if any */
K_MEM_PAGE_FRAME_FOREACH(phys, pf) {
if (k_mem_page_frame_is_evictable(pf)) {

Check notice on line 1156 in kernel/mmu.c

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

You may want to run clang-format on this change

kernel/mmu.c:1156 - K_MEM_PAGE_FRAME_FOREACH(phys, pf) { + K_MEM_PAGE_FRAME_FOREACH(phys, pf) + {
k_mem_paging_eviction_add(pf);
}
}
}
#endif /* CONFIG_DEMAND_PAGING */
Expand Down Expand Up @@ -1347,7 +1352,10 @@
return -ENOMEM;
}
arch_mem_page_out(k_mem_page_frame_to_virt(pf), *location_ptr);
k_mem_paging_eviction_remove(pf);

if (IS_ENABLED(CONFIG_EVICTION_TRACKING)) {
k_mem_paging_eviction_remove(pf);
}
} else {
/* Shouldn't happen unless this function is mis-used */
__ASSERT(!dirty, "un-mapped page determined to be dirty");
Expand Down Expand Up @@ -1683,7 +1691,9 @@

pf = k_mem_phys_to_page_frame(phys);
if (!k_mem_page_frame_is_pinned(pf)) {
k_mem_paging_eviction_remove(pf);
if (IS_ENABLED(CONFIG_EVICTION_TRACKING)) {
k_mem_paging_eviction_remove(pf);
}
k_mem_page_frame_set(pf, K_MEM_PAGE_FRAME_PINNED);
}
}
Expand Down Expand Up @@ -1738,7 +1748,7 @@

arch_mem_page_in(addr, k_mem_page_frame_to_phys(pf));
k_mem_paging_backing_store_page_finalize(pf, page_in_location);
if (!pin) {
if (IS_ENABLED(CONFIG_EVICTION_TRACKING) && (!pin)) {
k_mem_paging_eviction_add(pf);
}
out:
Expand Down Expand Up @@ -1807,7 +1817,10 @@
pf = k_mem_phys_to_page_frame(phys);
if (k_mem_page_frame_is_pinned(pf)) {
k_mem_page_frame_clear(pf, K_MEM_PAGE_FRAME_PINNED);
k_mem_paging_eviction_add(pf);

if (IS_ENABLED(CONFIG_EVICTION_TRACKING)) {
k_mem_paging_eviction_add(pf);
}
}
}
k_spin_unlock(&z_mm_lock, key);
Expand Down
10 changes: 10 additions & 0 deletions subsys/demand_paging/eviction/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ choice EVICTION_CHOICE

config EVICTION_CUSTOM
bool "Custom eviction algorithm"
imply EVICTION_TRACKING
help
This option is chosen when the eviction algorithm will be implemented
by the application, instead of using one included in Zephyr.
Expand All @@ -30,6 +31,7 @@ config EVICTION_NRU

config EVICTION_LRU
bool "Least Recently Used (LRU) page eviction algorithm"
select EVICTION_TRACKING
help
This implements a Least Recently Used page eviction algorithm.
Usage is tracked based on MMU protection making pages unaccessible
Expand All @@ -49,3 +51,11 @@ config EVICTION_NRU_PERIOD
pages that are capable of being paged out. At eviction time, if a page
still has the accessed property, it will be considered as recently used.
endif # EVICTION_NRU

config EVICTION_TRACKING
bool
depends on ARCH_SUPPORTS_EVICTION_TRACKING
help
Selected by eviction algorithms which needs page tracking and need to
implement the following functions: k_mem_paging_eviction_add(),
k_mem_paging_eviction_remove() and k_mem_paging_eviction_accessed().
7 changes: 6 additions & 1 deletion subsys/demand_paging/eviction/nru.c
Original file line number Diff line number Diff line change
Expand Up @@ -111,8 +111,11 @@ void k_mem_paging_eviction_init(void)
K_MSEC(CONFIG_EVICTION_NRU_PERIOD));
}

#ifdef CONFIG_EVICTION_TRACKING
/*
* unused interfaces
* Empty functions defined here so that architectures unconditionally
* implement eviction tracking can still use this algorithm for
* testing.
*/

void k_mem_paging_eviction_add(struct k_mem_page_frame *pf)
Expand All @@ -129,3 +132,5 @@ void k_mem_paging_eviction_accessed(uintptr_t phys)
{
ARG_UNUSED(phys);
}

#endif /* CONFIG_EVICTION_TRACKING */
Loading