2 Copyright © 1995-2017, The AROS Development Team. All rights reserved.
7 #include <aros/debug.h>
9 #include <exec/types.h>
10 #include <exec/resident.h>
11 #include <proto/exec.h>
12 #include <proto/kernel.h>
13 #include <proto/expansion.h>
14 #include <proto/utility.h>
15 #include <libraries/configvars.h>
16 #include <hardware/cpu/memory.h>
18 #include "exec_intern.h"
25 #define STR(A) _STR(A)
31 static AROS_UFP3 (APTR
, Init
,
32 AROS_UFPA(struct Library
*, lh
, D0
),
33 AROS_UFPA(BPTR
, segList
, A0
),
34 AROS_UFPA(struct ExecBase
*, sysBase
, A6
));
36 static const TEXT name_string
[] = NAME
;
37 static const TEXT version_string
[] =
38 NAME
" " STR(VERSION
) "." STR(REVISION
) "\n";
40 extern void mmu_end(void);
42 const struct Resident rom_tag
=
45 (struct Resident
*)&rom_tag
,
52 (STRPTR
)version_string
,
56 void enable_mmu(void *kb
);
57 void debug_mmu(void *kb
);
58 extern BOOL
init_mmu(void *kb
);
60 extern BYTE _rom_start
;
62 extern BYTE _ext_start
;
65 static void mmuprotect(void *KernelBase
, ULONG addr
, ULONG size
)
67 KrnSetProtection((void*)addr
, size
, MAP_Readable
| MAP_Executable
);
69 static void mmuram(void *KernelBase
, ULONG addr
, ULONG size
)
71 KrnSetProtection((void*)addr
, size
, MAP_Readable
| MAP_Writable
| MAP_Executable
);
73 static void mmuchipram(void *KernelBase
, ULONG addr
, ULONG size
)
75 KrnSetProtection((void*)addr
, size
, MAP_Readable
| MAP_Writable
| MAP_Executable
| MAP_CacheInhibit
);
77 static void mmuio(void *KernelBase
, ULONG addr
, ULONG size
)
79 KrnSetProtection((void*)addr
, size
, MAP_Readable
| MAP_Writable
| MAP_CacheInhibit
);
82 static APTR
AllocPagesAligned(ULONG pages
)
85 ret
= AllocMem((pages
+ 1) * PAGE_SIZE
, MEMF_CLEAR
| MEMF_FAST
| MEMF_REVERSE
);
89 FreeMem(ret
, (pages
+ 1) * PAGE_SIZE
);
90 ret
= AllocAbs((pages
* PAGE_SIZE
+ PAGE_SIZE
- 1) & PAGE_MASK
, (APTR
)((((ULONG
)ret
) + PAGE_SIZE
- 1) & PAGE_MASK
));
95 static void swapvbr(APTR vbr
)
101 "move.l %%a5,-(%%sp)\n"
102 "lea newvbr(%%pc),%%a5\n"
104 "move.l (%%sp)+,%%a5\n"
110 : : "m" (vbr
) : "d0", "d1", "a5", "a6");
113 static BOOL
ISA3000(void)
115 if (!(SysBase
->AttnFlags
& AFF_68030
))
117 if (SysBase
->AttnFlags
& AFF_68040
)
121 /* We should check for RAMSEY.. Later.. */
122 /* 0x07000000 - 0x07ffffff is A3000-only RAM region */
123 return TypeOfMem((APTR
)0x07ff0000) != 0;
126 static void mmuprotectregion(void *KernelBase
, const UBYTE
*name
, APTR addr
, ULONG size
, ULONG flags
)
128 ULONG allocsize
= (size
+ PAGE_SIZE
- 1) & ~(PAGE_SIZE
- 1);
129 KrnSetProtection(addr
, allocsize
, 0);
130 if (FASTREMAP
&& TypeOfMem(addr
) & MEMF_CHIP
) {
131 APTR newmem
= AllocPagesAligned(allocsize
/ PAGE_SIZE
);
133 CopyMem(addr
, newmem
, size
);
134 D(bug("Remapped %d byte Chip region to Fast, %p - %p -> %p - %p (%s), flags %08x\n",
135 size
, addr
, addr
+ size
- 1, newmem
, newmem
+ size
- 1, name
, flags
));
136 KrnMapGlobal(addr
, newmem
, allocsize
, flags
);
140 D(bug("Protected %d byte region %p - %p (%s) using flags %08x\n", size
, addr
, addr
+ size
- 1, name
, flags
));
141 KrnSetProtection(addr
, allocsize
, flags
);
144 /* MMU protect ArosBootStrap loaded ROM modules */
145 static void mmuprotectextrom(void *KernelBase
)
149 struct BootStruct
*bs
= GetBootStruct(SysBase
);
154 ForeachNode(bs
->mlist
, ml
) {
155 if (ml
->ml_Node
.ln_Type
== NT_KICKMEM
) {
156 for(i
= 0; i
< ml
->ml_NumEntries
; i
++) {
157 // me_Length bit 31 is KICKMEM_ALLOCATED bit
158 mmuprotectregion(KernelBase
, "ROM", ml
->ml_ME
[i
].me_Addr
, ml
->ml_ME
[i
].me_Length
& ~0x80000000, MAP_Readable
| MAP_Executable
);
164 #define MAX_HEADERS 100
166 static AROS_UFH3 (APTR
, Init
,
167 AROS_UFHA(struct Library
*, lh
, D0
),
168 AROS_UFHA(BPTR
, segList
, A0
),
169 AROS_UFHA(struct ExecBase
*, SysBase
, A6
)
176 struct ConfigDev
*cd
;
179 struct MemHeader
*mh
;
182 BOOL ZeroPageInvalid
= FALSE
, ZeroPageProtect
= FALSE
;
185 ULONG
*zero
= (ULONG
*)0;
187 if (!(SysBase
->AttnFlags
& AFF_68020
))
190 KernelBase
= OpenResource("kernel.resource");
194 /* Parse some arguments from command line */
195 args
= (char *)LibGetTagData(KRN_CmdLine
, 0, KrnGetBootInfo());
197 if (strstr(args
, "nommu")) {
199 } else if (strstr(args
, "debugmmu")) {
201 ZeroPageInvalid
= TRUE
;
202 } else if (strstr(args
, "pmmu")) {
204 ZeroPageProtect
= TRUE
;
205 } else if (strstr(args
, "mmu")) {
210 /* if 68030 A3000 = use MMU, we are guaranteed to have full 68030 */
211 if (!usemmu
&& ISA3000())
214 /* 68030/68851: Only enable if mmu commandline detected. */
215 if (!(SysBase
->AttnFlags
& AFF_68040
) && !usemmu
)
218 if (!init_mmu(KernelBase
)) {
219 D(bug("MMU initialization failed\n"));
223 D(bug("Initializing MMU setup\n"));
225 vbrpage
= AllocPagesAligned(1);
227 /* Move VBR to Fast RAM */
228 CopyMem(zero
, vbrpage
, PAGE_SIZE
);
230 D(bug("VBR %p\n", vbrpage
));
231 if (ZeroPageInvalid
|| ZeroPageProtect
) {
232 /* Corrupt original zero page vectors, makes bad programs crash faster if we don't
233 * want MMU special zero page handling */
234 for (i
= 0; i
< 64; i
++) {
236 zero
[i
] = 0xdeadf00d;
242 memheaders
= AllocVec(sizeof(ULONG
) * 2 * MAX_HEADERS
, MEMF_PUBLIC
);
247 mh
= (struct MemHeader
*)SysBase
->MemList
.lh_Head
;
248 while (mh
->mh_Node
.ln_Succ
&& cnt
< MAX_HEADERS
) {
249 memheaders
[cnt
* 2 + 0] = (ULONG
)mh
->mh_Lower
;
250 memheaders
[cnt
* 2 + 1] = (ULONG
)mh
->mh_Upper
;
252 mh
= (struct MemHeader
*)(mh
->mh_Node
.ln_Succ
);
255 for (i
= 0; i
< cnt
; i
++) {
257 addr
= memheaders
[i
* 2 + 0];
259 size
= memheaders
[i
* 2 + 1] - addr
;
260 size
+= PAGE_SIZE
- 1;
262 tm
= TypeOfMem((void*)(addr
+ 2 * PAGE_SIZE
));
264 mmuchipram(KernelBase
, addr
, size
);
265 else if (tm
& MEMF_FAST
)
266 mmuram(KernelBase
, addr
, size
);
271 mmuram(KernelBase
, 0x00600000, 0x00400000);
272 mmuio(KernelBase
, 0x00a00000, 0x00050000);
275 if (ZeroPageInvalid
) {
276 /* Mark "zero page" invalid, MMU support handles ExecBase fetches transparently.
277 * Special bus error handler checks if access was LONG READ from address 4.
279 KrnSetProtection(0, PAGE_SIZE
, 0);
280 } else if (ZeroPageProtect
) {
281 /* Remap zero page to Fast RAM, faster SysBase access */
282 mmuprotectregion(KernelBase
, "ZeroPage", 0, PAGE_SIZE
, MAP_Readable
);
284 /* No special protection, cacheable */
285 KrnSetProtection(0, PAGE_SIZE
, MAP_Readable
| MAP_Writable
);
287 /* Protect Supervisor stack if MMU debugging mode */
288 mmuprotectregion(KernelBase
, "SS_Stack", SysBase
->SysStkLower
, SysBase
->SysStkUpper
- SysBase
->SysStkLower
,
289 MAP_Readable
| MAP_Writable
| ((ZeroPageInvalid
|| ZeroPageProtect
) ? MAP_Supervisor
: 0));
291 /* Expansion IO devices */
292 ExpansionBase
= TaggedOpenLibrary(TAGGEDOPEN_EXPANSION
);
294 while ((cd
= FindConfigDev(cd
, -1, -1))) {
295 if (cd
->cd_Rom
.er_Type
& ERTF_MEMLIST
)
297 /* Mark all non-RAM (IO) regions as noncacheabled */
298 mmuio(KernelBase
, (ULONG
)cd
->cd_BoardAddr
, cd
->cd_BoardSize
);
300 CloseLibrary(ExpansionBase
);
302 /* Some boards may use this as an IO.. */
303 mmuio(KernelBase
, 0x00f00000, 0x00080000);
305 mmuprotect(KernelBase
, 0x00e00000, 0x00080000);
306 mmuprotect(KernelBase
, 0x00f80000, 0x00080000);
308 mmuprotectextrom(KernelBase
);
310 /* Custom chipset & Clock & Mainboard IO */
311 addr
= (ULONG
)SysBase
->MaxExtMem
;
312 if (addr
< 0x00d80000)
314 mmuio(KernelBase
, addr
, 0x00e00000 - addr
);
316 mmuio(KernelBase
, 0x00bfd000, 0x00001000);
317 mmuio(KernelBase
, 0x00bfe000, 0x00001000);
319 mmuio(KernelBase
, 0x00b80000, 0x00001000);
321 //debug_mmu(KernelBase);
324 enable_mmu(KernelBase
);
331 void mmu_end(void) { };