xref: /haiku/src/system/kernel/arch/ppc/arch_cpu.cpp (revision 6c678c57c736f4688c9bab047bed3fe00fd27a13)
1 /*
2  * Copyright 2003-2005, Axel Dörfler, axeld@pinc-software.de.
3  * Distributed under the terms of the MIT License.
4  *
5  * Copyright 2001, Travis Geiselbrecht. All rights reserved.
6  * Distributed under the terms of the NewOS License.
7  */
8 
9 
10 #include <KernelExport.h>
11 
12 #include <arch_platform.h>
13 #include <arch_thread.h>
14 #include <arch/cpu.h>
15 #include <boot/kernel_args.h>
16 
17 
18 status_t
19 arch_cpu_preboot_init(kernel_args *args)
20 {
21 	// The current thread must be NULL for all CPUs till we have threads.
22 	// Some boot code relies on this.
23 	arch_thread_set_current_thread(NULL);
24 
25 	return B_OK;
26 }
27 
28 
29 status_t
30 arch_cpu_init(kernel_args *args)
31 {
32 	return B_OK;
33 }
34 
35 
36 status_t
37 arch_cpu_init_post_vm(kernel_args *args)
38 {
39 	return B_OK;
40 }
41 
42 status_t
43 arch_cpu_init_post_modules(kernel_args *args)
44 {
45 	return B_OK;
46 }
47 
48 #define CACHELINE 32
49 
50 void
51 arch_cpu_sync_icache(void *address, size_t len)
52 {
53 	int l, off;
54 	char *p;
55 
56 	off = (unsigned int)address & (CACHELINE - 1);
57 	len += off;
58 
59 	l = len;
60 	p = (char *)address - off;
61 	do {
62 		asm volatile ("dcbst 0,%0" :: "r"(p));
63 		p += CACHELINE;
64 	} while ((l -= CACHELINE) > 0);
65 	asm volatile ("sync");
66 
67 	p = (char *)address - off;
68 	do {
69 		asm volatile ("icbi 0,%0" :: "r"(p));
70 		p += CACHELINE;
71 	} while ((len -= CACHELINE) > 0);
72 	asm volatile ("sync");
73 	isync();
74 }
75 
76 
77 void
78 arch_cpu_invalidate_TLB_range(addr_t start, addr_t end)
79 {
80 	asm volatile("sync");
81 	while (start < end) {
82 		asm volatile("tlbie %0" :: "r" (start));
83 		asm volatile("eieio");
84 		asm volatile("sync");
85 		start += B_PAGE_SIZE;
86 	}
87 	asm volatile("tlbsync");
88 	asm volatile("sync");
89 }
90 
91 
92 void
93 arch_cpu_invalidate_TLB_list(addr_t pages[], int num_pages)
94 {
95 	int i;
96 
97 	asm volatile("sync");
98 	for (i = 0; i < num_pages; i++) {
99 		asm volatile("tlbie %0" :: "r" (pages[i]));
100 		asm volatile("eieio");
101 		asm volatile("sync");
102 	}
103 	asm volatile("tlbsync");
104 	asm volatile("sync");
105 }
106 
107 
108 void
109 arch_cpu_global_TLB_invalidate(void)
110 {
111 	ppc_sync();
112 	tlbia();
113 	ppc_sync();
114 }
115 
116 
117 void
118 arch_cpu_user_TLB_invalidate(void)
119 {
120 	ppc_sync();
121 	tlbia();
122 	ppc_sync();
123 }
124 
125 
126 status_t
127 arch_cpu_user_memcpy(void *to, const void *from, size_t size, addr_t *fault_handler)
128 {
129 	char *tmp = (char *)to;
130 	char *s = (char *)from;
131 
132 	*fault_handler = (addr_t)&&error;
133 
134 	while (size--)
135 		*tmp++ = *s++;
136 
137 	*fault_handler = 0;
138 	return 0;
139 
140 error:
141 	*fault_handler = 0;
142 	return B_BAD_ADDRESS;
143 }
144 
145 
146 /**	\brief Copies at most (\a size - 1) characters from the string in \a from to
147  *	the string in \a to, NULL-terminating the result.
148  *
149  *	\param to Pointer to the destination C-string.
150  *	\param from Pointer to the source C-string.
151  *	\param size Size in bytes of the string buffer pointed to by \a to.
152  *
153  *	\return strlen(\a from).
154  */
155 
156 ssize_t
157 arch_cpu_user_strlcpy(char *to, const char *from, size_t size, addr_t *faultHandler)
158 {
159 	int from_length = 0;
160 
161 	*faultHandler = (addr_t)&&error;
162 
163 	if (size > 0) {
164 		to[--size] = '\0';
165 		// copy
166 		for ( ; size; size--, from_length++, to++, from++) {
167 			if ((*to = *from) == '\0')
168 				break;
169 		}
170 	}
171 	// count any leftover from chars
172 	while (*from++ != '\0')
173 		from_length++;
174 
175 	*faultHandler = 0;
176 	return from_length;
177 
178 error:
179 	*faultHandler = 0;
180 	return B_BAD_ADDRESS;
181 }
182 
183 
184 status_t
185 arch_cpu_user_memset(void *s, char c, size_t count, addr_t *fault_handler)
186 {
187 	char *xs = (char *)s;
188 
189 	*fault_handler = (addr_t)&&error;
190 
191 	while (count--)
192 		*xs++ = c;
193 
194 	*fault_handler = 0;
195 	return 0;
196 
197 error:
198 	*fault_handler = 0;
199 	return B_BAD_ADDRESS;
200 }
201 
202 
203 status_t
204 arch_cpu_shutdown(bool reboot)
205 {
206 	PPCPlatform::Default()->ShutDown(reboot);
207 	return B_ERROR;
208 }
209 
210 
211 void
212 arch_cpu_idle(void)
213 {
214 }
215 
216