machdep.c revision 265996
1285242Sachim/*-
2285242Sachim * Copyright (C) 1995, 1996 Wolfgang Solfrank.
3285242Sachim * Copyright (C) 1995, 1996 TooLs GmbH.
4285242Sachim * All rights reserved.
5285242Sachim *
6285242Sachim * Redistribution and use in source and binary forms, with or without
7285242Sachim * modification, are permitted provided that the following conditions
8285242Sachim * are met:
9285242Sachim * 1. Redistributions of source code must retain the above copyright
10285242Sachim *    notice, this list of conditions and the following disclaimer.
11285242Sachim * 2. Redistributions in binary form must reproduce the above copyright
12285242Sachim *    notice, this list of conditions and the following disclaimer in the
13285242Sachim *    documentation and/or other materials provided with the distribution.
14285242Sachim * 3. All advertising materials mentioning features or use of this software
15285242Sachim *    must display the following acknowledgement:
16285242Sachim *      This product includes software developed by TooLs GmbH.
17285242Sachim * 4. The name of TooLs GmbH may not be used to endorse or promote products
18285242Sachim *    derived from this software without specific prior written permission.
19285242Sachim *
20285242Sachim * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
21285242Sachim * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22285242Sachim * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23285242Sachim * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24285242Sachim * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25285242Sachim * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
26285242Sachim * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27285242Sachim * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
28285242Sachim * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
29285242Sachim * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30285242Sachim */
31285242Sachim/*-
32285242Sachim * Copyright (C) 2001 Benno Rice
33285242Sachim * All rights reserved.
34285242Sachim *
35285242Sachim * Redistribution and use in source and binary forms, with or without
36285242Sachim * modification, are permitted provided that the following conditions
37285242Sachim * are met:
38285242Sachim * 1. Redistributions of source code must retain the above copyright
39285242Sachim *    notice, this list of conditions and the following disclaimer.
40285242Sachim * 2. Redistributions in binary form must reproduce the above copyright
41285242Sachim *    notice, this list of conditions and the following disclaimer in the
42285242Sachim *    documentation and/or other materials provided with the distribution.
43285242Sachim *
44285242Sachim * THIS SOFTWARE IS PROVIDED BY Benno Rice ``AS IS'' AND ANY EXPRESS OR
45285242Sachim * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
46285242Sachim * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
47285242Sachim * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
48285242Sachim * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
49285242Sachim * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
50285242Sachim * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
51285242Sachim * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
52285242Sachim * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
53285242Sachim * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
54285242Sachim *	$NetBSD: machdep.c,v 1.74.2.1 2000/11/01 16:13:48 tv Exp $
55285242Sachim */
56285242Sachim
57285242Sachim#include <sys/cdefs.h>
58285242Sachim__FBSDID("$FreeBSD: stable/10/sys/powerpc/aim/machdep.c 265996 2014-05-14 00:51:26Z ian $");
59285242Sachim
60285242Sachim#include "opt_compat.h"
61285242Sachim#include "opt_ddb.h"
62285242Sachim#include "opt_kstack_pages.h"
63285242Sachim#include "opt_platform.h"
64285242Sachim
65285242Sachim#include <sys/param.h>
66285242Sachim#include <sys/proc.h>
67285242Sachim#include <sys/systm.h>
68285242Sachim#include <sys/bio.h>
69285242Sachim#include <sys/buf.h>
70285242Sachim#include <sys/bus.h>
71285242Sachim#include <sys/cons.h>
72285242Sachim#include <sys/cpu.h>
73285242Sachim#include <sys/eventhandler.h>
74285242Sachim#include <sys/exec.h>
75285242Sachim#include <sys/imgact.h>
76285242Sachim#include <sys/kdb.h>
77285242Sachim#include <sys/kernel.h>
78285242Sachim#include <sys/ktr.h>
79285242Sachim#include <sys/linker.h>
80285242Sachim#include <sys/lock.h>
81285242Sachim#include <sys/malloc.h>
82285242Sachim#include <sys/mbuf.h>
83285242Sachim#include <sys/msgbuf.h>
84285242Sachim#include <sys/mutex.h>
85285242Sachim#include <sys/ptrace.h>
86285242Sachim#include <sys/reboot.h>
87285242Sachim#include <sys/rwlock.h>
88285242Sachim#include <sys/signalvar.h>
89285242Sachim#include <sys/syscallsubr.h>
90285242Sachim#include <sys/sysctl.h>
91285242Sachim#include <sys/sysent.h>
92285242Sachim#include <sys/sysproto.h>
93285242Sachim#include <sys/ucontext.h>
94285242Sachim#include <sys/uio.h>
95285242Sachim#include <sys/vmmeter.h>
96285242Sachim#include <sys/vnode.h>
97285242Sachim
98285242Sachim#include <net/netisr.h>
99285242Sachim
100285242Sachim#include <vm/vm.h>
101285242Sachim#include <vm/vm_extern.h>
102285242Sachim#include <vm/vm_kern.h>
103285242Sachim#include <vm/vm_page.h>
104285242Sachim#include <vm/vm_map.h>
105285242Sachim#include <vm/vm_object.h>
106285242Sachim#include <vm/vm_pager.h>
107285242Sachim
108285242Sachim#include <machine/altivec.h>
109285242Sachim#ifndef __powerpc64__
110285242Sachim#include <machine/bat.h>
111285242Sachim#endif
112285242Sachim#include <machine/cpu.h>
113285242Sachim#include <machine/elf.h>
114285242Sachim#include <machine/fpu.h>
115285242Sachim#include <machine/hid.h>
116285242Sachim#include <machine/kdb.h>
117285242Sachim#include <machine/md_var.h>
118285242Sachim#include <machine/metadata.h>
119285242Sachim#include <machine/mmuvar.h>
120285242Sachim#include <machine/pcb.h>
121285242Sachim#include <machine/reg.h>
122285242Sachim#include <machine/sigframe.h>
123285242Sachim#include <machine/spr.h>
124285242Sachim#include <machine/trap.h>
125285242Sachim#include <machine/vmparam.h>
126285242Sachim#include <machine/ofw_machdep.h>
127285242Sachim
128285242Sachim#include <ddb/ddb.h>
129285242Sachim
130285242Sachim#include <dev/ofw/openfirm.h>
131285242Sachim
132285242Sachim#ifdef DDB
133285242Sachimextern vm_offset_t ksym_start, ksym_end;
134285242Sachim#endif
135285242Sachim
136285242Sachimint cold = 1;
137285242Sachim#ifdef __powerpc64__
138285242Sachimextern int n_slbs;
139285242Sachimint cacheline_size = 128;
140285242Sachim#else
141285242Sachimint cacheline_size = 32;
142285242Sachim#endif
143285242Sachimint hw_direct_map = 1;
144285242Sachim
145285242Sachimextern void *ap_pcpu;
146285242Sachim
147285242Sachimstruct pcpu __pcpu[MAXCPU];
148285242Sachim
149285242Sachimstatic struct trapframe frame0;
150285242Sachim
151285242Sachimchar		machine[] = "powerpc";
152285242SachimSYSCTL_STRING(_hw, HW_MACHINE, machine, CTLFLAG_RD, machine, 0, "");
153285242Sachim
154285242Sachimstatic void	cpu_startup(void *);
155285242SachimSYSINIT(cpu, SI_SUB_CPU, SI_ORDER_FIRST, cpu_startup, NULL);
156285242Sachim
157285242SachimSYSCTL_INT(_machdep, CPU_CACHELINE, cacheline_size,
158285242Sachim	   CTLFLAG_RD, &cacheline_size, 0, "");
159285242Sachim
160285242Sachimuintptr_t	powerpc_init(vm_offset_t, vm_offset_t, vm_offset_t, void *);
161285242Sachim
162285242Sachimint             setfault(faultbuf);             /* defined in locore.S */
163285242Sachim
164285242Sachimlong		Maxmem = 0;
165285242Sachimlong		realmem = 0;
166285242Sachim
167285242Sachim#ifndef __powerpc64__
168285242Sachimstruct bat	battable[16];
169285242Sachim#endif
170285242Sachim
171285242Sachimstruct kva_md_info kmi;
172285242Sachim
173285242Sachimstatic void
174285242Sachimcpu_startup(void *dummy)
175285242Sachim{
176285242Sachim
177285242Sachim	/*
178285242Sachim	 * Initialise the decrementer-based clock.
179285242Sachim	 */
180285242Sachim	decr_init();
181285242Sachim
182285242Sachim	/*
183285242Sachim	 * Good {morning,afternoon,evening,night}.
184285242Sachim	 */
185285242Sachim	cpu_setup(PCPU_GET(cpuid));
186285242Sachim
187285242Sachim#ifdef PERFMON
188285242Sachim	perfmon_init();
189285242Sachim#endif
190285242Sachim	printf("real memory  = %ld (%ld MB)\n", ptoa(physmem),
191285242Sachim	    ptoa(physmem) / 1048576);
192285242Sachim	realmem = physmem;
193285242Sachim
194285242Sachim	if (bootverbose)
195285242Sachim		printf("available KVA = %zd (%zd MB)\n",
196285242Sachim		    virtual_end - virtual_avail,
197285242Sachim		    (virtual_end - virtual_avail) / 1048576);
198285242Sachim
199285242Sachim	/*
200285242Sachim	 * Display any holes after the first chunk of extended memory.
201285242Sachim	 */
202285242Sachim	if (bootverbose) {
203285242Sachim		int indx;
204285242Sachim
205285242Sachim		printf("Physical memory chunk(s):\n");
206285242Sachim		for (indx = 0; phys_avail[indx + 1] != 0; indx += 2) {
207285242Sachim			vm_offset_t size1 =
208285242Sachim			    phys_avail[indx + 1] - phys_avail[indx];
209285242Sachim
210285242Sachim			#ifdef __powerpc64__
211285242Sachim			printf("0x%016lx - 0x%016lx, %ld bytes (%ld pages)\n",
212285242Sachim			#else
213285242Sachim			printf("0x%08x - 0x%08x, %d bytes (%ld pages)\n",
214285242Sachim			#endif
215285242Sachim			    phys_avail[indx], phys_avail[indx + 1] - 1, size1,
216285242Sachim			    size1 / PAGE_SIZE);
217285242Sachim		}
218285242Sachim	}
219285242Sachim
220285242Sachim	vm_ksubmap_init(&kmi);
221285242Sachim
222285242Sachim	printf("avail memory = %ld (%ld MB)\n", ptoa(cnt.v_free_count),
223285242Sachim	    ptoa(cnt.v_free_count) / 1048576);
224285242Sachim
225285242Sachim	/*
226285242Sachim	 * Set up buffers, so they can be used to read disk labels.
227285242Sachim	 */
228285242Sachim	bufinit();
229285242Sachim	vm_pager_bufferinit();
230285242Sachim}
231285242Sachim
232285242Sachimextern char	kernel_text[], _end[];
233285242Sachim
234285242Sachim#ifndef __powerpc64__
235285242Sachim/* Bits for running on 64-bit systems in 32-bit mode. */
236285242Sachimextern void	*testppc64, *testppc64size;
237285242Sachimextern void	*restorebridge, *restorebridgesize;
238285242Sachimextern void	*rfid_patch, *rfi_patch1, *rfi_patch2;
239285242Sachimextern void	*trapcode64;
240285242Sachim#endif
241285242Sachim
242285242Sachimextern void	*rstcode, *rstsize;
243285242Sachimextern void	*trapcode, *trapsize;
244285242Sachimextern void	*slbtrap, *slbtrapsize;
245285242Sachimextern void	*alitrap, *alisize;
246285242Sachimextern void	*dsitrap, *dsisize;
247285242Sachimextern void	*decrint, *decrsize;
248285242Sachimextern void     *extint, *extsize;
249285242Sachimextern void	*dblow, *dbsize;
250285242Sachimextern void	*imisstrap, *imisssize;
251285242Sachimextern void	*dlmisstrap, *dlmisssize;
252285242Sachimextern void	*dsmisstrap, *dsmisssize;
253285242Sachimchar 		save_trap_init[0x2f00];		/* EXC_LAST */
254285242Sachim
255285242Sachimuintptr_t
256285242Sachimpowerpc_init(vm_offset_t startkernel, vm_offset_t endkernel,
257285242Sachim    vm_offset_t basekernel, void *mdp)
258285242Sachim{
259285242Sachim	struct		pcpu *pc;
260285242Sachim	void		*generictrap;
261285242Sachim	size_t		trap_offset;
262285242Sachim	void		*kmdp;
263285242Sachim        char		*env;
264285242Sachim	register_t	msr, scratch;
265285242Sachim#ifdef WII
266285242Sachim	register_t 	vers;
267285242Sachim#endif
268285242Sachim	uint8_t		*cache_check;
269285242Sachim	int		cacheline_warn;
270285242Sachim	#ifndef __powerpc64__
271285242Sachim	int		ppc64;
272285242Sachim	#endif
273285242Sachim
274285242Sachim	kmdp = NULL;
275285242Sachim	trap_offset = 0;
276285242Sachim	cacheline_warn = 0;
277285242Sachim
278285242Sachim	/* Save trap vectors. */
279285242Sachim	ofw_save_trap_vec(save_trap_init);
280285242Sachim
281285242Sachim#ifdef WII
282285242Sachim	/*
283285242Sachim	 * The Wii loader doesn't pass us any environment so, mdp
284285242Sachim	 * points to garbage at this point. The Wii CPU is a 750CL.
285285242Sachim	 */
286285242Sachim	vers = mfpvr();
287285242Sachim	if ((vers & 0xfffff0e0) == (MPC750 << 16 | MPC750CL))
288285242Sachim		mdp = NULL;
289285242Sachim#endif
290285242Sachim
291285242Sachim	/*
292285242Sachim	 * Parse metadata if present and fetch parameters.  Must be done
293285242Sachim	 * before console is inited so cninit gets the right value of
294285242Sachim	 * boothowto.
295285242Sachim	 */
296285242Sachim	if (mdp != NULL) {
297285242Sachim		preload_metadata = mdp;
298285242Sachim		kmdp = preload_search_by_type("elf kernel");
299285242Sachim		if (kmdp != NULL) {
300285242Sachim			boothowto = MD_FETCH(kmdp, MODINFOMD_HOWTO, int);
301285242Sachim			kern_envp = MD_FETCH(kmdp, MODINFOMD_ENVP, char *);
302285242Sachim			endkernel = ulmax(endkernel, MD_FETCH(kmdp,
303285242Sachim			    MODINFOMD_KERNEND, vm_offset_t));
304285242Sachim#ifdef DDB
305285242Sachim			ksym_start = MD_FETCH(kmdp, MODINFOMD_SSYM, uintptr_t);
306285242Sachim			ksym_end = MD_FETCH(kmdp, MODINFOMD_ESYM, uintptr_t);
307285242Sachim#endif
308285242Sachim		}
309285242Sachim	}
310285242Sachim
311285242Sachim	/*
312285242Sachim	 * Init params/tunables that can be overridden by the loader
313285242Sachim	 */
314285242Sachim	init_param1();
315285242Sachim
316285242Sachim	/*
317285242Sachim	 * Start initializing proc0 and thread0.
318285242Sachim	 */
319285242Sachim	proc_linkup0(&proc0, &thread0);
320285242Sachim	thread0.td_frame = &frame0;
321285242Sachim
322285242Sachim	/*
323285242Sachim	 * Set up per-cpu data.
324285242Sachim	 */
325285242Sachim	pc = __pcpu;
326285242Sachim	pcpu_init(pc, 0, sizeof(struct pcpu));
327285242Sachim	pc->pc_curthread = &thread0;
328285242Sachim#ifdef __powerpc64__
329285242Sachim	__asm __volatile("mr 13,%0" :: "r"(pc->pc_curthread));
330285242Sachim#else
331285242Sachim	__asm __volatile("mr 2,%0" :: "r"(pc->pc_curthread));
332285242Sachim#endif
333285242Sachim	pc->pc_cpuid = 0;
334285242Sachim
335285242Sachim	__asm __volatile("mtsprg 0, %0" :: "r"(pc));
336285242Sachim
337285242Sachim	/*
338285242Sachim	 * Init mutexes, which we use heavily in PMAP
339285242Sachim	 */
340285242Sachim
341285242Sachim	mutex_init();
342285242Sachim
343285242Sachim	/*
344285242Sachim	 * Install the OF client interface
345285242Sachim	 */
346285242Sachim
347285242Sachim	OF_bootstrap();
348285242Sachim
349285242Sachim	/*
350285242Sachim	 * Initialize the console before printing anything.
351285242Sachim	 */
352285242Sachim	cninit();
353285242Sachim
354285242Sachim	/*
355285242Sachim	 * Complain if there is no metadata.
356285242Sachim	 */
357285242Sachim	if (mdp == NULL || kmdp == NULL) {
358285242Sachim		printf("powerpc_init: no loader metadata.\n");
359285242Sachim	}
360285242Sachim
361285242Sachim	/*
362285242Sachim	 * Init KDB
363285242Sachim	 */
364285242Sachim
365285242Sachim	kdb_init();
366285242Sachim
367285242Sachim	/* Various very early CPU fix ups */
368285242Sachim	switch (mfpvr() >> 16) {
369285242Sachim		/*
370285242Sachim		 * PowerPC 970 CPUs have a misfeature requested by Apple that
371285242Sachim		 * makes them pretend they have a 32-byte cacheline. Turn this
372285242Sachim		 * off before we measure the cacheline size.
373285242Sachim		 */
374285242Sachim		case IBM970:
375285242Sachim		case IBM970FX:
376285242Sachim		case IBM970MP:
377285242Sachim		case IBM970GX:
378285242Sachim			scratch = mfspr(SPR_HID5);
379285242Sachim			scratch &= ~HID5_970_DCBZ_SIZE_HI;
380285242Sachim			mtspr(SPR_HID5, scratch);
381285242Sachim			break;
382285242Sachim	#ifdef __powerpc64__
383285242Sachim		case IBMPOWER7:
384285242Sachim			/* XXX: get from ibm,slb-size in device tree */
385285242Sachim			n_slbs = 32;
386285242Sachim			break;
387285242Sachim	#endif
388285242Sachim	}
389285242Sachim
390285242Sachim	/*
391285242Sachim	 * Initialize the interrupt tables and figure out our cache line
392285242Sachim	 * size and whether or not we need the 64-bit bridge code.
393285242Sachim	 */
394285242Sachim
395285242Sachim	/*
396285242Sachim	 * Disable translation in case the vector area hasn't been
397285242Sachim	 * mapped (G5). Note that no OFW calls can be made until
398285242Sachim	 * translation is re-enabled.
399285242Sachim	 */
400285242Sachim
401285242Sachim	msr = mfmsr();
402285242Sachim	mtmsr((msr & ~(PSL_IR | PSL_DR)) | PSL_RI);
403285242Sachim
404285242Sachim	/*
405285242Sachim	 * Measure the cacheline size using dcbz
406285242Sachim	 *
407285242Sachim	 * Use EXC_PGM as a playground. We are about to overwrite it
408285242Sachim	 * anyway, we know it exists, and we know it is cache-aligned.
409285242Sachim	 */
410285242Sachim
411285242Sachim	cache_check = (void *)EXC_PGM;
412285242Sachim
413285242Sachim	for (cacheline_size = 0; cacheline_size < 0x100; cacheline_size++)
414285242Sachim		cache_check[cacheline_size] = 0xff;
415285242Sachim
416285242Sachim	__asm __volatile("dcbz 0,%0":: "r" (cache_check) : "memory");
417285242Sachim
418285242Sachim	/* Find the first byte dcbz did not zero to get the cache line size */
419285242Sachim	for (cacheline_size = 0; cacheline_size < 0x100 &&
420285242Sachim	    cache_check[cacheline_size] == 0; cacheline_size++);
421285242Sachim
422285242Sachim	/* Work around psim bug */
423285242Sachim	if (cacheline_size == 0) {
424285242Sachim		cacheline_warn = 1;
425285242Sachim		cacheline_size = 32;
426285242Sachim	}
427285242Sachim
428285242Sachim	/* Make sure the kernel icache is valid before we go too much further */
429285242Sachim	__syncicache((caddr_t)startkernel, endkernel - startkernel);
430285242Sachim
431285242Sachim	#ifndef __powerpc64__
432285242Sachim	/*
433285242Sachim	 * Figure out whether we need to use the 64 bit PMAP. This works by
434285242Sachim	 * executing an instruction that is only legal on 64-bit PPC (mtmsrd),
435285242Sachim	 * and setting ppc64 = 0 if that causes a trap.
436285242Sachim	 */
437285242Sachim
438285242Sachim	ppc64 = 1;
439285242Sachim
440285242Sachim	bcopy(&testppc64, (void *)EXC_PGM,  (size_t)&testppc64size);
441285242Sachim	__syncicache((void *)EXC_PGM, (size_t)&testppc64size);
442285242Sachim
443285242Sachim	__asm __volatile("\
444285242Sachim		mfmsr %0;	\
445285242Sachim		mtsprg2 %1;	\
446285242Sachim				\
447285242Sachim		mtmsrd %0;	\
448285242Sachim		mfsprg2 %1;"
449285242Sachim	    : "=r"(scratch), "=r"(ppc64));
450285242Sachim
451285242Sachim	if (ppc64)
452285242Sachim		cpu_features |= PPC_FEATURE_64;
453285242Sachim
454285242Sachim	/*
455285242Sachim	 * Now copy restorebridge into all the handlers, if necessary,
456285242Sachim	 * and set up the trap tables.
457285242Sachim	 */
458285242Sachim
459285242Sachim	if (cpu_features & PPC_FEATURE_64) {
460285242Sachim		/* Patch the two instances of rfi -> rfid */
461285242Sachim		bcopy(&rfid_patch,&rfi_patch1,4);
462285242Sachim	#ifdef KDB
463285242Sachim		/* rfi_patch2 is at the end of dbleave */
464285242Sachim		bcopy(&rfid_patch,&rfi_patch2,4);
465285242Sachim	#endif
466285242Sachim
467285242Sachim		/*
468285242Sachim		 * Copy a code snippet to restore 32-bit bridge mode
469285242Sachim		 * to the top of every non-generic trap handler
470285242Sachim		 */
471285242Sachim
472285242Sachim		trap_offset += (size_t)&restorebridgesize;
473285242Sachim		bcopy(&restorebridge, (void *)EXC_RST, trap_offset);
474285242Sachim		bcopy(&restorebridge, (void *)EXC_DSI, trap_offset);
475285242Sachim		bcopy(&restorebridge, (void *)EXC_ALI, trap_offset);
476285242Sachim		bcopy(&restorebridge, (void *)EXC_PGM, trap_offset);
477285242Sachim		bcopy(&restorebridge, (void *)EXC_MCHK, trap_offset);
478285242Sachim		bcopy(&restorebridge, (void *)EXC_TRC, trap_offset);
479285242Sachim		bcopy(&restorebridge, (void *)EXC_BPT, trap_offset);
480285242Sachim
481285242Sachim		/*
482285242Sachim		 * Set the common trap entry point to the one that
483285242Sachim		 * knows to restore 32-bit operation on execution.
484285242Sachim		 */
485285242Sachim
486285242Sachim		generictrap = &trapcode64;
487285242Sachim	} else {
488285242Sachim		generictrap = &trapcode;
489285242Sachim	}
490285242Sachim
491285242Sachim	#else /* powerpc64 */
492285242Sachim	cpu_features |= PPC_FEATURE_64;
493285242Sachim	generictrap = &trapcode;
494285242Sachim	#endif
495285242Sachim
496285242Sachim	bcopy(&rstcode, (void *)(EXC_RST + trap_offset),  (size_t)&rstsize);
497285242Sachim
498285242Sachim#ifdef KDB
499285242Sachim	bcopy(&dblow,	(void *)(EXC_MCHK + trap_offset), (size_t)&dbsize);
500285242Sachim	bcopy(&dblow,   (void *)(EXC_PGM + trap_offset),  (size_t)&dbsize);
501285242Sachim	bcopy(&dblow,   (void *)(EXC_TRC + trap_offset),  (size_t)&dbsize);
502285242Sachim	bcopy(&dblow,   (void *)(EXC_BPT + trap_offset),  (size_t)&dbsize);
503285242Sachim#else
504285242Sachim	bcopy(generictrap, (void *)EXC_MCHK, (size_t)&trapsize);
505285242Sachim	bcopy(generictrap, (void *)EXC_PGM,  (size_t)&trapsize);
506285242Sachim	bcopy(generictrap, (void *)EXC_TRC,  (size_t)&trapsize);
507285242Sachim	bcopy(generictrap, (void *)EXC_BPT,  (size_t)&trapsize);
508285242Sachim#endif
509285242Sachim	bcopy(&alitrap,  (void *)(EXC_ALI + trap_offset),  (size_t)&alisize);
510285242Sachim	bcopy(&dsitrap,  (void *)(EXC_DSI + trap_offset),  (size_t)&dsisize);
511285242Sachim	bcopy(generictrap, (void *)EXC_ISI,  (size_t)&trapsize);
512285242Sachim	#ifdef __powerpc64__
513285242Sachim	bcopy(&slbtrap, (void *)EXC_DSE,  (size_t)&slbtrapsize);
514285242Sachim	bcopy(&slbtrap, (void *)EXC_ISE,  (size_t)&slbtrapsize);
515285242Sachim	#endif
516285242Sachim	bcopy(generictrap, (void *)EXC_EXI,  (size_t)&trapsize);
517285242Sachim	bcopy(generictrap, (void *)EXC_FPU,  (size_t)&trapsize);
518285242Sachim	bcopy(generictrap, (void *)EXC_DECR, (size_t)&trapsize);
519285242Sachim	bcopy(generictrap, (void *)EXC_SC,   (size_t)&trapsize);
520285242Sachim	bcopy(generictrap, (void *)EXC_FPA,  (size_t)&trapsize);
521285242Sachim	bcopy(generictrap, (void *)EXC_VEC,  (size_t)&trapsize);
522285242Sachim	bcopy(generictrap, (void *)EXC_PERF,  (size_t)&trapsize);
523285242Sachim	bcopy(generictrap, (void *)EXC_VECAST_G4, (size_t)&trapsize);
524285242Sachim	bcopy(generictrap, (void *)EXC_VECAST_G5, (size_t)&trapsize);
525285242Sachim	#ifndef __powerpc64__
526285242Sachim	/* G2-specific TLB miss helper handlers */
527285242Sachim	bcopy(&imisstrap, (void *)EXC_IMISS,  (size_t)&imisssize);
528285242Sachim	bcopy(&dlmisstrap, (void *)EXC_DLMISS,  (size_t)&dlmisssize);
529285242Sachim	bcopy(&dsmisstrap, (void *)EXC_DSMISS,  (size_t)&dsmisssize);
530285242Sachim	#endif
531285242Sachim	__syncicache(EXC_RSVD, EXC_LAST - EXC_RSVD);
532285242Sachim
533285242Sachim	/*
534285242Sachim	 * Restore MSR
535285242Sachim	 */
536285242Sachim	mtmsr(msr);
537285242Sachim
538285242Sachim	/* Warn if cachline size was not determined */
539285242Sachim	if (cacheline_warn == 1) {
540285242Sachim		printf("WARNING: cacheline size undetermined, setting to 32\n");
541285242Sachim	}
542285242Sachim
543285242Sachim	/*
544285242Sachim	 * Choose a platform module so we can get the physical memory map.
545285242Sachim	 */
546285242Sachim
547285242Sachim	platform_probe_and_attach();
548285242Sachim
549285242Sachim	/*
550285242Sachim	 * Initialise virtual memory. Use BUS_PROBE_GENERIC priority
551285242Sachim	 * in case the platform module had a better idea of what we
552285242Sachim	 * should do.
553285242Sachim	 */
554285242Sachim	if (cpu_features & PPC_FEATURE_64)
555285242Sachim		pmap_mmu_install(MMU_TYPE_G5, BUS_PROBE_GENERIC);
556285242Sachim	else
557285242Sachim		pmap_mmu_install(MMU_TYPE_OEA, BUS_PROBE_GENERIC);
558285242Sachim
559285242Sachim	pmap_bootstrap(startkernel, endkernel);
560285242Sachim	mtmsr(PSL_KERNSET & ~PSL_EE);
561285242Sachim
562285242Sachim	/*
563285242Sachim	 * Initialize params/tunables that are derived from memsize
564285242Sachim	 */
565285242Sachim	init_param2(physmem);
566285242Sachim
567285242Sachim	/*
568285242Sachim	 * Grab booted kernel's name
569285242Sachim	 */
570285242Sachim        env = getenv("kernelname");
571285242Sachim        if (env != NULL) {
572285242Sachim		strlcpy(kernelname, env, sizeof(kernelname));
573285242Sachim		freeenv(env);
574285242Sachim	}
575285242Sachim
576285242Sachim	/*
577285242Sachim	 * Finish setting up thread0.
578285242Sachim	 */
579285242Sachim	thread0.td_pcb = (struct pcb *)
580285242Sachim	    ((thread0.td_kstack + thread0.td_kstack_pages * PAGE_SIZE -
581285242Sachim	    sizeof(struct pcb)) & ~15UL);
582285242Sachim	bzero((void *)thread0.td_pcb, sizeof(struct pcb));
583285242Sachim	pc->pc_curpcb = thread0.td_pcb;
584285242Sachim
585285242Sachim	/* Initialise the message buffer. */
586285242Sachim	msgbufinit(msgbufp, msgbufsize);
587285242Sachim
588285242Sachim#ifdef KDB
589285242Sachim	if (boothowto & RB_KDB)
590285242Sachim		kdb_enter(KDB_WHY_BOOTFLAGS,
591285242Sachim		    "Boot flags requested debugger");
592285242Sachim#endif
593285242Sachim
594285242Sachim	return (((uintptr_t)thread0.td_pcb -
595285242Sachim	    (sizeof(struct callframe) - 3*sizeof(register_t))) & ~15UL);
596285242Sachim}
597285242Sachim
598285242Sachimvoid
599285242Sachimbzero(void *buf, size_t len)
600285242Sachim{
601285242Sachim	caddr_t	p;
602285242Sachim
603285242Sachim	p = buf;
604285242Sachim
605285242Sachim	while (((vm_offset_t) p & (sizeof(u_long) - 1)) && len) {
606285242Sachim		*p++ = 0;
607285242Sachim		len--;
608285242Sachim	}
609285242Sachim
610285242Sachim	while (len >= sizeof(u_long) * 8) {
611285242Sachim		*(u_long*) p = 0;
612285242Sachim		*((u_long*) p + 1) = 0;
613285242Sachim		*((u_long*) p + 2) = 0;
614285242Sachim		*((u_long*) p + 3) = 0;
615285242Sachim		len -= sizeof(u_long) * 8;
616285242Sachim		*((u_long*) p + 4) = 0;
617285242Sachim		*((u_long*) p + 5) = 0;
618285242Sachim		*((u_long*) p + 6) = 0;
619285242Sachim		*((u_long*) p + 7) = 0;
620285242Sachim		p += sizeof(u_long) * 8;
621285242Sachim	}
622285242Sachim
623285242Sachim	while (len >= sizeof(u_long)) {
624285242Sachim		*(u_long*) p = 0;
625285242Sachim		len -= sizeof(u_long);
626285242Sachim		p += sizeof(u_long);
627285242Sachim	}
628285242Sachim
629285242Sachim	while (len) {
630285242Sachim		*p++ = 0;
631285242Sachim		len--;
632285242Sachim	}
633285242Sachim}
634285242Sachim
635285242Sachimvoid
636285242Sachimcpu_boot(int howto)
637285242Sachim{
638285242Sachim}
639285242Sachim
640285242Sachim/*
641285242Sachim * Flush the D-cache for non-DMA I/O so that the I-cache can
642285242Sachim * be made coherent later.
643285242Sachim */
644285242Sachimvoid
645285242Sachimcpu_flush_dcache(void *ptr, size_t len)
646285242Sachim{
647285242Sachim	/* TBD */
648285242Sachim}
649285242Sachim
650285242Sachim/*
651285242Sachim * Shutdown the CPU as much as possible.
652285242Sachim */
653285242Sachimvoid
654285242Sachimcpu_halt(void)
655285242Sachim{
656285242Sachim
657285242Sachim	OF_exit();
658285242Sachim}
659285242Sachim
660285242Sachimint
661285242Sachimptrace_set_pc(struct thread *td, unsigned long addr)
662285242Sachim{
663285242Sachim	struct trapframe *tf;
664285242Sachim
665285242Sachim	tf = td->td_frame;
666285242Sachim	tf->srr0 = (register_t)addr;
667285242Sachim
668285242Sachim	return (0);
669285242Sachim}
670285242Sachim
671285242Sachimint
672285242Sachimptrace_single_step(struct thread *td)
673285242Sachim{
674285242Sachim	struct trapframe *tf;
675285242Sachim
676285242Sachim	tf = td->td_frame;
677285242Sachim	tf->srr1 |= PSL_SE;
678285242Sachim
679285242Sachim	return (0);
680285242Sachim}
681285242Sachim
682285242Sachimint
683285242Sachimptrace_clear_single_step(struct thread *td)
684285242Sachim{
685285242Sachim	struct trapframe *tf;
686285242Sachim
687285242Sachim	tf = td->td_frame;
688285242Sachim	tf->srr1 &= ~PSL_SE;
689285242Sachim
690285242Sachim	return (0);
691285242Sachim}
692285242Sachim
693285242Sachimvoid
694285242Sachimkdb_cpu_clear_singlestep(void)
695285242Sachim{
696285242Sachim
697285242Sachim	kdb_frame->srr1 &= ~PSL_SE;
698285242Sachim}
699285242Sachim
700285242Sachimvoid
701285242Sachimkdb_cpu_set_singlestep(void)
702285242Sachim{
703285242Sachim
704285242Sachim	kdb_frame->srr1 |= PSL_SE;
705285242Sachim}
706285242Sachim
707285242Sachim/*
708285242Sachim * Initialise a struct pcpu.
709285242Sachim */
710285242Sachimvoid
711285242Sachimcpu_pcpu_init(struct pcpu *pcpu, int cpuid, size_t sz)
712285242Sachim{
713285242Sachim#ifdef __powerpc64__
714285242Sachim/* Copy the SLB contents from the current CPU */
715285242Sachimmemcpy(pcpu->pc_slb, PCPU_GET(slb), sizeof(pcpu->pc_slb));
716285242Sachim#endif
717285242Sachim}
718285242Sachim
719285242Sachimvoid
720285242Sachimspinlock_enter(void)
721285242Sachim{
722285242Sachim	struct thread *td;
723285242Sachim	register_t msr;
724285242Sachim
725285242Sachim	td = curthread;
726285242Sachim	if (td->td_md.md_spinlock_count == 0) {
727285242Sachim		msr = intr_disable();
728285242Sachim		td->td_md.md_spinlock_count = 1;
729285242Sachim		td->td_md.md_saved_msr = msr;
730285242Sachim	} else
731285242Sachim		td->td_md.md_spinlock_count++;
732285242Sachim	critical_enter();
733285242Sachim}
734285242Sachim
735285242Sachimvoid
736285242Sachimspinlock_exit(void)
737285242Sachim{
738285242Sachim	struct thread *td;
739285242Sachim	register_t msr;
740285242Sachim
741285242Sachim	td = curthread;
742285242Sachim	critical_exit();
743285242Sachim	msr = td->td_md.md_saved_msr;
744285242Sachim	td->td_md.md_spinlock_count--;
745285242Sachim	if (td->td_md.md_spinlock_count == 0)
746285242Sachim		intr_restore(msr);
747285242Sachim}
748285242Sachim
749285242Sachimint db_trap_glue(struct trapframe *);		/* Called from trap_subr.S */
750285242Sachim
751285242Sachimint
752285242Sachimdb_trap_glue(struct trapframe *frame)
753285242Sachim{
754285242Sachim	if (!(frame->srr1 & PSL_PR)
755285242Sachim	    && (frame->exc == EXC_TRC || frame->exc == EXC_RUNMODETRC
756285242Sachim		|| (frame->exc == EXC_PGM
757285242Sachim		    && (frame->srr1 & 0x20000))
758285242Sachim		|| frame->exc == EXC_BPT
759285242Sachim		|| frame->exc == EXC_DSI)) {
760285242Sachim		int type = frame->exc;
761285242Sachim		if (type == EXC_PGM && (frame->srr1 & 0x20000)) {
762285242Sachim			type = T_BREAKPOINT;
763285242Sachim		}
764285242Sachim		return (kdb_trap(type, 0, frame));
765285242Sachim	}
766285242Sachim
767285242Sachim	return (0);
768285242Sachim}
769285242Sachim
770285242Sachim#ifndef __powerpc64__
771285242Sachim
772285242Sachimuint64_t
773285242Sachimva_to_vsid(pmap_t pm, vm_offset_t va)
774285242Sachim{
775285242Sachim	return ((pm->pm_sr[(uintptr_t)va >> ADDR_SR_SHFT]) & SR_VSID_MASK);
776285242Sachim}
777285242Sachim
778285242Sachim#endif
779285242Sachim
780285242Sachimvm_offset_t
781285242Sachimpmap_early_io_map(vm_paddr_t pa, vm_size_t size)
782285242Sachim{
783285242Sachim
784285242Sachim	return (pa);
785285242Sachim}
786285242Sachim
787285242Sachim/* From p3-53 of the MPC7450 RISC Microprocessor Family Reference Manual */
788285242Sachimvoid
789285242Sachimflush_disable_caches(void)
790285242Sachim{
791285242Sachim	register_t msr;
792285242Sachim	register_t msscr0;
793285242Sachim	register_t cache_reg;
794285242Sachim	volatile uint32_t *memp;
795285242Sachim	uint32_t temp;
796285242Sachim	int i;
797285242Sachim	int x;
798285242Sachim
799285242Sachim	msr = mfmsr();
800285242Sachim	powerpc_sync();
801285242Sachim	mtmsr(msr & ~(PSL_EE | PSL_DR));
802285242Sachim	msscr0 = mfspr(SPR_MSSCR0);
803285242Sachim	msscr0 &= ~MSSCR0_L2PFE;
804285242Sachim	mtspr(SPR_MSSCR0, msscr0);
805285242Sachim	powerpc_sync();
806285242Sachim	isync();
807285242Sachim	__asm__ __volatile__("dssall; sync");
808285242Sachim	powerpc_sync();
809285242Sachim	isync();
810285242Sachim	__asm__ __volatile__("dcbf 0,%0" :: "r"(0));
811285242Sachim	__asm__ __volatile__("dcbf 0,%0" :: "r"(0));
812285242Sachim	__asm__ __volatile__("dcbf 0,%0" :: "r"(0));
813285242Sachim
814285242Sachim	/* Lock the L1 Data cache. */
815285242Sachim	mtspr(SPR_LDSTCR, mfspr(SPR_LDSTCR) | 0xFF);
816285242Sachim	powerpc_sync();
817285242Sachim	isync();
818285242Sachim
819285242Sachim	mtspr(SPR_LDSTCR, 0);
820285242Sachim
821285242Sachim	/*
822285242Sachim	 * Perform this in two stages: Flush the cache starting in RAM, then do it
823285242Sachim	 * from ROM.
824285242Sachim	 */
825285242Sachim	memp = (volatile uint32_t *)0x00000000;
826285242Sachim	for (i = 0; i < 128 * 1024; i++) {
827285242Sachim		temp = *memp;
828285242Sachim		__asm__ __volatile__("dcbf 0,%0" :: "r"(memp));
829285242Sachim		memp += 32/sizeof(*memp);
830285242Sachim	}
831285242Sachim
832285242Sachim	memp = (volatile uint32_t *)0xfff00000;
833285242Sachim	x = 0xfe;
834285242Sachim
835285242Sachim	for (; x != 0xff;) {
836285242Sachim		mtspr(SPR_LDSTCR, x);
837285242Sachim		for (i = 0; i < 128; i++) {
838285242Sachim			temp = *memp;
839285242Sachim			__asm__ __volatile__("dcbf 0,%0" :: "r"(memp));
840285242Sachim			memp += 32/sizeof(*memp);
841285242Sachim		}
842285242Sachim		x = ((x << 1) | 1) & 0xff;
843285242Sachim	}
844285242Sachim	mtspr(SPR_LDSTCR, 0);
845285242Sachim
846285242Sachim	cache_reg = mfspr(SPR_L2CR);
847285242Sachim	if (cache_reg & L2CR_L2E) {
848285242Sachim		cache_reg &= ~(L2CR_L2IO_7450 | L2CR_L2DO_7450);
849285242Sachim		mtspr(SPR_L2CR, cache_reg);
850285242Sachim		powerpc_sync();
851285242Sachim		mtspr(SPR_L2CR, cache_reg | L2CR_L2HWF);
852285242Sachim		while (mfspr(SPR_L2CR) & L2CR_L2HWF)
853285242Sachim			; /* Busy wait for cache to flush */
854285242Sachim		powerpc_sync();
855285242Sachim		cache_reg &= ~L2CR_L2E;
856285242Sachim		mtspr(SPR_L2CR, cache_reg);
857285242Sachim		powerpc_sync();
858285242Sachim		mtspr(SPR_L2CR, cache_reg | L2CR_L2I);
859285242Sachim		powerpc_sync();
860285242Sachim		while (mfspr(SPR_L2CR) & L2CR_L2I)
861285242Sachim			; /* Busy wait for L2 cache invalidate */
862285242Sachim		powerpc_sync();
863285242Sachim	}
864285242Sachim
865285242Sachim	cache_reg = mfspr(SPR_L3CR);
866285242Sachim	if (cache_reg & L3CR_L3E) {
867285242Sachim		cache_reg &= ~(L3CR_L3IO | L3CR_L3DO);
868285242Sachim		mtspr(SPR_L3CR, cache_reg);
869285242Sachim		powerpc_sync();
870285242Sachim		mtspr(SPR_L3CR, cache_reg | L3CR_L3HWF);
871285242Sachim		while (mfspr(SPR_L3CR) & L3CR_L3HWF)
872285242Sachim			; /* Busy wait for cache to flush */
873285242Sachim		powerpc_sync();
874285242Sachim		cache_reg &= ~L3CR_L3E;
875285242Sachim		mtspr(SPR_L3CR, cache_reg);
876285242Sachim		powerpc_sync();
877285242Sachim		mtspr(SPR_L3CR, cache_reg | L3CR_L3I);
878285242Sachim		powerpc_sync();
879285242Sachim		while (mfspr(SPR_L3CR) & L3CR_L3I)
880285242Sachim			; /* Busy wait for L3 cache invalidate */
881285242Sachim		powerpc_sync();
882285242Sachim	}
883285242Sachim
884285242Sachim	mtspr(SPR_HID0, mfspr(SPR_HID0) & ~HID0_DCE);
885285242Sachim	powerpc_sync();
886285242Sachim	isync();
887285242Sachim
888285242Sachim	mtmsr(msr);
889285242Sachim}
890285242Sachim
891285242Sachimvoid
892285242Sachimcpu_sleep()
893285242Sachim{
894285242Sachim	static u_quad_t timebase = 0;
895285242Sachim	static register_t sprgs[4];
896285242Sachim	static register_t srrs[2];
897285242Sachim
898285242Sachim	jmp_buf resetjb;
899285242Sachim	struct thread *fputd;
900285242Sachim	struct thread *vectd;
901285242Sachim	register_t hid0;
902285242Sachim	register_t msr;
903285242Sachim	register_t saved_msr;
904285242Sachim
905285242Sachim	ap_pcpu = pcpup;
906285242Sachim
907285242Sachim	PCPU_SET(restore, &resetjb);
908285242Sachim
909285242Sachim	saved_msr = mfmsr();
910285242Sachim	fputd = PCPU_GET(fputhread);
911285242Sachim	vectd = PCPU_GET(vecthread);
912285242Sachim	if (fputd != NULL)
913285242Sachim		save_fpu(fputd);
914285242Sachim	if (vectd != NULL)
915285242Sachim		save_vec(vectd);
916285242Sachim	if (setjmp(resetjb) == 0) {
917285242Sachim		sprgs[0] = mfspr(SPR_SPRG0);
918285242Sachim		sprgs[1] = mfspr(SPR_SPRG1);
919285242Sachim		sprgs[2] = mfspr(SPR_SPRG2);
920285242Sachim		sprgs[3] = mfspr(SPR_SPRG3);
921285242Sachim		srrs[0] = mfspr(SPR_SRR0);
922285242Sachim		srrs[1] = mfspr(SPR_SRR1);
923		timebase = mftb();
924		powerpc_sync();
925		flush_disable_caches();
926		hid0 = mfspr(SPR_HID0);
927		hid0 = (hid0 & ~(HID0_DOZE | HID0_NAP)) | HID0_SLEEP;
928		powerpc_sync();
929		isync();
930		msr = mfmsr() | PSL_POW;
931		mtspr(SPR_HID0, hid0);
932		powerpc_sync();
933
934		while (1)
935			mtmsr(msr);
936	}
937	mttb(timebase);
938	PCPU_SET(curthread, curthread);
939	PCPU_SET(curpcb, curthread->td_pcb);
940	pmap_activate(curthread);
941	powerpc_sync();
942	mtspr(SPR_SPRG0, sprgs[0]);
943	mtspr(SPR_SPRG1, sprgs[1]);
944	mtspr(SPR_SPRG2, sprgs[2]);
945	mtspr(SPR_SPRG3, sprgs[3]);
946	mtspr(SPR_SRR0, srrs[0]);
947	mtspr(SPR_SRR1, srrs[1]);
948	mtmsr(saved_msr);
949	if (fputd == curthread)
950		enable_fpu(curthread);
951	if (vectd == curthread)
952		enable_vec(curthread);
953	powerpc_sync();
954}