xref: /haiku/src/system/boot/arch/m68k/mmu_030.cpp (revision 2b76973fa2401f7a5edf68e6470f3d3210cbcff3)
1 /*
2  * Copyright 2004-2007, Axel Dörfler, axeld@pinc-software.de.
3  * Based on code written by Travis Geiselbrecht for NewOS.
4  *
5  * Distributed under the terms of the MIT License.
6  */
7 
8 
9 #include "mmu.h"
10 
11 #include <boot/platform.h>
12 #include <boot/stdio.h>
13 #include <boot/kernel_args.h>
14 #include <boot/stage2.h>
15 #include <arch/cpu.h>
16 #include <arch_kernel.h>
17 #include <kernel.h>
18 
19 #include <OS.h>
20 
21 #include <string.h>
22 
23 #include "arch_030_mmu.h"
24 
25 
26 #define TRACE_MMU
27 #ifdef TRACE_MMU
28 #	define TRACE(x) dprintf x
29 #else
30 #	define TRACE(x) ;
31 #endif
32 
33 
34 extern page_root_entry *gPageRoot;
35 
36 
37 static void
38 initialize(void)
39 {
40 	TRACE(("mmu_030:initialize\n"));
41 }
42 
43 
44 static status_t
45 set_tt(int which, addr_t pa, size_t len, uint32 perms)
46 {
47 	TRACE(("mmu_030:set_tt(%d, 0x%lx, 0x%lx, 0x%08lx)\n", which, pa, len, perms));
48 	uint32 mask;
49 	uint32 ttr = 0;
50 	mask = 0x0000ffff;
51 	if (len) {
52 		len = (len >> 24) & 0x00ff;
53 		while (len >>= 1)
54 			mask <<= 1;
55 		// enable, cachable(?), r/w
56 		// super only
57 		// mc68030 user's manual, page 9-57
58 		ttr = 0x08043;
59 		ttr |= (pa & 0xff000000);
60 		ttr |= (mask & 0x00ff0000);
61 	}
62 	TRACE(("mmu_030:set_tt: 0x%08lx\n", ttr));
63 
64 	/* as seen in linux and BSD code,
65 	 * we need to use .chip pseudo op here as -m68030 doesn't seem to help gas grok it.
66 	 */
67 	switch (which) {
68 		case 0:
69 			asm volatile(  \
70 				".chip 68030\n\t"				\
71 				"pmove %%tt0,(%0)\n\t"				\
72 				".chip 68k\n\t"					\
73 				: : "a"(&ttr));
74 			break;
75 		case 1:
76 			asm volatile(  \
77 				".chip 68030\n\t"				\
78 				"pmove (%0),%%tt1\n"				\
79 				".chip 68k\n\t"					\
80 				: : "a"(&ttr));
81 			break;
82 		default:
83 			return EINVAL;
84 	}
85 	return B_OK;
86 }
87 
88 
89 static status_t
90 load_rp(addr_t pa)
91 {
92 	TRACE(("mmu_030:load_rp(0x%lx)\n", pa));
93 	long_page_directory_entry entry;
94 	*(uint64 *)&entry = DFL_PAGEENT_VAL;
95 	entry.type = DT_ROOT;
96 	entry.addr = TA_TO_PREA(((addr_t)pa));
97 
98 	asm volatile( \
99 		"pmove (%0),%%srp\n" \
100 		"pmove (%0),%%crp\n" \
101 		: : "a"((uint64 *)&entry));
102 	return B_OK;
103 }
104 
105 
106 static status_t
107 allocate_kernel_pgdirs(void)
108 {
109 	page_root_entry *pr = gPageRoot;
110 	page_directory_entry *pd;
111 	addr_t tbl;
112 	int i;
113 
114 	// we'll fill in the 2nd half with ready made page dirs
115 	for (i = NUM_ROOTENT_PER_TBL/2; i < NUM_ROOTENT_PER_TBL; i++) {
116 		if (i % NUM_DIRTBL_PER_PAGE)
117 			tbl += SIZ_DIRTBL;
118 		else
119 			tbl = mmu_get_next_page_tables();
120 		pr[i].addr = TA_TO_PREA(tbl);
121 		pr[i].type = DT_ROOT;
122 		pd = (page_directory_entry *)tbl;
123 		for (int32 j = 0; j < NUM_DIRENT_PER_TBL; j++)
124 			*(page_directory_entry_scalar *)(&pd[j]) = DFL_DIRENT_VAL;
125 	}
126 	return B_OK;
127 }
128 
129 
130 static status_t
131 enable_paging(void)
132 {
133 	TRACE(("mmu_030:enable_paging\n"));
134 	return B_NO_INIT;
135 }
136 
137 
138 const struct boot_mmu_ops k030MMUOps = {
139 	&initialize,
140 	&set_tt,
141 	&load_rp,
142 	&allocate_kernel_pgdirs,
143 	&enable_paging
144 };
145