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