KallistiOS git master
Independent SDK for the Sega Dreamcast
Loading...
Searching...
No Matches
mmu.h
Go to the documentation of this file.
1/* KallistiOS ##version##
2
3 arch/dreamcast/include/arch/mmu.h
4 Copyright (C) 2001 Megan Potter
5
6*/
7
8/** \file arch/mmu.h
9 \brief Memory Management Unit and Translation Lookaside Buffer handling.
10 \ingroup mmu
11
12 This file defines the interface to the Memory Management Unit (MMU) in the
13 SH4. The MMU, while not used normally by KOS, is available for virtual
14 memory use, if you so desire. While using this functionality is probably
15 overkill for most homebrew, there are a few very interesting things that
16 this functionality could be used for (like mapping large files into memory
17 that wouldn't otherwise fit).
18
19 The whole system is set up as a normal paged memory virtual->physical
20 address translation. KOS implements the page table as a sparse, two-level
21 page table. By default, pages are 4KB in size. Each top-level page table
22 entry has 512 2nd level entries (there are 1024 entries in the top-level
23 entry). This works out to about 2KB of space needed for one top-level entry.
24
25 The SH4 itself has 4 TLB entries for instruction fetches, and 64 "unified"
26 TLB entries (for combined instructions + data). Essentially, the UTLB acts
27 both as the TLB for data accesses (from mov instructions) and as a cache for
28 entries for the ITLB. If there is no entry in the ITLB for an instruction
29 access, the UTLB will automatically be searched. If no entry is found still,
30 an ITLB miss exception will be generated. Data accesses are handled
31 similarly to this (although additional complications are involved due to
32 write accesses, and of course the ITLB doesn't play into data accesses).
33
34 For more information about how the MMU works, refer to the Hitachi/Renesas
35 SH4 programming manual. It has much more detailed information than what is
36 in here, for obvious reasons.
37
38 This functionality was ported over to mainline KOS from the KOS-MMU project
39 of Megan Potter. Unfortunately, KOS-MMU never reached a real phase of maturity
40 and usefulness, but this piece can be quite useful on its own.
41
42 \author Megan Potter
43*/
44
45#ifndef __ARCH_MMU_H
46#define __ARCH_MMU_H
47
48#include <sys/cdefs.h>
49__BEGIN_DECLS
50
51#include <stdbool.h>
52
53#include <sys/uio.h>
54
55/** \defgroup mmu MMU
56 \brief Driver for the SH4's MMU (disabled by default).
57 \ingroup system
58
59 Since the software has to handle TLB misses on the SH-4, we have freedom
60 to use any page table format we want (and thus save space), but we must
61 make it quick to access. The SH-4 can address a maximum of 512M of address
62 space per "area", but we only care about one area, so this is the total
63 maximum addressable space. With 4K pages, that works out to 2^17 pages
64 that must be mappable, or 17 bits. We use 18 bits just to be sure (there
65 are a few left over).
66
67 Page tables (per-process) are a sparse two-level array. The virtual address
68 space is actually 2^30 bytes, or 2^(30-12)=2^18 pages, so there must be
69 a possibility of having that many page entries per process space. A full
70 page table for a process would be 1M, so this is obviously too big!! Thus
71 the sparse array.
72
73 The bottom layer of the page tables consists of a sub-context array for
74 512 pages, which translates into 2K of storage space. The process then
75 has the possibility of using one or more of the 512 top-level slots. For
76 a very small process (using one page for code/data and one for stack), it
77 should be possible to achieve a page table footprint of one page. The tables
78 can grow from there as necessary.
79
80 Virtual addresses are broken up as follows:
81 - Bits 31 - 22 10 bits top-level page directory
82 - Bits 21 - 13 9 bits bottom-level page entry
83 - Bits 11 - 0 Byte index into page
84
85*/
86
87/** \defgroup mmu_prot_values Protection Settings
88 \brief SH4 MMU page protection settings values
89 \ingroup mmu
90
91 Each page mapped via the MMU can be protected in a couple of different ways,
92 as specified here.
93
94 @{
95*/
96typedef enum page_prot {
97 MMU_KERNEL_RDONLY, /**< \brief No user access, kernel read-only */
98 MMU_KERNEL_RDWR, /**< \brief No user access, kernel full */
99 MMU_ALL_RDONLY, /**< \brief Read-only user and kernel */
100 MMU_ALL_RDWR, /**< \brief Full access, user and kernel */
102/** @} */
103
104/** \defgroup mmu_cache_values Cacheability Settings
105 \brief SH4 MMU page cachability settings values
106 \ingroup mmu
107
108 Each page mapped via the MMU can have its cacheability set individually.
109
110 @{
111*/
112typedef enum page_cache {
113 MMU_NO_CACHE, /**< \brief Cache disabled */
114 MMU_CACHE_BACK, /**< \brief Write-back caching */
115 MMU_CACHE_WT, /**< \brief Write-through caching */
116 MMU_CACHEABLE = MMU_CACHE_BACK, /**< \brief Default caching */
118/** @} */
119
120/** \defgroup mmu_page_size Page size settings
121 \brief SH4 MMU page sizes
122 \ingroup mmu
123
124 @{
125*/
132/** @} */
133
134/** \brief MMU TLB entry for a single page.
135 \ingroup mmu
136
137 The TLB entries on the SH4 are a single 32-bit dword in length. We store
138 some other data here too for ease of use.
139
140 \headerfile arch/mmu.h
141*/
142typedef struct mmupage {
143 /* Explicit pieces, used for reference */
144 /*uint32_t virtual; */ /* implicit */
145 uint32_t physical: 18; /**< \brief Physical page ID -- 18 bits */
146 uint32_t prkey: 2; /**< \brief Protection key data -- 2 bits */
147 uint32_t valid: 1; /**< \brief Valid mapping -- 1 bit */
148 uint32_t shared: 1; /**< \brief Shared between procs -- 1 bit */
149 uint32_t cache: 1; /**< \brief Cacheable -- 1 bit */
150 uint32_t dirty: 1; /**< \brief Dirty -- 1 bit */
151 uint32_t wthru: 1; /**< \brief Write-thru enable -- 1 bit */
152 uint32_t blank: 7; /**< \brief Reserved -- 7 bits */
153
154 /* Pre-compiled pieces. These waste a bit of ram, but they also
155 speed loading immensely at runtime. */
156 uint32_t pteh; /**< \brief Pre-built PTEH value */
157 uint32_t ptel; /**< \brief Pre-built PTEL value */
158} mmupage_t;
159
160/** \brief The number of pages in a sub-context.
161 \ingroup mmu
162 */
163#define MMU_SUB_PAGES 512
164
165/** \brief MMU sub-context type.
166 \ingroup mmu
167
168 We have two-level page tables on SH4, and each sub-context contains 512
169 entries.
170
171 \headerfile arch/mmu.h
172*/
173typedef struct mmusubcontext {
174 mmupage_t page[MMU_SUB_PAGES]; /**< \brief 512 page entries */
176
177/** \brief The number of sub-contexts in the main level context. */
178#define MMU_PAGES 1024
179
180/** \brief MMU context type.
181 \ingroup mmu
182
183 This type is the top-level context that makes up the page table. There is
184 one of these, with 1024 sub-contexts.
185
186 \headerfile arch/mmu.h
187*/
188typedef struct mmucontext {
189 mmusubcontext_t *sub[MMU_PAGES]; /**< \brief 1024 sub-contexts */
190 int asid; /**< \brief Address Space ID */
192
193/** \cond
194 You should not modify this directly, but rather use the functions provided
195 to do so.
196*/
197extern mmucontext_t *mmu_cxt_current;
198/** \endcond */
199
200/** \brief Set the "current" page tables for TLB handling.
201 \ingroup mmu
202
203 This function is useful if you're trying to implement a process model or
204 something of the like on top of KOS. Essentially, this allows you to
205 completely boot the MMU context in use out and replace it with another. You
206 will need to call the mmu_switch_context() function afterwards to set the
207 address space id.
208
209 \param context The context to make current.
210*/
212
213/** \brief Allocate a new MMU context.
214 \ingroup mmu
215
216 Each process should have exactly one of these, and these should not exist
217 without a process. Since KOS doesn't actually have a process model of its
218 own, that means you will only ever have one of these, if any.
219
220 \param asid The address space ID of this process.
221 \return The newly created context or NULL on fail.
222*/
224
225/** \brief Destroy an MMU context when a process is being destroyed.
226 \ingroup mmu
227
228 This function cleans up a MMU context, deallocating any memory its using.
229
230 \param context The context to clean up after.
231*/
233
234/** \brief Using the given page tables, translate the virtual page ID to a
235 physical page ID.
236 \ingroup mmu
237
238 \param context The context to look in.
239 \param virtpage The virtual page number to look for.
240 \return The physical page number, or -1 on failure.
241 \see mmu_phys_to_virt()
242*/
243int mmu_virt_to_phys(mmucontext_t *context, int virtpage);
244
245/** \brief Using the given page tables, translate the physical page ID to a
246 virtual page ID.
247 \ingroup mmu
248
249 \param context The context to look in.
250 \param physpage The physical page number to look for.
251 \return The virtual page number, or -1 on failure.
252 \see mmu_virt_to_phys()
253*/
254int mmu_phys_to_virt(mmucontext_t *context, int physpage);
255
256/** \brief Switch to the given context.
257 \ingroup mmu
258
259 This function switches to the given context's address space ID. The context
260 should have already been made current with mmu_use_table().
261 You are responsible for invalidating any caches as necessary, as well as
262 invalidating any stale TLB entries.
263
264 \param context The context to make current.
265*/
267
268/** \brief Set the given virtual page to map to the given physical page.
269 \ingroup mmu
270
271 This implies turning on the "valid" bit. Also sets the other named
272 attributes as specified.
273
274 \param context The context to modify.
275 \param virtpage The first virtual page to map.
276 \param physpage The first physical page to map.
277 \param count The number of sequential pages to map.
278 \param prot Memory protection for page (see
279 \ref mmu_prot_values).
280 \param cache Cache scheme for page (see \ref mmu_cache_values).
281 \param share Set to share between processes (meaningless).
282 \param dirty Set to mark the page as dirty.
283*/
284void mmu_page_map(mmucontext_t *context, int virtpage, int physpage,
285 int count, page_prot_t prot, page_cache_t cache,
286 bool share, bool dirty);
287
288/** \brief Copy a chunk of data from a process' address space into a kernel
289 buffer, taking into account page mappings.
290 \ingroup mmu
291
292 \param context The context to use.
293 \param srcaddr Source, in the mapped memory space.
294 \param srccnt The number of bytes to copy.
295 \param buffer The kernel buffer to copy into (should be in P1).
296 \return The number of bytes copied (failure causes arch_panic).
297*/
298int mmu_copyin(mmucontext_t *context, uint32_t srcaddr, uint32_t srccnt,
299 void *buffer);
300
301/** \brief Copy a chunk of data from one process' address space to another
302 process' address space, taking into account page mappings.
303 \ingroup mmu
304
305 \param context1 The source's context.
306 \param iov1 The scatter/gather array to copy from.
307 \param iovcnt1 The number of entries in iov1.
308 \param context2 The destination's context.
309 \param iov2 The scatter/gather array to copy to.
310 \param iovcnt2 The number of entries in iov2.
311 \return The number of bytes copied (failure causes arch_panic).
312*/
313int mmu_copyv(mmucontext_t *context1, struct iovec *iov1, int iovcnt1,
314 mmucontext_t *context2, struct iovec *iov2, int iovcnt2);
315
316/** \brief MMU mapping handler.
317 \ingroup mmu
318
319 This type is used for functions that will take over the mapping for the
320 kernel. In general, there shouldn't be much use for taking this over
321 yourself, unless you want to change the size of the page table entries or
322 something of the like.
323
324 \param context The context in use.
325 \param virtpage The virtual page to map.
326 \return The page table entry, or NULL if none exists.
327*/
328typedef mmupage_t * (*mmu_mapfunc_t)(mmucontext_t * context, int virtpage);
329
330/** \brief Get the current mapping function.
331 \ingroup mmu
332 \return The current function that maps pages.
333*/
335
336/** \brief Set a new MMU mapping handler.
337 \ingroup mmu
338
339 This function will allow you to set a new function to handle mapping for
340 memory pages. There's not much of a reason to do this unless you really do
341 not like the way KOS handles the page mapping internally.
342
343 \param newfunc The new function to handle mapping.
344 \return The old function that did mapping.
345*/
347
348/** \brief Create a static virtual memory maping.
349 \ingroup mmu
350
351 This function reserves one TLB entry to create a static mapping from a
352 virtual memory address to a physical memory address. Static mappings are
353 never flushed out of the TLB, and are sometimes useful when the whole MMU
354 function is not necesary. Static memory mappings can also use different page
355 sizes.
356
357 Note that the only way to undo static mappings is to call
358 mmu_shutdown_basic().
359
360 \param virt The virtual address for the memory mapping.
361 \param phys The physical address for the memory mapping.
362 \param page_size The size of the memory page used.
363 \param page_prot The memory protection usef for that mapping.
364 \param cached True if the mapped memory area is cached,
365 false otherwise.
366 \retval 0 On success.
367 \retval -1 When the virtual or physical addresses are not
368 aligned to the page size.
369*/
370int mmu_page_map_static(uintptr_t virt, uintptr_t phys,
371 page_size_t page_size,
372 page_prot_t page_prot,
373 bool cached);
374
375/** \brief Initialize MMU support.
376 \ingroup mmu
377
378 Unlike most things in KOS, the MMU is not initialized by a normal startup.
379 This is because for most homebrew, its not needed.
380
381 This implies mmu_init_basic().
382*/
383void mmu_init(void);
384
385/** \brief Initialize basic MMU support.
386 \ingroup mmu
387
388 This function can be used to initialize the very minimum for MMU to work
389 with static mappings. Dynamic mapping (and mmu_page_map()) will not work.
390 If you need dynamic mapping, use mmu_init() instead.
391*/
392void mmu_init_basic(void);
393
394/** \brief Shutdown MMU support.
395 \ingroup mmu
396
397 Turn off MMU support after it was initialized with mmu_init().
398 You should try to make sure this gets done if you initialize the MMU in your
399 program, so as to play nice with loaders and the like (that will not expect
400 that its on, in general).
401*/
402void mmu_shutdown(void);
403
404/** \brief Shutdown basic MMU support.
405 \ingroup mmu
406
407 Turn off basic MMU support after it was initialized with mmu_init_basic().
408 You should try to make sure this gets done if you initialize the MMU in your
409 program, so as to play nice with loaders and the like (that will not expect
410 that its on, in general).
411*/
413
414/** \brief Reset ITLB.
415 \ingroup mmu
416 */
417void mmu_reset_itlb(void);
418
419/** \brief Check if MMU translation is enabled.
420 \ingroup mmu
421
422 \return True if MMU translation is enabled, false otherwise.
423 */
424bool mmu_enabled(void);
425
426/** \brief Reset the base target address for store queues.
427 * \ingroup mmu
428 *
429 * \param addr The base address to reset to */
430void mmu_set_sq_addr(void *addr);
431
432__END_DECLS
433
434#endif /* __ARCH_MMU_H */
page_cache_t
Definition mmu.h:112
@ MMU_CACHE_BACK
Write-back caching.
Definition mmu.h:114
@ MMU_CACHE_WT
Write-through caching.
Definition mmu.h:115
@ MMU_CACHEABLE
Default caching.
Definition mmu.h:116
@ MMU_NO_CACHE
Cache disabled.
Definition mmu.h:113
page_size_t
Definition mmu.h:126
@ PAGE_SIZE_1K
Definition mmu.h:127
@ PAGE_SIZE_4K
Definition mmu.h:128
@ PAGE_SIZE_64K
Definition mmu.h:129
@ PAGE_SIZE_1M
Definition mmu.h:130
page_prot_t
Definition mmu.h:96
@ MMU_ALL_RDONLY
Read-only user and kernel.
Definition mmu.h:99
@ MMU_KERNEL_RDWR
No user access, kernel full.
Definition mmu.h:98
@ MMU_ALL_RDWR
Full access, user and kernel.
Definition mmu.h:100
@ MMU_KERNEL_RDONLY
No user access, kernel read-only.
Definition mmu.h:97
void mmu_context_destroy(mmucontext_t *context)
Destroy an MMU context when a process is being destroyed.
mmu_mapfunc_t mmu_map_set_callback(mmu_mapfunc_t newfunc)
Set a new MMU mapping handler.
#define MMU_SUB_PAGES
The number of pages in a sub-context.
Definition mmu.h:163
int mmu_copyin(mmucontext_t *context, uint32_t srcaddr, uint32_t srccnt, void *buffer)
Copy a chunk of data from a process' address space into a kernel buffer, taking into account page map...
void mmu_switch_context(mmucontext_t *context)
Switch to the given context.
int mmu_phys_to_virt(mmucontext_t *context, int physpage)
Using the given page tables, translate the physical page ID to a virtual page ID.
mmupage_t *(* mmu_mapfunc_t)(mmucontext_t *context, int virtpage)
MMU mapping handler.
Definition mmu.h:328
void mmu_init_basic(void)
Initialize basic MMU support.
mmucontext_t * mmu_context_create(int asid)
Allocate a new MMU context.
void mmu_page_map(mmucontext_t *context, int virtpage, int physpage, int count, page_prot_t prot, page_cache_t cache, bool share, bool dirty)
Set the given virtual page to map to the given physical page.
void mmu_use_table(mmucontext_t *context)
Set the "current" page tables for TLB handling.
void mmu_shutdown_basic(void)
Shutdown basic MMU support.
int mmu_virt_to_phys(mmucontext_t *context, int virtpage)
Using the given page tables, translate the virtual page ID to a physical page ID.
void mmu_shutdown(void)
Shutdown MMU support.
int mmu_page_map_static(uintptr_t virt, uintptr_t phys, page_size_t page_size, page_prot_t page_prot, bool cached)
Create a static virtual memory maping.
void mmu_set_sq_addr(void *addr)
Reset the base target address for store queues.
void mmu_reset_itlb(void)
Reset ITLB.
void mmu_init(void)
Initialize MMU support.
int mmu_copyv(mmucontext_t *context1, struct iovec *iov1, int iovcnt1, mmucontext_t *context2, struct iovec *iov2, int iovcnt2)
Copy a chunk of data from one process' address space to another process' address space,...
mmu_mapfunc_t mmu_map_get_callback(void)
Get the current mapping function.
bool mmu_enabled(void)
Check if MMU translation is enabled.
#define MMU_PAGES
The number of sub-contexts in the main level context.
Definition mmu.h:178
I/O vector structure.
Definition uio.h:34
MMU context type.
Definition mmu.h:188
int asid
Address Space ID.
Definition mmu.h:190
MMU TLB entry for a single page.
Definition mmu.h:142
uint32_t shared
Shared between procs – 1 bit.
Definition mmu.h:148
uint32_t valid
Valid mapping – 1 bit.
Definition mmu.h:147
uint32_t dirty
Dirty – 1 bit.
Definition mmu.h:150
uint32_t ptel
Pre-built PTEL value.
Definition mmu.h:157
uint32_t cache
Cacheable – 1 bit.
Definition mmu.h:149
uint32_t blank
Reserved – 7 bits.
Definition mmu.h:152
uint32_t physical
Physical page ID – 18 bits.
Definition mmu.h:145
uint32_t wthru
Write-thru enable – 1 bit.
Definition mmu.h:151
uint32_t pteh
Pre-built PTEH value.
Definition mmu.h:156
uint32_t prkey
Protection key data – 2 bits.
Definition mmu.h:146
MMU sub-context type.
Definition mmu.h:173
Header for vector I/O.