xref: /haiku/src/system/kernel/arch/m68k/arch_cpu.cpp (revision 5e7964b0a929555415798dea3373db9ac4611caa)
1 /*
2  * Copyright 2007, François Revol, revol@free.fr.
3  * Distributed under the terms of the MIT License.
4  *
5  * Copyright 2003-2005, Axel Dörfler, axeld@pinc-software.de.
6  * Distributed under the terms of the MIT License.
7  *
8  * Copyright 2001, Travis Geiselbrecht. All rights reserved.
9  * Distributed under the terms of the NewOS License.
10  */
11 
12 
13 #include <KernelExport.h>
14 
15 #include <arch_platform.h>
16 #include <arch_thread.h>
17 #include <arch/cpu.h>
18 #include <boot/kernel_args.h>
19 #include <commpage.h>
20 #include <elf.h>
21 
22 extern struct m68k_cpu_ops cpu_ops_030;
23 extern struct m68k_cpu_ops cpu_ops_040;
24 extern struct m68k_cpu_ops cpu_ops_060;
25 
26 struct m68k_cpu_ops cpu_ops;
27 
28 int arch_cpu_type;
29 int arch_fpu_type;
30 int arch_mmu_type;
31 int arch_platform;
32 
33 status_t
34 arch_cpu_preboot_init_percpu(kernel_args *args, int curr_cpu)
35 {
36 	// enable FPU
37 	//ppc:set_msr(get_msr() | MSR_FP_AVAILABLE);
38 
39 	// The current thread must be NULL for all CPUs till we have threads.
40 	// Some boot code relies on this.
41 	arch_thread_set_current_thread(NULL);
42 
43 	return B_OK;
44 }
45 
46 
47 status_t
48 arch_cpu_init_percpu(kernel_args *args, int curr_cpu)
49 {
50 	//detect_cpu(curr_cpu);
51 
52 	// we only support one anyway...
53 	return 0;
54 }
55 
56 
57 status_t
58 arch_cpu_init(kernel_args *args)
59 {
60 	arch_cpu_type = args->arch_args.cpu_type;
61 	arch_fpu_type = args->arch_args.fpu_type;
62 	arch_mmu_type = args->arch_args.mmu_type;
63 	arch_platform = args->arch_args.platform;
64 	arch_platform = args->arch_args.machine;
65 
66 	switch (arch_cpu_type) {
67 		case 68020:
68 		case 68030:
69 			memcpy(&cpu_ops, &cpu_ops_030, sizeof(cpu_ops));
70 			break;
71 
72 		case 68040:
73 			memcpy(&cpu_ops, &cpu_ops_040, sizeof(cpu_ops));
74 			break;
75 
76 #ifdef SUPPORTS_060
77 		case 68060:
78 			memcpy(&cpu_ops, &cpu_ops_060, sizeof(cpu_ops));
79 			break;
80 #endif
81 		default:
82 			panic("unknown cpu_type %d\n", arch_cpu_type);
83 	}
84 
85 	return B_OK;
86 }
87 
88 
89 status_t
90 arch_cpu_init_post_vm(kernel_args *args)
91 {
92 	return B_OK;
93 }
94 
95 status_t
96 arch_cpu_init_post_modules(kernel_args *args)
97 {
98 	// add the functions to the commpage image
99 	image_id image = get_commpage_image();
100 
101 	return B_OK;
102 }
103 
104 
105 void
106 arch_cpu_sync_icache(void *address, size_t len)
107 {
108 	cpu_ops.flush_icache((addr_t)address, len);
109 }
110 
111 
112 void
113 arch_cpu_memory_read_barrier(void)
114 {
115 	asm volatile ("nop;" : : : "memory");
116 #warning M68k: check arch_cpu_memory_read_barrier (FNOP ?)
117 }
118 
119 
120 void
121 arch_cpu_memory_write_barrier(void)
122 {
123 	asm volatile ("nop;" : : : "memory");
124 #warning M68k: check arch_cpu_memory_write_barrier (FNOP ?)
125 }
126 
127 
128 void
129 arch_cpu_invalidate_TLB_range(addr_t start, addr_t end)
130 {
131 	int32 num_pages = end / B_PAGE_SIZE - start / B_PAGE_SIZE;
132 	cpu_ops.flush_insn_pipeline();
133 	while (num_pages-- >= 0) {
134 		cpu_ops.flush_atc_addr(start);
135 		cpu_ops.flush_insn_pipeline();
136 		start += B_PAGE_SIZE;
137 	}
138 	cpu_ops.flush_insn_pipeline();
139 }
140 
141 
142 void
143 arch_cpu_invalidate_TLB_list(addr_t pages[], int num_pages)
144 {
145 	int i;
146 
147 	cpu_ops.flush_insn_pipeline();
148 	for (i = 0; i < num_pages; i++) {
149 		cpu_ops.flush_atc_addr(pages[i]);
150 		cpu_ops.flush_insn_pipeline();
151 	}
152 	cpu_ops.flush_insn_pipeline();
153 }
154 
155 
156 void
157 arch_cpu_global_TLB_invalidate(void)
158 {
159 	cpu_ops.flush_insn_pipeline();
160 	cpu_ops.flush_atc_all();
161 	cpu_ops.flush_insn_pipeline();
162 }
163 
164 
165 void
166 arch_cpu_user_TLB_invalidate(void)
167 {
168 	cpu_ops.flush_insn_pipeline();
169 	cpu_ops.flush_atc_user();
170 	cpu_ops.flush_insn_pipeline();
171 }
172 
173 
174 status_t
175 arch_cpu_shutdown(bool reboot)
176 {
177 	M68KPlatform::Default()->ShutDown(reboot);
178 	return B_ERROR;
179 }
180 
181 
182 // The purpose of this function is to trick the compiler. When setting the
183 // page_handler to a label that is obviously (to the compiler) never used,
184 // it may reorganize the control flow, so that the labeled part is optimized
185 // away.
186 // By invoking the function like this
187 //
188 //	if (m68k_set_fault_handler(faultHandler, (addr_t)&&error))
189 //		goto error;
190 //
191 // the compiler has to keep the labeled code, since it can't guess the return
192 // value of this (non-inlinable) function. At least in my tests it worked that
193 // way, and I hope it will continue to work like this in the future.
194 //
195 bool
196 m68k_set_fault_handler(addr_t *handlerLocation, addr_t handler)
197 {
198 // TODO: This doesn't work correctly with gcc 4 anymore!
199 	*handlerLocation = handler;
200 	return false;
201 }
202