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 <arch/types.h>
52#include <sys/uio.h>
53
54/** \defgroup mmu MMU
55 \brief Driver for the SH4's MMU (disabled by default).
56 \ingroup system
57
58 Since the software has to handle TLB misses on the SH-4, we have freedom
59 to use any page table format we want (and thus save space), but we must
60 make it quick to access. The SH-4 can address a maximum of 512M of address
61 space per "area", but we only care about one area, so this is the total
62 maximum addressable space. With 4K pages, that works out to 2^17 pages
63 that must be mappable, or 17 bits. We use 18 bits just to be sure (there
64 are a few left over).
65
66 Page tables (per-process) are a sparse two-level array. The virtual address
67 space is actually 2^30 bytes, or 2^(30-12)=2^18 pages, so there must be
68 a possibility of having that many page entries per process space. A full
69 page table for a process would be 1M, so this is obviously too big!! Thus
70 the sparse array.
71
72 The bottom layer of the page tables consists of a sub-context array for
73 512 pages, which translates into 2K of storage space. The process then
74 has the possibility of using one or more of the 512 top-level slots. For
75 a very small process (using one page for code/data and one for stack), it
76 should be possible to achieve a page table footprint of one page. The tables
77 can grow from there as necessary.
78
79 Virtual addresses are broken up as follows:
80 - Bits 31 - 22 10 bits top-level page directory
81 - Bits 21 - 13 9 bits bottom-level page entry
82 - Bits 11 - 0 Byte index into page
83
84*/
85
86/** \defgroup mmu_bit_macros Address Bits
87 \brief Definitions and masks for address pages
88 \ingroup mmu
89
90 The MMU code uses these to determine the page of a request.
91
92 @{
93*/
94#define MMU_TOP_SHIFT 21 /**< \brief Top-level shift */
95#define MMU_TOP_BITS 10 /**< \brief Top-level bits */
96#define MMU_TOP_MASK ((1 << MMU_TOP_BITS) - 1) /**< \brief Top-level mask */
97#define MMU_BOT_SHIFT 12 /**< \brief Bottom shift */
98#define MMU_BOT_BITS 9 /**< \brief Bottom bits */
99#define MMU_BOT_MASK ((1 << MMU_BOT_BITS) - 1) /**< \brief Bottom mask */
100#define MMU_IND_SHIFT 0 /**< \brief Index shift */
101#define MMU_IND_BITS 12 /**< \brief Index bits */
102#define MMU_IND_MASK ((1 << MMU_IND_BITS) - 1) /**< \brief Index mask */
103/** @} */
104
105/** \defgroup mmu_prot_values Protection Settings
106 \brief SH4 MMU page protection settings values
107 \ingroup mmu
108
109 Each page mapped via the MMU can be protected in a couple of different ways,
110 as specified here.
111
112 @{
113*/
114#define MMU_KERNEL_RDONLY 0 /**< \brief No user access, kernel read-only */
115#define MMU_KERNEL_RDWR 1 /**< \brief No user access, kernel full */
116#define MMU_ALL_RDONLY 2 /**< \brief Read-only user and kernel */
117#define MMU_ALL_RDWR 3 /**< \brief Full access, user and kernel */
118/** @} */
119
120/** \defgroup mmu_cache_values Cacheability Settings
121 \brief SH4 MMU page cachability settings values
122 \ingroup mmu
123
124 Each page mapped via the MMU can have its cacheability set individually.
125
126 @{
127*/
128#define MMU_NO_CACHE 1 /**< \brief Cache disabled */
129#define MMU_CACHE_BACK 2 /**< \brief Write-back caching */
130#define MMU_CACHE_WT 3 /**< \brief Write-through caching */
131#define MMU_CACHEABLE MMU_CACHE_BACK /**< \brief Default caching */
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 virtual; */ /* implicit */
145 uint32 physical: 18; /**< \brief Physical page ID -- 18 bits */
146 uint32 prkey: 2; /**< \brief Protection key data -- 2 bits */
147 uint32 valid: 1; /**< \brief Valid mapping -- 1 bit */
148 uint32 shared: 1; /**< \brief Shared between procs -- 1 bit */
149 uint32 cache: 1; /**< \brief Cacheable -- 1 bit */
150 uint32 dirty: 1; /**< \brief Dirty -- 1 bit */
151 uint32 wthru: 1; /**< \brief Write-thru enable -- 1 bit */
152 uint32 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 pteh; /**< \brief Pre-built PTEH value */
157 uint32 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
199struct mmu_token;
200typedef struct mmu_token *mmu_token_t;
201/** \endcond */
202
203/** \brief Set the "current" page tables for TLB handling.
204 \ingroup mmu
205
206 This function is useful if you're trying to implement a process model or
207 something of the like on top of KOS. Essentially, this allows you to
208 completely boot the MMU context in use out and replace it with another. You
209 will need to call the mmu_switch_context() function afterwards to set the
210 address space id.
211
212 \param context The context to make current.
213*/
215
216/** \brief Allocate a new MMU context.
217 \ingroup mmu
218
219 Each process should have exactly one of these, and these should not exist
220 without a process. Since KOS doesn't actually have a process model of its
221 own, that means you will only ever have one of these, if any.
222
223 \param asid The address space ID of this process.
224 \return The newly created context or NULL on fail.
225*/
227
228/** \brief Destroy an MMU context when a process is being destroyed.
229 \ingroup mmu
230
231 This function cleans up a MMU context, deallocating any memory its using.
232
233 \param context The context to clean up after.
234*/
236
237/** \brief Using the given page tables, translate the virtual page ID to a
238 physical page ID.
239 \ingroup mmu
240
241 \param context The context to look in.
242 \param virtpage The virtual page number to look for.
243 \return The physical page number, or -1 on failure.
244 \see mmu_phys_to_virt()
245*/
246int mmu_virt_to_phys(mmucontext_t *context, int virtpage);
247
248/** \brief Using the given page tables, translate the physical page ID to a
249 virtual page ID.
250 \ingroup mmu
251
252 \param context The context to look in.
253 \param physpage The physical page number to look for.
254 \return The virtual page number, or -1 on failure.
255 \see mmu_virt_to_phys()
256*/
257int mmu_phys_to_virt(mmucontext_t *context, int physpage);
258
259/** \brief Switch to the given context.
260 \ingroup mmu
261
262 This function switches to the given context's address space ID. The context
263 should have already been made current with mmu_use_table().
264 You are responsible for invalidating any caches as necessary, as well as
265 invalidating any stale TLB entries.
266
267 \param context The context to make current.
268*/
270
271/** \brief Set the given virtual page to map to the given physical page.
272 \ingroup mmu
273
274 This implies turning on the "valid" bit. Also sets the other named
275 attributes as specified.
276
277 \param context The context to modify.
278 \param virtpage The first virtual page to map.
279 \param physpage The first physical page to map.
280 \param count The number of sequential pages to map.
281 \param prot Memory protection for page (see
282 \ref mmu_prot_values).
283 \param cache Cache scheme for page (see \ref mmu_cache_values).
284 \param share Set to 1 to share between processes (meaningless),
285 otherwise set to 0.
286 \param dirty Set to 1 to mark the page as dirty, otherwise set to
287 0.
288*/
289void mmu_page_map(mmucontext_t *context, int virtpage, int physpage,
290 int count, int prot, int cache, int share, int dirty);
291
292/** \brief Copy a chunk of data from a process' address space into a kernel
293 buffer, taking into account page mappings.
294 \ingroup mmu
295
296 \param context The context to use.
297 \param srcaddr Source, in the mapped memory space.
298 \param srccnt The number of bytes to copy.
299 \param buffer The kernel buffer to copy into (should be in P1).
300 \return The number of bytes copied (failure causes arch_panic).
301*/
302int mmu_copyin(mmucontext_t *context, uint32 srcaddr, uint32 srccnt,
303 void *buffer);
304
305/** \brief Copy a chunk of data from one process' address space to another
306 process' address space, taking into account page mappings.
307 \ingroup mmu
308
309 \param context1 The source's context.
310 \param iov1 The scatter/gather array to copy from.
311 \param iovcnt1 The number of entries in iov1.
312 \param context2 The destination's context.
313 \param iov2 The scatter/gather array to copy to.
314 \param iovcnt2 The number of entries in iov2.
315 \return The number of bytes copied (failure causes arch_panic).
316*/
317int mmu_copyv(mmucontext_t *context1, struct iovec *iov1, int iovcnt1,
318 mmucontext_t *context2, struct iovec *iov2, int iovcnt2);
319
320/** \brief MMU mapping handler.
321 \ingroup mmu
322
323 This type is used for functions that will take over the mapping for the
324 kernel. In general, there shouldn't be much use for taking this over
325 yourself, unless you want to change the size of the page table entries or
326 something of the like.
327
328 \param context The context in use.
329 \param virtpage The virtual page to map.
330 \return The page table entry, or NULL if none exists.
331*/
332typedef mmupage_t * (*mmu_mapfunc_t)(mmucontext_t * context, int virtpage);
333
334/** \brief Get the current mapping function.
335 \ingroup mmu
336 \return The current function that maps pages.
337*/
339
340/** \brief Set a new MMU mapping handler.
341 \ingroup mmu
342
343 This function will allow you to set a new function to handle mapping for
344 memory pages. There's not much of a reason to do this unless you really do
345 not like the way KOS handles the page mapping internally.
346
347 \param newfunc The new function to handle mapping.
348 \return The old function that did mapping.
349*/
351
352/** \brief Initialize MMU support.
353 \ingroup mmu
354
355 Unlike most things in KOS, the MMU is not initialized by a normal startup.
356 This is because for most homebrew, its not needed.
357
358 \retval 0 On success (no error conditions defined).
359*/
360int mmu_init(void);
361
362/** \brief Shutdown MMU support.
363 \ingroup mmu
364
365 Turn off the MMU after it was initialized. You should try to make sure this
366 gets done if you initialize the MMU in your program, so as to play nice with
367 loaders and the like (that will not expect that its on, in general).
368*/
369void mmu_shutdown(void);
370
371/** \brief Reset ITLB.
372 \ingroup mmu
373 */
374void mmu_reset_itlb(void);
375
376/** \brief Temporarily disable MMU address translation.
377 \ingroup mmu
378
379 \return An opaque token to be passed to mmu_restore()
380 */
381mmu_token_t mmu_disable(void);
382
383/** \brief Restore MMU address translation.
384 \ingroup mmu
385
386 \param token The opaque token obtained from mmu_disable()
387 */
388void mmu_restore(mmu_token_t token);
389
390__END_DECLS
391
392#endif /* __ARCH_MMU_H */
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
void mmu_restore(mmu_token_t token)
Restore MMU address translation.
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:332
mmucontext_t * mmu_context_create(int asid)
Allocate a new MMU context.
int mmu_init(void)
Initialize MMU support.
void mmu_use_table(mmucontext_t *context)
Set the "current" page tables for TLB handling.
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.
void mmu_page_map(mmucontext_t *context, int virtpage, int physpage, int count, int prot, int cache, int share, int dirty)
Set the given virtual page to map to the given physical page.
void mmu_reset_itlb(void)
Reset ITLB.
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.
int mmu_copyin(mmucontext_t *context, uint32 srcaddr, uint32 srccnt, void *buffer)
Copy a chunk of data from a process' address space into a kernel buffer, taking into account page map...
mmu_token_t mmu_disable(void)
Temporarily disable MMU address translation.
unsigned long uint32
32-bit unsigned integer
Definition types.h:33
#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 shared
Shared between procs – 1 bit.
Definition mmu.h:148
uint32 dirty
Dirty – 1 bit.
Definition mmu.h:150
uint32 prkey
Protection key data – 2 bits.
Definition mmu.h:146
uint32 blank
Reserved – 7 bits.
Definition mmu.h:152
uint32 cache
Cacheable – 1 bit.
Definition mmu.h:149
uint32 pteh
Pre-built PTEH value.
Definition mmu.h:156
uint32 wthru
Write-thru enable – 1 bit.
Definition mmu.h:151
uint32 valid
Valid mapping – 1 bit.
Definition mmu.h:147
uint32 ptel
Pre-built PTEL value.
Definition mmu.h:157
uint32 physical
Physical page ID – 18 bits.
Definition mmu.h:145
MMU sub-context type.
Definition mmu.h:173
Common integer types.
Header for terminal control operations.