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 7181398Smarius * unchanged, you can do what ever you want with this file. 884996Srobert */ 9182916Smarius/*- 10238904Smarius * Copyright (c) 2008 - 2012 Marius Strobl <marius@FreeBSD.org> 11182916Smarius * All rights reserved. 12182916Smarius * 13182916Smarius * Redistribution and use in source and binary forms, with or without 14182916Smarius * modification, are permitted provided that the following conditions 15182916Smarius * are met: 16182916Smarius * 1. Redistributions of source code must retain the above copyright 17182916Smarius * notice, this list of conditions and the following disclaimer. 18182916Smarius * 2. Redistributions in binary form must reproduce the above copyright 19182916Smarius * notice, this list of conditions and the following disclaimer in the 20182916Smarius * documentation and/or other materials provided with the distribution. 21182916Smarius * 22182916Smarius * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 23182916Smarius * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24182916Smarius * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25182916Smarius * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 26182916Smarius * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27182916Smarius * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28182916Smarius * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29182916Smarius * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30182916Smarius * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31182916Smarius * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32182916Smarius * SUCH DAMAGE. 33182916Smarius */ 34124139Sobrien 35124139Sobrien#include <sys/cdefs.h> 36124139Sobrien__FBSDID("$FreeBSD$"); 37182020Smarius 3884996Srobert/* 3984996Srobert * FreeBSD/sparc64 kernel loader - machine dependent part 4084996Srobert * 4184996Srobert * - implements copyin and readin functions that map kernel 4284996Srobert * pages on demand. The machine independent code does not 4384996Srobert * know the size of the kernel early enough to pre-enter 4484996Srobert * TTEs and install just one 4MB mapping seemed to limiting 4584996Srobert * to me. 4684996Srobert */ 4791139Sjake 4884996Srobert#include <stand.h> 49203829Smarius#include <sys/param.h> 5084996Srobert#include <sys/exec.h> 51203829Smarius#include <sys/linker.h> 52102219Srobert#include <sys/queue.h> 53163145Skmacy#include <sys/types.h> 54236076Smarius#ifdef LOADER_ZFS_SUPPORT 55236076Smarius#include <sys/vtoc.h> 56237766Savg#include "../zfs/libzfs.h" 57236076Smarius#endif 5884996Srobert 59163145Skmacy#include <vm/vm.h> 6084996Srobert#include <machine/asi.h> 61203829Smarius#include <machine/cmt.h> 6291139Sjake#include <machine/cpufunc.h> 6384996Srobert#include <machine/elf.h> 64203829Smarius#include <machine/fireplane.h> 65203829Smarius#include <machine/jbus.h> 6691110Sjake#include <machine/lsu.h> 6791110Sjake#include <machine/metadata.h> 6884996Srobert#include <machine/tte.h> 69181398Smarius#include <machine/tlb.h> 7091139Sjake#include <machine/upa.h> 71182478Smarius#include <machine/ver.h> 72182877Smarius#include <machine/vmparam.h> 7384996Srobert 7484996Srobert#include "bootstrap.h" 7584996Srobert#include "libofw.h" 7685719Sjake#include "dev_net.h" 7784996Srobert 78170839Smariusextern char bootprog_name[], bootprog_rev[], bootprog_date[], bootprog_maker[]; 79170839Smarius 8084996Srobertenum { 8184996Srobert HEAPVA = 0x800000, 8284996Srobert HEAPSZ = 0x1000000, 8384996Srobert LOADSZ = 0x1000000 /* for kernel and modules */ 8484996Srobert}; 8584996Srobert 86203829Smarius/* At least Sun Fire V1280 require page sized allocations to be claimed. */ 87203829SmariusCTASSERT(HEAPSZ % PAGE_SIZE == 0); 88203829Smarius 89170839Smariusstatic struct mmu_ops { 90163145Skmacy void (*tlb_init)(void); 91163145Skmacy int (*mmu_mapin)(vm_offset_t va, vm_size_t len); 92163145Skmacy} *mmu_ops; 93163145Skmacy 9485719Sjaketypedef void kernel_entry_t(vm_offset_t mdp, u_long o1, u_long o2, u_long o3, 95170839Smarius void *openfirmware); 9685719Sjake 97223719Smariusstatic inline u_long dtlb_get_data_sun4u(u_int, u_int); 98203830Smariusstatic int dtlb_enter_sun4u(u_int, u_long data, vm_offset_t); 99181398Smariusstatic vm_offset_t dtlb_va_to_pa_sun4u(vm_offset_t); 100223719Smariusstatic inline u_long itlb_get_data_sun4u(u_int, u_int); 101203830Smariusstatic int itlb_enter_sun4u(u_int, u_long data, vm_offset_t); 102181398Smariusstatic vm_offset_t itlb_va_to_pa_sun4u(vm_offset_t); 103182916Smariusstatic void itlb_relocate_locked0_sun4u(void); 10485719Sjakeextern vm_offset_t md_load(char *, vm_offset_t *); 105170839Smariusstatic int sparc64_autoload(void); 106170839Smariusstatic ssize_t sparc64_readin(const int, vm_offset_t, const size_t); 107170839Smariusstatic ssize_t sparc64_copyin(const void *, vm_offset_t, size_t); 108170854Smariusstatic vm_offset_t claim_virt(vm_offset_t, size_t, int); 109170854Smariusstatic vm_offset_t alloc_phys(size_t, int); 110170854Smariusstatic int map_phys(int, size_t, vm_offset_t, vm_offset_t); 111170854Smariusstatic void release_phys(vm_offset_t, u_int); 112114386Speterstatic int __elfN(exec)(struct preloaded_file *); 113163145Skmacystatic int mmu_mapin_sun4u(vm_offset_t, vm_size_t); 114170839Smariusstatic vm_offset_t init_heap(void); 115203829Smariusstatic phandle_t find_bsp_sun4u(phandle_t, uint32_t); 116203829Smariusconst char *cpu_cpuid_prop_sun4u(void); 117203829Smariusuint32_t cpu_get_mid_sun4u(void); 118163145Skmacystatic void tlb_init_sun4u(void); 11984996Srobert 120181398Smarius#ifdef LOADER_DEBUG 121181398Smariustypedef u_int64_t tte_t; 122181398Smarius 123181398Smariusstatic void pmap_print_tlb_sun4u(void); 124181398Smariusstatic void pmap_print_tte_sun4u(tte_t, tte_t); 125181398Smarius#endif 126181398Smarius 127170839Smariusstatic struct mmu_ops mmu_ops_sun4u = { tlb_init_sun4u, mmu_mapin_sun4u }; 128163145Skmacy 129163145Skmacy/* sun4u */ 13097445Sjakestruct tlb_entry *dtlb_store; 13197445Sjakestruct tlb_entry *itlb_store; 132203829Smariusu_int dtlb_slot; 133203829Smariusu_int itlb_slot; 134204152Smariusstatic int cpu_impl; 135203829Smariusstatic u_int dtlb_slot_max; 136203829Smariusstatic u_int itlb_slot_max; 137223719Smariusstatic u_int tlb_locked; 13891139Sjake 139170839Smariusstatic vm_offset_t curkva = 0; 140170839Smariusstatic vm_offset_t heapva; 141163145Skmacy 142237815Smariusstatic char bootpath[64]; 143170854Smariusstatic phandle_t root; 14484996Srobert 145245943Savg#ifdef LOADER_ZFS_SUPPORT 146245943Savgstatic struct zfs_devdesc zfs_currdev; 147245943Savg#endif 148245943Savg 14984996Srobert/* 15084996Srobert * Machine dependent structures that the machine independent 15184996Srobert * loader part uses. 15284996Srobert */ 15384996Srobertstruct devsw *devsw[] = { 15485719Sjake#ifdef LOADER_DISK_SUPPORT 15584996Srobert &ofwdisk, 15685719Sjake#endif 15785719Sjake#ifdef LOADER_NET_SUPPORT 15885719Sjake &netdev, 15985719Sjake#endif 160236076Smarius#ifdef LOADER_ZFS_SUPPORT 161236076Smarius &zfs_dev, 162236076Smarius#endif 163252296Smarius NULL 16484996Srobert}; 165252296Smarius 16684996Srobertstruct arch_switch archsw; 16784996Srobert 168170839Smariusstatic struct file_format sparc64_elf = { 169114386Speter __elfN(loadfile), 170114386Speter __elfN(exec) 17184996Srobert}; 172252296Smarius 17384996Srobertstruct file_format *file_formats[] = { 17484996Srobert &sparc64_elf, 175252296Smarius NULL 17684996Srobert}; 177236076Smarius 17884996Srobertstruct fs_ops *file_system[] = { 179243243Sae#ifdef LOADER_ZFS_SUPPORT 180243243Sae &zfs_fsops, 181243243Sae#endif 18291110Sjake#ifdef LOADER_UFS_SUPPORT 18384996Srobert &ufs_fsops, 18485719Sjake#endif 18593606Stmm#ifdef LOADER_CD9660_SUPPORT 18693606Stmm &cd9660_fsops, 18793606Stmm#endif 188108100Sjake#ifdef LOADER_ZIP_SUPPORT 189105065Sjake &zipfs_fsops, 190105065Sjake#endif 191108100Sjake#ifdef LOADER_GZIP_SUPPORT 192108100Sjake &gzipfs_fsops, 193108100Sjake#endif 194105065Sjake#ifdef LOADER_BZIP2_SUPPORT 195105065Sjake &bzipfs_fsops, 196105065Sjake#endif 197117448Stmm#ifdef LOADER_NFS_SUPPORT 19885719Sjake &nfs_fsops, 19985719Sjake#endif 20091110Sjake#ifdef LOADER_TFTP_SUPPORT 20191110Sjake &tftp_fsops, 20291110Sjake#endif 203252296Smarius NULL 20484996Srobert}; 205252296Smarius 20685719Sjakestruct netif_driver *netif_drivers[] = { 20785719Sjake#ifdef LOADER_NET_SUPPORT 20885719Sjake &ofwnet, 20985719Sjake#endif 210252296Smarius NULL 21185719Sjake}; 21284996Srobert 21384996Srobertextern struct console ofwconsole; 21484996Srobertstruct console *consoles[] = { 21584996Srobert &ofwconsole, 216252296Smarius NULL 21784996Srobert}; 21884996Srobert 21991110Sjake#ifdef LOADER_DEBUG 22091110Sjakestatic int 22191110Sjakewatch_phys_set_mask(vm_offset_t pa, u_long mask) 22291110Sjake{ 22391110Sjake u_long lsucr; 22491110Sjake 22591110Sjake stxa(AA_DMMU_PWPR, ASI_DMMU, pa & (((2UL << 38) - 1) << 3)); 22691110Sjake lsucr = ldxa(0, ASI_LSU_CTL_REG); 22791110Sjake lsucr = ((lsucr | LSU_PW) & ~LSU_PM_MASK) | 22891110Sjake (mask << LSU_PM_SHIFT); 22991110Sjake stxa(0, ASI_LSU_CTL_REG, lsucr); 23091110Sjake return (0); 23191110Sjake} 23291110Sjake 23391110Sjakestatic int 23491110Sjakewatch_phys_set(vm_offset_t pa, int sz) 23591110Sjake{ 23691110Sjake u_long off; 23791110Sjake 23891110Sjake off = (u_long)pa & 7; 23991110Sjake /* Test for misaligned watch points. */ 24091110Sjake if (off + sz > 8) 24191110Sjake return (-1); 24291110Sjake return (watch_phys_set_mask(pa, ((1 << sz) - 1) << off)); 24391110Sjake} 24491110Sjake 24591110Sjake 24691110Sjakestatic int 24791110Sjakewatch_virt_set_mask(vm_offset_t va, u_long mask) 24891110Sjake{ 24991110Sjake u_long lsucr; 25091110Sjake 25191110Sjake stxa(AA_DMMU_VWPR, ASI_DMMU, va & (((2UL << 41) - 1) << 3)); 25291110Sjake lsucr = ldxa(0, ASI_LSU_CTL_REG); 25391110Sjake lsucr = ((lsucr | LSU_VW) & ~LSU_VM_MASK) | 25491110Sjake (mask << LSU_VM_SHIFT); 25591110Sjake stxa(0, ASI_LSU_CTL_REG, lsucr); 25691110Sjake return (0); 25791110Sjake} 25891110Sjake 25991110Sjakestatic int 26091110Sjakewatch_virt_set(vm_offset_t va, int sz) 26191110Sjake{ 26291110Sjake u_long off; 26391110Sjake 26491110Sjake off = (u_long)va & 7; 26591110Sjake /* Test for misaligned watch points. */ 26691110Sjake if (off + sz > 8) 26791110Sjake return (-1); 26891110Sjake return (watch_virt_set_mask(va, ((1 << sz) - 1) << off)); 26991110Sjake} 27091110Sjake#endif 27191110Sjake 27284996Srobert/* 27384996Srobert * archsw functions 27484996Srobert */ 27584996Srobertstatic int 27684996Srobertsparc64_autoload(void) 27784996Srobert{ 278170839Smarius 279170839Smarius return (0); 28084996Srobert} 28184996Srobert 28284996Srobertstatic ssize_t 28384996Srobertsparc64_readin(const int fd, vm_offset_t va, const size_t len) 28484996Srobert{ 285170839Smarius 286163145Skmacy mmu_ops->mmu_mapin(va, len); 287170839Smarius return (read(fd, (void *)va, len)); 28884996Srobert} 28984996Srobert 29084996Srobertstatic ssize_t 29184996Srobertsparc64_copyin(const void *src, vm_offset_t dest, size_t len) 29284996Srobert{ 293170839Smarius 294163145Skmacy mmu_ops->mmu_mapin(dest, len); 29584996Srobert memcpy((void *)dest, src, len); 296170839Smarius return (len); 29784996Srobert} 29884996Srobert 29984996Srobert/* 30084996Srobert * other MD functions 30184996Srobert */ 302170854Smariusstatic vm_offset_t 303170854Smariusclaim_virt(vm_offset_t virt, size_t size, int align) 304170854Smarius{ 305170854Smarius vm_offset_t mva; 306170854Smarius 307170854Smarius if (OF_call_method("claim", mmu, 3, 1, virt, size, align, &mva) == -1) 308170854Smarius return ((vm_offset_t)-1); 309170854Smarius return (mva); 310170854Smarius} 311170854Smarius 312170854Smariusstatic vm_offset_t 313170854Smariusalloc_phys(size_t size, int align) 314170854Smarius{ 315170854Smarius cell_t phys_hi, phys_low; 316170854Smarius 317170854Smarius if (OF_call_method("claim", memory, 2, 2, size, align, &phys_low, 318170854Smarius &phys_hi) == -1) 319170854Smarius return ((vm_offset_t)-1); 320170854Smarius return ((vm_offset_t)phys_hi << 32 | phys_low); 321170854Smarius} 322170854Smarius 32384996Srobertstatic int 324170854Smariusmap_phys(int mode, size_t size, vm_offset_t virt, vm_offset_t phys) 325170854Smarius{ 326170854Smarius 327170854Smarius return (OF_call_method("map", mmu, 5, 0, (uint32_t)phys, 328170854Smarius (uint32_t)(phys >> 32), virt, size, mode)); 329170854Smarius} 330170854Smarius 331170854Smariusstatic void 332170854Smariusrelease_phys(vm_offset_t phys, u_int size) 333170854Smarius{ 334170854Smarius 335170854Smarius (void)OF_call_method("release", memory, 3, 0, (uint32_t)phys, 336170854Smarius (uint32_t)(phys >> 32), size); 337170854Smarius} 338170854Smarius 339170854Smariusstatic int 340114386Speter__elfN(exec)(struct preloaded_file *fp) 34184996Srobert{ 34284996Srobert struct file_metadata *fmp; 34385719Sjake vm_offset_t mdp; 344116415Sjake Elf_Addr entry; 34591139Sjake Elf_Ehdr *e; 34685719Sjake int error; 34784996Srobert 348170839Smarius if ((fmp = file_findmetadata(fp, MODINFOMD_ELFHDR)) == 0) 349170839Smarius return (EFTYPE); 35091139Sjake e = (Elf_Ehdr *)&fmp->md_data; 35184996Srobert 35285719Sjake if ((error = md_load(fp->f_args, &mdp)) != 0) 353170839Smarius return (error); 35484996Srobert 35591139Sjake printf("jumping to kernel entry at %#lx.\n", e->e_entry); 356188455Smarius#ifdef LOADER_DEBUG 357181398Smarius pmap_print_tlb_sun4u(); 35884996Srobert#endif 35985719Sjake 360200946Smarius dev_cleanup(); 361200946Smarius 362116415Sjake entry = e->e_entry; 363116415Sjake 364165325Skmacy OF_release((void *)heapva, HEAPSZ); 365116415Sjake 366116415Sjake ((kernel_entry_t *)entry)(mdp, 0, 0, 0, openfirmware); 367116415Sjake 368170854Smarius panic("%s: exec returned", __func__); 36984996Srobert} 37084996Srobert 371182478Smariusstatic inline u_long 372223719Smariusdtlb_get_data_sun4u(u_int tlb, u_int slot) 373182478Smarius{ 374223719Smarius u_long data, pstate; 375182478Smarius 376223719Smarius slot = TLB_DAR_SLOT(tlb, slot); 377182478Smarius /* 378223719Smarius * We read ASI_DTLB_DATA_ACCESS_REG twice back-to-back in order to 379223719Smarius * work around errata of USIII and beyond. 380182478Smarius */ 381223719Smarius pstate = rdpr(pstate); 382223719Smarius wrpr(pstate, pstate & ~PSTATE_IE, 0); 383223719Smarius (void)ldxa(slot, ASI_DTLB_DATA_ACCESS_REG); 384223719Smarius data = ldxa(slot, ASI_DTLB_DATA_ACCESS_REG); 385223719Smarius wrpr(pstate, pstate, 0); 386223719Smarius return (data); 387182478Smarius} 388182478Smarius 389182478Smariusstatic inline u_long 390223719Smariusitlb_get_data_sun4u(u_int tlb, u_int slot) 391182478Smarius{ 392223719Smarius u_long data, pstate; 393182478Smarius 394223719Smarius slot = TLB_DAR_SLOT(tlb, slot); 395182478Smarius /* 396223719Smarius * We read ASI_DTLB_DATA_ACCESS_REG twice back-to-back in order to 397223719Smarius * work around errata of USIII and beyond. 398182478Smarius */ 399223719Smarius pstate = rdpr(pstate); 400223719Smarius wrpr(pstate, pstate & ~PSTATE_IE, 0); 401223719Smarius (void)ldxa(slot, ASI_ITLB_DATA_ACCESS_REG); 402223719Smarius data = ldxa(slot, ASI_ITLB_DATA_ACCESS_REG); 403223719Smarius wrpr(pstate, pstate, 0); 404223719Smarius return (data); 405182478Smarius} 406182478Smarius 407181398Smariusstatic vm_offset_t 408181398Smariusdtlb_va_to_pa_sun4u(vm_offset_t va) 409181398Smarius{ 410182766Smarius u_long pstate, reg; 411223719Smarius u_int i, tlb; 412181398Smarius 413182766Smarius pstate = rdpr(pstate); 414182766Smarius wrpr(pstate, pstate & ~PSTATE_IE, 0); 415181398Smarius for (i = 0; i < dtlb_slot_max; i++) { 416223719Smarius reg = ldxa(TLB_DAR_SLOT(tlb_locked, i), 417223719Smarius ASI_DTLB_TAG_READ_REG); 418181398Smarius if (TLB_TAR_VA(reg) != va) 419181398Smarius continue; 420223719Smarius reg = dtlb_get_data_sun4u(tlb_locked, i); 421182766Smarius wrpr(pstate, pstate, 0); 422191071Smarius reg >>= TD_PA_SHIFT; 423207537Smarius if (cpu_impl == CPU_IMPL_SPARC64V || 424207537Smarius cpu_impl >= CPU_IMPL_ULTRASPARCIII) 425191071Smarius return (reg & TD_PA_CH_MASK); 426191071Smarius return (reg & TD_PA_SF_MASK); 427181398Smarius } 428182766Smarius wrpr(pstate, pstate, 0); 429181398Smarius return (-1); 430181398Smarius} 431181398Smarius 432181398Smariusstatic vm_offset_t 433181398Smariusitlb_va_to_pa_sun4u(vm_offset_t va) 434181398Smarius{ 435182766Smarius u_long pstate, reg; 436181398Smarius int i; 437181398Smarius 438182766Smarius pstate = rdpr(pstate); 439182766Smarius wrpr(pstate, pstate & ~PSTATE_IE, 0); 440181398Smarius for (i = 0; i < itlb_slot_max; i++) { 441223719Smarius reg = ldxa(TLB_DAR_SLOT(tlb_locked, i), 442223719Smarius ASI_ITLB_TAG_READ_REG); 443181398Smarius if (TLB_TAR_VA(reg) != va) 444181398Smarius continue; 445223719Smarius reg = itlb_get_data_sun4u(tlb_locked, i); 446182766Smarius wrpr(pstate, pstate, 0); 447191071Smarius reg >>= TD_PA_SHIFT; 448207537Smarius if (cpu_impl == CPU_IMPL_SPARC64V || 449207537Smarius cpu_impl >= CPU_IMPL_ULTRASPARCIII) 450191071Smarius return (reg & TD_PA_CH_MASK); 451191071Smarius return (reg & TD_PA_SF_MASK); 452181398Smarius } 453182766Smarius wrpr(pstate, pstate, 0); 454181398Smarius return (-1); 455181398Smarius} 456181398Smarius 457203830Smariusstatic int 458203830Smariusdtlb_enter_sun4u(u_int index, u_long data, vm_offset_t virt) 459181398Smarius{ 460181398Smarius 461203830Smarius return (OF_call_method("SUNW,dtlb-load", mmu, 3, 0, index, data, 462203830Smarius virt)); 463181398Smarius} 464181398Smarius 465203830Smariusstatic int 466203830Smariusitlb_enter_sun4u(u_int index, u_long data, vm_offset_t virt) 467181398Smarius{ 468181398Smarius 469203830Smarius if (cpu_impl == CPU_IMPL_ULTRASPARCIIIp && index == 0 && 470203830Smarius (data & TD_L) != 0) 471203830Smarius panic("%s: won't enter locked TLB entry at index 0 on USIII+", 472203830Smarius __func__); 473203830Smarius return (OF_call_method("SUNW,itlb-load", mmu, 3, 0, index, data, 474203830Smarius virt)); 475181398Smarius} 476181398Smarius 477182916Smariusstatic void 478182916Smariusitlb_relocate_locked0_sun4u(void) 479182916Smarius{ 480182916Smarius u_long data, pstate, tag; 481182916Smarius int i; 482182916Smarius 483182916Smarius if (cpu_impl != CPU_IMPL_ULTRASPARCIIIp) 484182916Smarius return; 485182916Smarius 486182916Smarius pstate = rdpr(pstate); 487182916Smarius wrpr(pstate, pstate & ~PSTATE_IE, 0); 488182916Smarius 489223719Smarius data = itlb_get_data_sun4u(tlb_locked, 0); 490182916Smarius if ((data & (TD_V | TD_L)) != (TD_V | TD_L)) { 491182916Smarius wrpr(pstate, pstate, 0); 492182916Smarius return; 493182916Smarius } 494182916Smarius 495182916Smarius /* Flush the mapping of slot 0. */ 496223719Smarius tag = ldxa(TLB_DAR_SLOT(tlb_locked, 0), ASI_ITLB_TAG_READ_REG); 497182916Smarius stxa(TLB_DEMAP_VA(TLB_TAR_VA(tag)) | TLB_DEMAP_PRIMARY | 498182916Smarius TLB_DEMAP_PAGE, ASI_IMMU_DEMAP, 0); 499182916Smarius flush(0); /* The USIII-family ignores the address. */ 500182916Smarius 501182916Smarius /* 502182916Smarius * Search a replacement slot != 0 and enter the data and tag 503182916Smarius * that formerly were in slot 0. 504182916Smarius */ 505182916Smarius for (i = 1; i < itlb_slot_max; i++) { 506223719Smarius if ((itlb_get_data_sun4u(tlb_locked, i) & TD_V) != 0) 507182916Smarius continue; 508182916Smarius 509182916Smarius stxa(AA_IMMU_TAR, ASI_IMMU, tag); 510223719Smarius stxa(TLB_DAR_SLOT(tlb_locked, i), ASI_ITLB_DATA_ACCESS_REG, 511223719Smarius data); 512182916Smarius flush(0); /* The USIII-family ignores the address. */ 513182916Smarius break; 514182916Smarius } 515182916Smarius wrpr(pstate, pstate, 0); 516182916Smarius if (i == itlb_slot_max) 517182916Smarius panic("%s: could not find a replacement slot", __func__); 518182916Smarius} 519182916Smarius 52084996Srobertstatic int 521163145Skmacymmu_mapin_sun4u(vm_offset_t va, vm_size_t len) 52284996Srobert{ 52391110Sjake vm_offset_t pa, mva; 52497445Sjake u_long data; 525203830Smarius u_int index; 52684996Srobert 52784996Srobert if (va + len > curkva) 52884996Srobert curkva = va + len; 52984996Srobert 53091110Sjake pa = (vm_offset_t)-1; 53185719Sjake len += va & PAGE_MASK_4M; 53285719Sjake va &= ~PAGE_MASK_4M; 53384996Srobert while (len) { 534181398Smarius if (dtlb_va_to_pa_sun4u(va) == (vm_offset_t)-1 || 535181398Smarius itlb_va_to_pa_sun4u(va) == (vm_offset_t)-1) { 536182020Smarius /* Allocate a physical page, claim the virtual area. */ 53791110Sjake if (pa == (vm_offset_t)-1) { 538170854Smarius pa = alloc_phys(PAGE_SIZE_4M, PAGE_SIZE_4M); 53991110Sjake if (pa == (vm_offset_t)-1) 540170854Smarius panic("%s: out of memory", __func__); 541170854Smarius mva = claim_virt(va, PAGE_SIZE_4M, 0); 542170839Smarius if (mva != va) 543170854Smarius panic("%s: can't claim virtual page " 54491110Sjake "(wanted %#lx, got %#lx)", 545170854Smarius __func__, va, mva); 546182020Smarius /* 547182020Smarius * The mappings may have changed, be paranoid. 548182020Smarius */ 54991110Sjake continue; 55091110Sjake } 55193678Stmm /* 55293678Stmm * Actually, we can only allocate two pages less at 55393678Stmm * most (depending on the kernel TSB size). 55493678Stmm */ 55593678Stmm if (dtlb_slot >= dtlb_slot_max) 556170839Smarius panic("%s: out of dtlb_slots", __func__); 55793678Stmm if (itlb_slot >= itlb_slot_max) 558170839Smarius panic("%s: out of itlb_slots", __func__); 55997445Sjake data = TD_V | TD_4M | TD_PA(pa) | TD_L | TD_CP | 56091139Sjake TD_CV | TD_P | TD_W; 56197445Sjake dtlb_store[dtlb_slot].te_pa = pa; 56297445Sjake dtlb_store[dtlb_slot].te_va = va; 563203830Smarius index = dtlb_slot_max - dtlb_slot - 1; 564203830Smarius if (dtlb_enter_sun4u(index, data, va) < 0) 565203830Smarius panic("%s: can't enter dTLB slot %d data " 566203831Smarius "%#lx va %#lx", __func__, index, data, 567203831Smarius va); 568203830Smarius dtlb_slot++; 56997445Sjake itlb_store[itlb_slot].te_pa = pa; 57097445Sjake itlb_store[itlb_slot].te_va = va; 571203830Smarius index = itlb_slot_max - itlb_slot - 1; 572203830Smarius if (itlb_enter_sun4u(index, data, va) < 0) 573203830Smarius panic("%s: can't enter iTLB slot %d data " 574203831Smarius "%#lx va %#lxd", __func__, index, data, 575203831Smarius va); 57697445Sjake itlb_slot++; 57791110Sjake pa = (vm_offset_t)-1; 57884996Srobert } 57985719Sjake len -= len > PAGE_SIZE_4M ? PAGE_SIZE_4M : len; 58085719Sjake va += PAGE_SIZE_4M; 58184996Srobert } 58291110Sjake if (pa != (vm_offset_t)-1) 583170854Smarius release_phys(pa, PAGE_SIZE_4M); 584170839Smarius return (0); 58584996Srobert} 58684996Srobert 58784996Srobertstatic vm_offset_t 58884996Srobertinit_heap(void) 58984996Srobert{ 59084996Srobert 59184996Srobert /* There is no need for continuous physical heap memory. */ 59284996Srobert heapva = (vm_offset_t)OF_claim((void *)HEAPVA, HEAPSZ, 32); 593170839Smarius return (heapva); 59484996Srobert} 59584996Srobert 596203829Smariusstatic phandle_t 597203829Smariusfind_bsp_sun4u(phandle_t node, uint32_t bspid) 598203829Smarius{ 599203829Smarius char type[sizeof("cpu")]; 600203829Smarius phandle_t child; 601203829Smarius uint32_t cpuid; 602203829Smarius 603203829Smarius for (; node > 0; node = OF_peer(node)) { 604203829Smarius child = OF_child(node); 605203829Smarius if (child > 0) { 606203829Smarius child = find_bsp_sun4u(child, bspid); 607203829Smarius if (child > 0) 608203829Smarius return (child); 609203829Smarius } else { 610203829Smarius if (OF_getprop(node, "device_type", type, 611203829Smarius sizeof(type)) <= 0) 612203829Smarius continue; 613203829Smarius if (strcmp(type, "cpu") != 0) 614203829Smarius continue; 615203829Smarius if (OF_getprop(node, cpu_cpuid_prop_sun4u(), &cpuid, 616203829Smarius sizeof(cpuid)) <= 0) 617203829Smarius continue; 618203829Smarius if (cpuid == bspid) 619203829Smarius return (node); 620203829Smarius } 621203829Smarius } 622203829Smarius return (0); 623203829Smarius} 624203829Smarius 625203829Smariusconst char * 626203829Smariuscpu_cpuid_prop_sun4u(void) 627203829Smarius{ 628203829Smarius 629203829Smarius switch (cpu_impl) { 630203829Smarius case CPU_IMPL_SPARC64: 631207537Smarius case CPU_IMPL_SPARC64V: 632203829Smarius case CPU_IMPL_ULTRASPARCI: 633203829Smarius case CPU_IMPL_ULTRASPARCII: 634203829Smarius case CPU_IMPL_ULTRASPARCIIi: 635203829Smarius case CPU_IMPL_ULTRASPARCIIe: 636203829Smarius return ("upa-portid"); 637203829Smarius case CPU_IMPL_ULTRASPARCIII: 638203829Smarius case CPU_IMPL_ULTRASPARCIIIp: 639203829Smarius case CPU_IMPL_ULTRASPARCIIIi: 640203829Smarius case CPU_IMPL_ULTRASPARCIIIip: 641203829Smarius return ("portid"); 642203829Smarius case CPU_IMPL_ULTRASPARCIV: 643203829Smarius case CPU_IMPL_ULTRASPARCIVp: 644203829Smarius return ("cpuid"); 645203829Smarius default: 646203829Smarius return (""); 647203829Smarius } 648203829Smarius} 649203829Smarius 650203829Smariusuint32_t 651203829Smariuscpu_get_mid_sun4u(void) 652203829Smarius{ 653203829Smarius 654203829Smarius switch (cpu_impl) { 655203829Smarius case CPU_IMPL_SPARC64: 656207537Smarius case CPU_IMPL_SPARC64V: 657203829Smarius case CPU_IMPL_ULTRASPARCI: 658203829Smarius case CPU_IMPL_ULTRASPARCII: 659203829Smarius case CPU_IMPL_ULTRASPARCIIi: 660203829Smarius case CPU_IMPL_ULTRASPARCIIe: 661203829Smarius return (UPA_CR_GET_MID(ldxa(0, ASI_UPA_CONFIG_REG))); 662203829Smarius case CPU_IMPL_ULTRASPARCIII: 663203829Smarius case CPU_IMPL_ULTRASPARCIIIp: 664203829Smarius return (FIREPLANE_CR_GET_AID(ldxa(AA_FIREPLANE_CONFIG, 665203829Smarius ASI_FIREPLANE_CONFIG_REG))); 666203829Smarius case CPU_IMPL_ULTRASPARCIIIi: 667203829Smarius case CPU_IMPL_ULTRASPARCIIIip: 668203829Smarius return (JBUS_CR_GET_JID(ldxa(0, ASI_JBUS_CONFIG_REG))); 669203829Smarius case CPU_IMPL_ULTRASPARCIV: 670203829Smarius case CPU_IMPL_ULTRASPARCIVp: 671203829Smarius return (INTR_ID_GET_ID(ldxa(AA_INTR_ID, ASI_INTR_ID))); 672203829Smarius default: 673203829Smarius return (0); 674203829Smarius } 675203829Smarius} 676203829Smarius 67791139Sjakestatic void 678163145Skmacytlb_init_sun4u(void) 67991139Sjake{ 680203829Smarius phandle_t bsp; 68191139Sjake 682182478Smarius cpu_impl = VER_IMPL(rdpr(ver)); 683223719Smarius switch (cpu_impl) { 684223719Smarius case CPU_IMPL_SPARC64: 685223719Smarius case CPU_IMPL_ULTRASPARCI: 686223719Smarius case CPU_IMPL_ULTRASPARCII: 687223719Smarius case CPU_IMPL_ULTRASPARCIIi: 688223719Smarius case CPU_IMPL_ULTRASPARCIIe: 689223719Smarius tlb_locked = TLB_DAR_T32; 690223719Smarius break; 691223719Smarius case CPU_IMPL_ULTRASPARCIII: 692223719Smarius case CPU_IMPL_ULTRASPARCIIIp: 693223719Smarius case CPU_IMPL_ULTRASPARCIIIi: 694223719Smarius case CPU_IMPL_ULTRASPARCIIIip: 695223719Smarius case CPU_IMPL_ULTRASPARCIV: 696223719Smarius case CPU_IMPL_ULTRASPARCIVp: 697223719Smarius tlb_locked = TLB_DAR_T16; 698223719Smarius break; 699223719Smarius case CPU_IMPL_SPARC64V: 700223719Smarius tlb_locked = TLB_DAR_FTLB; 701223719Smarius break; 702223719Smarius } 703203829Smarius bsp = find_bsp_sun4u(OF_child(root), cpu_get_mid_sun4u()); 704203829Smarius if (bsp == 0) 705170839Smarius panic("%s: no node for bootcpu?!?!", __func__); 706182020Smarius 707203829Smarius if (OF_getprop(bsp, "#dtlb-entries", &dtlb_slot_max, 70891139Sjake sizeof(dtlb_slot_max)) == -1 || 709203829Smarius OF_getprop(bsp, "#itlb-entries", &itlb_slot_max, 71091139Sjake sizeof(itlb_slot_max)) == -1) 711170854Smarius panic("%s: can't get TLB slot max.", __func__); 712182916Smarius 713182916Smarius if (cpu_impl == CPU_IMPL_ULTRASPARCIIIp) { 714182916Smarius#ifdef LOADER_DEBUG 715182916Smarius printf("pre fixup:\n"); 716182916Smarius pmap_print_tlb_sun4u(); 717182916Smarius#endif 718182916Smarius 719182916Smarius /* 720182916Smarius * Relocate the locked entry in it16 slot 0 (if existent) 721182916Smarius * as part of working around Cheetah+ erratum 34. 722182916Smarius */ 723182916Smarius itlb_relocate_locked0_sun4u(); 724182916Smarius 725182916Smarius#ifdef LOADER_DEBUG 726182916Smarius printf("post fixup:\n"); 727182916Smarius pmap_print_tlb_sun4u(); 728182916Smarius#endif 729182916Smarius } 730182916Smarius 73191139Sjake dtlb_store = malloc(dtlb_slot_max * sizeof(*dtlb_store)); 73291139Sjake itlb_store = malloc(itlb_slot_max * sizeof(*itlb_store)); 73391139Sjake if (dtlb_store == NULL || itlb_store == NULL) 734170854Smarius panic("%s: can't allocate TLB store", __func__); 73591139Sjake} 73691139Sjake 737236076Smarius#ifdef LOADER_ZFS_SUPPORT 738237766Savgstatic void 739237766Savgsparc64_zfs_probe(void) 740236076Smarius{ 741236076Smarius struct vtoc8 vtoc; 742238904Smarius char alias[64], devname[sizeof(alias) + sizeof(":x") - 1]; 743238904Smarius char type[sizeof("device_type")]; 744238904Smarius char *bdev, *dev, *odev; 745236076Smarius uint64_t guid; 746238904Smarius int fd, len, part; 747238904Smarius phandle_t aliases, options; 748236076Smarius 749237766Savg /* Get the GUID of the ZFS pool on the boot device. */ 750236076Smarius guid = 0; 751237815Smarius zfs_probe_dev(bootpath, &guid); 752236076Smarius 753238904Smarius /* 754238904Smarius * Get the GUIDs of the ZFS pools on any additional disks listed in 755238904Smarius * the boot-device environment variable. 756238904Smarius */ 757238904Smarius if ((aliases = OF_finddevice("/aliases")) == -1) 758238904Smarius goto out; 759238904Smarius options = OF_finddevice("/options"); 760238904Smarius len = OF_getproplen(options, "boot-device"); 761238904Smarius if (len <= 0) 762238904Smarius goto out; 763238904Smarius bdev = odev = malloc(len + 1); 764238904Smarius if (bdev == NULL) 765238904Smarius goto out; 766238904Smarius if (OF_getprop(options, "boot-device", bdev, len) <= 0) 767238904Smarius goto out; 768238904Smarius bdev[len] = '\0'; 769238904Smarius while ((dev = strsep(&bdev, " ")) != NULL) { 770238904Smarius if (*dev == '\0') 771238904Smarius continue; 772238904Smarius strcpy(alias, dev); 773238904Smarius (void)OF_getprop(aliases, dev, alias, sizeof(alias)); 774238904Smarius /* 775238904Smarius * Don't probe the boot disk twice. Note that bootpath 776238904Smarius * includes the partition specifier. 777238904Smarius */ 778238904Smarius if (strncmp(alias, bootpath, strlen(alias)) == 0) 779238904Smarius continue; 780238904Smarius if (OF_getprop(OF_finddevice(alias), "device_type", type, 781238904Smarius sizeof(type)) == -1) 782238904Smarius continue; 783238904Smarius if (strcmp(type, "block") != 0) 784238904Smarius continue; 785238904Smarius 786236076Smarius /* Find freebsd-zfs slices in the VTOC. */ 787238904Smarius fd = open(alias, O_RDONLY); 788236076Smarius if (fd == -1) 789236076Smarius continue; 790236076Smarius lseek(fd, 0, SEEK_SET); 791236076Smarius if (read(fd, &vtoc, sizeof(vtoc)) != sizeof(vtoc)) { 792236076Smarius close(fd); 793236076Smarius continue; 794236076Smarius } 795236076Smarius close(fd); 796236076Smarius 797236076Smarius for (part = 0; part < 8; part++) { 798236076Smarius if (part == 2 || vtoc.part[part].tag != 799237815Smarius VTOC_TAG_FREEBSD_ZFS) 800236076Smarius continue; 801238904Smarius (void)sprintf(devname, "%s:%c", alias, part + 'a'); 802237766Savg if (zfs_probe_dev(devname, NULL) == ENXIO) 803236076Smarius break; 804236076Smarius } 805236076Smarius } 806238904Smarius free(odev); 807236076Smarius 808238904Smarius out: 809236076Smarius if (guid != 0) { 810237766Savg zfs_currdev.pool_guid = guid; 811237766Savg zfs_currdev.root_guid = 0; 812237766Savg zfs_currdev.d_dev = &zfs_dev; 813237766Savg zfs_currdev.d_type = zfs_currdev.d_dev->dv_type; 814236076Smarius } 815236076Smarius} 816236076Smarius#endif /* LOADER_ZFS_SUPPORT */ 817236076Smarius 81885719Sjakeint 81985719Sjakemain(int (*openfirm)(void *)) 82084996Srobert{ 821163145Skmacy char compatible[32]; 82284996Srobert struct devsw **dp; 82384996Srobert 82484996Srobert /* 825182020Smarius * Tell the Open Firmware functions where they find the OFW gate. 82684996Srobert */ 82785719Sjake OF_init(openfirm); 82884996Srobert 82984996Srobert archsw.arch_getdev = ofw_getdev; 83084996Srobert archsw.arch_copyin = sparc64_copyin; 83184996Srobert archsw.arch_copyout = ofw_copyout; 83284996Srobert archsw.arch_readin = sparc64_readin; 83384996Srobert archsw.arch_autoload = sparc64_autoload; 834237766Savg#ifdef LOADER_ZFS_SUPPORT 835237766Savg archsw.arch_zfs_probe = sparc64_zfs_probe; 836237766Savg#endif 83784996Srobert 838214526Smarius if (init_heap() == (vm_offset_t)-1) 839214526Smarius OF_exit(); 840214526Smarius setheap((void *)heapva, (void *)(heapva + HEAPSZ)); 841214526Smarius 84284996Srobert /* 84384996Srobert * Probe for a console. 84484996Srobert */ 84584996Srobert cons_probe(); 84684996Srobert 847170854Smarius if ((root = OF_peer(0)) == -1) 848170854Smarius panic("%s: can't get root phandle", __func__); 849170854Smarius OF_getprop(root, "compatible", compatible, sizeof(compatible)); 850221869Sattilio mmu_ops = &mmu_ops_sun4u; 85191139Sjake 852163145Skmacy mmu_ops->tlb_init(); 853163145Skmacy 85484996Srobert /* 85584996Srobert * Set up the current device. 85684996Srobert */ 857170854Smarius OF_getprop(chosen, "bootpath", bootpath, sizeof(bootpath)); 85884996Srobert 859106738Sjake /* 860236076Smarius * Initialize devices. 861236076Smarius */ 862236076Smarius for (dp = devsw; *dp != 0; dp++) 863236076Smarius if ((*dp)->dv_init != 0) 864236076Smarius (*dp)->dv_init(); 865236076Smarius 866245943Savg#ifdef LOADER_ZFS_SUPPORT 867245943Savg if (zfs_currdev.pool_guid != 0) { 868245943Savg (void)strncpy(bootpath, zfs_fmtdev(&zfs_currdev), 869245943Savg sizeof(bootpath) - 1); 870245943Savg bootpath[sizeof(bootpath) - 1] = '\0'; 871252296Smarius } else 872245943Savg#endif 873245943Savg 874252296Smarius /* 875252296Smarius * Sun compatible bootable CD-ROMs have a disk label placed before 876252296Smarius * the ISO 9660 data, with the actual file system being in the first 877252296Smarius * partition, while the other partitions contain pseudo disk labels 878252296Smarius * with embedded boot blocks for different architectures, which may 879252296Smarius * be followed by UFS file systems. 880252296Smarius * The firmware will set the boot path to the partition it boots from 881252296Smarius * ('f' in the sun4u/sun4v case), but we want the kernel to be loaded 882252296Smarius * from the ISO 9660 file system ('a'), so the boot path needs to be 883252296Smarius * altered. 884252296Smarius */ 885252296Smarius if (bootpath[strlen(bootpath) - 2] == ':' && 886252296Smarius bootpath[strlen(bootpath) - 1] == 'f') 887252296Smarius bootpath[strlen(bootpath) - 1] = 'a'; 888252296Smarius 889237815Smarius env_setenv("currdev", EV_VOLATILE, bootpath, 890237815Smarius ofw_setcurrdev, env_nounset); 891237815Smarius env_setenv("loaddev", EV_VOLATILE, bootpath, 892237815Smarius env_noset, env_nounset); 893237815Smarius 894101287Sjake printf("\n"); 895101287Sjake printf("%s, Revision %s\n", bootprog_name, bootprog_rev); 896101287Sjake printf("(%s, %s)\n", bootprog_maker, bootprog_date); 89784996Srobert printf("bootpath=\"%s\"\n", bootpath); 89884996Srobert 89984996Srobert /* Give control to the machine independent loader code. */ 90084996Srobert interact(); 901170839Smarius return (1); 90284996Srobert} 90384996Srobert 904235997SmariusCOMMAND_SET(heap, "heap", "show heap usage", command_heap); 905235997Smarius 906235997Smariusstatic int 907235997Smariuscommand_heap(int argc, char *argv[]) 908235997Smarius{ 909235997Smarius 910235997Smarius mallocstats(); 911235997Smarius printf("heap base at %p, top at %p, upper limit at %p\n", heapva, 912235997Smarius sbrk(0), heapva + HEAPSZ); 913235997Smarius return(CMD_OK); 914235997Smarius} 915235997Smarius 91691110SjakeCOMMAND_SET(reboot, "reboot", "reboot the system", command_reboot); 91791110Sjake 91891110Sjakestatic int 91991110Sjakecommand_reboot(int argc, char *argv[]) 92091110Sjake{ 92191110Sjake int i; 92291110Sjake 92391110Sjake for (i = 0; devsw[i] != NULL; ++i) 92491110Sjake if (devsw[i]->dv_cleanup != NULL) 92591110Sjake (devsw[i]->dv_cleanup)(); 92691110Sjake 92791110Sjake printf("Rebooting...\n"); 92891110Sjake OF_exit(); 92991110Sjake} 93091110Sjake 93191110Sjake/* provide this for panic, as it's not in the startup code */ 93291110Sjakevoid 93391110Sjakeexit(int code) 93491110Sjake{ 935170839Smarius 93691110Sjake OF_exit(); 93791110Sjake} 93891110Sjake 93991110Sjake#ifdef LOADER_DEBUG 940188455Smariusstatic const char *const page_sizes[] = { 94184996Srobert " 8k", " 64k", "512k", " 4m" 94284996Srobert}; 94384996Srobert 94484996Srobertstatic void 945181398Smariuspmap_print_tte_sun4u(tte_t tag, tte_t tte) 94684996Srobert{ 947170839Smarius 94884996Srobert printf("%s %s ", 949191071Smarius page_sizes[(tte >> TD_SIZE_SHIFT) & TD_SIZE_MASK], 95084996Srobert tag & TD_G ? "G" : " "); 95184996Srobert printf(tte & TD_W ? "W " : " "); 95284996Srobert printf(tte & TD_P ? "\e[33mP\e[0m " : " "); 95384996Srobert printf(tte & TD_E ? "E " : " "); 95484996Srobert printf(tte & TD_CV ? "CV " : " "); 95584996Srobert printf(tte & TD_CP ? "CP " : " "); 95684996Srobert printf(tte & TD_L ? "\e[32mL\e[0m " : " "); 95784996Srobert printf(tte & TD_IE ? "IE " : " "); 95884996Srobert printf(tte & TD_NFO ? "NFO " : " "); 959181398Smarius printf("pa=0x%lx va=0x%lx ctx=%ld\n", 960181398Smarius TD_PA(tte), TLB_TAR_VA(tag), TLB_TAR_CTX(tag)); 96184996Srobert} 962181398Smarius 963181398Smariusstatic void 964181398Smariuspmap_print_tlb_sun4u(void) 96584996Srobert{ 966181398Smarius tte_t tag, tte; 967182478Smarius u_long pstate; 96884996Srobert int i; 96984996Srobert 970182478Smarius pstate = rdpr(pstate); 971181398Smarius for (i = 0; i < itlb_slot_max; i++) { 972182478Smarius wrpr(pstate, pstate & ~PSTATE_IE, 0); 973223719Smarius tte = itlb_get_data_sun4u(tlb_locked, i); 974182478Smarius wrpr(pstate, pstate, 0); 97584996Srobert if (!(tte & TD_V)) 97684996Srobert continue; 977223719Smarius tag = ldxa(TLB_DAR_SLOT(tlb_locked, i), 978223719Smarius ASI_ITLB_TAG_READ_REG); 979181398Smarius printf("iTLB-%2u: ", i); 980181398Smarius pmap_print_tte_sun4u(tag, tte); 98184996Srobert } 982181398Smarius for (i = 0; i < dtlb_slot_max; i++) { 983182478Smarius wrpr(pstate, pstate & ~PSTATE_IE, 0); 984223719Smarius tte = dtlb_get_data_sun4u(tlb_locked, i); 985182478Smarius wrpr(pstate, pstate, 0); 986181398Smarius if (!(tte & TD_V)) 987181398Smarius continue; 988223719Smarius tag = ldxa(TLB_DAR_SLOT(tlb_locked, i), 989223719Smarius ASI_DTLB_TAG_READ_REG); 990181398Smarius printf("dTLB-%2u: ", i); 991181398Smarius pmap_print_tte_sun4u(tag, tte); 992181398Smarius } 99384996Srobert} 99491110Sjake#endif 995