KallistiOS
##version##
|
Memory Management Unit and Translation Lookaside Buffer handling. More...
Go to the source code of this file.
Data Structures | |
struct | mmupage |
MMU TLB entry for a single page. More... | |
struct | mmusubcontext |
MMU sub-context type. More... | |
struct | mmucontext |
MMU context type. More... | |
Macros | |
#define | MMU_TOP_SHIFT 21 |
Top-level shift. More... | |
#define | MMU_TOP_BITS 10 |
Top-level bits. More... | |
#define | MMU_TOP_MASK ((1 << MMU_TOP_BITS) - 1) |
Top-level mask. More... | |
#define | MMU_BOT_SHIFT 12 |
Bottom shift. More... | |
#define | MMU_BOT_BITS 9 |
Bottom bits. More... | |
#define | MMU_BOT_MASK ((1 << MMU_BOT_BITS) - 1) |
Bottom mask. More... | |
#define | MMU_IND_SHIFT 0 |
Index shift. More... | |
#define | MMU_IND_BITS 12 |
Index bits. More... | |
#define | MMU_IND_MASK ((1 << MMU_IND_BITS) - 1) |
Index mask. More... | |
#define | MMU_KERNEL_RDONLY 0 |
No user access, kernel read-only. More... | |
#define | MMU_KERNEL_RDWR 1 |
No user access, kernel full. More... | |
#define | MMU_ALL_RDONLY 2 |
Read-only user and kernel. More... | |
#define | MMU_ALL_RDWR 3 |
Full access, user and kernel. More... | |
#define | MMU_NO_CACHE 1 |
Cache disabled. More... | |
#define | MMU_CACHE_BACK 2 |
Write-back cacheing. More... | |
#define | MMU_CACHE_WT 3 |
Write-through cacheing. More... | |
#define | MMU_CACHEABLE MMU_CACHE_BACK |
Default cacheing. More... | |
#define | MMU_SUB_PAGES 512 |
The number of pages in a sub-context. More... | |
#define | MMU_PAGES 1024 |
The number of sub-contexts in the main level context. More... | |
Typedefs | |
typedef struct mmupage | mmupage_t |
MMU TLB entry for a single page. More... | |
typedef struct mmusubcontext | mmusubcontext_t |
MMU sub-context type. More... | |
typedef struct mmucontext | mmucontext_t |
MMU context type. More... | |
typedef mmupage_t *(* | mmu_mapfunc_t )(mmucontext_t *context, int virtpage) |
MMU mapping handler. More... | |
Functions | |
void | mmu_use_table (mmucontext_t *context) |
Set the "current" page tables for TLB handling. More... | |
mmucontext_t * | mmu_context_create (int asid) |
Allocate a new MMU context. More... | |
void | mmu_context_destroy (mmucontext_t *context) |
Destroy an MMU context when a process is being destroyed. More... | |
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. More... | |
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. More... | |
void | mmu_switch_context (mmucontext_t *context) |
Switch to the given context. More... | |
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. More... | |
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 mappings. More... | |
int | mmu_copyv (mmucontext_t *context1, iovec_t *iov1, int iovcnt1, mmucontext_t *context2, iovec_t *iov2, int iovcnt2) |
Copy a chunk of data from one process' address space to another process' address space, taking into account page mappings. More... | |
mmu_mapfunc_t | mmu_map_get_callback () |
Get the current mapping function. More... | |
mmu_mapfunc_t | mmu_map_set_callback (mmu_mapfunc_t newfunc) |
Set a new MMU mapping handler. More... | |
int | mmu_init () |
Initialize MMU support. More... | |
void | mmu_shutdown () |
Shutdown MMU support. More... | |
Variables | |
mmucontext_t * | mmu_cxt_current |
"Current" page tables (for TLB exception handling). More... | |
Memory Management Unit and Translation Lookaside Buffer handling.
This file defines the interface to the Memory Management Unit (MMU) in the SH4. The MMU, while not used normally by KOS, is available for virtual memory use, if you so desire. While using this functionality is probably overkill for most homebrew, there are a few very interesting things that this functionality could be used for (like mapping large files into memory that wouldn't otherwise fit).
The whole system is set up as a normal paged memory virtual->physical address translation. KOS implements the page table as a sparse, two-level page table. By default, pages are 4KB in size. Each top-level page table entry has 512 2nd level entries (there are 1024 entries in the top-level entry). This works out to about 2KB of space needed for one top-level entry.
The SH4 itself has 4 TLB entries for instruction fetches, and 64 "unified" TLB entries (for combined instructions + data). Essentially, the UTLB acts both as the TLB for data accesses (from mov instructions) and as a cache for entries for the ITLB. If there is no entry in the ITLB for an instruction access, the UTLB will automatically be searched. If no entry is found still, an ITLB miss exception will be generated. Data accesses are handled similarly to this (although additional complications are involved due to write accesses, and of course the ITLB doesn't play into data accesses).
For more information about how the MMU works, refer to the Hitachi/Renesas SH4 programming manual. It has much more detailed information than what is in here, for obvious reasons.
This functionality was ported over to mainline KOS from the KOS-MMU project of Dan Potter. Unfortunately, KOS-MMU never reached a real phase of maturity and usefulness, but this piece can be quite useful on its own.
#define MMU_PAGES 1024 |
The number of sub-contexts in the main level context.
#define MMU_SUB_PAGES 512 |
The number of pages in a sub-context.
typedef mmupage_t*(* mmu_mapfunc_t)(mmucontext_t *context, int virtpage) |
MMU mapping handler.
This type is used for functions that will take over the mapping for the kernel. In general, there shouldn't be much use for taking this over yourself, unless you want to change the size of the page table entries or something of the like.
context | The context in use. |
virtpage | The virtual page to map. |
typedef struct mmucontext mmucontext_t |
MMU context type.
This type is the top-level context that makes up the page table. There is one of these, with 1024 sub-contexts.
MMU TLB entry for a single page.
The TLB entries on the SH4 are a single 32-bit dword in length. We store some other data here too for ease of use.
typedef struct mmusubcontext mmusubcontext_t |
MMU sub-context type.
We have two-level page tables on SH4, and each sub-context contains 512 entries.
mmucontext_t* mmu_context_create | ( | int | asid | ) |
Allocate a new MMU context.
Each process should have exactly one of these, and these should not exist without a process. Since KOS doesn't actually have a process model of its own, that means you will only ever have one of these, if any.
asid | The address space ID of this process. |
void mmu_context_destroy | ( | mmucontext_t * | context | ) |
Destroy an MMU context when a process is being destroyed.
This function cleans up a MMU context, deallocating any memory its using.
context | The context to clean up after. |
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 mappings.
context | The context to use. |
srcaddr | Source, in the mapped memory space. |
srccnt | The number of bytes to copy. |
buffer | The kernel buffer to copy into (should be in P1). |
int mmu_copyv | ( | mmucontext_t * | context1, |
iovec_t * | iov1, | ||
int | iovcnt1, | ||
mmucontext_t * | context2, | ||
iovec_t * | iov2, | ||
int | iovcnt2 | ||
) |
Copy a chunk of data from one process' address space to another process' address space, taking into account page mappings.
context1 | The source's context. |
iov1 | The scatter/gather array to copy from. |
iovcnt1 | The number of entries in iov1. |
context2 | The destination's context. |
iov2 | The scatter/gather array to copy to. |
iovcnt2 | The number of entries in iov2. |
int mmu_init | ( | ) |
Initialize MMU support.
Unlike most things in KOS, the MMU is not initialized by a normal startup. This is because for most homebrew, its not needed.
0 | On success (no error conditions defined). |
mmu_mapfunc_t mmu_map_get_callback | ( | ) |
Get the current mapping function.
mmu_mapfunc_t mmu_map_set_callback | ( | mmu_mapfunc_t | newfunc | ) |
Set a new MMU mapping handler.
This function will allow you to set a new function to handle mapping for memory pages. There's not much of a reason to do this unless you really do not like the way KOS handles the page mapping internally.
newfunc | The new function to handle mapping. |
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.
This implies turning on the "valid" bit. Also sets the other named attributes as specified.
context | The context to modify. |
virtpage | The first virtual page to map. |
physpage | The first physical page to map. |
count | The number of sequential pages to map. |
prot | Memory protection for page (see MMU protection settings). |
cache | Cache scheme for page (see MMU cacheability settings). |
share | Set to 1 to share between processes (meaningless), otherwise set to 0. |
dirty | Set to 1 to mark the page as dirty, otherwise set to 0. |
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.
context | The context to look in. |
physpage | The physical page number to look for. |
void mmu_shutdown | ( | ) |
Shutdown MMU support.
Turn off the MMU after it was initialized. You should try to make sure this gets done if you initialize the MMU in your program, so as to play nice with loaders and the like (that will not expect that its on, in general).
void mmu_switch_context | ( | mmucontext_t * | context | ) |
Switch to the given context.
This function switches to the given context's address space ID. The context should have already been made current with mmu_use_table(). You are responsible for invalidating any caches as neccessary, as well as invalidating any stale TLB entries.
context | The context to make current. |
void mmu_use_table | ( | mmucontext_t * | context | ) |
Set the "current" page tables for TLB handling.
This function is useful if you're trying to implement a process model or something of the like on top of KOS. Essentially, this allows you to completely boot the MMU context in use out and replace it with another. You will need to call the mmu_switch_context() function afterwards to set the address space id.
context | The context to make current. |
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.
context | The context to look in. |
virtpage | The virtual page number to look for. |
mmucontext_t* mmu_cxt_current |
"Current" page tables (for TLB exception handling).
You should not modify this directly, but rather use the functions provided to do so.