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