main.c revision 105065
184996Srobert/* 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 * 984996Srobert * $FreeBSD: head/sys/boot/sparc64/loader/main.c 105065 2002-10-13 18:52:46Z jake $ 1084996Srobert */ 1184996Srobert/* 1284996Srobert * FreeBSD/sparc64 kernel loader - machine dependent part 1384996Srobert * 1484996Srobert * - implements copyin and readin functions that map kernel 1584996Srobert * pages on demand. The machine independent code does not 1684996Srobert * know the size of the kernel early enough to pre-enter 1784996Srobert * TTEs and install just one 4MB mapping seemed to limiting 1884996Srobert * to me. 1984996Srobert */ 2091139Sjake 2184996Srobert#include <stand.h> 2284996Srobert#include <sys/exec.h> 2384996Srobert#include <sys/param.h> 24102219Srobert#include <sys/queue.h> 2584996Srobert#include <sys/linker.h> 2684996Srobert 2784996Srobert#include <machine/asi.h> 2891139Sjake#include <machine/atomic.h> 2991139Sjake#include <machine/cpufunc.h> 3084996Srobert#include <machine/elf.h> 3191110Sjake#include <machine/lsu.h> 3291110Sjake#include <machine/metadata.h> 3384996Srobert#include <machine/tte.h> 3491139Sjake#include <machine/upa.h> 3584996Srobert 3684996Srobert#include "bootstrap.h" 3784996Srobert#include "libofw.h" 3885719Sjake#include "dev_net.h" 3984996Srobert 4084996Srobertenum { 4184996Srobert HEAPVA = 0x800000, 4284996Srobert HEAPSZ = 0x1000000, 4384996Srobert LOADSZ = 0x1000000 /* for kernel and modules */ 4484996Srobert}; 4584996Srobert 4684996Srobertstruct memory_slice { 4784996Srobert vm_offset_t pstart; 4884996Srobert vm_offset_t size; 4984996Srobert}; 5084996Srobert 5185719Sjaketypedef void kernel_entry_t(vm_offset_t mdp, u_long o1, u_long o2, u_long o3, 5285719Sjake void *openfirmware); 5385719Sjake 5493678Stmmextern void itlb_enter(u_long vpn, u_long data); 5593678Stmmextern void dtlb_enter(u_long vpn, u_long data); 5684996Srobertextern vm_offset_t itlb_va_to_pa(vm_offset_t); 5784996Srobertextern vm_offset_t dtlb_va_to_pa(vm_offset_t); 5885719Sjakeextern vm_offset_t md_load(char *, vm_offset_t *); 5984996Srobertstatic int elf_exec(struct preloaded_file *); 6084996Srobertstatic int sparc64_autoload(void); 6184996Srobertstatic int mmu_mapin(vm_offset_t, vm_size_t); 6284996Srobert 63101287Sjakeextern char bootprog_name[], bootprog_rev[], bootprog_date[], bootprog_maker[]; 6484996Srobert 6597445Sjakestruct tlb_entry *dtlb_store; 6697445Sjakestruct tlb_entry *itlb_store; 6791139Sjake 6891139Sjakeint dtlb_slot; 6991139Sjakeint itlb_slot; 7091139Sjakeint dtlb_slot_max; 7191139Sjakeint itlb_slot_max; 7291139Sjake 7384996Srobertvm_offset_t curkva = 0; 7484996Srobertvm_offset_t heapva; 7584996Srobertphandle_t pmemh; /* OFW memory handle */ 7684996Srobert 7784996Srobertstruct memory_slice memslices[18]; 7884996Srobertstruct ofw_devdesc bootdev; 7984996Srobert 8084996Srobert/* 8184996Srobert * Machine dependent structures that the machine independent 8284996Srobert * loader part uses. 8384996Srobert */ 8484996Srobertstruct devsw *devsw[] = { 8585719Sjake#ifdef LOADER_DISK_SUPPORT 8684996Srobert &ofwdisk, 8785719Sjake#endif 8885719Sjake#ifdef LOADER_NET_SUPPORT 8985719Sjake &netdev, 9085719Sjake#endif 9184996Srobert 0 9284996Srobert}; 9384996Srobertstruct arch_switch archsw; 9484996Srobert 9584996Srobertstruct file_format sparc64_elf = { 9684996Srobert elf_loadfile, 9784996Srobert elf_exec 9884996Srobert}; 9984996Srobertstruct file_format *file_formats[] = { 10084996Srobert &sparc64_elf, 10184996Srobert 0 10284996Srobert}; 10384996Srobertstruct fs_ops *file_system[] = { 10491110Sjake#ifdef LOADER_UFS_SUPPORT 10584996Srobert &ufs_fsops, 10685719Sjake#endif 10793606Stmm#ifdef LOADER_CD9660_SUPPORT 10893606Stmm &cd9660_fsops, 10993606Stmm#endif 110105065Sjake#ifdef LOADER_GZIP_SUPPORT 111105065Sjake &zipfs_fsops, 112105065Sjake#endif 113105065Sjake#ifdef LOADER_BZIP2_SUPPORT 114105065Sjake &bzipfs_fsops, 115105065Sjake#endif 11691139Sjake#ifdef LOADER_NET_SUPPORT 11785719Sjake &nfs_fsops, 11885719Sjake#endif 11991110Sjake#ifdef LOADER_TFTP_SUPPORT 12091110Sjake &tftp_fsops, 12191110Sjake#endif 12284996Srobert 0 12384996Srobert}; 12485719Sjakestruct netif_driver *netif_drivers[] = { 12585719Sjake#ifdef LOADER_NET_SUPPORT 12685719Sjake &ofwnet, 12785719Sjake#endif 12885719Sjake 0 12985719Sjake}; 13084996Srobert 13184996Srobertextern struct console ofwconsole; 13284996Srobertstruct console *consoles[] = { 13384996Srobert &ofwconsole, 13484996Srobert 0 13584996Srobert}; 13684996Srobert 13791110Sjake#ifdef LOADER_DEBUG 13891110Sjakestatic int 13991110Sjakewatch_phys_set_mask(vm_offset_t pa, u_long mask) 14091110Sjake{ 14191110Sjake u_long lsucr; 14291110Sjake 14391110Sjake stxa(AA_DMMU_PWPR, ASI_DMMU, pa & (((2UL << 38) - 1) << 3)); 14491110Sjake lsucr = ldxa(0, ASI_LSU_CTL_REG); 14591110Sjake lsucr = ((lsucr | LSU_PW) & ~LSU_PM_MASK) | 14691110Sjake (mask << LSU_PM_SHIFT); 14791110Sjake stxa(0, ASI_LSU_CTL_REG, lsucr); 14891110Sjake return (0); 14991110Sjake} 15091110Sjake 15191110Sjakestatic int 15291110Sjakewatch_phys_set(vm_offset_t pa, int sz) 15391110Sjake{ 15491110Sjake u_long off; 15591110Sjake 15691110Sjake off = (u_long)pa & 7; 15791110Sjake /* Test for misaligned watch points. */ 15891110Sjake if (off + sz > 8) 15991110Sjake return (-1); 16091110Sjake return (watch_phys_set_mask(pa, ((1 << sz) - 1) << off)); 16191110Sjake} 16291110Sjake 16391110Sjake 16491110Sjakestatic int 16591110Sjakewatch_virt_set_mask(vm_offset_t va, u_long mask) 16691110Sjake{ 16791110Sjake u_long lsucr; 16891110Sjake 16991110Sjake stxa(AA_DMMU_VWPR, ASI_DMMU, va & (((2UL << 41) - 1) << 3)); 17091110Sjake lsucr = ldxa(0, ASI_LSU_CTL_REG); 17191110Sjake lsucr = ((lsucr | LSU_VW) & ~LSU_VM_MASK) | 17291110Sjake (mask << LSU_VM_SHIFT); 17391110Sjake stxa(0, ASI_LSU_CTL_REG, lsucr); 17491110Sjake return (0); 17591110Sjake} 17691110Sjake 17791110Sjakestatic int 17891110Sjakewatch_virt_set(vm_offset_t va, int sz) 17991110Sjake{ 18091110Sjake u_long off; 18191110Sjake 18291110Sjake off = (u_long)va & 7; 18391110Sjake /* Test for misaligned watch points. */ 18491110Sjake if (off + sz > 8) 18591110Sjake return (-1); 18691110Sjake return (watch_virt_set_mask(va, ((1 << sz) - 1) << off)); 18791110Sjake} 18891110Sjake#endif 18991110Sjake 19084996Srobert/* 19184996Srobert * archsw functions 19284996Srobert */ 19384996Srobertstatic int 19484996Srobertsparc64_autoload(void) 19584996Srobert{ 19684996Srobert printf("nothing to autoload yet.\n"); 19784996Srobert return 0; 19884996Srobert} 19984996Srobert 20084996Srobertstatic ssize_t 20184996Srobertsparc64_readin(const int fd, vm_offset_t va, const size_t len) 20284996Srobert{ 20384996Srobert mmu_mapin(va, len); 20484996Srobert return read(fd, (void *)va, len); 20584996Srobert} 20684996Srobert 20784996Srobertstatic ssize_t 20884996Srobertsparc64_copyin(const void *src, vm_offset_t dest, size_t len) 20984996Srobert{ 21084996Srobert mmu_mapin(dest, len); 21184996Srobert memcpy((void *)dest, src, len); 21284996Srobert return len; 21384996Srobert} 21484996Srobert 21584996Srobert/* 21684996Srobert * other MD functions 21784996Srobert */ 21884996Srobertstatic int 21984996Srobertelf_exec(struct preloaded_file *fp) 22084996Srobert{ 22184996Srobert struct file_metadata *fmp; 22285719Sjake vm_offset_t mdp; 22391139Sjake Elf_Ehdr *e; 22485719Sjake int error; 22584996Srobert 22684996Srobert if ((fmp = file_findmetadata(fp, MODINFOMD_ELFHDR)) == 0) { 22784996Srobert return EFTYPE; 22884996Srobert } 22991139Sjake e = (Elf_Ehdr *)&fmp->md_data; 23084996Srobert 23185719Sjake if ((error = md_load(fp->f_args, &mdp)) != 0) 23285719Sjake return error; 23384996Srobert 23491139Sjake printf("jumping to kernel entry at %#lx.\n", e->e_entry); 23584996Srobert#if 0 23684996Srobert pmap_print_tlb('i'); 23784996Srobert pmap_print_tlb('d'); 23884996Srobert#endif 23991139Sjake ((kernel_entry_t *)e->e_entry)(mdp, 0, 0, 0, openfirmware); 24085719Sjake 24185719Sjake panic("exec returned"); 24284996Srobert} 24384996Srobert 24484996Srobertstatic int 24584996Srobertmmu_mapin(vm_offset_t va, vm_size_t len) 24684996Srobert{ 24791110Sjake vm_offset_t pa, mva; 24897445Sjake u_long data; 24984996Srobert 25084996Srobert if (va + len > curkva) 25184996Srobert curkva = va + len; 25284996Srobert 25391110Sjake pa = (vm_offset_t)-1; 25485719Sjake len += va & PAGE_MASK_4M; 25585719Sjake va &= ~PAGE_MASK_4M; 25684996Srobert while (len) { 25784996Srobert if (dtlb_va_to_pa(va) == (vm_offset_t)-1 || 25884996Srobert itlb_va_to_pa(va) == (vm_offset_t)-1) { 25991110Sjake /* Allocate a physical page, claim the virtual area */ 26091110Sjake if (pa == (vm_offset_t)-1) { 26191110Sjake pa = (vm_offset_t)OF_alloc_phys(PAGE_SIZE_4M, 26291110Sjake PAGE_SIZE_4M); 26391110Sjake if (pa == (vm_offset_t)-1) 26491110Sjake panic("out of memory"); 26591110Sjake mva = (vm_offset_t)OF_claim_virt(va, 26691110Sjake PAGE_SIZE_4M, 0); 26791110Sjake if (mva != va) { 26891110Sjake panic("can't claim virtual page " 26991110Sjake "(wanted %#lx, got %#lx)", 27091110Sjake va, mva); 27191110Sjake } 27291110Sjake /* The mappings may have changed, be paranoid. */ 27391110Sjake continue; 27491110Sjake } 27593678Stmm /* 27693678Stmm * Actually, we can only allocate two pages less at 27793678Stmm * most (depending on the kernel TSB size). 27893678Stmm */ 27993678Stmm if (dtlb_slot >= dtlb_slot_max) 28093678Stmm panic("mmu_mapin: out of dtlb_slots"); 28193678Stmm if (itlb_slot >= itlb_slot_max) 28293678Stmm panic("mmu_mapin: out of itlb_slots"); 28397445Sjake data = TD_V | TD_4M | TD_PA(pa) | TD_L | TD_CP | 28491139Sjake TD_CV | TD_P | TD_W; 28597445Sjake dtlb_store[dtlb_slot].te_pa = pa; 28697445Sjake dtlb_store[dtlb_slot].te_va = va; 28797445Sjake itlb_store[itlb_slot].te_pa = pa; 28897445Sjake itlb_store[itlb_slot].te_va = va; 28997445Sjake dtlb_slot++; 29097445Sjake itlb_slot++; 29197445Sjake dtlb_enter(va, data); 29297445Sjake itlb_enter(va, data); 29391110Sjake pa = (vm_offset_t)-1; 29484996Srobert } 29585719Sjake len -= len > PAGE_SIZE_4M ? PAGE_SIZE_4M : len; 29685719Sjake va += PAGE_SIZE_4M; 29784996Srobert } 29891110Sjake if (pa != (vm_offset_t)-1) 29991110Sjake OF_release_phys(pa, PAGE_SIZE_4M); 30084996Srobert return 0; 30184996Srobert} 30284996Srobert 30384996Srobertstatic vm_offset_t 30484996Srobertinit_heap(void) 30584996Srobert{ 30684996Srobert if ((pmemh = OF_finddevice("/memory")) == (phandle_t)-1) 30784996Srobert OF_exit(); 30885719Sjake if (OF_getprop(pmemh, "available", memslices, sizeof(memslices)) <= 0) 30984996Srobert OF_exit(); 31084996Srobert 31184996Srobert /* There is no need for continuous physical heap memory. */ 31284996Srobert heapva = (vm_offset_t)OF_claim((void *)HEAPVA, HEAPSZ, 32); 31384996Srobert return heapva; 31484996Srobert} 31584996Srobert 31691139Sjakestatic void 31791139Sjaketlb_init(void) 31891139Sjake{ 31991139Sjake phandle_t child; 32091139Sjake phandle_t root; 32191139Sjake char buf[128]; 32291139Sjake u_int bootcpu; 32391139Sjake u_int cpu; 32491139Sjake 32591139Sjake bootcpu = UPA_CR_GET_MID(ldxa(0, ASI_UPA_CONFIG_REG)); 32691139Sjake if ((root = OF_peer(0)) == -1) 32791139Sjake panic("main: OF_peer"); 32891139Sjake for (child = OF_child(root); child != 0; child = OF_peer(child)) { 32991139Sjake if (child == -1) 33091139Sjake panic("main: OF_child"); 33191139Sjake if (OF_getprop(child, "device_type", buf, sizeof(buf)) > 0 && 33291139Sjake strcmp(buf, "cpu") == 0) { 33391139Sjake if (OF_getprop(child, "upa-portid", &cpu, 33496428Sjake sizeof(cpu)) == -1 && OF_getprop(child, "portid", 33596428Sjake &cpu, sizeof(cpu)) == -1) 33691139Sjake panic("main: OF_getprop"); 33791139Sjake if (cpu == bootcpu) 33891139Sjake break; 33991139Sjake } 34091139Sjake } 34191139Sjake if (cpu != bootcpu) 34291139Sjake panic("init_tlb: no node for bootcpu?!?!"); 34391139Sjake if (OF_getprop(child, "#dtlb-entries", &dtlb_slot_max, 34491139Sjake sizeof(dtlb_slot_max)) == -1 || 34591139Sjake OF_getprop(child, "#itlb-entries", &itlb_slot_max, 34691139Sjake sizeof(itlb_slot_max)) == -1) 34791139Sjake panic("init_tlb: OF_getprop"); 34891139Sjake dtlb_store = malloc(dtlb_slot_max * sizeof(*dtlb_store)); 34991139Sjake itlb_store = malloc(itlb_slot_max * sizeof(*itlb_store)); 35091139Sjake if (dtlb_store == NULL || itlb_store == NULL) 35191139Sjake panic("init_tlb: malloc"); 35291139Sjake} 35391139Sjake 35485719Sjakeint 35585719Sjakemain(int (*openfirm)(void *)) 35684996Srobert{ 35784996Srobert char bootpath[64]; 35884996Srobert struct devsw **dp; 35984996Srobert phandle_t chosenh; 36084996Srobert 36184996Srobert /* 36284996Srobert * Tell the OpenFirmware functions where they find the ofw gate. 36384996Srobert */ 36485719Sjake OF_init(openfirm); 36584996Srobert 36684996Srobert archsw.arch_getdev = ofw_getdev; 36784996Srobert archsw.arch_copyin = sparc64_copyin; 36884996Srobert archsw.arch_copyout = ofw_copyout; 36984996Srobert archsw.arch_readin = sparc64_readin; 37084996Srobert archsw.arch_autoload = sparc64_autoload; 37191139Sjake#ifdef ELF_CRC32 37291139Sjake archsw.arch_crc32 = sparc64_crc32; 37391139Sjake#endif 37484996Srobert 37584996Srobert init_heap(); 37684996Srobert setheap((void *)heapva, (void *)(heapva + HEAPSZ)); 37784996Srobert 37884996Srobert /* 37984996Srobert * Probe for a console. 38084996Srobert */ 38184996Srobert cons_probe(); 38284996Srobert 38391139Sjake tlb_init(); 38491139Sjake 38584996Srobert bcache_init(32, 512); 38684996Srobert 38784996Srobert /* 38884996Srobert * Initialize devices. 38984996Srobert */ 39084996Srobert for (dp = devsw; *dp != 0; dp++) { 39184996Srobert if ((*dp)->dv_init != 0) 39284996Srobert (*dp)->dv_init(); 39384996Srobert } 39484996Srobert 39584996Srobert /* 39684996Srobert * Set up the current device. 39784996Srobert */ 39884996Srobert chosenh = OF_finddevice("/chosen"); 39984996Srobert OF_getprop(chosenh, "bootpath", bootpath, sizeof(bootpath)); 40084996Srobert 40184996Srobert bootdev.d_type = ofw_devicetype(bootpath); 40284996Srobert switch (bootdev.d_type) { 40384996Srobert case DEVT_DISK: 40484996Srobert bootdev.d_dev = &ofwdisk; 40593606Stmm /* 40693606Stmm * Sun compatible bootable CD-ROMs have a disk label placed 40796755Strhodes * before the cd9660 data, with the actual filesystem being 40893606Stmm * in the first partition, while the other partitions contain 40993606Stmm * pseudo disk labels with embedded boot blocks for different 41096755Strhodes * architectures, which may be followed by UFS filesystems. 41193606Stmm * The firmware will set the boot path to the partition it 41293606Stmm * boots from ('f' in the sun4u case), but we want the kernel 41393606Stmm * to be loaded from the cd9660 fs ('a'), so the boot path 41493606Stmm * needs to be altered. 41593606Stmm */ 41693606Stmm if (strstr(bootpath, "cdrom") != NULL && 41793606Stmm bootpath[strlen(bootpath) - 2] == ':') { 41893606Stmm bootpath[strlen(bootpath) - 1] = 'a'; 41993606Stmm printf("Boot path set to %s\n", bootpath); 42093606Stmm } 42184996Srobert strncpy(bootdev.d_kind.ofwdisk.path, bootpath, 64); 42284996Srobert ofw_parseofwdev(&bootdev, bootpath); 42384996Srobert break; 42484996Srobert case DEVT_NET: 42585719Sjake bootdev.d_dev = &netdev; 42684996Srobert strncpy(bootdev.d_kind.netif.path, bootpath, 64); 42784996Srobert bootdev.d_kind.netif.unit = 0; 42884996Srobert break; 42984996Srobert } 43084996Srobert 43184996Srobert env_setenv("currdev", EV_VOLATILE, ofw_fmtdev(&bootdev), 43284996Srobert ofw_setcurrdev, env_nounset); 43384996Srobert env_setenv("loaddev", EV_VOLATILE, ofw_fmtdev(&bootdev), 43484996Srobert env_noset, env_nounset); 43584996Srobert 436101287Sjake printf("\n"); 437101287Sjake printf("%s, Revision %s\n", bootprog_name, bootprog_rev); 438101287Sjake printf("(%s, %s)\n", bootprog_maker, bootprog_date); 43984996Srobert printf("bootpath=\"%s\"\n", bootpath); 44084996Srobert printf("loaddev=%s\n", getenv("loaddev")); 44184996Srobert 44284996Srobert /* Give control to the machine independent loader code. */ 44384996Srobert interact(); 44484996Srobert return 1; 44584996Srobert} 44684996Srobert 44791110SjakeCOMMAND_SET(reboot, "reboot", "reboot the system", command_reboot); 44891110Sjake 44991110Sjakestatic int 45091110Sjakecommand_reboot(int argc, char *argv[]) 45191110Sjake{ 45291110Sjake int i; 45391110Sjake 45491110Sjake for (i = 0; devsw[i] != NULL; ++i) 45591110Sjake if (devsw[i]->dv_cleanup != NULL) 45691110Sjake (devsw[i]->dv_cleanup)(); 45791110Sjake 45891110Sjake printf("Rebooting...\n"); 45991110Sjake OF_exit(); 46091110Sjake} 46191110Sjake 46291110Sjake/* provide this for panic, as it's not in the startup code */ 46391110Sjakevoid 46491110Sjakeexit(int code) 46591110Sjake{ 46691110Sjake OF_exit(); 46791110Sjake} 46891110Sjake 46991110Sjake#ifdef LOADER_DEBUG 47084996Sroberttypedef u_int64_t tte_t; 47184996Srobert 47284996Srobertconst char *page_sizes[] = { 47384996Srobert " 8k", " 64k", "512k", " 4m" 47484996Srobert}; 47584996Srobert 47684996Srobertstatic void 47784996Srobertpmap_print_tte(tte_t tag, tte_t tte) 47884996Srobert{ 47984996Srobert printf("%s %s ", 48084996Srobert page_sizes[(tte & TD_SIZE_MASK) >> TD_SIZE_SHIFT], 48184996Srobert tag & TD_G ? "G" : " "); 48284996Srobert printf(tte & TD_W ? "W " : " "); 48384996Srobert printf(tte & TD_P ? "\e[33mP\e[0m " : " "); 48484996Srobert printf(tte & TD_E ? "E " : " "); 48584996Srobert printf(tte & TD_CV ? "CV " : " "); 48684996Srobert printf(tte & TD_CP ? "CP " : " "); 48784996Srobert printf(tte & TD_L ? "\e[32mL\e[0m " : " "); 48884996Srobert printf(tte & TD_IE ? "IE " : " "); 48984996Srobert printf(tte & TD_NFO ? "NFO " : " "); 49084997Srobert printf("tag=0x%lx pa=0x%lx va=0x%lx ctx=%ld\n", tag, TD_PA(tte), 49184996Srobert TT_VA(tag), TT_CTX(tag)); 49284996Srobert} 49384996Srobertvoid 49484996Srobertpmap_print_tlb(char which) 49584996Srobert{ 49684996Srobert int i; 49784996Srobert tte_t tte, tag; 49884996Srobert 49984996Srobert for (i = 0; i < 64*8; i += 8) { 50084996Srobert if (which == 'i') { 50184996Srobert __asm__ __volatile__("ldxa [%1] %2, %0\n" : 50284996Srobert "=r" (tag) : "r" (i), 50384996Srobert "i" (ASI_ITLB_TAG_READ_REG)); 50484996Srobert __asm__ __volatile__("ldxa [%1] %2, %0\n" : 50584996Srobert "=r" (tte) : "r" (i), 50684996Srobert "i" (ASI_ITLB_DATA_ACCESS_REG)); 50784996Srobert } 50884996Srobert else { 50984996Srobert __asm__ __volatile__("ldxa [%1] %2, %0\n" : 51084996Srobert "=r" (tag) : "r" (i), 51184996Srobert "i" (ASI_DTLB_TAG_READ_REG)); 51284996Srobert __asm__ __volatile__("ldxa [%1] %2, %0\n" : 51384996Srobert "=r" (tte) : "r" (i), 51484996Srobert "i" (ASI_DTLB_DATA_ACCESS_REG)); 51584996Srobert } 51684996Srobert if (!(tte & TD_V)) 51784996Srobert continue; 51884996Srobert printf("%cTLB-%2u: ", which, i>>3); 51984996Srobert pmap_print_tte(tag, tte); 52084996Srobert } 52184996Srobert} 52291110Sjake#endif 523