forked from tomsci/lupi
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmmu.h
115 lines (91 loc) · 4.15 KB
/
mmu.h
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
#ifndef MMU_H
#define MMU_H
#include <std.h>
#define PAGE_ROUND(addr) ((addr + KPageSize - 1) & ~(KPageSize-1))
#define KNumPreallocatedUserPages 0
typedef struct PageAllocator PageAllocator;
/**
Sets up initial page tables. These are the minimum needed to switch on the MMU and still
be able to sucessfully execute code. Therefore this function:
* Sets up the kernel PDE
* Makes a section mapping for Section Zero
* Maps in the kernel and abort mode stacks
* Maps in the code segment
* Makes a mapping for the PDE itself (so we can update it)
* Configures `TTBR0` with the address of the kernel PDE
* Configures `TTBCR` with the user/kernel address space split
* Sets `DACR` to something sensible
*/
void mmu_init();
#ifdef ICACHE_IS_STILL_BROKEN
void mmu_setCache(bool icache, bool dcache);
#else
void mmu_enable();
#endif
void mmu_mapSect0Data(uintptr virtualAddress, uintptr physicalAddress, int npages);
/**
Maps 1MB of physically contiguous memory in the top-level PDE at the given
virtual address. Returns the physical address, or zero on error.
*/
uintptr mmu_mapSectionContiguous(PageAllocator* pa, uintptr virtualAddress, uint8 type);
/**
Only currently supports freeing sections created with `mmu_mapSectionContiguous`.
*/
void mmu_unmapSection(PageAllocator* pa, uintptr virtualAddress);
/**
Let 'PTS' be the section where the page table for the new section is going to go.
This function does 3 things.
1. It allocates a physical page to be a page table, and maps this into PTS at `pteAddr`
(using PTS's page table, `ptsPt`) using the page type `ptPageType`.
2. It tells the top-level PDE that `virtualAddress` is a 1MB section defined by the
newly-allocated page table.
3. zeros the new page table so all of the section starts out unmapped
*/
bool mmu_mapSection(PageAllocator* pa, uintptr sectionAddress, uintptr ptAddress, uint32* ptsPt, uint8 ptPageType);
/**
Convenience function to create a new section whose page table is in section zero and is called
`<sectionName>_pt`.
*/
#define mmu_createSection(pa, sectionName) \
mmu_mapSection(pa, sectionName, sectionName ## _pt, (uint32*)KSectionZeroPt, KPageSect0)
/**
Allocates a new physical page with the specified type, and maps it into the section whose page
table is located at `pt`, giving the page the virtual address `virtualAddress`. virtualAddress
really better point into the section given by pt otherwise BAD THINGS will happen.
Returns the physical address of the new page
*/
uintptr mmu_mapPageInSection(PageAllocator* pa, uint32* pt, uintptr virtualAddress, uint8 type);
/**
Map pages into the user process p. Will call [mmu_createUserSection()](#mmu_createUserSection)
if necessary. Note, does _not_ zero the memory. That is caller's responsiblility.
*/
bool mmu_mapPagesInProcess(PageAllocator* pa, Process* p, uintptr virtualAddress, int numPages);
#define mmu_newSharedPage(pa, p, va) mmu_mapPagesInProcess(pa, p, va, -KPageSharedPage)
#define mmu_mapSvcStack(pa, p, va) mmu_mapPagesInProcess(pa, p, va, -KPageThreadSvcStack)
/**
Maps the page at `srcUserAddr` into `dest` *at the same address*.
*/
bool mmu_sharePage(PageAllocator* pa, Process* src, Process* dest, uintptr srcUserAddr);
/**
Pages need not be in same section, although behaviour is
undefined if any of the PTs involved don't actually exist
*/
void mmu_unmapPagesInProcess(PageAllocator* pa, Process* p, uintptr virtualAddress, int numPages);
void mmu_finishedUpdatingPageTables();
/**
Sets TTBR0 and contextId register to the values appropriate for process p.
Also sets `TheSuperPage->currentProcess` to p. Switching to a process means you
can access its memory with a normal pointer dereference, or preferably using
`LDRT` instructions which enforce user access permissions.
Returns the old current process if different to p, or NULL if p is already the
current process. If p is NULL, does nothing. This means you can temporarily
switch to a process by doing:
Process* oldp = switch_process(p);
// Do stuff with p...
switch_process(oldp); // Restores the previous process if necessary
*/
Process* switch_process(Process* p);
int mmu_processInit(Process* p);
void mmu_processExited(PageAllocator* pa, Process* p);
Process* mmu_newProcess(PageAllocator* pa);
#endif