2 Copyright © 1995-2014, The AROS Development Team. All rights reserved.
7 #include <aros/debug.h>
8 #include <exec/types.h>
9 #include <exec/resident.h>
10 #include <proto/exec.h>
11 #include <proto/kernel.h>
12 #include <proto/expansion.h>
13 #include <proto/utility.h>
14 #include <libraries/configvars.h>
15 #include <hardware/cpu/memory.h>
17 #include "exec_intern.h"
24 #define STR(A) _STR(A)
30 static AROS_UFP3 (APTR
, Init
,
31 AROS_UFPA(struct Library
*, lh
, D0
),
32 AROS_UFPA(BPTR
, segList
, A0
),
33 AROS_UFPA(struct ExecBase
*, sysBase
, A6
));
35 static const TEXT name_string
[] = NAME
;
36 static const TEXT version_string
[] =
37 NAME
" " STR(VERSION
) "." STR(REVISION
) "\n";
39 extern void mmu_end(void);
41 const struct Resident rom_tag
=
44 (struct Resident
*)&rom_tag
,
51 (STRPTR
)version_string
,
55 void enable_mmu(void *kb
);
56 void debug_mmu(void *kb
);
57 extern BOOL
init_mmu(void *kb
);
59 extern BYTE _rom_start
;
61 extern BYTE _ext_start
;
64 static void mmuprotect(void *KernelBase
, ULONG addr
, ULONG size
)
66 KrnSetProtection((void*)addr
, size
, MAP_Readable
| MAP_Executable
);
68 static void mmuram(void *KernelBase
, ULONG addr
, ULONG size
)
70 KrnSetProtection((void*)addr
, size
, MAP_Readable
| MAP_Writable
| MAP_Executable
);
72 static void mmuchipram(void *KernelBase
, ULONG addr
, ULONG size
)
74 KrnSetProtection((void*)addr
, size
, MAP_Readable
| MAP_Writable
| MAP_Executable
| MAP_CacheInhibit
);
76 static void mmuio(void *KernelBase
, ULONG addr
, ULONG size
)
78 KrnSetProtection((void*)addr
, size
, MAP_Readable
| MAP_Writable
| MAP_CacheInhibit
);
81 static APTR
AllocPagesAligned(ULONG pages
)
84 ret
= AllocMem((pages
+ 1) * PAGE_SIZE
, MEMF_CLEAR
| MEMF_FAST
| MEMF_REVERSE
);
88 FreeMem(ret
, (pages
+ 1) * PAGE_SIZE
);
89 ret
= AllocAbs((pages
* PAGE_SIZE
+ PAGE_SIZE
- 1) & PAGE_MASK
, (APTR
)((((ULONG
)ret
) + PAGE_SIZE
- 1) & PAGE_MASK
));
94 static void swapvbr(APTR vbr
)
100 "lea newvbr(%%pc),%%a5\n"
107 : : "m" (vbr
) : "d0", "d1", "a5", "a6");
110 static BOOL
ISA3000(void)
112 if (!(SysBase
->AttnFlags
& AFF_68030
))
114 if (SysBase
->AttnFlags
& AFF_68040
)
118 /* We should check for RAMSEY.. Later.. */
119 /* 0x07000000 - 0x07ffffff is A3000-only RAM region */
120 return TypeOfMem((APTR
)0x07ff0000) != 0;
123 static void mmuprotectregion(void *KernelBase
, const UBYTE
*name
, APTR addr
, ULONG size
, ULONG flags
)
125 ULONG allocsize
= (size
+ PAGE_SIZE
- 1) & ~(PAGE_SIZE
- 1);
126 KrnSetProtection(addr
, allocsize
, 0);
127 if (FASTREMAP
&& TypeOfMem(addr
) & MEMF_CHIP
) {
128 APTR newmem
= AllocPagesAligned(allocsize
/ PAGE_SIZE
);
130 CopyMem(addr
, newmem
, size
);
131 D(bug("Remapped %d byte Chip region to Fast, %p - %p -> %p - %p (%s), flags %08x\n",
132 size
, addr
, addr
+ size
- 1, newmem
, newmem
+ size
- 1, name
, flags
));
133 KrnMapGlobal(addr
, newmem
, allocsize
, flags
);
137 D(bug("Protected %d byte region %p - %p (%s) using flags %08x\n", size
, addr
, addr
+ size
- 1, name
, flags
));
138 KrnSetProtection(addr
, allocsize
, flags
);
141 /* MMU protect ArosBootStrap loaded ROM modules */
142 static void mmuprotectextrom(void *KernelBase
)
146 struct BootStruct
*bs
= GetBootStruct(SysBase
);
151 ForeachNode(bs
->mlist
, ml
) {
152 if (ml
->ml_Node
.ln_Type
== NT_KICKMEM
) {
153 for(i
= 0; i
< ml
->ml_NumEntries
; i
++) {
154 mmuprotectregion(KernelBase
, "ROM", ml
->ml_ME
[i
].me_Addr
, ml
->ml_ME
[i
].me_Length
, MAP_Readable
| MAP_Executable
);
160 #define MAX_HEADERS 100
162 static AROS_UFH3 (APTR
, Init
,
163 AROS_UFHA(struct Library
*, lh
, D0
),
164 AROS_UFHA(BPTR
, segList
, A0
),
165 AROS_UFHA(struct ExecBase
*, SysBase
, A6
)
172 struct ConfigDev
*cd
;
175 struct MemHeader
*mh
;
178 BOOL ZeroPageInvalid
= FALSE
, ZeroPageProtect
= FALSE
;
181 ULONG
*zero
= (ULONG
*)0;
183 if (!(SysBase
->AttnFlags
& AFF_68020
))
186 KernelBase
= OpenResource("kernel.resource");
190 /* Parse some arguments from command line */
191 args
= (char *)LibGetTagData(KRN_CmdLine
, 0, KrnGetBootInfo());
193 if (strstr(args
, "nommu")) {
195 } else if (strstr(args
, "debugmmu")) {
197 ZeroPageInvalid
= TRUE
;
198 } else if (strstr(args
, "pmmu")) {
200 ZeroPageProtect
= TRUE
;
201 } else if (strstr(args
, "mmu")) {
206 /* if 68030 A3000 = use MMU, we are guaranteed to have full 68030 */
207 if (!usemmu
&& ISA3000())
210 /* 68030/68851: Only enable if mmu commandline detected. */
211 if (!(SysBase
->AttnFlags
& AFF_68040
) && !usemmu
)
214 if (!init_mmu(KernelBase
)) {
215 D(bug("MMU initialization failed\n"));
219 D(bug("Initializing MMU setup\n"));
223 vbrpage
= AllocPagesAligned(1);
225 /* Move VBR to Fast RAM */
226 CopyMem(zero
, vbrpage
, PAGE_SIZE
);
228 D(bug("VBR %p\n", vbrpage
));
229 if (ZeroPageInvalid
|| ZeroPageProtect
) {
230 /* Corrupt original zero page vectors, makes bad programs crash faster if we don't
231 * want MMU special zero page handling */
232 for (i
= 0; i
< 64; i
++) {
234 zero
[i
] = 0xdeadf00d;
240 memheaders
= AllocVec(sizeof(ULONG
) * 2 * MAX_HEADERS
, MEMF_PUBLIC
);
245 mh
= (struct MemHeader
*)SysBase
->MemList
.lh_Head
;
246 while (mh
->mh_Node
.ln_Succ
&& cnt
< MAX_HEADERS
) {
247 memheaders
[cnt
* 2 + 0] = (ULONG
)mh
->mh_Lower
;
248 memheaders
[cnt
* 2 + 1] = (ULONG
)mh
->mh_Upper
;
250 mh
= (struct MemHeader
*)(mh
->mh_Node
.ln_Succ
);
253 for (i
= 0; i
< cnt
; i
++) {
255 addr
= memheaders
[i
* 2 + 0];
257 size
= memheaders
[i
* 2 + 1] - addr
;
258 size
+= PAGE_SIZE
- 1;
260 tm
= TypeOfMem((void*)(addr
+ 2 * PAGE_SIZE
));
262 mmuchipram(KernelBase
, addr
, size
);
263 else if (tm
& MEMF_FAST
)
264 mmuram(KernelBase
, addr
, size
);
269 mmuram(KernelBase
, 0x00600000, 0x00400000);
270 mmuio(KernelBase
, 0x00a00000, 0x00050000);
273 if (ZeroPageInvalid
) {
274 /* Mark "zero page" invalid, MMU support handles ExecBase fetches transparently.
275 * Special bus error handler checks if access was LONG READ from address 4.
277 KrnSetProtection(0, PAGE_SIZE
, 0);
278 } else if (ZeroPageProtect
) {
279 /* Remap zero page to Fast RAM, faster SysBase access */
280 mmuprotectregion(KernelBase
, "ZeroPage", 0, PAGE_SIZE
, MAP_Readable
);
282 /* No special protection, cacheable */
283 KrnSetProtection(0, PAGE_SIZE
, MAP_Readable
| MAP_Writable
);
285 /* Protect Supervisor stack if MMU debugging mode */
286 mmuprotectregion(KernelBase
, "SS_Stack", SysBase
->SysStkLower
, SysBase
->SysStkUpper
- SysBase
->SysStkLower
,
287 MAP_Readable
| MAP_Writable
| ((ZeroPageInvalid
|| ZeroPageProtect
) ? MAP_Supervisor
: 0));
289 /* Expansion IO devices */
290 ExpansionBase
= TaggedOpenLibrary(TAGGEDOPEN_EXPANSION
);
292 while ((cd
= FindConfigDev(cd
, -1, -1))) {
293 if (cd
->cd_Rom
.er_Type
& ERTF_MEMLIST
)
295 /* Mark all non-RAM (IO) regions as noncacheabled */
296 mmuio(KernelBase
, (ULONG
)cd
->cd_BoardAddr
, cd
->cd_BoardSize
);
298 CloseLibrary(ExpansionBase
);
300 /* Some boards may use this as an IO.. */
301 mmuio(KernelBase
, 0x00f00000, 0x00080000);
303 mmuprotect(KernelBase
, 0x00e00000, 0x00080000);
304 mmuprotect(KernelBase
, 0x00f80000, 0x00080000);
306 mmuprotectextrom(KernelBase
);
308 /* Custom chipset & Clock & Mainboard IO */
309 addr
= (ULONG
)SysBase
->MaxExtMem
;
310 if (addr
< 0x00d80000)
312 mmuio(KernelBase
, addr
, 0x00e00000 - addr
);
314 mmuio(KernelBase
, 0x00bfd000, 0x00001000);
315 mmuio(KernelBase
, 0x00bfe000, 0x00001000);
317 mmuio(KernelBase
, 0x00b80000, 0x00001000);
319 //debug_mmu(KernelBase);
322 enable_mmu(KernelBase
);
331 void mmu_end(void) { };