diff --git a/tests/kernel/mem_protect/demand_paging/ondemand_section/CMakeLists.txt b/tests/kernel/mem_protect/demand_paging/ondemand_section/CMakeLists.txt new file mode 100644 index 00000000000000..bb6a9f7749f7b3 --- /dev/null +++ b/tests/kernel/mem_protect/demand_paging/ondemand_section/CMakeLists.txt @@ -0,0 +1,13 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(ondemand_section) + +target_include_directories(app PRIVATE + ${ZEPHYR_BASE}/kernel/include + ${ZEPHYR_BASE}/arch/${ARCH}/include + ) + +FILE(GLOB app_sources src/*.c) +target_sources(app PRIVATE ${app_sources}) diff --git a/tests/kernel/mem_protect/demand_paging/ondemand_section/prj.conf b/tests/kernel/mem_protect/demand_paging/ondemand_section/prj.conf new file mode 100644 index 00000000000000..250ef75771bf07 --- /dev/null +++ b/tests/kernel/mem_protect/demand_paging/ondemand_section/prj.conf @@ -0,0 +1,6 @@ +CONFIG_ZTEST=y +CONFIG_DEMAND_PAGING=y +CONFIG_DEMAND_PAGING_ALLOW_IRQ=y +CONFIG_DEMAND_PAGING_STATS=y +CONFIG_DEMAND_MAPPING=y +CONFIG_LINKER_USE_ONDEMAND_SECTION=y diff --git a/tests/kernel/mem_protect/demand_paging/ondemand_section/src/main.c b/tests/kernel/mem_protect/demand_paging/ondemand_section/src/main.c new file mode 100644 index 00000000000000..0e1753552acf59 --- /dev/null +++ b/tests/kernel/mem_protect/demand_paging/ondemand_section/src/main.c @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2024 BayLibre SAS + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include + +static const char __ondemand_rodata message[] = "was evicted"; + +static void __ondemand_func evictable_function(void) +{ + static int count; + + printk("This %s code, count=%d\n", message, ++count); +} + +ZTEST(ondemand_section, test_ondemand_basic) +{ + unsigned long faults_before, faults_after; + void *addr = (void *)ROUND_DOWN(&evictable_function, CONFIG_MMU_PAGE_SIZE); + + printk("About to call unpaged code\n"); + faults_before = k_mem_num_pagefaults_get(); + evictable_function(); + faults_after = k_mem_num_pagefaults_get(); + zassert_not_equal(faults_before, faults_after, "should have faulted"); + + printk("Code should be resident on second call\n"); + faults_before = k_mem_num_pagefaults_get(); + evictable_function(); + faults_after = k_mem_num_pagefaults_get(); + zassert_equal(faults_before, faults_after, "should not have faulted"); + + printk("Forcefully evicting it from memory\n"); + zassert_ok(k_mem_page_out(addr, CONFIG_MMU_PAGE_SIZE), ""); + + printk("Calling it again\n"); + faults_before = k_mem_num_pagefaults_get(); + evictable_function(); + faults_after = k_mem_num_pagefaults_get(); + zassert_not_equal(faults_before, faults_after, "should have faulted"); + + printk("Forcefully evicting it from memory again\n"); + zassert_ok(k_mem_page_out(addr, CONFIG_MMU_PAGE_SIZE), ""); + + printk("Preemptively fetching it back in\n"); + /* strangely, k_mem_page_in() returns void */ + k_mem_page_in(addr, CONFIG_MMU_PAGE_SIZE); + + printk("Code should be resident\n"); + faults_before = k_mem_num_pagefaults_get(); + evictable_function(); + faults_after = k_mem_num_pagefaults_get(); + zassert_equal(faults_before, faults_after, "should not have faulted"); +} + +ZTEST_SUITE(ondemand_section, NULL, NULL, NULL, NULL, NULL); diff --git a/tests/kernel/mem_protect/demand_paging/ondemand_section/testcase.yaml b/tests/kernel/mem_protect/demand_paging/ondemand_section/testcase.yaml new file mode 100644 index 00000000000000..53839ac8f44b60 --- /dev/null +++ b/tests/kernel/mem_protect/demand_paging/ondemand_section/testcase.yaml @@ -0,0 +1,12 @@ +common: + tags: + - kernel + - mmu + - demand_paging +tests: + kernel.demand_paging.ondemand_section.arm64_semihost: + platform_allow: + - qemu_cortex_a53 + extra_configs: + - CONFIG_SEMIHOST=y + - CONFIG_BACKING_STORE_ONDEMAND_SEMIHOST=y