1 /*
2 * Copyright (c) 2024 BayLibre SAS
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6 #include <mmu.h>
7 #include <kernel_arch_interface.h>
8 #include <zephyr/kernel/mm/demand_paging.h>
9 #include <zephyr/linker/linker-defs.h>
10 #include <zephyr/arch/common/semihost.h>
11
12 /*
13 * semihost.h declares prototypes with longs but (at least on QEMU)
14 * returned values are 32-bits only. Let's use an int.
15 */
16 static int semih_fd = -1;
17
k_mem_paging_backing_store_location_get(struct k_mem_page_frame * pf,uintptr_t * location,bool page_fault)18 int k_mem_paging_backing_store_location_get(struct k_mem_page_frame *pf,
19 uintptr_t *location,
20 bool page_fault)
21 {
22 if (k_mem_page_frame_is_backed(pf)) {
23 return k_mem_paging_backing_store_location_query(
24 k_mem_page_frame_to_virt(pf), location);
25 } else {
26 /* this is a read-only backing store */
27 return -ENOMEM;
28 }
29 }
30
k_mem_paging_backing_store_location_free(uintptr_t location)31 void k_mem_paging_backing_store_location_free(uintptr_t location)
32 {
33 }
34
k_mem_paging_backing_store_page_out(uintptr_t location)35 void k_mem_paging_backing_store_page_out(uintptr_t location)
36 {
37 __ASSERT(false, "not ever supposed to be called");
38 k_panic();
39 }
40
k_mem_paging_backing_store_page_in(uintptr_t location)41 void k_mem_paging_backing_store_page_in(uintptr_t location)
42 {
43 long size = CONFIG_MMU_PAGE_SIZE;
44
45 if (semihost_seek(semih_fd, (long)location) != 0 ||
46 semihost_read(semih_fd, K_MEM_SCRATCH_PAGE, size) != size) {
47 k_panic();
48 }
49 }
50
k_mem_paging_backing_store_page_finalize(struct k_mem_page_frame * pf,uintptr_t location)51 void k_mem_paging_backing_store_page_finalize(struct k_mem_page_frame *pf,
52 uintptr_t location)
53 {
54 k_mem_page_frame_set(pf, K_MEM_PAGE_FRAME_BACKED);
55 }
56
k_mem_paging_backing_store_location_query(void * addr,uintptr_t * location)57 int k_mem_paging_backing_store_location_query(void *addr, uintptr_t *location)
58 {
59 uintptr_t offset = (uintptr_t)addr - (uintptr_t)lnkr_ondemand_start;
60 uintptr_t file_offset = (uintptr_t)lnkr_ondemand_load_start
61 - (uintptr_t)__text_region_start + offset;
62
63 __ASSERT(file_offset % CONFIG_MMU_PAGE_SIZE == 0, "file_offset = %#lx", file_offset);
64 *location = file_offset;
65 return 0;
66 }
67
k_mem_paging_backing_store_init(void)68 void k_mem_paging_backing_store_init(void)
69 {
70 semih_fd = semihost_open("./zephyr/zephyr.bin", SEMIHOST_OPEN_RB);
71 __ASSERT(semih_fd >= 0, "semihost_open() returned %d", semih_fd);
72 if (semih_fd < 0) {
73 k_panic();
74 }
75 }
76