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