xref: /haiku/src/system/kernel/arch/arm/arch_cpu.cpp (revision 7a74a5df454197933bc6e80a542102362ee98703)
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/cpu.h>
16 #include <boot/kernel_args.h>
17 #include <commpage.h>
18 #include <elf.h>
19 
20 
21 int arch_cpu_type;
22 int arch_fpu_type;
23 int arch_mmu_type;
24 int arch_platform;
25 
26 status_t
27 arch_cpu_preboot_init_percpu(kernel_args *args, int curr_cpu)
28 {
29 	// enable FPU
30 	//ppc:set_msr(get_msr() | MSR_FP_AVAILABLE);
31 
32 	// The current thread must be NULL for all CPUs till we have threads.
33 	// Some boot code relies on this.
34 	arch_thread_set_current_thread(NULL);
35 
36 	return B_OK;
37 }
38 
39 
40 status_t
41 arch_cpu_init_percpu(kernel_args *args, int curr_cpu)
42 {
43 	if (curr_cpu != 0)
44 		panic("No SMP support on ARM yet!\n");
45 
46 	return 0;
47 }
48 
49 
50 status_t
51 arch_cpu_init(kernel_args *args)
52 {
53 	arch_cpu_type = args->arch_args.cpu_type;
54 	arch_fpu_type = args->arch_args.fpu_type;
55 	arch_mmu_type = args->arch_args.mmu_type;
56 	arch_platform = args->arch_args.platform;
57 	arch_platform = args->arch_args.machine;
58 
59 	return B_OK;
60 }
61 
62 
63 status_t
64 arch_cpu_init_post_vm(kernel_args *args)
65 {
66 	return B_OK;
67 }
68 
69 
70 status_t
71 arch_cpu_init_post_modules(kernel_args *args)
72 {
73 	// add the functions to the commpage image
74 	image_id image = get_commpage_image();
75 
76 	return B_OK;
77 }
78 
79 
80 void
81 arch_cpu_idle(void)
82 {
83 	uint32 Rd = 0;
84 	asm volatile("mcr p15, 0, %[c7format], c7, c0, 4" : : [c7format] "r" (Rd) );
85 }
86 
87 
88 status_t
89 arch_cpu_shutdown(bool reboot)
90 {
91 	while(1)
92 		arch_cpu_idle();
93 
94 	// never reached
95 	return B_ERROR;
96 }
97 
98 
99 void
100 arch_cpu_sync_icache(void *address, size_t len)
101 {
102 	uint32 Rd = 0;
103 	asm volatile ("mcr p15, 0, %[c7format], c7, c5, 0"
104 		: : [c7format] "r" (Rd) );
105 }
106 
107 
108 void
109 arch_cpu_memory_read_barrier(void)
110 {
111 	asm volatile ("" : : : "memory");
112 }
113 
114 
115 void
116 arch_cpu_memory_write_barrier(void)
117 {
118 	asm volatile ("" : : : "memory");
119 }
120 
121 
122 void
123 arch_cpu_invalidate_TLB_range(addr_t start, addr_t end)
124 {
125 	int32 num_pages = end / B_PAGE_SIZE - start / B_PAGE_SIZE;
126 	while (num_pages-- >= 0) {
127 		asm volatile ("mcr p15, 0, %[c8format], c8, c6, 1"
128 			: : [c8format] "r" (start) );
129 		start += B_PAGE_SIZE;
130 	}
131 }
132 
133 
134 void
135 arch_cpu_invalidate_TLB_list(addr_t pages[], int num_pages)
136 {
137 	for (int i = 0; i < num_pages; i++) {
138 		asm volatile ("mcr p15, 0, %[c8format], c8, c6, 1":
139 			: [c8format] "r" (pages[i]) );
140 	}
141 }
142 
143 
144 void
145 arch_cpu_global_TLB_invalidate(void)
146 {
147 	uint32 Rd = 0;
148 	asm volatile ("mcr p15, 0, %[c8format], c8, c7, 0"
149 		: : [c8format] "r" (Rd) );
150 }
151 
152 
153 void
154 arch_cpu_user_TLB_invalidate(void)
155 {/*
156 	cpu_ops.flush_insn_pipeline();
157 	cpu_ops.flush_atc_user();
158 	cpu_ops.flush_insn_pipeline();
159 */
160 #warning WRITEME
161 }
162 
163 
164 // TODO: all functions that use fault handlers need to be implemented
165 // in assembly due to problems passing in label addresses in gcc4.
166 status_t
167 arch_cpu_user_memcpy(void *to, const void *from, size_t size,
168 	addr_t *faultHandler)
169 {
170 #warning WRITEME
171 /*
172 	char *tmp = (char *)to;
173 	char *s = (char *)from;
174 	addr_t oldFaultHandler = *faultHandler;
175 
176 	if (m68k_set_fault_handler(faultHandler, (addr_t)&&error))
177 		goto error;
178 
179 	while (size--)
180 		*tmp++ = *s++;
181 
182 	*faultHandler = oldFaultHandler;
183 	return 0;
184 
185 error:
186 	*faultHandler = oldFaultHandler;*/
187 	return B_BAD_ADDRESS;
188 }
189 
190 
191 /**	\brief Copies at most (\a size - 1) characters from the string in \a from to
192  *	the string in \a to, NULL-terminating the result.
193  *
194  *	\param to Pointer to the destination C-string.
195  *	\param from Pointer to the source C-string.
196  *	\param size Size in bytes of the string buffer pointed to by \a to.
197  *
198  *	\return strlen(\a from).
199  */
200 
201 ssize_t
202 arch_cpu_user_strlcpy(char *to, const char *from,
203 	size_t size, addr_t *faultHandler)
204 {
205 #warning WRITEME
206 /*
207 	int from_length = 0;
208 	addr_t oldFaultHandler = *faultHandler;
209 
210 	if (m68k_set_fault_handler(faultHandler, (addr_t)&&error))
211 		goto error;
212 
213 	if (size > 0) {
214 		to[--size] = '\0';
215 		// copy
216 		for ( ; size; size--, from_length++, to++, from++) {
217 			if ((*to = *from) == '\0')
218 				break;
219 		}
220 	}
221 	// count any leftover from chars
222 	while (*from++ != '\0')
223 		from_length++;
224 
225 	*faultHandler = oldFaultHandler;
226 	return from_length;
227 
228 error:
229 	*faultHandler = oldFaultHandler;*/
230 	return B_BAD_ADDRESS;
231 }
232 
233 
234 status_t
235 arch_cpu_user_memset(void *s, char c, size_t count, addr_t *faultHandler)
236 {
237 #warning WRITEME
238 
239 /*
240 	char *xs = (char *)s;
241 	addr_t oldFaultHandler = *faultHandler;
242 
243 	if (m68k_set_fault_handler(faultHandler, (addr_t)&&error))
244 		goto error;
245 
246 	while (count--)
247 		*xs++ = c;
248 
249 	*faultHandler = oldFaultHandler;
250 	return 0;
251 
252 error:
253 	*faultHandler = oldFaultHandler;*/
254 
255 	return B_BAD_ADDRESS;
256 }
257 
258 
259 // The purpose of this function is to trick the compiler. When setting the
260 // page_handler to a label that is obviously (to the compiler) never used,
261 // it may reorganize the control flow, so that the labeled part is optimized
262 // away.
263 // By invoking the function like this
264 //
265 //	if (m68k_set_fault_handler(faultHandler, (addr_t)&&error))
266 //		goto error;
267 //
268 // the compiler has to keep the labeled code, since it can't guess the return
269 // value of this (non-inlinable) function. At least in my tests it worked that
270 // way, and I hope it will continue to work like this in the future.
271 //
272 /*bool
273 m68k_set_fault_handler(addr_t *handlerLocation, addr_t handler)
274 {
275 	*handlerLocation = handler;
276 	return false;
277 }*/
278