1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
|
/* SPDX-License-Identifier: copyleft-next-0.3.1 */
/* Copyright 2021 - 2022, Kim Kuparinen < kimi.h.kuparinen@gmail.com > */
#ifndef KMI_ARCH_PAGES_H
#define KMI_ARCH_PAGES_H
/**
* @file vmem.h
* Arch-specific virtual memory handling, generally implemented in
* arch/whatever/kernel/vmem.c
*/
#if defined(__riscv)
# if __riscv_xlen == 64
#include "../../arch/riscv64/include/vmem.h"
# else
#include "../../arch/riscv32/include/vmem.h"
# endif
#endif
#include <kmi/types.h>
#include <kmi/attrs.h>
/**
* Map one virtual page to physical page.
*
* The caller is responsible for checking that both virtual and physical page of
* the correct order are available.
*
* @param branch Virtual memory to work in.
* @param paddr Physical address of page.
* @param vaddr Virtual address to map page to.
* @param flags Page flags.
* @param order Order of page.
* @return \ref OK when succesful, possibly \ref ERR_OOMEM if we don't have
* enough pages to create the mapping.
*/
stat_t map_vpage(struct vmem *branch, pm_t paddr, vm_t vaddr, vmflags_t flags,
enum mm_order order);
/**
* Unmap one page.
*
* @param branch Virtual memory to work in.
* @param vaddr Virtual address of page to unmap.
* @return \ref OK when succesful, \ref ERR_NF if no page at \c vaddr could be
* found.
*/
stat_t unmap_vpage(struct vmem *branch, vm_t vaddr);
/**
* Set flags in page at virtual address \p vaddr.
*
* @param branch Branch in which to work.
* @param vaddr Virtual address of page.
* @param flags Flags to set.
* @return \ref ERR_NF if no page could be found at \p vaddr, otherwise \ref OK.
*/
stat_t set_vpage_flags(struct vmem *branch, vm_t vaddr, vmflags_t flags);
/**
* Clear flags in page at virtual address \p vaddr.
*
* @param branch Branch in which to work.
* @param vaddr Virtual address of page.
* @param flags Flags to clear.
* @return \ref ERR_NF if no page could be found at \p vaddr,
* otherwise \ref OK.
*/
stat_t clear_vpage_flags(struct vmem *branch, vm_t vaddr, vmflags_t flags);
/**
* Modify page mapping physical address and flags.
*
* Note that changing the order of a page is not supported, to do that unmap and
* remap a page.
*
* @param branch Virtual memory to work in.
* @param vaddr Virtual address of map to modify.
* @param paddr Physical address to map to.
* @param flags Flags to set.
* @return \ref ERR_NF if no virtual page is found at \c vaddr, \ref OK otherwise.
*/
stat_t mod_vpage(struct vmem *branch, vm_t vaddr, pm_t paddr, vmflags_t flags);
/**
* Get information about physical page.
*
* @param branch Virtual memory to work in.
* @param vaddr Virtual address of map to get parameters of.
* @param paddr Where to write physical address of the page.
* @param order Where to write the order of the page.
* @param flags Where to write the physical mapping flags of the page.
* @return \ref ERR_NF when no page is found at \c vaddr, \ref OK otherwise.
*/
stat_t stat_vpage(struct vmem *branch, vm_t vaddr, pm_t *paddr,
enum mm_order *order, vmflags_t *flags);
/**
* Flush tlb entry where associated with address \p addr.
*
* @param addr Virtual address region to flush.
*/
void flush_tlb(uintptr_t addr);
/** Flush full tlb of current address space. */
void flush_tlb_full();
/** Flush tlbs of all processors. */
void flush_tlb_all();
/** \todo Add flushing of only some region in memory? */
/**
* Populate virtual memory with kernel virtual address info.
*
* @param b Virtual memory to work in.
* @return \ref OK.
*/
stat_t populate_kvmem(struct vmem *b);
/**
* Initialize arch virtual memory and return boot virtual memory.
*
* @param fdt Global FDT pointer.
* @return Pointer to new boot virtual memory when succesful, \c NULL otherwise.
*/
struct vmem *init_vmem(void *fdt);
#if defined(DEBUG)
/**
* Map and setup serial port.
*
* @param b Virtual memory to work in.
* @param paddr Physical address of serial port.
* @return Virtual address of serial port.
*/
vm_t setup_kernel_io(struct vmem *b, vm_t paddr);
#endif
/**
* Create a direct mapping, with 1:1 physical addresses in one half of the
* address space and the kernel address space in the other.
* Called at boot, not allowed to allocate memory.
*
* @param load_addr Where in physical memory kernel was loaded to. Could in
* theory be fetched from \ref get_load_addr(), but the fewer globals are
* touched during initialization the better.
*
* @return The vmem node used to build the address space. Probably statically
* allocated.
*/
struct vmem *init_mapping(uintptr_t load_addr);
/**
* Create new virtual memory space.
*
* @return Pointer to virtual memory root when succesful, \c NULL otherwise.
*/
struct vmem *create_vmem();
/**
* Jump into virtual memory context.
*
* @param b Virtual memory to jump into.
*/
void use_vmem(struct vmem *b);
/**
* Destroy virtual memory space.
*
* @param b Virtual memory to destroy.
*/
void destroy_vmem(struct vmem *b);
/**
* Raw clone user virtual memory.
*
* @param r Source virtual memory of clone.
* @param b Destination virtual memory of clone.
*/
void clone_uvmem(struct vmem * restrict r, struct vmem * restrict b);
/**
* Jump into kernelspace from a physical address space.
* Really only called by main() during boot so the parameters are kind of weird.
*
* @param fdt Flattened devicetree.
* @param load_addr Address where kernel was loaded to.
* @param direct_mapping Direct mapping vmem.
* @param ram_base Physical base address of ram.
*/
__noreturn void to_kernelspace(void *fdt,
uintptr_t load_addr,
struct vmem *direct_mapping,
pm_t ram_base);
#endif /* KMI_ARCH_PAGES_H */
|