Browse Source
This is especially handy for tests and validation using QEMU. Signed-off-by: Nicolas Pitre <npitre@baylibre.com>pull/78288/head
3 changed files with 90 additions and 0 deletions
@ -0,0 +1,75 @@ |
|||||||
|
/*
|
||||||
|
* Copyright (c) 2024 BayLibre SAS |
||||||
|
* |
||||||
|
* SPDX-License-Identifier: Apache-2.0 |
||||||
|
*/ |
||||||
|
#include <mmu.h> |
||||||
|
#include <kernel_arch_interface.h> |
||||||
|
#include <zephyr/kernel/mm/demand_paging.h> |
||||||
|
#include <zephyr/linker/linker-defs.h> |
||||||
|
#include <zephyr/arch/common/semihost.h> |
||||||
|
|
||||||
|
/*
|
||||||
|
* semihost.h declares prototypes with longs but (at least on QEMU) |
||||||
|
* returned values are 32-bits only. Let's use an int. |
||||||
|
*/ |
||||||
|
static int semih_fd = -1; |
||||||
|
|
||||||
|
int k_mem_paging_backing_store_location_get(struct k_mem_page_frame *pf, |
||||||
|
uintptr_t *location, |
||||||
|
bool page_fault) |
||||||
|
{ |
||||||
|
if (k_mem_page_frame_is_backed(pf)) { |
||||||
|
return k_mem_paging_backing_store_location_query( |
||||||
|
k_mem_page_frame_to_virt(pf), location); |
||||||
|
} else { |
||||||
|
/* this is a read-only backing store */ |
||||||
|
return -ENOMEM; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
void k_mem_paging_backing_store_location_free(uintptr_t location) |
||||||
|
{ |
||||||
|
} |
||||||
|
|
||||||
|
void k_mem_paging_backing_store_page_out(uintptr_t location) |
||||||
|
{ |
||||||
|
__ASSERT(true, "not ever supposed to be called"); |
||||||
|
k_panic(); |
||||||
|
} |
||||||
|
|
||||||
|
void k_mem_paging_backing_store_page_in(uintptr_t location) |
||||||
|
{ |
||||||
|
long size = CONFIG_MMU_PAGE_SIZE; |
||||||
|
|
||||||
|
if (semihost_seek(semih_fd, (long)location) != 0 || |
||||||
|
semihost_read(semih_fd, K_MEM_SCRATCH_PAGE, size) != size) { |
||||||
|
k_panic(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
void k_mem_paging_backing_store_page_finalize(struct k_mem_page_frame *pf, |
||||||
|
uintptr_t location) |
||||||
|
{ |
||||||
|
k_mem_page_frame_set(pf, K_MEM_PAGE_FRAME_BACKED); |
||||||
|
} |
||||||
|
|
||||||
|
int k_mem_paging_backing_store_location_query(void *addr, uintptr_t *location) |
||||||
|
{ |
||||||
|
uintptr_t offset = (uintptr_t)addr - (uintptr_t)lnkr_ondemand_start; |
||||||
|
uintptr_t file_offset = (uintptr_t)lnkr_ondemand_load_start |
||||||
|
- (uintptr_t)__text_region_start + offset; |
||||||
|
|
||||||
|
__ASSERT(file_offset % CONFIG_MMU_PAGE_SIZE == 0, "file_offset = %#lx", file_offset); |
||||||
|
*location = file_offset; |
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
void k_mem_paging_backing_store_init(void) |
||||||
|
{ |
||||||
|
semih_fd = semihost_open("./zephyr/zephyr.bin", SEMIHOST_OPEN_RB); |
||||||
|
__ASSERT(semih_fd >= 0, "semihost_open() returned %d", semih_fd); |
||||||
|
if (semih_fd < 0) { |
||||||
|
k_panic(); |
||||||
|
} |
||||||
|
} |
Loading…
Reference in new issue