1176771Sraj/*-
2236324Sraj * Copyright (C) 2006-2012 Semihalf
3176771Sraj * All rights reserved.
4176771Sraj *
5176771Sraj * Redistribution and use in source and binary forms, with or without
6176771Sraj * modification, are permitted provided that the following conditions
7176771Sraj * are met:
8176771Sraj * 1. Redistributions of source code must retain the above copyright
9176771Sraj *    notice, this list of conditions and the following disclaimer.
10176771Sraj * 2. Redistributions in binary form must reproduce the above copyright
11176771Sraj *    notice, this list of conditions and the following disclaimer in the
12176771Sraj *    documentation and/or other materials provided with the distribution.
13176771Sraj *
14176771Sraj * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15176771Sraj * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16176771Sraj * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
17176771Sraj * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
18176771Sraj * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
19176771Sraj * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20176771Sraj * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
21176771Sraj * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
22176771Sraj * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
23176771Sraj * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24176771Sraj */
25176771Sraj/*-
26176771Sraj * Copyright (C) 2001 Benno Rice
27176771Sraj * All rights reserved.
28176771Sraj *
29176771Sraj * Redistribution and use in source and binary forms, with or without
30176771Sraj * modification, are permitted provided that the following conditions
31176771Sraj * are met:
32176771Sraj * 1. Redistributions of source code must retain the above copyright
33176771Sraj *    notice, this list of conditions and the following disclaimer.
34176771Sraj * 2. Redistributions in binary form must reproduce the above copyright
35176771Sraj *    notice, this list of conditions and the following disclaimer in the
36176771Sraj *    documentation and/or other materials provided with the distribution.
37176771Sraj *
38176771Sraj * THIS SOFTWARE IS PROVIDED BY Benno Rice ``AS IS'' AND ANY EXPRESS OR
39176771Sraj * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
40176771Sraj * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
41176771Sraj * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
42176771Sraj * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
43176771Sraj * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
44176771Sraj * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
45176771Sraj * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
46176771Sraj * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
47176771Sraj * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
48176771Sraj * $NetBSD: machdep.c,v 1.74.2.1 2000/11/01 16:13:48 tv Exp $
49176771Sraj */
50176771Sraj/*-
51176771Sraj * Copyright (C) 1995, 1996 Wolfgang Solfrank.
52176771Sraj * Copyright (C) 1995, 1996 TooLs GmbH.
53176771Sraj * All rights reserved.
54176771Sraj *
55176771Sraj * Redistribution and use in source and binary forms, with or without
56176771Sraj * modification, are permitted provided that the following conditions
57176771Sraj * are met:
58176771Sraj * 1. Redistributions of source code must retain the above copyright
59176771Sraj *    notice, this list of conditions and the following disclaimer.
60176771Sraj * 2. Redistributions in binary form must reproduce the above copyright
61176771Sraj *    notice, this list of conditions and the following disclaimer in the
62176771Sraj *    documentation and/or other materials provided with the distribution.
63176771Sraj * 3. All advertising materials mentioning features or use of this software
64176771Sraj *    must display the following acknowledgement:
65176771Sraj *      This product includes software developed by TooLs GmbH.
66176771Sraj * 4. The name of TooLs GmbH may not be used to endorse or promote products
67176771Sraj *    derived from this software without specific prior written permission.
68176771Sraj *
69176771Sraj * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
70176771Sraj * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
71176771Sraj * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
72176771Sraj * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
73176771Sraj * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
74176771Sraj * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
75176771Sraj * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
76176771Sraj * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
77176771Sraj * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
78176771Sraj * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
79176771Sraj */
80176771Sraj
81176771Sraj#include <sys/cdefs.h>
82176771Sraj__FBSDID("$FreeBSD: releng/10.3/sys/powerpc/booke/machdep.c 266003 2014-05-14 04:14:58Z ian $");
83176771Sraj
84176771Sraj#include "opt_compat.h"
85191362Smarcel#include "opt_ddb.h"
86176771Sraj#include "opt_kstack_pages.h"
87217523Smarcel#include "opt_platform.h"
88176771Sraj
89176771Sraj#include <sys/cdefs.h>
90176771Sraj#include <sys/types.h>
91176771Sraj#include <sys/param.h>
92176771Sraj#include <sys/proc.h>
93176771Sraj#include <sys/systm.h>
94176771Sraj#include <sys/time.h>
95176771Sraj#include <sys/bio.h>
96176771Sraj#include <sys/buf.h>
97176771Sraj#include <sys/bus.h>
98176771Sraj#include <sys/cons.h>
99176771Sraj#include <sys/cpu.h>
100176771Sraj#include <sys/kdb.h>
101176771Sraj#include <sys/kernel.h>
102176771Sraj#include <sys/lock.h>
103176771Sraj#include <sys/mutex.h>
104248084Sattilio#include <sys/rwlock.h>
105176771Sraj#include <sys/sysctl.h>
106176771Sraj#include <sys/exec.h>
107176771Sraj#include <sys/ktr.h>
108209613Sjhb#include <sys/syscallsubr.h>
109176771Sraj#include <sys/sysproto.h>
110176771Sraj#include <sys/signalvar.h>
111176771Sraj#include <sys/sysent.h>
112176771Sraj#include <sys/imgact.h>
113176771Sraj#include <sys/msgbuf.h>
114176771Sraj#include <sys/ptrace.h>
115176771Sraj
116176771Sraj#include <vm/vm.h>
117176771Sraj#include <vm/pmap.h>
118176771Sraj#include <vm/vm_page.h>
119176771Sraj#include <vm/vm_object.h>
120176771Sraj#include <vm/vm_pager.h>
121176771Sraj
122176771Sraj#include <machine/cpu.h>
123176771Sraj#include <machine/kdb.h>
124176771Sraj#include <machine/reg.h>
125176771Sraj#include <machine/vmparam.h>
126176771Sraj#include <machine/spr.h>
127176771Sraj#include <machine/hid.h>
128176771Sraj#include <machine/psl.h>
129176771Sraj#include <machine/trap.h>
130176771Sraj#include <machine/md_var.h>
131176771Sraj#include <machine/mmuvar.h>
132176771Sraj#include <machine/sigframe.h>
133236324Sraj#include <machine/machdep.h>
134176771Sraj#include <machine/metadata.h>
135192067Snwhitehorn#include <machine/platform.h>
136176771Sraj
137176771Sraj#include <sys/linker.h>
138176771Sraj#include <sys/reboot.h>
139176771Sraj
140265996Sian#include <contrib/libfdt/libfdt.h>
141209908Sraj#include <dev/fdt/fdt_common.h>
142209908Sraj#include <dev/ofw/openfirm.h>
143209908Sraj
144191362Smarcel#ifdef DDB
145191362Smarcelextern vm_offset_t ksym_start, ksym_end;
146191362Smarcel#endif
147191362Smarcel
148176771Sraj#ifdef  DEBUG
149176771Sraj#define debugf(fmt, args...) printf(fmt, ##args)
150176771Sraj#else
151176771Sraj#define debugf(fmt, args...)
152176771Sraj#endif
153176771Sraj
154176771Srajextern unsigned char kernel_text[];
155176771Srajextern unsigned char _etext[];
156176771Srajextern unsigned char _edata[];
157176771Srajextern unsigned char __bss_start[];
158176771Srajextern unsigned char __sbss_start[];
159176771Srajextern unsigned char __sbss_end[];
160176771Srajextern unsigned char _end[];
161176771Sraj
162217523Smarcel/*
163217523Smarcel * Bootinfo is passed to us by legacy loaders. Save the address of the
164217523Smarcel * structure to handle backward compatibility.
165217523Smarcel */
166217523Smarceluint32_t *bootinfo;
167217523Smarcel
168176771Srajstruct kva_md_info kmi;
169176771Srajstruct pcpu __pcpu[MAXCPU];
170176771Srajstruct trapframe frame0;
171176771Srajint cold = 1;
172176771Srajlong realmem = 0;
173176771Srajlong Maxmem = 0;
174176771Srajchar machine[] = "powerpc";
175176771SrajSYSCTL_STRING(_hw, HW_MACHINE, machine, CTLFLAG_RD, machine, 0, "");
176176771Sraj
177183319Snwhitehornint cacheline_size = 32;
178183319Snwhitehorn
179176771SrajSYSCTL_INT(_machdep, CPU_CACHELINE, cacheline_size,
180183319Snwhitehorn	   CTLFLAG_RD, &cacheline_size, 0, "");
181176771Sraj
182190681Snwhitehornint hw_direct_map = 0;
183190681Snwhitehorn
184236097Srajstatic void cpu_booke_startup(void *);
185236097SrajSYSINIT(cpu, SI_SUB_CPU, SI_ORDER_FIRST, cpu_booke_startup, NULL);
186176771Sraj
187176771Srajvoid print_kernel_section_addr(void);
188186228Srajvoid print_kenv(void);
189222400Smarcelu_int booke_init(uint32_t, uint32_t);
190176771Sraj
191230767Skibextern int elf32_nxstack;
192230767Skib
193176771Srajstatic void
194236097Srajcpu_booke_startup(void *dummy)
195176771Sraj{
196265954Sian	int indx;
197265954Sian	unsigned long size;
198176771Sraj
199176771Sraj	/* Initialise the decrementer-based clock. */
200176771Sraj	decr_init();
201176771Sraj
202176771Sraj	/* Good {morning,afternoon,evening,night}. */
203176771Sraj	cpu_setup(PCPU_GET(cpuid));
204176771Sraj
205265954Sian	printf("real memory  = %lu (%ld MB)\n", ptoa(physmem),
206182198Sraj	    ptoa(physmem) / 1048576);
207176771Sraj	realmem = physmem;
208176771Sraj
209176771Sraj	/* Display any holes after the first chunk of extended memory. */
210176771Sraj	if (bootverbose) {
211176771Sraj		printf("Physical memory chunk(s):\n");
212176771Sraj		for (indx = 0; phys_avail[indx + 1] != 0; indx += 2) {
213182198Sraj			size = phys_avail[indx + 1] - phys_avail[indx];
214186228Sraj
215265954Sian			printf("0x%08x - 0x%08x, %lu bytes (%lu pages)\n",
216186228Sraj			    phys_avail[indx], phys_avail[indx + 1] - 1,
217186228Sraj			    size, size / PAGE_SIZE);
218176771Sraj		}
219176771Sraj	}
220176771Sraj
221176771Sraj	vm_ksubmap_init(&kmi);
222176771Sraj
223265954Sian	printf("avail memory = %lu (%ld MB)\n", ptoa(cnt.v_free_count),
224186228Sraj	    ptoa(cnt.v_free_count) / 1048576);
225176771Sraj
226176771Sraj	/* Set up buffers, so they can be used to read disk labels. */
227176771Sraj	bufinit();
228176771Sraj	vm_pager_bufferinit();
229230767Skib
230230767Skib	/* Cpu supports execution permissions on the pages. */
231230767Skib	elf32_nxstack = 1;
232176771Sraj}
233176771Sraj
234176771Srajstatic char *
235176771Srajkenv_next(char *cp)
236176771Sraj{
237176771Sraj
238176771Sraj	if (cp != NULL) {
239176771Sraj		while (*cp != 0)
240176771Sraj			cp++;
241176771Sraj		cp++;
242176771Sraj		if (*cp == 0)
243176771Sraj			cp = NULL;
244176771Sraj	}
245176771Sraj	return (cp);
246176771Sraj}
247176771Sraj
248176771Srajvoid
249186228Srajprint_kenv(void)
250176771Sraj{
251176771Sraj	int len;
252176771Sraj	char *cp;
253176771Sraj
254176771Sraj	debugf("loader passed (static) kenv:\n");
255176771Sraj	if (kern_envp == NULL) {
256176771Sraj		debugf(" no env, null ptr\n");
257176771Sraj		return;
258176771Sraj	}
259176771Sraj	debugf(" kern_envp = 0x%08x\n", (u_int32_t)kern_envp);
260176771Sraj
261176771Sraj	len = 0;
262176771Sraj	for (cp = kern_envp; cp != NULL; cp = kenv_next(cp))
263176771Sraj		debugf(" %x %s\n", (u_int32_t)cp, cp);
264176771Sraj}
265176771Sraj
266176771Srajvoid
267176771Srajprint_kernel_section_addr(void)
268176771Sraj{
269176771Sraj
270176771Sraj	debugf("kernel image addresses:\n");
271186228Sraj	debugf(" kernel_text    = 0x%08x\n", (uint32_t)kernel_text);
272186228Sraj	debugf(" _etext (sdata) = 0x%08x\n", (uint32_t)_etext);
273186228Sraj	debugf(" _edata         = 0x%08x\n", (uint32_t)_edata);
274186228Sraj	debugf(" __sbss_start   = 0x%08x\n", (uint32_t)__sbss_start);
275186228Sraj	debugf(" __sbss_end     = 0x%08x\n", (uint32_t)__sbss_end);
276186228Sraj	debugf(" __sbss_start   = 0x%08x\n", (uint32_t)__bss_start);
277186228Sraj	debugf(" _end           = 0x%08x\n", (uint32_t)_end);
278176771Sraj}
279176771Sraj
280265996Sianstatic int
281265996Sianbooke_check_for_fdt(uint32_t arg1, vm_offset_t *dtbp)
282265996Sian{
283265996Sian	void *ptr;
284265996Sian
285265996Sian	if (arg1 % 8 != 0)
286265996Sian		return (-1);
287265996Sian
288265996Sian	ptr = (void *)pmap_early_io_map(arg1, PAGE_SIZE);
289265996Sian	if (fdt_check_header(ptr) != 0)
290265996Sian		return (-1);
291265996Sian
292265996Sian	*dtbp = (vm_offset_t)ptr;
293265996Sian
294265996Sian	return (0);
295265996Sian}
296265996Sian
297182198Sraju_int
298222400Smarcelbooke_init(uint32_t arg1, uint32_t arg2)
299176771Sraj{
300176771Sraj	struct pcpu *pc;
301222400Smarcel	void *kmdp, *mdp;
302209908Sraj	vm_offset_t dtbp, end;
303176771Sraj
304176771Sraj	kmdp = NULL;
305176771Sraj
306222400Smarcel	end = (uintptr_t)_end;
307209908Sraj	dtbp = (vm_offset_t)NULL;
308176771Sraj
309265996Sian	/* Set up TLB initially */
310265996Sian	bootinfo = NULL;
311265996Sian	tlb1_init();
312265996Sian
313176771Sraj	/*
314222400Smarcel	 * Handle the various ways we can get loaded and started:
315222400Smarcel	 *  -	FreeBSD's loader passes the pointer to the metadata
316222400Smarcel	 *	in arg1, with arg2 undefined. arg1 has a value that's
317222400Smarcel	 *	relative to the kernel's link address (i.e. larger
318222400Smarcel	 *	than 0xc0000000).
319222400Smarcel	 *  -	Juniper's loader passes the metadata pointer in arg2
320222400Smarcel	 *	and sets arg1 to zero. This is to signal that the
321222400Smarcel	 *	loader maps the kernel and starts it at its link
322222400Smarcel	 *	address (unlike the FreeBSD loader).
323222400Smarcel	 *  -	U-Boot passes the standard argc and argv parameters
324222400Smarcel	 *	in arg1 and arg2 (resp). arg1 is between 1 and some
325222400Smarcel	 *	relatively small number, such as 64K. arg2 is the
326222400Smarcel	 *	physical address of the argv vector.
327265996Sian	 *  -   ePAPR loaders pass an FDT blob in r3 (arg1) and the magic hex
328265996Sian	 *      string 0x45504150 ('ePAP') in r6 (which has been lost by now).
329265996Sian	 *      r4 (arg2) is supposed to be set to zero, but is not always.
330222400Smarcel	 */
331265996Sian
332265996Sian	if (arg1 == 0)				/* Juniper loader */
333265996Sian		mdp = (void *)arg2;
334265996Sian	else if (booke_check_for_fdt(arg1, &dtbp) == 0) { /* ePAPR */
335265996Sian		end = roundup(end, 8);
336265996Sian		memmove((void *)end, (void *)dtbp, fdt_totalsize((void *)dtbp));
337265996Sian		dtbp = end;
338265996Sian		end += fdt_totalsize((void *)dtbp);
339265996Sian		mdp = NULL;
340265996Sian	} else if (arg1 > (uintptr_t)kernel_text)	/* FreeBSD loader */
341222400Smarcel		mdp = (void *)arg1;
342222400Smarcel	else					/* U-Boot */
343222400Smarcel		mdp = NULL;
344222400Smarcel
345222400Smarcel	/*
346209908Sraj	 * Parse metadata and fetch parameters.
347176771Sraj	 */
348176771Sraj	if (mdp != NULL) {
349176771Sraj		preload_metadata = mdp;
350176771Sraj		kmdp = preload_search_by_type("elf kernel");
351176771Sraj		if (kmdp != NULL) {
352176771Sraj			boothowto = MD_FETCH(kmdp, MODINFOMD_HOWTO, int);
353176771Sraj			kern_envp = MD_FETCH(kmdp, MODINFOMD_ENVP, char *);
354209908Sraj			dtbp = MD_FETCH(kmdp, MODINFOMD_DTBP, vm_offset_t);
355176771Sraj			end = MD_FETCH(kmdp, MODINFOMD_KERNEND, vm_offset_t);
356217523Smarcel
357217523Smarcel			bootinfo = (uint32_t *)preload_search_info(kmdp,
358217523Smarcel			    MODINFO_METADATA | MODINFOMD_BOOTINFO);
359217523Smarcel
360191362Smarcel#ifdef DDB
361191362Smarcel			ksym_start = MD_FETCH(kmdp, MODINFOMD_SSYM, uintptr_t);
362191362Smarcel			ksym_end = MD_FETCH(kmdp, MODINFOMD_ESYM, uintptr_t);
363191362Smarcel#endif
364176771Sraj		}
365176771Sraj	} else {
366222400Smarcel		bzero(__sbss_start, __sbss_end - __sbss_start);
367222400Smarcel		bzero(__bss_start, _end - __bss_start);
368176771Sraj	}
369176771Sraj
370217523Smarcel#if defined(FDT_DTB_STATIC)
371217523Smarcel	/*
372217523Smarcel	 * In case the device tree blob was not retrieved (from metadata) try
373217523Smarcel	 * to use the statically embedded one.
374217523Smarcel	 */
375217523Smarcel	if (dtbp == (vm_offset_t)NULL)
376217523Smarcel		dtbp = (vm_offset_t)&fdt_static_dtb;
377217523Smarcel#endif
378217523Smarcel
379209908Sraj	if (OF_install(OFW_FDT, 0) == FALSE)
380209908Sraj		while (1);
381209908Sraj
382209908Sraj	if (OF_init((void *)dtbp) != 0)
383209908Sraj		while (1);
384209908Sraj
385209908Sraj	OF_interpret("perform-fixup", 0);
386236324Sraj
387265996Sian	/* Reset TLB1 to get rid of temporary mappings */
388265996Sian	tlb1_init();
389209908Sraj
390192532Sraj	/* Reset Time Base */
391192532Sraj	mttb(0);
392192532Sraj
393176771Sraj	/* Init params/tunables that can be overridden by the loader. */
394176771Sraj	init_param1();
395176771Sraj
396176771Sraj	/* Start initializing proc0 and thread0. */
397203924Sraj	proc_linkup0(&proc0, &thread0);
398176771Sraj	thread0.td_frame = &frame0;
399176771Sraj
400176771Sraj	/* Set up per-cpu data and store the pointer in SPR general 0. */
401176771Sraj	pc = &__pcpu[0];
402176771Sraj	pcpu_init(pc, 0, sizeof(struct pcpu));
403176771Sraj	pc->pc_curthread = &thread0;
404266001Sian#ifdef __powerpc64__
405266001Sian	__asm __volatile("mr 13,%0" :: "r"(pc->pc_curthread));
406266001Sian#else
407266001Sian	__asm __volatile("mr 2,%0" :: "r"(pc->pc_curthread));
408266001Sian#endif
409176771Sraj	__asm __volatile("mtsprg 0, %0" :: "r"(pc));
410176771Sraj
411176771Sraj	/* Initialize system mutexes. */
412176771Sraj	mutex_init();
413176771Sraj
414176771Sraj	/* Initialize the console before printing anything. */
415176771Sraj	cninit();
416176771Sraj
417176771Sraj	/* Print out some debug info... */
418222400Smarcel	debugf("%s: console initialized\n", __func__);
419186228Sraj	debugf(" arg3 mdp = 0x%08x\n", (u_int32_t)mdp);
420176771Sraj	debugf(" end = 0x%08x\n", (u_int32_t)end);
421176771Sraj	debugf(" boothowto = 0x%08x\n", boothowto);
422176771Sraj	debugf(" kernel ccsrbar = 0x%08x\n", CCSRBAR_VA);
423176771Sraj	debugf(" MSR = 0x%08x\n", mfmsr());
424236141Sraj#if defined(BOOKE_E500)
425186228Sraj	debugf(" HID0 = 0x%08x\n", mfspr(SPR_HID0));
426186228Sraj	debugf(" HID1 = 0x%08x\n", mfspr(SPR_HID1));
427192532Sraj	debugf(" BUCSR = 0x%08x\n", mfspr(SPR_BUCSR));
428236141Sraj#endif
429192532Sraj
430209908Sraj	debugf(" dtbp = 0x%08x\n", (uint32_t)dtbp);
431209908Sraj
432176771Sraj	print_kernel_section_addr();
433186228Sraj	print_kenv();
434236141Sraj#if defined(BOOKE_E500)
435176771Sraj	//tlb1_print_entries();
436176771Sraj	//tlb1_print_tlbentries();
437236141Sraj#endif
438176771Sraj
439176771Sraj	kdb_init();
440176771Sraj
441176771Sraj#ifdef KDB
442176771Sraj	if (boothowto & RB_KDB)
443176771Sraj		kdb_enter(KDB_WHY_BOOTFLAGS, "Boot flags requested debugger");
444176771Sraj#endif
445176771Sraj
446192067Snwhitehorn	/* Initialise platform module */
447192067Snwhitehorn	platform_probe_and_attach();
448192067Snwhitehorn
449176771Sraj	/* Initialise virtual memory. */
450176771Sraj	pmap_mmu_install(MMU_TYPE_BOOKE, 0);
451222400Smarcel	pmap_bootstrap((uintptr_t)kernel_text, end);
452242526Smarcel	pmap_bootstrapped = 1;
453176771Sraj	debugf("MSR = 0x%08x\n", mfmsr());
454236141Sraj#if defined(BOOKE_E500)
455176771Sraj	//tlb1_print_entries();
456176771Sraj	//tlb1_print_tlbentries();
457236141Sraj#endif
458176771Sraj
459176771Sraj	/* Initialize params/tunables that are derived from memsize. */
460176771Sraj	init_param2(physmem);
461176771Sraj
462176771Sraj	/* Finish setting up thread0. */
463176771Sraj	thread0.td_pcb = (struct pcb *)
464182198Sraj	    ((thread0.td_kstack + thread0.td_kstack_pages * PAGE_SIZE -
465182198Sraj	    sizeof(struct pcb)) & ~15);
466176771Sraj	bzero((void *)thread0.td_pcb, sizeof(struct pcb));
467176771Sraj	pc->pc_curpcb = thread0.td_pcb;
468176771Sraj
469176771Sraj	/* Initialise the message buffer. */
470217688Spluknet	msgbufinit(msgbufp, msgbufsize);
471176771Sraj
472176771Sraj	/* Enable Machine Check interrupt. */
473176771Sraj	mtmsr(mfmsr() | PSL_ME);
474176771Sraj	isync();
475176771Sraj
476236324Sraj	/* Enable L1 caches */
477236324Sraj	booke_enable_l1_cache();
478186228Sraj
479222400Smarcel	debugf("%s: SP = 0x%08x\n", __func__,
480222400Smarcel	    ((uintptr_t)thread0.td_pcb - 16) & ~15);
481182198Sraj
482182198Sraj	return (((uintptr_t)thread0.td_pcb - 16) & ~15);
483176771Sraj}
484176771Sraj
485192532Sraj#define RES_GRANULE 32
486192532Srajextern uint32_t tlb0_miss_locks[];
487192532Sraj
488176771Sraj/* Initialise a struct pcpu. */
489176771Srajvoid
490176771Srajcpu_pcpu_init(struct pcpu *pcpu, int cpuid, size_t sz)
491176771Sraj{
492176771Sraj
493187149Sraj	pcpu->pc_tid_next = TID_MIN;
494192532Sraj
495192532Sraj#ifdef SMP
496192532Sraj	uint32_t *ptr;
497192532Sraj	int words_per_gran = RES_GRANULE / sizeof(uint32_t);
498192532Sraj
499192532Sraj	ptr = &tlb0_miss_locks[cpuid * words_per_gran];
500192532Sraj	pcpu->pc_booke_tlb_lock = ptr;
501215119Sraj	*ptr = TLB_UNLOCKED;
502192532Sraj	*(ptr + 1) = 0;		/* recurse counter */
503192532Sraj#endif
504176771Sraj}
505176771Sraj
506192323Smarcel/*
507192323Smarcel * Flush the D-cache for non-DMA I/O so that the I-cache can
508192323Smarcel * be made coherent later.
509192323Smarcel */
510192323Smarcelvoid
511192323Smarcelcpu_flush_dcache(void *ptr, size_t len)
512192323Smarcel{
513238030Smarcel	register_t addr, off;
514238030Smarcel
515238030Smarcel	/*
516238030Smarcel	 * Align the address to a cacheline and adjust the length
517238030Smarcel	 * accordingly. Then round the length to a multiple of the
518238030Smarcel	 * cacheline for easy looping.
519238030Smarcel	 */
520238030Smarcel	addr = (uintptr_t)ptr;
521238030Smarcel	off = addr & (cacheline_size - 1);
522238030Smarcel	addr -= off;
523238030Smarcel	len = (len + off + cacheline_size - 1) & ~(cacheline_size - 1);
524238030Smarcel
525238030Smarcel	while (len > 0) {
526238030Smarcel		__asm __volatile ("dcbf 0,%0" :: "r"(addr));
527238030Smarcel		__asm __volatile ("sync");
528238030Smarcel		addr += cacheline_size;
529238030Smarcel		len -= cacheline_size;
530238030Smarcel	}
531192323Smarcel}
532192323Smarcel
533176771Srajvoid
534176771Srajspinlock_enter(void)
535176771Sraj{
536176771Sraj	struct thread *td;
537214835Sjhb	register_t msr;
538176771Sraj
539176771Sraj	td = curthread;
540214835Sjhb	if (td->td_md.md_spinlock_count == 0) {
541214835Sjhb		msr = intr_disable();
542214835Sjhb		td->td_md.md_spinlock_count = 1;
543214835Sjhb		td->td_md.md_saved_msr = msr;
544214835Sjhb	} else
545214835Sjhb		td->td_md.md_spinlock_count++;
546176771Sraj	critical_enter();
547176771Sraj}
548176771Sraj
549176771Srajvoid
550176771Srajspinlock_exit(void)
551176771Sraj{
552176771Sraj	struct thread *td;
553214835Sjhb	register_t msr;
554176771Sraj
555176771Sraj	td = curthread;
556176771Sraj	critical_exit();
557214835Sjhb	msr = td->td_md.md_saved_msr;
558176771Sraj	td->td_md.md_spinlock_count--;
559176771Sraj	if (td->td_md.md_spinlock_count == 0)
560214835Sjhb		intr_restore(msr);
561176771Sraj}
562176771Sraj
563176771Sraj/* Shutdown the CPU as much as possible. */
564176771Srajvoid
565176771Srajcpu_halt(void)
566176771Sraj{
567176771Sraj
568176771Sraj	mtmsr(mfmsr() & ~(PSL_CE | PSL_EE | PSL_ME | PSL_DE));
569236097Sraj	while (1)
570236097Sraj		;
571176771Sraj}
572176771Sraj
573176771Srajint
574176771Srajptrace_set_pc(struct thread *td, unsigned long addr)
575176771Sraj{
576176771Sraj	struct trapframe *tf;
577176771Sraj
578176771Sraj	tf = td->td_frame;
579176771Sraj	tf->srr0 = (register_t)addr;
580176771Sraj
581176771Sraj	return (0);
582176771Sraj}
583176771Sraj
584176771Srajint
585176771Srajptrace_single_step(struct thread *td)
586176771Sraj{
587176771Sraj	struct trapframe *tf;
588176771Sraj
589176771Sraj	tf = td->td_frame;
590176771Sraj	tf->srr1 |= PSL_DE;
591189100Sraj	tf->cpu.booke.dbcr0 |= (DBCR0_IDM | DBCR0_IC);
592176771Sraj	return (0);
593176771Sraj}
594176771Sraj
595176771Srajint
596176771Srajptrace_clear_single_step(struct thread *td)
597176771Sraj{
598176771Sraj	struct trapframe *tf;
599176771Sraj
600176771Sraj	tf = td->td_frame;
601176771Sraj	tf->srr1 &= ~PSL_DE;
602189100Sraj	tf->cpu.booke.dbcr0 &= ~(DBCR0_IDM | DBCR0_IC);
603176771Sraj	return (0);
604176771Sraj}
605176771Sraj
606176771Srajvoid
607176771Srajkdb_cpu_clear_singlestep(void)
608176771Sraj{
609176771Sraj	register_t r;
610176771Sraj
611176771Sraj	r = mfspr(SPR_DBCR0);
612176771Sraj	mtspr(SPR_DBCR0, r & ~DBCR0_IC);
613176771Sraj	kdb_frame->srr1 &= ~PSL_DE;
614176771Sraj}
615176771Sraj
616176771Srajvoid
617176771Srajkdb_cpu_set_singlestep(void)
618176771Sraj{
619176771Sraj	register_t r;
620176771Sraj
621176771Sraj	r = mfspr(SPR_DBCR0);
622176771Sraj	mtspr(SPR_DBCR0, r | DBCR0_IC | DBCR0_IDM);
623176771Sraj	kdb_frame->srr1 |= PSL_DE;
624176771Sraj}
625176771Sraj
626176771Srajvoid
627176771Srajbzero(void *buf, size_t len)
628176771Sraj{
629176771Sraj	caddr_t p;
630176771Sraj
631176771Sraj	p = buf;
632176771Sraj
633176771Sraj	while (((vm_offset_t) p & (sizeof(u_long) - 1)) && len) {
634176771Sraj		*p++ = 0;
635176771Sraj		len--;
636176771Sraj	}
637176771Sraj
638176771Sraj	while (len >= sizeof(u_long) * 8) {
639176771Sraj		*(u_long*) p = 0;
640176771Sraj		*((u_long*) p + 1) = 0;
641176771Sraj		*((u_long*) p + 2) = 0;
642176771Sraj		*((u_long*) p + 3) = 0;
643176771Sraj		len -= sizeof(u_long) * 8;
644176771Sraj		*((u_long*) p + 4) = 0;
645176771Sraj		*((u_long*) p + 5) = 0;
646176771Sraj		*((u_long*) p + 6) = 0;
647176771Sraj		*((u_long*) p + 7) = 0;
648176771Sraj		p += sizeof(u_long) * 8;
649176771Sraj	}
650176771Sraj
651176771Sraj	while (len >= sizeof(u_long)) {
652176771Sraj		*(u_long*) p = 0;
653176771Sraj		len -= sizeof(u_long);
654176771Sraj		p += sizeof(u_long);
655176771Sraj	}
656176771Sraj
657176771Sraj	while (len) {
658176771Sraj		*p++ = 0;
659176771Sraj		len--;
660176771Sraj	}
661176771Sraj}
662176771Sraj
663