diff --git a/kernel/include/mmu.h b/kernel/include/mmu.h index a2a0300fca1..00d9579d04c 100644 --- a/kernel/include/mmu.h +++ b/kernel/include/mmu.h @@ -355,6 +355,16 @@ void z_backing_store_init(void); * Core kernel demand paging APIs */ +/** + * Number of page faults since system startup + * + * Counts only those page faults that were handled successfully by the demand + * paging mechanism and were not errors. + * + * @return Number of successful page faults + */ +unsigned long z_num_pagefaults_get(void); + /** * Free a page frame physical address by evicting its contents * diff --git a/kernel/mmu.c b/kernel/mmu.c index c1c88265866..15defbfd959 100644 --- a/kernel/mmu.c +++ b/kernel/mmu.c @@ -564,6 +564,8 @@ void z_mem_manage_init(void) } #ifdef CONFIG_DEMAND_PAGING +static unsigned long z_num_pagefaults; + /* Current implementation relies on interrupt locking to any prevent page table * access, which falls over if other CPUs are active. Addressing this is not * as simple as using spinlocks as regular memory reads/writes constitute @@ -944,7 +946,30 @@ void z_mem_pin(void *addr, size_t size) bool z_page_fault(void *addr) { - return do_page_fault(addr, false); + bool ret; + + ret = do_page_fault(addr, false); + if (ret) { + /* Wasn't an error, increment page fault count */ + int key; + + key = irq_lock(); + z_num_pagefaults++; + irq_unlock(key); + } + return ret; +} + +unsigned long z_num_pagefaults_get(void) +{ + unsigned long ret; + int key; + + key = irq_lock(); + ret = z_num_pagefaults; + irq_unlock(key); + + return ret; } static void do_mem_unpin(void *addr) diff --git a/tests/kernel/mem_protect/demand_paging/src/main.c b/tests/kernel/mem_protect/demand_paging/src/main.c index 3a692c3ab02..44406718d7d 100644 --- a/tests/kernel/mem_protect/demand_paging/src/main.c +++ b/tests/kernel/mem_protect/demand_paging/src/main.c @@ -40,8 +40,11 @@ void test_map_anon_pages(void) void test_touch_anon_pages(void) { + unsigned long faults; static const char *nums = "0123456789"; + faults = z_num_pagefaults_get(); + printk("checking zeroes\n"); /* The mapped area should have started out zeroed. Check this. */ for (size_t i = 0; i < arena_size; i++) { @@ -63,6 +66,12 @@ void test_touch_anon_pages(void) "arena corrupted at index %d (%p): got 0x%hhx expected 0x%hhx", i, &arena[i], arena[i], nums[i % 10]); } + + faults = z_num_pagefaults_get() - faults; + + /* Specific number depends on how much RAM we have but shouldn't be 0 */ + zassert_not_equal(faults, 0UL, "no page faults handled?"); + printk("Kernel handled %lu page faults\n", faults); } /* ztest main entry*/