main.c revision 170854
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 170854 2007-06-17 00:17:15Z marius $");
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
43170839Smariusextern char bootprog_name[], bootprog_rev[], bootprog_date[], bootprog_maker[];
44170839Smarius
4584996Srobertenum {
4684996Srobert	HEAPVA		= 0x800000,
4784996Srobert	HEAPSZ		= 0x1000000,
4884996Srobert	LOADSZ		= 0x1000000	/* for kernel and modules */
4984996Srobert};
5084996Srobert
51170839Smariusstatic struct mmu_ops {
52163145Skmacy	void (*tlb_init)(void);
53163145Skmacy	int (*mmu_mapin)(vm_offset_t va, vm_size_t len);
54163145Skmacy} *mmu_ops;
55163145Skmacy
5685719Sjaketypedef void kernel_entry_t(vm_offset_t mdp, u_long o1, u_long o2, u_long o3,
57170839Smarius    void *openfirmware);
5885719Sjake
5993678Stmmextern void itlb_enter(u_long vpn, u_long data);
6093678Stmmextern void dtlb_enter(u_long vpn, u_long data);
6184996Srobertextern vm_offset_t itlb_va_to_pa(vm_offset_t);
6284996Srobertextern vm_offset_t dtlb_va_to_pa(vm_offset_t);
6385719Sjakeextern vm_offset_t md_load(char *, vm_offset_t *);
64170839Smariusstatic int sparc64_autoload(void);
65170839Smariusstatic ssize_t sparc64_readin(const int, vm_offset_t, const size_t);
66170839Smariusstatic ssize_t sparc64_copyin(const void *, vm_offset_t, size_t);
67170839Smariusstatic void sparc64_maphint(vm_offset_t, size_t);
68170854Smariusstatic vm_offset_t claim_virt(vm_offset_t, size_t, int);
69170854Smariusstatic vm_offset_t alloc_phys(size_t, int);
70170854Smariusstatic int map_phys(int, size_t, vm_offset_t, vm_offset_t);
71170854Smariusstatic void release_phys(vm_offset_t, u_int);
72114386Speterstatic int __elfN(exec)(struct preloaded_file *);
73163145Skmacystatic int mmu_mapin_sun4u(vm_offset_t, vm_size_t);
74163145Skmacystatic int mmu_mapin_sun4v(vm_offset_t, vm_size_t);
75170839Smariusstatic vm_offset_t init_heap(void);
76163145Skmacystatic void tlb_init_sun4u(void);
77163145Skmacystatic void tlb_init_sun4v(void);
7884996Srobert
79170839Smariusstatic struct mmu_ops mmu_ops_sun4u = { tlb_init_sun4u, mmu_mapin_sun4u };
80170839Smariusstatic struct mmu_ops mmu_ops_sun4v = { tlb_init_sun4v, mmu_mapin_sun4v };
81163145Skmacy
82163145Skmacy/* sun4u */
8397445Sjakestruct tlb_entry *dtlb_store;
8497445Sjakestruct tlb_entry *itlb_store;
85163145Skmacyint dtlb_slot;
86163145Skmacyint itlb_slot;
87170839Smariusstatic int dtlb_slot_max;
88170839Smariusstatic int itlb_slot_max;
8991139Sjake
90163145Skmacy/* sun4v */
91170839Smariusstatic struct tlb_entry *tlb_store;
92170839Smariusstatic int is_sun4v = 0;
93170839Smarius/*
94163145Skmacy * no direct TLB access on sun4v
95170839Smarius * we somewhat arbitrarily declare enough
96163145Skmacy * slots to cover a 4GB AS with 4MB pages
97163145Skmacy */
98170839Smarius#define	SUN4V_TLB_SLOT_MAX	(1 << 10)
99163145Skmacy
100170839Smariusstatic vm_offset_t curkva = 0;
101170839Smariusstatic vm_offset_t heapva;
102163145Skmacy
103170854Smariusstatic phandle_t root;
10484996Srobert
10584996Srobert/*
10684996Srobert * Machine dependent structures that the machine independent
10784996Srobert * loader part uses.
10884996Srobert */
10984996Srobertstruct devsw *devsw[] = {
11085719Sjake#ifdef LOADER_DISK_SUPPORT
11184996Srobert	&ofwdisk,
11285719Sjake#endif
11385719Sjake#ifdef LOADER_NET_SUPPORT
11485719Sjake	&netdev,
11585719Sjake#endif
11684996Srobert	0
11784996Srobert};
11884996Srobertstruct arch_switch archsw;
11984996Srobert
120170839Smariusstatic struct file_format sparc64_elf = {
121114386Speter	__elfN(loadfile),
122114386Speter	__elfN(exec)
12384996Srobert};
12484996Srobertstruct file_format *file_formats[] = {
12584996Srobert	&sparc64_elf,
12684996Srobert	0
12784996Srobert};
12884996Srobertstruct fs_ops *file_system[] = {
12991110Sjake#ifdef LOADER_UFS_SUPPORT
13084996Srobert	&ufs_fsops,
13185719Sjake#endif
13293606Stmm#ifdef LOADER_CD9660_SUPPORT
13393606Stmm	&cd9660_fsops,
13493606Stmm#endif
135108100Sjake#ifdef LOADER_ZIP_SUPPORT
136105065Sjake	&zipfs_fsops,
137105065Sjake#endif
138108100Sjake#ifdef LOADER_GZIP_SUPPORT
139108100Sjake	&gzipfs_fsops,
140108100Sjake#endif
141105065Sjake#ifdef LOADER_BZIP2_SUPPORT
142105065Sjake	&bzipfs_fsops,
143105065Sjake#endif
144117448Stmm#ifdef LOADER_NFS_SUPPORT
14585719Sjake	&nfs_fsops,
14685719Sjake#endif
14791110Sjake#ifdef LOADER_TFTP_SUPPORT
14891110Sjake	&tftp_fsops,
14991110Sjake#endif
15084996Srobert	0
15184996Srobert};
15285719Sjakestruct netif_driver *netif_drivers[] = {
15385719Sjake#ifdef LOADER_NET_SUPPORT
15485719Sjake	&ofwnet,
15585719Sjake#endif
15685719Sjake	0
15785719Sjake};
15884996Srobert
15984996Srobertextern struct console ofwconsole;
16084996Srobertstruct console *consoles[] = {
16184996Srobert	&ofwconsole,
16284996Srobert	0
16384996Srobert};
16484996Srobert
16591110Sjake#ifdef LOADER_DEBUG
16691110Sjakestatic int
16791110Sjakewatch_phys_set_mask(vm_offset_t pa, u_long mask)
16891110Sjake{
16991110Sjake	u_long lsucr;
17091110Sjake
17191110Sjake	stxa(AA_DMMU_PWPR, ASI_DMMU, pa & (((2UL << 38) - 1) << 3));
17291110Sjake	lsucr = ldxa(0, ASI_LSU_CTL_REG);
17391110Sjake	lsucr = ((lsucr | LSU_PW) & ~LSU_PM_MASK) |
17491110Sjake	    (mask << LSU_PM_SHIFT);
17591110Sjake	stxa(0, ASI_LSU_CTL_REG, lsucr);
17691110Sjake	return (0);
17791110Sjake}
17891110Sjake
17991110Sjakestatic int
18091110Sjakewatch_phys_set(vm_offset_t pa, int sz)
18191110Sjake{
18291110Sjake	u_long off;
18391110Sjake
18491110Sjake	off = (u_long)pa & 7;
18591110Sjake	/* Test for misaligned watch points. */
18691110Sjake	if (off + sz > 8)
18791110Sjake		return (-1);
18891110Sjake	return (watch_phys_set_mask(pa, ((1 << sz) - 1) << off));
18991110Sjake}
19091110Sjake
19191110Sjake
19291110Sjakestatic int
19391110Sjakewatch_virt_set_mask(vm_offset_t va, u_long mask)
19491110Sjake{
19591110Sjake	u_long lsucr;
19691110Sjake
19791110Sjake	stxa(AA_DMMU_VWPR, ASI_DMMU, va & (((2UL << 41) - 1) << 3));
19891110Sjake	lsucr = ldxa(0, ASI_LSU_CTL_REG);
19991110Sjake	lsucr = ((lsucr | LSU_VW) & ~LSU_VM_MASK) |
20091110Sjake	    (mask << LSU_VM_SHIFT);
20191110Sjake	stxa(0, ASI_LSU_CTL_REG, lsucr);
20291110Sjake	return (0);
20391110Sjake}
20491110Sjake
20591110Sjakestatic int
20691110Sjakewatch_virt_set(vm_offset_t va, int sz)
20791110Sjake{
20891110Sjake	u_long off;
20991110Sjake
21091110Sjake	off = (u_long)va & 7;
21191110Sjake	/* Test for misaligned watch points. */
21291110Sjake	if (off + sz > 8)
21391110Sjake		return (-1);
21491110Sjake	return (watch_virt_set_mask(va, ((1 << sz) - 1) << off));
21591110Sjake}
21691110Sjake#endif
21791110Sjake
21884996Srobert/*
21984996Srobert * archsw functions
22084996Srobert */
22184996Srobertstatic int
22284996Srobertsparc64_autoload(void)
22384996Srobert{
224170839Smarius
225134944Skensmith	printf("nothing to autoload yet.\n");
226170839Smarius	return (0);
22784996Srobert}
22884996Srobert
22984996Srobertstatic ssize_t
23084996Srobertsparc64_readin(const int fd, vm_offset_t va, const size_t len)
23184996Srobert{
232170839Smarius
233163145Skmacy	mmu_ops->mmu_mapin(va, len);
234170839Smarius	return (read(fd, (void *)va, len));
23584996Srobert}
23684996Srobert
23784996Srobertstatic ssize_t
23884996Srobertsparc64_copyin(const void *src, vm_offset_t dest, size_t len)
23984996Srobert{
240170839Smarius
241163145Skmacy	mmu_ops->mmu_mapin(dest, len);
24284996Srobert	memcpy((void *)dest, src, len);
243170839Smarius	return (len);
24484996Srobert}
24584996Srobert
246165325Skmacystatic void
247165325Skmacysparc64_maphint(vm_offset_t va, size_t len)
248165325Skmacy{
249165325Skmacy	vm_paddr_t pa;
250165325Skmacy	vm_offset_t mva;
251165325Skmacy	size_t size;
252170854Smarius	int i, free_excess = 0;
253165325Skmacy
254165325Skmacy	if (!is_sun4v)
255165325Skmacy		return;
256165325Skmacy
257165325Skmacy	if (tlb_store[va >> 22].te_pa != -1)
258165325Skmacy		return;
259165325Skmacy
260165325Skmacy	/* round up to nearest 4MB page */
261165325Skmacy	size = (len + PAGE_MASK_4M) & ~PAGE_MASK_4M;
262170839Smarius#if 0
263170854Smarius	pa = alloc_phys(PAGE_SIZE_256M, PAGE_SIZE_256M);
264165325Skmacy
265165325Skmacy	if (pa != -1)
266165325Skmacy		free_excess = 1;
267165325Skmacy	else
268165325Skmacy#endif
269170854Smarius		pa = alloc_phys(size, PAGE_SIZE_256M);
270165325Skmacy	if (pa == -1)
271170854Smarius		pa = alloc_phys(size, PAGE_SIZE_4M);
272165325Skmacy	if (pa == -1)
273170854Smarius		panic("%s: out of memory", __func__);
274165325Skmacy
275165325Skmacy	for (i = 0; i < size; i += PAGE_SIZE_4M) {
276170854Smarius		mva = claim_virt(va + i, PAGE_SIZE_4M, 0);
277170839Smarius		if (mva != (va + i))
278170854Smarius			panic("%s: can't claim virtual page "
279170839Smarius			    "(wanted %#lx, got %#lx)",
280170854Smarius			    __func__, va, mva);
281165325Skmacy
282165325Skmacy		tlb_store[mva >> 22].te_pa = pa + i;
283170854Smarius		if (map_phys(-1, PAGE_SIZE_4M, mva, pa + i) != 0)
284170854Smarius			printf("%s: can't map physical page\n", __func__);
285165325Skmacy	}
286165325Skmacy	if (free_excess)
287170854Smarius		release_phys(pa, PAGE_SIZE_256M);
288165325Skmacy}
289165325Skmacy
29084996Srobert/*
29184996Srobert * other MD functions
29284996Srobert */
293170854Smariusstatic vm_offset_t
294170854Smariusclaim_virt(vm_offset_t virt, size_t size, int align)
295170854Smarius{
296170854Smarius	vm_offset_t mva;
297170854Smarius
298170854Smarius	if (OF_call_method("claim", mmu, 3, 1, virt, size, align, &mva) == -1)
299170854Smarius		return ((vm_offset_t)-1);
300170854Smarius	return (mva);
301170854Smarius}
302170854Smarius
303170854Smariusstatic vm_offset_t
304170854Smariusalloc_phys(size_t size, int align)
305170854Smarius{
306170854Smarius	cell_t phys_hi, phys_low;
307170854Smarius
308170854Smarius	if (OF_call_method("claim", memory, 2, 2, size, align, &phys_low,
309170854Smarius	    &phys_hi) == -1)
310170854Smarius		return ((vm_offset_t)-1);
311170854Smarius	return ((vm_offset_t)phys_hi << 32 | phys_low);
312170854Smarius}
313170854Smarius
31484996Srobertstatic int
315170854Smariusmap_phys(int mode, size_t size, vm_offset_t virt, vm_offset_t phys)
316170854Smarius{
317170854Smarius
318170854Smarius	return (OF_call_method("map", mmu, 5, 0, (uint32_t)phys,
319170854Smarius	    (uint32_t)(phys >> 32), virt, size, mode));
320170854Smarius}
321170854Smarius
322170854Smariusstatic void
323170854Smariusrelease_phys(vm_offset_t phys, u_int size)
324170854Smarius{
325170854Smarius
326170854Smarius	(void)OF_call_method("release", memory, 3, 0, (uint32_t)phys,
327170854Smarius	    (uint32_t)(phys >> 32), size);
328170854Smarius}
329170854Smarius
330170854Smariusstatic int
331114386Speter__elfN(exec)(struct preloaded_file *fp)
33284996Srobert{
33384996Srobert	struct file_metadata *fmp;
33485719Sjake	vm_offset_t mdp;
335116415Sjake	Elf_Addr entry;
33691139Sjake	Elf_Ehdr *e;
33785719Sjake	int error;
33884996Srobert
339170839Smarius	if ((fmp = file_findmetadata(fp, MODINFOMD_ELFHDR)) == 0)
340170839Smarius		return (EFTYPE);
34191139Sjake	e = (Elf_Ehdr *)&fmp->md_data;
34284996Srobert
34385719Sjake	if ((error = md_load(fp->f_args, &mdp)) != 0)
344170839Smarius		return (error);
34584996Srobert
34691139Sjake	printf("jumping to kernel entry at %#lx.\n", e->e_entry);
34784996Srobert#if 0
34884996Srobert	pmap_print_tlb('i');
34984996Srobert	pmap_print_tlb('d');
35084996Srobert#endif
35185719Sjake
352116415Sjake	entry = e->e_entry;
353116415Sjake
354165325Skmacy	OF_release((void *)heapva, HEAPSZ);
355116415Sjake
356116415Sjake	((kernel_entry_t *)entry)(mdp, 0, 0, 0, openfirmware);
357116415Sjake
358170854Smarius	panic("%s: exec returned", __func__);
35984996Srobert}
36084996Srobert
36184996Srobertstatic int
362163145Skmacymmu_mapin_sun4u(vm_offset_t va, vm_size_t len)
36384996Srobert{
36491110Sjake	vm_offset_t pa, mva;
36597445Sjake	u_long data;
36684996Srobert
36784996Srobert	if (va + len > curkva)
36884996Srobert		curkva = va + len;
36984996Srobert
37091110Sjake	pa = (vm_offset_t)-1;
37185719Sjake	len += va & PAGE_MASK_4M;
37285719Sjake	va &= ~PAGE_MASK_4M;
37384996Srobert	while (len) {
37484996Srobert		if (dtlb_va_to_pa(va) == (vm_offset_t)-1 ||
37584996Srobert		    itlb_va_to_pa(va) == (vm_offset_t)-1) {
37691110Sjake			/* Allocate a physical page, claim the virtual area */
37791110Sjake			if (pa == (vm_offset_t)-1) {
378170854Smarius				pa = alloc_phys(PAGE_SIZE_4M, PAGE_SIZE_4M);
37991110Sjake				if (pa == (vm_offset_t)-1)
380170854Smarius					panic("%s: out of memory", __func__);
381170854Smarius				mva = claim_virt(va, PAGE_SIZE_4M, 0);
382170839Smarius				if (mva != va)
383170854Smarius					panic("%s: can't claim virtual page "
38491110Sjake					    "(wanted %#lx, got %#lx)",
385170854Smarius					    __func__, va, mva);
38691110Sjake				/* The mappings may have changed, be paranoid. */
38791110Sjake				continue;
38891110Sjake			}
38993678Stmm			/*
39093678Stmm			 * Actually, we can only allocate two pages less at
39193678Stmm			 * most (depending on the kernel TSB size).
39293678Stmm			 */
39393678Stmm			if (dtlb_slot >= dtlb_slot_max)
394170839Smarius				panic("%s: out of dtlb_slots", __func__);
39593678Stmm			if (itlb_slot >= itlb_slot_max)
396170839Smarius				panic("%s: out of itlb_slots", __func__);
39797445Sjake			data = TD_V | TD_4M | TD_PA(pa) | TD_L | TD_CP |
39891139Sjake			    TD_CV | TD_P | TD_W;
39997445Sjake			dtlb_store[dtlb_slot].te_pa = pa;
40097445Sjake			dtlb_store[dtlb_slot].te_va = va;
40197445Sjake			itlb_store[itlb_slot].te_pa = pa;
40297445Sjake			itlb_store[itlb_slot].te_va = va;
40397445Sjake			dtlb_slot++;
40497445Sjake			itlb_slot++;
40597445Sjake			dtlb_enter(va, data);
40697445Sjake			itlb_enter(va, data);
40791110Sjake			pa = (vm_offset_t)-1;
40884996Srobert		}
40985719Sjake		len -= len > PAGE_SIZE_4M ? PAGE_SIZE_4M : len;
41085719Sjake		va += PAGE_SIZE_4M;
41184996Srobert	}
41291110Sjake	if (pa != (vm_offset_t)-1)
413170854Smarius		release_phys(pa, PAGE_SIZE_4M);
414170839Smarius	return (0);
41584996Srobert}
41684996Srobert
417163145Skmacystatic int
418163145Skmacymmu_mapin_sun4v(vm_offset_t va, vm_size_t len)
419163145Skmacy{
420163145Skmacy	vm_offset_t pa, mva;
421163145Skmacy
422163145Skmacy	if (va + len > curkva)
423163145Skmacy		curkva = va + len;
424163145Skmacy
425163145Skmacy	pa = (vm_offset_t)-1;
426163145Skmacy	len += va & PAGE_MASK_4M;
427163145Skmacy	va &= ~PAGE_MASK_4M;
428163145Skmacy	while (len) {
429163145Skmacy		if ((va >> 22) > SUN4V_TLB_SLOT_MAX)
430170854Smarius			panic("%s: trying to map more than 4GB", __func__);
431163145Skmacy		if (tlb_store[va >> 22].te_pa == -1) {
432163145Skmacy			/* Allocate a physical page, claim the virtual area */
433163145Skmacy			if (pa == (vm_offset_t)-1) {
434170854Smarius				pa = alloc_phys(PAGE_SIZE_4M, PAGE_SIZE_4M);
435163145Skmacy				if (pa == (vm_offset_t)-1)
436170854Smarius				    panic("%s: out of memory", __func__);
437170854Smarius				mva = claim_virt(va, PAGE_SIZE_4M, 0);
438170839Smarius				if (mva != va)
439170854Smarius					panic("%s: can't claim virtual page "
440163145Skmacy					    "(wanted %#lx, got %#lx)",
441170854Smarius					    __func__, va, mva);
442163145Skmacy			}
443163145Skmacy
444163145Skmacy			tlb_store[va >> 22].te_pa = pa;
445170854Smarius			if (map_phys(-1, PAGE_SIZE_4M, va, pa) == -1)
446170854Smarius				printf("%s: can't map physical page\n",
447170854Smarius				    __func__);
448163145Skmacy			pa = (vm_offset_t)-1;
449163145Skmacy		}
450163145Skmacy		len -= len > PAGE_SIZE_4M ? PAGE_SIZE_4M : len;
451163145Skmacy		va += PAGE_SIZE_4M;
452163145Skmacy	}
453163145Skmacy	if (pa != (vm_offset_t)-1)
454170854Smarius		release_phys(pa, PAGE_SIZE_4M);
455170839Smarius	return (0);
456163145Skmacy}
457163145Skmacy
45884996Srobertstatic vm_offset_t
45984996Srobertinit_heap(void)
46084996Srobert{
46184996Srobert
46284996Srobert	/* There is no need for continuous physical heap memory. */
46384996Srobert	heapva = (vm_offset_t)OF_claim((void *)HEAPVA, HEAPSZ, 32);
464170839Smarius	return (heapva);
46584996Srobert}
46684996Srobert
46791139Sjakestatic void
468163145Skmacytlb_init_sun4u(void)
46991139Sjake{
47091139Sjake	phandle_t child;
47191139Sjake	char buf[128];
47291139Sjake	u_int bootcpu;
47391139Sjake	u_int cpu;
47491139Sjake
47591139Sjake	bootcpu = UPA_CR_GET_MID(ldxa(0, ASI_UPA_CONFIG_REG));
47691139Sjake	for (child = OF_child(root); child != 0; child = OF_peer(child)) {
47791139Sjake		if (child == -1)
478170854Smarius			panic("%s: can't get child phandle", __func__);
47991139Sjake		if (OF_getprop(child, "device_type", buf, sizeof(buf)) > 0 &&
48091139Sjake		    strcmp(buf, "cpu") == 0) {
48191139Sjake			if (OF_getprop(child, "upa-portid", &cpu,
48296428Sjake			    sizeof(cpu)) == -1 && OF_getprop(child, "portid",
48396428Sjake			    &cpu, sizeof(cpu)) == -1)
484170854Smarius				panic("%s: can't get portid", __func__);
48591139Sjake			if (cpu == bootcpu)
48691139Sjake				break;
48791139Sjake		}
48891139Sjake	}
48991139Sjake	if (cpu != bootcpu)
490170839Smarius		panic("%s: no node for bootcpu?!?!", __func__);
49191139Sjake	if (OF_getprop(child, "#dtlb-entries", &dtlb_slot_max,
49291139Sjake	    sizeof(dtlb_slot_max)) == -1 ||
49391139Sjake	    OF_getprop(child, "#itlb-entries", &itlb_slot_max,
49491139Sjake	    sizeof(itlb_slot_max)) == -1)
495170854Smarius		panic("%s: can't get TLB slot max.", __func__);
49691139Sjake	dtlb_store = malloc(dtlb_slot_max * sizeof(*dtlb_store));
49791139Sjake	itlb_store = malloc(itlb_slot_max * sizeof(*itlb_store));
49891139Sjake	if (dtlb_store == NULL || itlb_store == NULL)
499170854Smarius		panic("%s: can't allocate TLB store", __func__);
50091139Sjake}
50191139Sjake
502163145Skmacystatic void
503163145Skmacytlb_init_sun4v(void)
504163145Skmacy{
505170839Smarius
506163145Skmacy	tlb_store = malloc(SUN4V_TLB_SLOT_MAX * sizeof(*tlb_store));
507163145Skmacy	memset(tlb_store, 0xFF, SUN4V_TLB_SLOT_MAX * sizeof(*tlb_store));
508163145Skmacy}
509163145Skmacy
51085719Sjakeint
51185719Sjakemain(int (*openfirm)(void *))
51284996Srobert{
51384996Srobert	char bootpath[64];
514163145Skmacy	char compatible[32];
51584996Srobert	struct devsw **dp;
51684996Srobert
51784996Srobert	/*
518133862Smarius	 * Tell the Open Firmware functions where they find the ofw gate.
51984996Srobert	 */
52085719Sjake	OF_init(openfirm);
52184996Srobert
52284996Srobert	archsw.arch_getdev = ofw_getdev;
52384996Srobert	archsw.arch_copyin = sparc64_copyin;
52484996Srobert	archsw.arch_copyout = ofw_copyout;
52584996Srobert	archsw.arch_readin = sparc64_readin;
52684996Srobert	archsw.arch_autoload = sparc64_autoload;
527165325Skmacy	archsw.arch_maphint = sparc64_maphint;
52884996Srobert
52984996Srobert	init_heap();
53084996Srobert	setheap((void *)heapva, (void *)(heapva + HEAPSZ));
531170839Smarius
53284996Srobert	/*
53384996Srobert	 * Probe for a console.
53484996Srobert	 */
53584996Srobert	cons_probe();
53684996Srobert
537170854Smarius	if ((root = OF_peer(0)) == -1)
538170854Smarius		panic("%s: can't get root phandle", __func__);
539170854Smarius	OF_getprop(root, "compatible", compatible, sizeof(compatible));
540163145Skmacy	if (!strcmp(compatible, "sun4v")) {
541163145Skmacy		printf("\nBooting with sun4v support.\n");
542163145Skmacy		mmu_ops = &mmu_ops_sun4v;
543165325Skmacy		is_sun4v = 1;
544163145Skmacy	} else {
545163145Skmacy		printf("\nBooting with sun4u support.\n");
546163145Skmacy		mmu_ops = &mmu_ops_sun4u;
547163145Skmacy	}
54891139Sjake
549163145Skmacy	mmu_ops->tlb_init();
550163145Skmacy
55184996Srobert	/*
55284996Srobert	 * Initialize devices.
55384996Srobert	 */
55484996Srobert	for (dp = devsw; *dp != 0; dp++) {
55584996Srobert		if ((*dp)->dv_init != 0)
55684996Srobert			(*dp)->dv_init();
55784996Srobert	}
55884996Srobert
55984996Srobert	/*
56084996Srobert	 * Set up the current device.
56184996Srobert	 */
562170854Smarius	OF_getprop(chosen, "bootpath", bootpath, sizeof(bootpath));
56384996Srobert
564106738Sjake	/*
565106738Sjake	 * Sun compatible bootable CD-ROMs have a disk label placed
566106738Sjake	 * before the cd9660 data, with the actual filesystem being
567106738Sjake	 * in the first partition, while the other partitions contain
568106738Sjake	 * pseudo disk labels with embedded boot blocks for different
569106738Sjake	 * architectures, which may be followed by UFS filesystems.
570106738Sjake	 * The firmware will set the boot path to the partition it
571106738Sjake	 * boots from ('f' in the sun4u case), but we want the kernel
572106738Sjake	 * to be loaded from the cd9660 fs ('a'), so the boot path
573106738Sjake	 * needs to be altered.
574106738Sjake	 */
575106738Sjake	if (bootpath[strlen(bootpath) - 2] == ':' &&
576106738Sjake	    bootpath[strlen(bootpath) - 1] == 'f') {
577106738Sjake		bootpath[strlen(bootpath) - 1] = 'a';
578106738Sjake		printf("Boot path set to %s\n", bootpath);
57984996Srobert	}
58084996Srobert
581106738Sjake	env_setenv("currdev", EV_VOLATILE, bootpath,
58284996Srobert	    ofw_setcurrdev, env_nounset);
583106738Sjake	env_setenv("loaddev", EV_VOLATILE, bootpath,
58484996Srobert	    env_noset, env_nounset);
58584996Srobert
586101287Sjake	printf("\n");
587101287Sjake	printf("%s, Revision %s\n", bootprog_name, bootprog_rev);
588101287Sjake	printf("(%s, %s)\n", bootprog_maker, bootprog_date);
58984996Srobert	printf("bootpath=\"%s\"\n", bootpath);
59084996Srobert
59184996Srobert	/* Give control to the machine independent loader code. */
59284996Srobert	interact();
593170839Smarius	return (1);
59484996Srobert}
59584996Srobert
59691110SjakeCOMMAND_SET(reboot, "reboot", "reboot the system", command_reboot);
59791110Sjake
59891110Sjakestatic int
59991110Sjakecommand_reboot(int argc, char *argv[])
60091110Sjake{
60191110Sjake	int i;
60291110Sjake
60391110Sjake	for (i = 0; devsw[i] != NULL; ++i)
60491110Sjake		if (devsw[i]->dv_cleanup != NULL)
60591110Sjake			(devsw[i]->dv_cleanup)();
60691110Sjake
60791110Sjake	printf("Rebooting...\n");
60891110Sjake	OF_exit();
60991110Sjake}
61091110Sjake
61191110Sjake/* provide this for panic, as it's not in the startup code */
61291110Sjakevoid
61391110Sjakeexit(int code)
61491110Sjake{
615170839Smarius
61691110Sjake	OF_exit();
61791110Sjake}
61891110Sjake
61991110Sjake#ifdef LOADER_DEBUG
62084996Sroberttypedef u_int64_t tte_t;
62184996Srobert
622170839Smariusstatic const char *page_sizes[] = {
62384996Srobert	"  8k", " 64k", "512k", "  4m"
62484996Srobert};
62584996Srobert
62684996Srobertstatic void
62784996Srobertpmap_print_tte(tte_t tag, tte_t tte)
62884996Srobert{
629170839Smarius
63084996Srobert	printf("%s %s ",
63184996Srobert	    page_sizes[(tte & TD_SIZE_MASK) >> TD_SIZE_SHIFT],
63284996Srobert	    tag & TD_G ? "G" : " ");
63384996Srobert	printf(tte & TD_W ? "W " : "  ");
63484996Srobert	printf(tte & TD_P ? "\e[33mP\e[0m " : "  ");
63584996Srobert	printf(tte & TD_E ? "E " : "  ");
63684996Srobert	printf(tte & TD_CV ? "CV " : "   ");
63784996Srobert	printf(tte & TD_CP ? "CP " : "   ");
63884996Srobert	printf(tte & TD_L ? "\e[32mL\e[0m " : "  ");
63984996Srobert	printf(tte & TD_IE ? "IE " : "   ");
64084996Srobert	printf(tte & TD_NFO ? "NFO " : "    ");
64184997Srobert	printf("tag=0x%lx pa=0x%lx va=0x%lx ctx=%ld\n", tag, TD_PA(tte),
64284996Srobert	    TT_VA(tag), TT_CTX(tag));
64384996Srobert}
64484996Srobertvoid
64584996Srobertpmap_print_tlb(char which)
64684996Srobert{
64784996Srobert	int i;
64884996Srobert	tte_t tte, tag;
64984996Srobert
65084996Srobert	for (i = 0; i < 64*8; i += 8) {
65184996Srobert		if (which == 'i') {
65284996Srobert			__asm__ __volatile__("ldxa	[%1] %2, %0\n" :
65384996Srobert			    "=r" (tag) : "r" (i),
65484996Srobert			    "i" (ASI_ITLB_TAG_READ_REG));
65584996Srobert			__asm__ __volatile__("ldxa	[%1] %2, %0\n" :
65684996Srobert			    "=r" (tte) : "r" (i),
65784996Srobert			    "i" (ASI_ITLB_DATA_ACCESS_REG));
65884996Srobert		}
65984996Srobert		else {
66084996Srobert			__asm__ __volatile__("ldxa	[%1] %2, %0\n" :
66184996Srobert			    "=r" (tag) : "r" (i),
66284996Srobert			    "i" (ASI_DTLB_TAG_READ_REG));
66384996Srobert			__asm__ __volatile__("ldxa	[%1] %2, %0\n" :
66484996Srobert			    "=r" (tte) : "r" (i),
66584996Srobert			    "i" (ASI_DTLB_DATA_ACCESS_REG));
66684996Srobert		}
66784996Srobert		if (!(tte & TD_V))
66884996Srobert			continue;
66984996Srobert		printf("%cTLB-%2u: ", which, i>>3);
67084996Srobert		pmap_print_tte(tag, tte);
67184996Srobert	}
67284996Srobert}
67391110Sjake#endif
674