3 #include <aros/debug.h>
4 #include <exec/types.h>
5 #include <exec/resident.h>
6 #include <proto/exec.h>
7 #include <proto/kernel.h>
8 #include <proto/expansion.h>
9 #include <proto/utility.h>
10 #include <libraries/configvars.h>
11 #include <hardware/cpu/memory.h>
13 #include "exec_intern.h"
19 #define STR(A) _STR(A)
25 static AROS_UFP3 (APTR
, Init
,
26 AROS_UFPA(struct Library
*, lh
, D0
),
27 AROS_UFPA(BPTR
, segList
, A0
),
28 AROS_UFPA(struct ExecBase
*, sysBase
, A6
));
30 static const TEXT name_string
[] = NAME
;
31 static const TEXT version_string
[] =
32 NAME
" " STR(VERSION
) "." STR(REVISION
) "\n";
34 extern void mmu_end(void);
36 const struct Resident rom_tag
=
39 (struct Resident
*)&rom_tag
,
46 (STRPTR
)version_string
,
50 void enable_mmu(void *kb
);
51 void debug_mmu(void *kb
);
52 extern BOOL
init_mmu(void *kb
);
54 extern BYTE _rom_start
;
56 extern BYTE _ext_start
;
59 static void mmuprotect(void *KernelBase
, ULONG addr
, ULONG size
)
61 KrnSetProtection((void*)addr
, size
, MAP_Readable
| MAP_Executable
);
63 static void mmuram(void *KernelBase
, ULONG addr
, ULONG size
)
65 KrnSetProtection((void*)addr
, size
, MAP_Readable
| MAP_Writable
| MAP_Executable
);
67 static void mmuchipram(void *KernelBase
, ULONG addr
, ULONG size
)
69 KrnSetProtection((void*)addr
, size
, MAP_Readable
| MAP_Writable
| MAP_Executable
| MAP_CacheInhibit
);
71 static void mmuio(void *KernelBase
, ULONG addr
, ULONG size
)
73 KrnSetProtection((void*)addr
, size
, MAP_Readable
| MAP_Writable
| MAP_CacheInhibit
);
76 static APTR
AllocPagesAligned(ULONG pages
)
79 ret
= AllocMem((pages
+ 1) * PAGE_SIZE
, MEMF_CLEAR
| MEMF_FAST
| MEMF_REVERSE
);
83 FreeMem(ret
, (pages
+ 1) * PAGE_SIZE
);
84 ret
= AllocAbs((pages
* PAGE_SIZE
+ PAGE_SIZE
- 1) & PAGE_MASK
, (APTR
)((((ULONG
)ret
) + PAGE_SIZE
- 1) & PAGE_MASK
));
89 static void swapvbr(APTR vbr
)
95 "lea newvbr(%%pc),%%a5\n"
102 : : "m" (vbr
) : "d0", "d1", "a5", "a6");
105 static BOOL
ISA3000(void)
107 if (!(SysBase
->AttnFlags
& AFF_68030
))
109 if (SysBase
->AttnFlags
& AFF_68040
)
113 /* We should check for RAMSEY.. Later.. */
114 /* 0x07000000 - 0x07ffffff is A3000-only RAM region */
115 return TypeOfMem((APTR
)0x07ff0000) != 0;
118 static void mmuprotectregion(void *KernelBase
, const UBYTE
*name
, APTR addr
, ULONG size
, ULONG flags
)
120 ULONG allocsize
= (size
+ PAGE_SIZE
- 1) & ~(PAGE_SIZE
- 1);
121 KrnSetProtection(addr
, allocsize
, 0);
122 if (FASTREMAP
&& TypeOfMem(addr
) & MEMF_CHIP
) {
123 APTR newmem
= AllocPagesAligned(allocsize
/ PAGE_SIZE
);
125 CopyMem(addr
, newmem
, size
);
126 D(bug("Remapped %d byte Chip region to Fast, %p - %p -> %p - %p (%s), flags %08x\n",
127 size
, addr
, addr
+ size
- 1, newmem
, newmem
+ size
- 1, name
, flags
));
128 KrnMapGlobal(addr
, newmem
, allocsize
, flags
);
132 D(bug("Protected %d byte region %p - %p (%s) using flags %08x\n", size
, addr
, addr
+ size
- 1, name
, flags
));
133 KrnSetProtection(addr
, allocsize
, flags
);
136 /* MMU protect ArosBootStrap loaded ROM modules */
137 static void mmuprotectextrom(void *KernelBase
)
139 struct MemList
*mlist
= (struct MemList
*)PrivExecBase(SysBase
)->PlatformData
.ep_KickMemPtr
;
143 for (i
= 0; i
< mlist
->ml_NumEntries
; i
++) {
144 IPTR
*list
= SysBase
->ResModules
;
145 while (list
&& *list
)
148 struct Resident
*res
;
149 if (*list
& RESLIST_NEXT
) {
150 list
= (IPTR
*)(*list
& ~RESLIST_NEXT
);
154 res
= (struct Resident
*)ptr
;
155 if (res
->rt_Flags
& (1 << 5)) {
156 if (ptr
>= mlist
->ml_ME
[i
].me_Addr
&& ptr
< mlist
->ml_ME
[i
].me_Addr
+ mlist
->ml_ME
[i
].me_Length
) {
157 mmuprotectregion(KernelBase
, "ROM", mlist
->ml_ME
[i
].me_Addr
, mlist
->ml_ME
[i
].me_Length
, MAP_Readable
| MAP_Executable
);
163 mlist
= (struct MemList
*)mlist
->ml_Node
.ln_Succ
;
167 #define MAX_HEADERS 100
169 static AROS_UFH3 (APTR
, Init
,
170 AROS_UFHA(struct Library
*, lh
, D0
),
171 AROS_UFHA(BPTR
, segList
, A0
),
172 AROS_UFHA(struct ExecBase
*, SysBase
, A6
)
179 struct ConfigDev
*cd
;
182 struct MemHeader
*mh
;
185 BOOL ZeroPageInvalid
= FALSE
, ZeroPageProtect
= FALSE
;
188 ULONG
*zero
= (ULONG
*)0;
190 if (!(SysBase
->AttnFlags
& AFF_68020
))
193 KernelBase
= OpenResource("kernel.resource");
197 /* Parse some arguments from command line */
198 args
= (char *)LibGetTagData(KRN_CmdLine
, 0, KrnGetBootInfo());
200 if (strstr(args
, "nommu")) {
202 } else if (strstr(args
, "debugmmu")) {
204 ZeroPageInvalid
= TRUE
;
205 } else if (strstr(args
, "pmmu")) {
207 ZeroPageProtect
= TRUE
;
208 } else if (strstr(args
, "mmu")) {
213 /* if 68030 A3000 = use MMU, we are guaranteed to have full 68030 */
214 if (!usemmu
&& ISA3000())
217 /* 68030/68851: Only enable if mmu commandline detected. */
218 if (!(SysBase
->AttnFlags
& AFF_68040
) && !usemmu
)
221 if (!init_mmu(KernelBase
)) {
222 D(bug("MMU initialization failed\n"));
226 D(bug("Initializing MMU setup\n"));
230 vbrpage
= AllocPagesAligned(1);
232 /* Move VBR to Fast RAM */
233 CopyMem(zero
, vbrpage
, PAGE_SIZE
);
235 D(bug("VBR %p\n", vbrpage
));
236 if (ZeroPageInvalid
|| ZeroPageProtect
) {
237 /* Corrupt original zero page vectors, makes bad programs crash faster if we don't
238 * want MMU special zero page handling */
239 for (i
= 0; i
< 64; i
++) {
241 zero
[i
] = 0xdeadf00d;
247 memheaders
= AllocVec(sizeof(ULONG
) * 2 * MAX_HEADERS
, MEMF_PUBLIC
);
252 mh
= (struct MemHeader
*)SysBase
->MemList
.lh_Head
;
253 while (mh
->mh_Node
.ln_Succ
&& cnt
< MAX_HEADERS
) {
254 memheaders
[cnt
* 2 + 0] = (ULONG
)mh
->mh_Lower
;
255 memheaders
[cnt
* 2 + 1] = (ULONG
)mh
->mh_Upper
;
257 mh
= (struct MemHeader
*)(mh
->mh_Node
.ln_Succ
);
260 for (i
= 0; i
< cnt
; i
++) {
262 addr
= memheaders
[i
* 2 + 0];
264 size
= memheaders
[i
* 2 + 1] - addr
;
265 size
+= PAGE_SIZE
- 1;
267 tm
= TypeOfMem((void*)(addr
+ 2 * PAGE_SIZE
));
269 mmuchipram(KernelBase
, addr
, size
);
270 else if (tm
& MEMF_FAST
)
271 mmuram(KernelBase
, addr
, size
);
276 mmuram(KernelBase
, 0x00600000, 0x00400000);
277 mmuio(KernelBase
, 0x00a00000, 0x00050000);
280 if (ZeroPageInvalid
) {
281 /* Mark "zero page" invalid, MMU support handles ExecBase fetches transparently.
282 * Special bus error handler checks if access was LONG READ from address 4.
284 KrnSetProtection(0, PAGE_SIZE
, 0);
285 } else if (ZeroPageProtect
) {
286 /* Remap zero page to Fast RAM, faster SysBase access */
287 mmuprotectregion(KernelBase
, "ZeroPage", 0, PAGE_SIZE
, MAP_Readable
);
289 /* No special protection, cacheable */
290 KrnSetProtection(0, PAGE_SIZE
, MAP_Readable
| MAP_Writable
);
292 /* Protect Supervisor stack if MMU debugging mode */
293 mmuprotectregion(KernelBase
, "SS_Stack", SysBase
->SysStkLower
, SysBase
->SysStkUpper
- SysBase
->SysStkLower
,
294 MAP_Readable
| MAP_Writable
| ((ZeroPageInvalid
|| ZeroPageProtect
) ? MAP_Supervisor
: 0));
296 /* Expansion IO devices */
297 ExpansionBase
= TaggedOpenLibrary(TAGGEDOPEN_EXPANSION
);
299 while ((cd
= FindConfigDev(cd
, -1, -1))) {
300 if (cd
->cd_Rom
.er_Type
& ERTF_MEMLIST
)
302 /* Mark all non-RAM (IO) regions as noncacheabled */
303 mmuio(KernelBase
, (ULONG
)cd
->cd_BoardAddr
, cd
->cd_BoardSize
);
305 CloseLibrary(ExpansionBase
);
307 /* Some boards may use this as an IO.. */
308 mmuio(KernelBase
, 0x00f00000, 0x00080000);
310 mmuprotect(KernelBase
, 0x00e00000, 0x00080000);
311 mmuprotect(KernelBase
, 0x00f80000, 0x00080000);
313 mmuprotectextrom(KernelBase
);
315 /* Custom chipset & Clock & Mainboard IO */
316 addr
= (ULONG
)SysBase
->MaxExtMem
;
317 if (addr
< 0x00d80000)
319 mmuio(KernelBase
, addr
, 0x00e00000 - addr
);
321 mmuio(KernelBase
, 0x00bfd000, 0x00001000);
322 mmuio(KernelBase
, 0x00bfe000, 0x00001000);
324 mmuio(KernelBase
, 0x00b80000, 0x00001000);
326 //debug_mmu(KernelBase);
329 enable_mmu(KernelBase
);
338 void mmu_end(void) { };