main.c revision 165325
1139738Simp/*-
284996Srobert * Initial implementation:
384996Srobert * Copyright (c) 2001 Robert Drehmel
484996Srobert * All rights reserved.
584996Srobert *
684996Srobert * As long as the above copyright statement and this notice remain
784996Srobert * unchanged, you can do what ever you want with this file.
884996Srobert */
9124139Sobrien
10124139Sobrien#include <sys/cdefs.h>
11124139Sobrien__FBSDID("$FreeBSD: head/sys/boot/sparc64/loader/main.c 165325 2006-12-18 07:35:14Z kmacy $");
1284996Srobert/*
1384996Srobert * FreeBSD/sparc64 kernel loader - machine dependent part
1484996Srobert *
1584996Srobert *  - implements copyin and readin functions that map kernel
1684996Srobert *    pages on demand.  The machine independent code does not
1784996Srobert *    know the size of the kernel early enough to pre-enter
1884996Srobert *    TTEs and install just one 4MB mapping seemed to limiting
1984996Srobert *    to me.
2084996Srobert */
2191139Sjake
2284996Srobert#include <stand.h>
2384996Srobert#include <sys/exec.h>
2484996Srobert#include <sys/param.h>
25102219Srobert#include <sys/queue.h>
2684996Srobert#include <sys/linker.h>
27163145Skmacy#include <sys/types.h>
2884996Srobert
29163145Skmacy#include <vm/vm.h>
3084996Srobert#include <machine/asi.h>
3191139Sjake#include <machine/atomic.h>
3291139Sjake#include <machine/cpufunc.h>
3384996Srobert#include <machine/elf.h>
3491110Sjake#include <machine/lsu.h>
3591110Sjake#include <machine/metadata.h>
3684996Srobert#include <machine/tte.h>
3791139Sjake#include <machine/upa.h>
3884996Srobert
3984996Srobert#include "bootstrap.h"
4084996Srobert#include "libofw.h"
4185719Sjake#include "dev_net.h"
4284996Srobert
4384996Srobertenum {
4484996Srobert	HEAPVA		= 0x800000,
4584996Srobert	HEAPSZ		= 0x1000000,
4684996Srobert	LOADSZ		= 0x1000000	/* for kernel and modules */
4784996Srobert};
4884996Srobert
4984996Srobertstruct memory_slice {
5084996Srobert	vm_offset_t pstart;
5184996Srobert	vm_offset_t size;
5284996Srobert};
5384996Srobert
54163145Skmacystruct mmu_ops {
55163145Skmacy	void (*tlb_init)(void);
56163145Skmacy	int (*mmu_mapin)(vm_offset_t va, vm_size_t len);
57163145Skmacy} *mmu_ops;
58163145Skmacy
59163145Skmacy
6085719Sjaketypedef void kernel_entry_t(vm_offset_t mdp, u_long o1, u_long o2, u_long o3,
6185719Sjake			    void *openfirmware);
6285719Sjake
6393678Stmmextern void itlb_enter(u_long vpn, u_long data);
6493678Stmmextern void dtlb_enter(u_long vpn, u_long data);
6584996Srobertextern vm_offset_t itlb_va_to_pa(vm_offset_t);
6684996Srobertextern vm_offset_t dtlb_va_to_pa(vm_offset_t);
6785719Sjakeextern vm_offset_t md_load(char *, vm_offset_t *);
68114386Speterstatic int __elfN(exec)(struct preloaded_file *);
6984996Srobertstatic int sparc64_autoload(void);
70163145Skmacystatic int mmu_mapin_sun4u(vm_offset_t, vm_size_t);
71163145Skmacystatic int mmu_mapin_sun4v(vm_offset_t, vm_size_t);
72163145Skmacystatic void tlb_init_sun4u(void);
73163145Skmacystatic void tlb_init_sun4v(void);
7484996Srobert
75163145Skmacystruct mmu_ops mmu_ops_sun4u = 	{ tlb_init_sun4u, mmu_mapin_sun4u };
76163145Skmacystruct mmu_ops mmu_ops_sun4v = 	{ tlb_init_sun4v, mmu_mapin_sun4v };
77163145Skmacy
78101287Sjakeextern char bootprog_name[], bootprog_rev[], bootprog_date[], bootprog_maker[];
7984996Srobert
80163145Skmacy/* sun4u */
8197445Sjakestruct tlb_entry *dtlb_store;
8297445Sjakestruct tlb_entry *itlb_store;
83163145Skmacyint dtlb_slot;
84163145Skmacyint itlb_slot;
85163145Skmacyint dtlb_slot_max;
86163145Skmacyint itlb_slot_max;
8791139Sjake
88163145Skmacy/* sun4v */
89163145Skmacystruct tlb_entry *tlb_store;
90165325Skmacyint is_sun4v = 0;
91163145Skmacy/*
92163145Skmacy * no direct TLB access on sun4v
93163145Skmacy * we somewhat arbitrarily declare enough
94163145Skmacy * slots to cover a 4GB AS with 4MB pages
95163145Skmacy */
96163145Skmacy#define SUN4V_TLB_SLOT_MAX (1 << 10)
97163145Skmacy
98163145Skmacy
99163145Skmacyextern char bootprog_name[], bootprog_rev[], bootprog_date[], bootprog_maker[];
100163145Skmacy
101163145Skmacystruct tlb_entry *dtlb_store;
102163145Skmacystruct tlb_entry *itlb_store;
103163145Skmacy
10491139Sjakeint dtlb_slot;
10591139Sjakeint itlb_slot;
10691139Sjakeint dtlb_slot_max;
10791139Sjakeint itlb_slot_max;
10891139Sjake
10984996Srobertvm_offset_t curkva = 0;
11084996Srobertvm_offset_t heapva;
11184996Srobertphandle_t pmemh;	/* OFW memory handle */
11284996Srobert
11384996Srobertstruct memory_slice memslices[18];
11484996Srobert
11584996Srobert/*
11684996Srobert * Machine dependent structures that the machine independent
11784996Srobert * loader part uses.
11884996Srobert */
11984996Srobertstruct devsw *devsw[] = {
12085719Sjake#ifdef LOADER_DISK_SUPPORT
12184996Srobert	&ofwdisk,
12285719Sjake#endif
12385719Sjake#ifdef LOADER_NET_SUPPORT
12485719Sjake	&netdev,
12585719Sjake#endif
12684996Srobert	0
12784996Srobert};
12884996Srobertstruct arch_switch archsw;
12984996Srobert
13084996Srobertstruct file_format sparc64_elf = {
131114386Speter	__elfN(loadfile),
132114386Speter	__elfN(exec)
13384996Srobert};
13484996Srobertstruct file_format *file_formats[] = {
13584996Srobert	&sparc64_elf,
13684996Srobert	0
13784996Srobert};
13884996Srobertstruct fs_ops *file_system[] = {
13991110Sjake#ifdef LOADER_UFS_SUPPORT
14084996Srobert	&ufs_fsops,
14185719Sjake#endif
14293606Stmm#ifdef LOADER_CD9660_SUPPORT
14393606Stmm	&cd9660_fsops,
14493606Stmm#endif
145108100Sjake#ifdef LOADER_ZIP_SUPPORT
146105065Sjake	&zipfs_fsops,
147105065Sjake#endif
148108100Sjake#ifdef LOADER_GZIP_SUPPORT
149108100Sjake	&gzipfs_fsops,
150108100Sjake#endif
151105065Sjake#ifdef LOADER_BZIP2_SUPPORT
152105065Sjake	&bzipfs_fsops,
153105065Sjake#endif
154117448Stmm#ifdef LOADER_NFS_SUPPORT
15585719Sjake	&nfs_fsops,
15685719Sjake#endif
15791110Sjake#ifdef LOADER_TFTP_SUPPORT
15891110Sjake	&tftp_fsops,
15991110Sjake#endif
16084996Srobert	0
16184996Srobert};
16285719Sjakestruct netif_driver *netif_drivers[] = {
16385719Sjake#ifdef LOADER_NET_SUPPORT
16485719Sjake	&ofwnet,
16585719Sjake#endif
16685719Sjake	0
16785719Sjake};
16884996Srobert
16984996Srobertextern struct console ofwconsole;
17084996Srobertstruct console *consoles[] = {
17184996Srobert	&ofwconsole,
17284996Srobert	0
17384996Srobert};
17484996Srobert
17591110Sjake#ifdef LOADER_DEBUG
17691110Sjakestatic int
17791110Sjakewatch_phys_set_mask(vm_offset_t pa, u_long mask)
17891110Sjake{
17991110Sjake	u_long lsucr;
18091110Sjake
18191110Sjake	stxa(AA_DMMU_PWPR, ASI_DMMU, pa & (((2UL << 38) - 1) << 3));
18291110Sjake	lsucr = ldxa(0, ASI_LSU_CTL_REG);
18391110Sjake	lsucr = ((lsucr | LSU_PW) & ~LSU_PM_MASK) |
18491110Sjake	    (mask << LSU_PM_SHIFT);
18591110Sjake	stxa(0, ASI_LSU_CTL_REG, lsucr);
18691110Sjake	return (0);
18791110Sjake}
18891110Sjake
18991110Sjakestatic int
19091110Sjakewatch_phys_set(vm_offset_t pa, int sz)
19191110Sjake{
19291110Sjake	u_long off;
19391110Sjake
19491110Sjake	off = (u_long)pa & 7;
19591110Sjake	/* Test for misaligned watch points. */
19691110Sjake	if (off + sz > 8)
19791110Sjake		return (-1);
19891110Sjake	return (watch_phys_set_mask(pa, ((1 << sz) - 1) << off));
19991110Sjake}
20091110Sjake
20191110Sjake
20291110Sjakestatic int
20391110Sjakewatch_virt_set_mask(vm_offset_t va, u_long mask)
20491110Sjake{
20591110Sjake	u_long lsucr;
20691110Sjake
20791110Sjake	stxa(AA_DMMU_VWPR, ASI_DMMU, va & (((2UL << 41) - 1) << 3));
20891110Sjake	lsucr = ldxa(0, ASI_LSU_CTL_REG);
20991110Sjake	lsucr = ((lsucr | LSU_VW) & ~LSU_VM_MASK) |
21091110Sjake	    (mask << LSU_VM_SHIFT);
21191110Sjake	stxa(0, ASI_LSU_CTL_REG, lsucr);
21291110Sjake	return (0);
21391110Sjake}
21491110Sjake
21591110Sjakestatic int
21691110Sjakewatch_virt_set(vm_offset_t va, int sz)
21791110Sjake{
21891110Sjake	u_long off;
21991110Sjake
22091110Sjake	off = (u_long)va & 7;
22191110Sjake	/* Test for misaligned watch points. */
22291110Sjake	if (off + sz > 8)
22391110Sjake		return (-1);
22491110Sjake	return (watch_virt_set_mask(va, ((1 << sz) - 1) << off));
22591110Sjake}
22691110Sjake#endif
22791110Sjake
22884996Srobert/*
22984996Srobert * archsw functions
23084996Srobert */
23184996Srobertstatic int
23284996Srobertsparc64_autoload(void)
23384996Srobert{
234134944Skensmith	printf("nothing to autoload yet.\n");
23584996Srobert	return 0;
23684996Srobert}
23784996Srobert
23884996Srobertstatic ssize_t
23984996Srobertsparc64_readin(const int fd, vm_offset_t va, const size_t len)
24084996Srobert{
241163145Skmacy	mmu_ops->mmu_mapin(va, len);
24284996Srobert	return read(fd, (void *)va, len);
24384996Srobert}
24484996Srobert
24584996Srobertstatic ssize_t
24684996Srobertsparc64_copyin(const void *src, vm_offset_t dest, size_t len)
24784996Srobert{
248163145Skmacy	mmu_ops->mmu_mapin(dest, len);
24984996Srobert	memcpy((void *)dest, src, len);
25084996Srobert	return len;
25184996Srobert}
25284996Srobert
253165325Skmacystatic void
254165325Skmacysparc64_maphint(vm_offset_t va, size_t len)
255165325Skmacy{
256165325Skmacy	vm_paddr_t pa;
257165325Skmacy	vm_offset_t mva;
258165325Skmacy	size_t size;
259165325Skmacy	int i, ret, free_excess = 0;
260165325Skmacy
261165325Skmacy	if (!is_sun4v)
262165325Skmacy		return;
263165325Skmacy
264165325Skmacy	if (tlb_store[va >> 22].te_pa != -1)
265165325Skmacy		return;
266165325Skmacy
267165325Skmacy	/* round up to nearest 4MB page */
268165325Skmacy	size = (len + PAGE_MASK_4M) & ~PAGE_MASK_4M;
269165325Skmacy#if 0
270165325Skmacy	pa = (vm_offset_t)OF_alloc_phys(PAGE_SIZE_256M,	PAGE_SIZE_256M);
271165325Skmacy
272165325Skmacy	if (pa != -1)
273165325Skmacy		free_excess = 1;
274165325Skmacy	else
275165325Skmacy#endif
276165325Skmacy		pa = (vm_offset_t)OF_alloc_phys(size, PAGE_SIZE_256M);
277165325Skmacy	if (pa == -1)
278165325Skmacy		pa = (vm_offset_t)OF_alloc_phys(size, PAGE_SIZE_4M);
279165325Skmacy	if (pa == -1)
280165325Skmacy		panic("out of memory");
281165325Skmacy
282165325Skmacy	for (i = 0; i < size; i += PAGE_SIZE_4M) {
283165325Skmacy		mva = (vm_offset_t)OF_claim_virt(va + i, PAGE_SIZE_4M, 0);
284165325Skmacy		if (mva != (va + i)) {
285165325Skmacy			panic("can't claim virtual page "
286165325Skmacy			      "(wanted %#lx, got %#lx)",
287165325Skmacy			      va, mva);
288165325Skmacy		}
289165325Skmacy
290165325Skmacy		tlb_store[mva >> 22].te_pa = pa + i;
291165325Skmacy		if ((ret = OF_map_phys(-1, PAGE_SIZE_4M, mva, pa + i)) != 0)
292165325Skmacy			printf("OF_map_phys failed: %d\n", ret);
293165325Skmacy	}
294165325Skmacy	if (free_excess)
295165325Skmacy		OF_release_phys((vm_offset_t)pa, PAGE_SIZE_256M);
296165325Skmacy}
297165325Skmacy
298165325Skmacy
29984996Srobert/*
30084996Srobert * other MD functions
30184996Srobert */
30284996Srobertstatic int
303114386Speter__elfN(exec)(struct preloaded_file *fp)
30484996Srobert{
30584996Srobert	struct file_metadata *fmp;
30685719Sjake	vm_offset_t mdp;
307116415Sjake	Elf_Addr entry;
30891139Sjake	Elf_Ehdr *e;
30985719Sjake	int error;
31084996Srobert
31184996Srobert	if ((fmp = file_findmetadata(fp, MODINFOMD_ELFHDR)) == 0) {
31284996Srobert		return EFTYPE;
31384996Srobert	}
31491139Sjake	e = (Elf_Ehdr *)&fmp->md_data;
31584996Srobert
31685719Sjake	if ((error = md_load(fp->f_args, &mdp)) != 0)
31785719Sjake		return error;
31884996Srobert
31991139Sjake	printf("jumping to kernel entry at %#lx.\n", e->e_entry);
32084996Srobert#if 0
32184996Srobert	pmap_print_tlb('i');
32284996Srobert	pmap_print_tlb('d');
32384996Srobert#endif
32485719Sjake
325116415Sjake	entry = e->e_entry;
326116415Sjake
327165325Skmacy	OF_release((void *)heapva, HEAPSZ);
328116415Sjake
329116415Sjake	((kernel_entry_t *)entry)(mdp, 0, 0, 0, openfirmware);
330116415Sjake
33185719Sjake	panic("exec returned");
33284996Srobert}
33384996Srobert
33484996Srobertstatic int
335163145Skmacymmu_mapin_sun4u(vm_offset_t va, vm_size_t len)
33684996Srobert{
33791110Sjake	vm_offset_t pa, mva;
33897445Sjake	u_long data;
33984996Srobert
34084996Srobert	if (va + len > curkva)
34184996Srobert		curkva = va + len;
34284996Srobert
34391110Sjake	pa = (vm_offset_t)-1;
34485719Sjake	len += va & PAGE_MASK_4M;
34585719Sjake	va &= ~PAGE_MASK_4M;
34684996Srobert	while (len) {
34784996Srobert		if (dtlb_va_to_pa(va) == (vm_offset_t)-1 ||
34884996Srobert		    itlb_va_to_pa(va) == (vm_offset_t)-1) {
34991110Sjake			/* Allocate a physical page, claim the virtual area */
35091110Sjake			if (pa == (vm_offset_t)-1) {
35191110Sjake				pa = (vm_offset_t)OF_alloc_phys(PAGE_SIZE_4M,
35291110Sjake				    PAGE_SIZE_4M);
35391110Sjake				if (pa == (vm_offset_t)-1)
35491110Sjake					panic("out of memory");
35591110Sjake				mva = (vm_offset_t)OF_claim_virt(va,
35691110Sjake				    PAGE_SIZE_4M, 0);
35791110Sjake				if (mva != va) {
35891110Sjake					panic("can't claim virtual page "
35991110Sjake					    "(wanted %#lx, got %#lx)",
36091110Sjake					    va, mva);
36191110Sjake				}
36291110Sjake				/* The mappings may have changed, be paranoid. */
36391110Sjake				continue;
36491110Sjake			}
36593678Stmm			/*
36693678Stmm			 * Actually, we can only allocate two pages less at
36793678Stmm			 * most (depending on the kernel TSB size).
36893678Stmm			 */
36993678Stmm			if (dtlb_slot >= dtlb_slot_max)
37093678Stmm				panic("mmu_mapin: out of dtlb_slots");
37193678Stmm			if (itlb_slot >= itlb_slot_max)
37293678Stmm				panic("mmu_mapin: out of itlb_slots");
37397445Sjake			data = TD_V | TD_4M | TD_PA(pa) | TD_L | TD_CP |
37491139Sjake			    TD_CV | TD_P | TD_W;
37597445Sjake			dtlb_store[dtlb_slot].te_pa = pa;
37697445Sjake			dtlb_store[dtlb_slot].te_va = va;
37797445Sjake			itlb_store[itlb_slot].te_pa = pa;
37897445Sjake			itlb_store[itlb_slot].te_va = va;
37997445Sjake			dtlb_slot++;
38097445Sjake			itlb_slot++;
38197445Sjake			dtlb_enter(va, data);
38297445Sjake			itlb_enter(va, data);
38391110Sjake			pa = (vm_offset_t)-1;
38484996Srobert		}
38585719Sjake		len -= len > PAGE_SIZE_4M ? PAGE_SIZE_4M : len;
38685719Sjake		va += PAGE_SIZE_4M;
38784996Srobert	}
38891110Sjake	if (pa != (vm_offset_t)-1)
38991110Sjake		OF_release_phys(pa, PAGE_SIZE_4M);
390163145Skmacy
39184996Srobert	return 0;
39284996Srobert}
39384996Srobert
394163145Skmacystatic int
395163145Skmacymmu_mapin_sun4v(vm_offset_t va, vm_size_t len)
396163145Skmacy{
397163145Skmacy
398163145Skmacy	vm_offset_t pa, mva;
399163145Skmacy	u_long data;
400163145Skmacy	int ret;
401163145Skmacy
402163145Skmacy	if (va + len > curkva)
403163145Skmacy		curkva = va + len;
404163145Skmacy
405163145Skmacy	pa = (vm_offset_t)-1;
406163145Skmacy	len += va & PAGE_MASK_4M;
407163145Skmacy	va &= ~PAGE_MASK_4M;
408163145Skmacy	while (len) {
409163145Skmacy		if ((va >> 22) > SUN4V_TLB_SLOT_MAX)
410163145Skmacy			panic("trying to map more than 4GB");
411163145Skmacy		if (tlb_store[va >> 22].te_pa == -1) {
412163145Skmacy			/* Allocate a physical page, claim the virtual area */
413163145Skmacy			if (pa == (vm_offset_t)-1) {
414163145Skmacy				pa = (vm_offset_t)OF_alloc_phys(PAGE_SIZE_4M,
415163145Skmacy				    PAGE_SIZE_4M);
416163145Skmacy				if (pa == (vm_offset_t)-1)
417163145Skmacy					panic("out of memory");
418163145Skmacy				mva = (vm_offset_t)OF_claim_virt(va,
419163145Skmacy				    PAGE_SIZE_4M, 0);
420163145Skmacy				if (mva != va) {
421163145Skmacy					panic("can't claim virtual page "
422163145Skmacy					    "(wanted %#lx, got %#lx)",
423163145Skmacy					    va, mva);
424163145Skmacy				}
425163145Skmacy			}
426163145Skmacy
427163145Skmacy			tlb_store[va >> 22].te_pa = pa;
428163145Skmacy			if ((ret = OF_map_phys(-1, PAGE_SIZE_4M, va, pa)) != 0)
429163145Skmacy				printf("OF_map_phys failed: %d\n", ret);
430163145Skmacy			pa = (vm_offset_t)-1;
431163145Skmacy		}
432163145Skmacy		len -= len > PAGE_SIZE_4M ? PAGE_SIZE_4M : len;
433163145Skmacy		va += PAGE_SIZE_4M;
434163145Skmacy	}
435163145Skmacy	if (pa != (vm_offset_t)-1)
436163145Skmacy		OF_release_phys(pa, PAGE_SIZE_4M);
437163145Skmacy	return 0;
438163145Skmacy}
439163145Skmacy
44084996Srobertstatic vm_offset_t
44184996Srobertinit_heap(void)
44284996Srobert{
44384996Srobert	if ((pmemh = OF_finddevice("/memory")) == (phandle_t)-1)
44484996Srobert		OF_exit();
44585719Sjake	if (OF_getprop(pmemh, "available", memslices, sizeof(memslices)) <= 0)
44684996Srobert		OF_exit();
44784996Srobert
44884996Srobert	/* There is no need for continuous physical heap memory. */
44984996Srobert	heapva = (vm_offset_t)OF_claim((void *)HEAPVA, HEAPSZ, 32);
45084996Srobert	return heapva;
45184996Srobert}
45284996Srobert
45391139Sjakestatic void
454163145Skmacytlb_init_sun4u(void)
45591139Sjake{
45691139Sjake	phandle_t child;
45791139Sjake	phandle_t root;
45891139Sjake	char buf[128];
45991139Sjake	u_int bootcpu;
46091139Sjake	u_int cpu;
46191139Sjake
46291139Sjake	bootcpu = UPA_CR_GET_MID(ldxa(0, ASI_UPA_CONFIG_REG));
46391139Sjake	if ((root = OF_peer(0)) == -1)
46491139Sjake		panic("main: OF_peer");
46591139Sjake	for (child = OF_child(root); child != 0; child = OF_peer(child)) {
46691139Sjake		if (child == -1)
46791139Sjake			panic("main: OF_child");
46891139Sjake		if (OF_getprop(child, "device_type", buf, sizeof(buf)) > 0 &&
46991139Sjake		    strcmp(buf, "cpu") == 0) {
47091139Sjake			if (OF_getprop(child, "upa-portid", &cpu,
47196428Sjake			    sizeof(cpu)) == -1 && OF_getprop(child, "portid",
47296428Sjake			    &cpu, sizeof(cpu)) == -1)
47391139Sjake				panic("main: OF_getprop");
47491139Sjake			if (cpu == bootcpu)
47591139Sjake				break;
47691139Sjake		}
47791139Sjake	}
47891139Sjake	if (cpu != bootcpu)
47991139Sjake		panic("init_tlb: no node for bootcpu?!?!");
48091139Sjake	if (OF_getprop(child, "#dtlb-entries", &dtlb_slot_max,
48191139Sjake	    sizeof(dtlb_slot_max)) == -1 ||
48291139Sjake	    OF_getprop(child, "#itlb-entries", &itlb_slot_max,
48391139Sjake	    sizeof(itlb_slot_max)) == -1)
48491139Sjake		panic("init_tlb: OF_getprop");
48591139Sjake	dtlb_store = malloc(dtlb_slot_max * sizeof(*dtlb_store));
48691139Sjake	itlb_store = malloc(itlb_slot_max * sizeof(*itlb_store));
48791139Sjake	if (dtlb_store == NULL || itlb_store == NULL)
48891139Sjake		panic("init_tlb: malloc");
48991139Sjake}
49091139Sjake
491163145Skmacystatic void
492163145Skmacytlb_init_sun4v(void)
493163145Skmacy{
494163145Skmacy	tlb_store = malloc(SUN4V_TLB_SLOT_MAX * sizeof(*tlb_store));
495163145Skmacy	memset(tlb_store, 0xFF, SUN4V_TLB_SLOT_MAX * sizeof(*tlb_store));
496163145Skmacy}
497163145Skmacy
49885719Sjakeint
49985719Sjakemain(int (*openfirm)(void *))
50084996Srobert{
50184996Srobert	char bootpath[64];
502163145Skmacy	char compatible[32];
50384996Srobert	struct devsw **dp;
504163145Skmacy	phandle_t rooth;
50584996Srobert	phandle_t chosenh;
50684996Srobert
50784996Srobert	/*
508133862Smarius	 * Tell the Open Firmware functions where they find the ofw gate.
50984996Srobert	 */
51085719Sjake	OF_init(openfirm);
51184996Srobert
51284996Srobert	archsw.arch_getdev = ofw_getdev;
51384996Srobert	archsw.arch_copyin = sparc64_copyin;
51484996Srobert	archsw.arch_copyout = ofw_copyout;
51584996Srobert	archsw.arch_readin = sparc64_readin;
51684996Srobert	archsw.arch_autoload = sparc64_autoload;
517165325Skmacy	archsw.arch_maphint = sparc64_maphint;
51884996Srobert
51984996Srobert	init_heap();
52084996Srobert	setheap((void *)heapva, (void *)(heapva + HEAPSZ));
52184996Srobert	/*
52284996Srobert	 * Probe for a console.
52384996Srobert	 */
52484996Srobert	cons_probe();
52584996Srobert
526163145Skmacy	rooth = OF_peer(0);
527163145Skmacy	OF_getprop(rooth, "compatible", compatible, sizeof(compatible));
528163145Skmacy	if (!strcmp(compatible, "sun4v")) {
529163145Skmacy		printf("\nBooting with sun4v support.\n");
530163145Skmacy		mmu_ops = &mmu_ops_sun4v;
531165325Skmacy		is_sun4v = 1;
532163145Skmacy	} else {
533163145Skmacy		printf("\nBooting with sun4u support.\n");
534163145Skmacy		mmu_ops = &mmu_ops_sun4u;
535163145Skmacy	}
53691139Sjake
537163145Skmacy	mmu_ops->tlb_init();
538163145Skmacy
53984996Srobert	/*
54084996Srobert	 * Initialize devices.
54184996Srobert	 */
54284996Srobert	for (dp = devsw; *dp != 0; dp++) {
54384996Srobert		if ((*dp)->dv_init != 0)
54484996Srobert			(*dp)->dv_init();
54584996Srobert	}
54684996Srobert
54784996Srobert	/*
54884996Srobert	 * Set up the current device.
54984996Srobert	 */
55084996Srobert	chosenh = OF_finddevice("/chosen");
55184996Srobert	OF_getprop(chosenh, "bootpath", bootpath, sizeof(bootpath));
55284996Srobert
553106738Sjake	/*
554106738Sjake	 * Sun compatible bootable CD-ROMs have a disk label placed
555106738Sjake	 * before the cd9660 data, with the actual filesystem being
556106738Sjake	 * in the first partition, while the other partitions contain
557106738Sjake	 * pseudo disk labels with embedded boot blocks for different
558106738Sjake	 * architectures, which may be followed by UFS filesystems.
559106738Sjake	 * The firmware will set the boot path to the partition it
560106738Sjake	 * boots from ('f' in the sun4u case), but we want the kernel
561106738Sjake	 * to be loaded from the cd9660 fs ('a'), so the boot path
562106738Sjake	 * needs to be altered.
563106738Sjake	 */
564106738Sjake	if (bootpath[strlen(bootpath) - 2] == ':' &&
565106738Sjake	    bootpath[strlen(bootpath) - 1] == 'f') {
566106738Sjake		bootpath[strlen(bootpath) - 1] = 'a';
567106738Sjake		printf("Boot path set to %s\n", bootpath);
56884996Srobert	}
56984996Srobert
570106738Sjake	env_setenv("currdev", EV_VOLATILE, bootpath,
57184996Srobert	    ofw_setcurrdev, env_nounset);
572106738Sjake	env_setenv("loaddev", EV_VOLATILE, bootpath,
57384996Srobert	    env_noset, env_nounset);
57484996Srobert
575101287Sjake	printf("\n");
576101287Sjake	printf("%s, Revision %s\n", bootprog_name, bootprog_rev);
577101287Sjake	printf("(%s, %s)\n", bootprog_maker, bootprog_date);
57884996Srobert	printf("bootpath=\"%s\"\n", bootpath);
57984996Srobert
58084996Srobert	/* Give control to the machine independent loader code. */
58184996Srobert	interact();
58284996Srobert	return 1;
58384996Srobert}
58484996Srobert
58591110SjakeCOMMAND_SET(reboot, "reboot", "reboot the system", command_reboot);
58691110Sjake
58791110Sjakestatic int
58891110Sjakecommand_reboot(int argc, char *argv[])
58991110Sjake{
59091110Sjake	int i;
59191110Sjake
59291110Sjake	for (i = 0; devsw[i] != NULL; ++i)
59391110Sjake		if (devsw[i]->dv_cleanup != NULL)
59491110Sjake			(devsw[i]->dv_cleanup)();
59591110Sjake
59691110Sjake	printf("Rebooting...\n");
59791110Sjake	OF_exit();
59891110Sjake}
59991110Sjake
60091110Sjake/* provide this for panic, as it's not in the startup code */
60191110Sjakevoid
60291110Sjakeexit(int code)
60391110Sjake{
60491110Sjake	OF_exit();
60591110Sjake}
60691110Sjake
60791110Sjake#ifdef LOADER_DEBUG
60884996Sroberttypedef u_int64_t tte_t;
60984996Srobert
61084996Srobertconst char *page_sizes[] = {
61184996Srobert	"  8k", " 64k", "512k", "  4m"
61284996Srobert};
61384996Srobert
61484996Srobertstatic void
61584996Srobertpmap_print_tte(tte_t tag, tte_t tte)
61684996Srobert{
61784996Srobert	printf("%s %s ",
61884996Srobert	    page_sizes[(tte & TD_SIZE_MASK) >> TD_SIZE_SHIFT],
61984996Srobert	    tag & TD_G ? "G" : " ");
62084996Srobert	printf(tte & TD_W ? "W " : "  ");
62184996Srobert	printf(tte & TD_P ? "\e[33mP\e[0m " : "  ");
62284996Srobert	printf(tte & TD_E ? "E " : "  ");
62384996Srobert	printf(tte & TD_CV ? "CV " : "   ");
62484996Srobert	printf(tte & TD_CP ? "CP " : "   ");
62584996Srobert	printf(tte & TD_L ? "\e[32mL\e[0m " : "  ");
62684996Srobert	printf(tte & TD_IE ? "IE " : "   ");
62784996Srobert	printf(tte & TD_NFO ? "NFO " : "    ");
62884997Srobert	printf("tag=0x%lx pa=0x%lx va=0x%lx ctx=%ld\n", tag, TD_PA(tte),
62984996Srobert	    TT_VA(tag), TT_CTX(tag));
63084996Srobert}
63184996Srobertvoid
63284996Srobertpmap_print_tlb(char which)
63384996Srobert{
63484996Srobert	int i;
63584996Srobert	tte_t tte, tag;
63684996Srobert
63784996Srobert	for (i = 0; i < 64*8; i += 8) {
63884996Srobert		if (which == 'i') {
63984996Srobert			__asm__ __volatile__("ldxa	[%1] %2, %0\n" :
64084996Srobert			    "=r" (tag) : "r" (i),
64184996Srobert			    "i" (ASI_ITLB_TAG_READ_REG));
64284996Srobert			__asm__ __volatile__("ldxa	[%1] %2, %0\n" :
64384996Srobert			    "=r" (tte) : "r" (i),
64484996Srobert			    "i" (ASI_ITLB_DATA_ACCESS_REG));
64584996Srobert		}
64684996Srobert		else {
64784996Srobert			__asm__ __volatile__("ldxa	[%1] %2, %0\n" :
64884996Srobert			    "=r" (tag) : "r" (i),
64984996Srobert			    "i" (ASI_DTLB_TAG_READ_REG));
65084996Srobert			__asm__ __volatile__("ldxa	[%1] %2, %0\n" :
65184996Srobert			    "=r" (tte) : "r" (i),
65284996Srobert			    "i" (ASI_DTLB_DATA_ACCESS_REG));
65384996Srobert		}
65484996Srobert		if (!(tte & TD_V))
65584996Srobert			continue;
65684996Srobert		printf("%cTLB-%2u: ", which, i>>3);
65784996Srobert		pmap_print_tte(tag, tte);
65884996Srobert	}
65984996Srobert}
66091110Sjake#endif
661