main.c revision 105065
166458Sdfr/* 266458Sdfr * Initial implementation: 366458Sdfr * Copyright (c) 2001 Robert Drehmel 466458Sdfr * All rights reserved. 566458Sdfr * 666458Sdfr * As long as the above copyright statement and this notice remain 766458Sdfr * unchanged, you can do what ever you want with this file. 866458Sdfr * 966458Sdfr * $FreeBSD: head/sys/boot/sparc64/loader/main.c 105065 2002-10-13 18:52:46Z jake $ 1066458Sdfr */ 1166458Sdfr/* 1266458Sdfr * FreeBSD/sparc64 kernel loader - machine dependent part 1366458Sdfr * 1466458Sdfr * - implements copyin and readin functions that map kernel 1566458Sdfr * pages on demand. The machine independent code does not 1666458Sdfr * know the size of the kernel early enough to pre-enter 1766458Sdfr * TTEs and install just one 4MB mapping seemed to limiting 1866458Sdfr * to me. 1966458Sdfr */ 2066458Sdfr 2166458Sdfr#include <stand.h> 2266458Sdfr#include <sys/exec.h> 2366458Sdfr#include <sys/param.h> 2466458Sdfr#include <sys/queue.h> 2566458Sdfr#include <sys/linker.h> 2666458Sdfr 2766458Sdfr#include <machine/asi.h> 2866458Sdfr#include <machine/atomic.h> 2966458Sdfr#include <machine/cpufunc.h> 3066458Sdfr#include <machine/elf.h> 3166458Sdfr#include <machine/lsu.h> 3266458Sdfr#include <machine/metadata.h> 3366458Sdfr#include <machine/tte.h> 3466458Sdfr#include <machine/upa.h> 3566458Sdfr 3666458Sdfr#include "bootstrap.h" 3766458Sdfr#include "libofw.h" 3866458Sdfr#include "dev_net.h" 3966458Sdfr 4066458Sdfrenum { 4166458Sdfr HEAPVA = 0x800000, 4266458Sdfr HEAPSZ = 0x1000000, 4366458Sdfr LOADSZ = 0x1000000 /* for kernel and modules */ 4466458Sdfr}; 4566458Sdfr 4666458Sdfrstruct memory_slice { 4766458Sdfr vm_offset_t pstart; 4866458Sdfr vm_offset_t size; 4966458Sdfr}; 50117126Sscottl 51117126Sscottltypedef void kernel_entry_t(vm_offset_t mdp, u_long o1, u_long o2, u_long o3, 5266458Sdfr void *openfirmware); 5366458Sdfr 5466458Sdfrextern void itlb_enter(u_long vpn, u_long data); 5566458Sdfrextern void dtlb_enter(u_long vpn, u_long data); 5666458Sdfrextern vm_offset_t itlb_va_to_pa(vm_offset_t); 5766458Sdfrextern vm_offset_t dtlb_va_to_pa(vm_offset_t); 58146214Snyanextern vm_offset_t md_load(char *, vm_offset_t *); 5966458Sdfrstatic int elf_exec(struct preloaded_file *); 6066458Sdfrstatic int sparc64_autoload(void); 6166458Sdfrstatic int mmu_mapin(vm_offset_t, vm_size_t); 6266458Sdfr 6366458Sdfrextern char bootprog_name[], bootprog_rev[], bootprog_date[], bootprog_maker[]; 6466458Sdfr 6566458Sdfrstruct tlb_entry *dtlb_store; 6666458Sdfrstruct tlb_entry *itlb_store; 6766458Sdfr 6866458Sdfrint dtlb_slot; 6966458Sdfrint itlb_slot; 7066458Sdfrint dtlb_slot_max; 7166458Sdfrint itlb_slot_max; 7266458Sdfr 7366458Sdfrvm_offset_t curkva = 0; 7466458Sdfrvm_offset_t heapva; 7566458Sdfrphandle_t pmemh; /* OFW memory handle */ 76135262Sphk 77135262Sphkstruct memory_slice memslices[18]; 7866458Sdfrstruct ofw_devdesc bootdev; 7966458Sdfr 8066458Sdfr/* 8166458Sdfr * Machine dependent structures that the machine independent 8266458Sdfr * loader part uses. 8366458Sdfr */ 8466458Sdfrstruct devsw *devsw[] = { 8566458Sdfr#ifdef LOADER_DISK_SUPPORT 8666458Sdfr &ofwdisk, 8766458Sdfr#endif 8866458Sdfr#ifdef LOADER_NET_SUPPORT 8966458Sdfr &netdev, 9066458Sdfr#endif 9166458Sdfr 0 9266458Sdfr}; 9366458Sdfrstruct arch_switch archsw; 9466458Sdfr 95135262Sphkstruct file_format sparc64_elf = { 9666458Sdfr elf_loadfile, 9766458Sdfr elf_exec 98135262Sphk}; 9966458Sdfrstruct file_format *file_formats[] = { 10066458Sdfr &sparc64_elf, 10166458Sdfr 0 10266458Sdfr}; 10366458Sdfrstruct fs_ops *file_system[] = { 10466458Sdfr#ifdef LOADER_UFS_SUPPORT 10566458Sdfr &ufs_fsops, 10666458Sdfr#endif 10766458Sdfr#ifdef LOADER_CD9660_SUPPORT 10866458Sdfr &cd9660_fsops, 109177215Simp#endif 110117126Sscottl#ifdef LOADER_GZIP_SUPPORT 111117126Sscottl &zipfs_fsops, 11266458Sdfr#endif 113135262Sphk#ifdef LOADER_BZIP2_SUPPORT 11466458Sdfr &bzipfs_fsops, 11566458Sdfr#endif 11666458Sdfr#ifdef LOADER_NET_SUPPORT 117135262Sphk &nfs_fsops, 11866458Sdfr#endif 11966458Sdfr#ifdef LOADER_TFTP_SUPPORT 120135262Sphk &tftp_fsops, 12166458Sdfr#endif 12266458Sdfr 0 12366458Sdfr}; 12466458Sdfrstruct netif_driver *netif_drivers[] = { 12566458Sdfr#ifdef LOADER_NET_SUPPORT 12666458Sdfr &ofwnet, 12766458Sdfr#endif 12866458Sdfr 0 12966458Sdfr}; 13066458Sdfr 13166458Sdfrextern struct console ofwconsole; 13266458Sdfrstruct console *consoles[] = { 13366458Sdfr &ofwconsole, 13466458Sdfr 0 13566458Sdfr}; 13666458Sdfr 13766458Sdfr#ifdef LOADER_DEBUG 13866458Sdfrstatic int 13966458Sdfrwatch_phys_set_mask(vm_offset_t pa, u_long mask) 14066458Sdfr{ 14166458Sdfr u_long lsucr; 14266458Sdfr 14366458Sdfr stxa(AA_DMMU_PWPR, ASI_DMMU, pa & (((2UL << 38) - 1) << 3)); 14466458Sdfr lsucr = ldxa(0, ASI_LSU_CTL_REG); 14566458Sdfr lsucr = ((lsucr | LSU_PW) & ~LSU_PM_MASK) | 14666458Sdfr (mask << LSU_PM_SHIFT); 14766458Sdfr stxa(0, ASI_LSU_CTL_REG, lsucr); 14866458Sdfr return (0); 14966458Sdfr} 15066458Sdfr 15166458Sdfrstatic int 15266458Sdfrwatch_phys_set(vm_offset_t pa, int sz) 15366458Sdfr{ 15466458Sdfr u_long off; 15566458Sdfr 15666458Sdfr off = (u_long)pa & 7; 15766458Sdfr /* Test for misaligned watch points. */ 15866458Sdfr if (off + sz > 8) 15966458Sdfr return (-1); 16066458Sdfr return (watch_phys_set_mask(pa, ((1 << sz) - 1) << off)); 16166458Sdfr} 16266458Sdfr 16366458Sdfr 16466458Sdfrstatic int 16566458Sdfrwatch_virt_set_mask(vm_offset_t va, u_long mask) 16666458Sdfr{ 16766458Sdfr u_long lsucr; 16866458Sdfr 16966458Sdfr stxa(AA_DMMU_VWPR, ASI_DMMU, va & (((2UL << 41) - 1) << 3)); 17066458Sdfr lsucr = ldxa(0, ASI_LSU_CTL_REG); 17166458Sdfr lsucr = ((lsucr | LSU_VW) & ~LSU_VM_MASK) | 17266458Sdfr (mask << LSU_VM_SHIFT); 17366458Sdfr stxa(0, ASI_LSU_CTL_REG, lsucr); 17466458Sdfr return (0); 17566458Sdfr} 17666458Sdfr 17766458Sdfrstatic int 17866458Sdfrwatch_virt_set(vm_offset_t va, int sz) 17966458Sdfr{ 18066458Sdfr u_long off; 18166458Sdfr 18266458Sdfr off = (u_long)va & 7; 18366458Sdfr /* Test for misaligned watch points. */ 18466458Sdfr if (off + sz > 8) 18566458Sdfr return (-1); 18666458Sdfr return (watch_virt_set_mask(va, ((1 << sz) - 1) << off)); 18766458Sdfr} 18866458Sdfr#endif 18966458Sdfr 19066458Sdfr/* 19166458Sdfr * archsw functions 19266458Sdfr */ 19366458Sdfrstatic int 19466458Sdfrsparc64_autoload(void) 19566458Sdfr{ 19666458Sdfr printf("nothing to autoload yet.\n"); 19766458Sdfr return 0; 19866458Sdfr} 19966458Sdfr 20066458Sdfrstatic ssize_t 20166458Sdfrsparc64_readin(const int fd, vm_offset_t va, const size_t len) 20266458Sdfr{ 20366458Sdfr mmu_mapin(va, len); 20466458Sdfr return read(fd, (void *)va, len); 20566458Sdfr} 20666458Sdfr 20766458Sdfrstatic ssize_t 20866458Sdfrsparc64_copyin(const void *src, vm_offset_t dest, size_t len) 20966458Sdfr{ 21066458Sdfr mmu_mapin(dest, len); 21166458Sdfr memcpy((void *)dest, src, len); 21292676Speter return len; 21366458Sdfr} 21492676Speter 21566458Sdfr/* 21666458Sdfr * other MD functions 21766458Sdfr */ 21866458Sdfrstatic int 21966458Sdfrelf_exec(struct preloaded_file *fp) 22066458Sdfr{ 22166458Sdfr struct file_metadata *fmp; 22266458Sdfr vm_offset_t mdp; 22366458Sdfr Elf_Ehdr *e; 22466458Sdfr int error; 22566458Sdfr 22695710Speter if ((fmp = file_findmetadata(fp, MODINFOMD_ELFHDR)) == 0) { 22766458Sdfr return EFTYPE; 22866458Sdfr } 22966458Sdfr e = (Elf_Ehdr *)&fmp->md_data; 23066458Sdfr 23166458Sdfr if ((error = md_load(fp->f_args, &mdp)) != 0) 23266458Sdfr return error; 23366458Sdfr 23466458Sdfr printf("jumping to kernel entry at %#lx.\n", e->e_entry); 23566458Sdfr#if 0 23666458Sdfr pmap_print_tlb('i'); 23766458Sdfr pmap_print_tlb('d'); 23866458Sdfr#endif 23966458Sdfr ((kernel_entry_t *)e->e_entry)(mdp, 0, 0, 0, openfirmware); 24066458Sdfr 24166458Sdfr panic("exec returned"); 24266458Sdfr} 24366458Sdfr 24466458Sdfrstatic int 24566458Sdfrmmu_mapin(vm_offset_t va, vm_size_t len) 24666458Sdfr{ 24766458Sdfr vm_offset_t pa, mva; 24866458Sdfr u_long data; 24966458Sdfr 25066458Sdfr if (va + len > curkva) 25166458Sdfr curkva = va + len; 25266458Sdfr 25366458Sdfr pa = (vm_offset_t)-1; 25466458Sdfr len += va & PAGE_MASK_4M; 25566458Sdfr va &= ~PAGE_MASK_4M; 25666458Sdfr while (len) { 25766458Sdfr if (dtlb_va_to_pa(va) == (vm_offset_t)-1 || 25866458Sdfr itlb_va_to_pa(va) == (vm_offset_t)-1) { 25966458Sdfr /* Allocate a physical page, claim the virtual area */ 26066458Sdfr if (pa == (vm_offset_t)-1) { 26166458Sdfr pa = (vm_offset_t)OF_alloc_phys(PAGE_SIZE_4M, 26266458Sdfr PAGE_SIZE_4M); 26366458Sdfr if (pa == (vm_offset_t)-1) 26466458Sdfr panic("out of memory"); 26566458Sdfr mva = (vm_offset_t)OF_claim_virt(va, 26666458Sdfr PAGE_SIZE_4M, 0); 26766458Sdfr if (mva != va) { 26866458Sdfr panic("can't claim virtual page " 26966458Sdfr "(wanted %#lx, got %#lx)", 27066458Sdfr va, mva); 27166458Sdfr } 27266458Sdfr /* The mappings may have changed, be paranoid. */ 27366458Sdfr continue; 27466458Sdfr } 27566458Sdfr /* 27666458Sdfr * Actually, we can only allocate two pages less at 27766458Sdfr * most (depending on the kernel TSB size). 27866458Sdfr */ 27966458Sdfr if (dtlb_slot >= dtlb_slot_max) 28066458Sdfr panic("mmu_mapin: out of dtlb_slots"); 28166458Sdfr if (itlb_slot >= itlb_slot_max) 28266458Sdfr panic("mmu_mapin: out of itlb_slots"); 28366458Sdfr data = TD_V | TD_4M | TD_PA(pa) | TD_L | TD_CP | 28466458Sdfr TD_CV | TD_P | TD_W; 28566458Sdfr dtlb_store[dtlb_slot].te_pa = pa; 28666458Sdfr dtlb_store[dtlb_slot].te_va = va; 28766458Sdfr itlb_store[itlb_slot].te_pa = pa; 28866458Sdfr itlb_store[itlb_slot].te_va = va; 28966458Sdfr dtlb_slot++; 29066458Sdfr itlb_slot++; 29166458Sdfr dtlb_enter(va, data); 29266458Sdfr itlb_enter(va, data); 29366458Sdfr pa = (vm_offset_t)-1; 29466458Sdfr } 29566458Sdfr len -= len > PAGE_SIZE_4M ? PAGE_SIZE_4M : len; 29666458Sdfr va += PAGE_SIZE_4M; 29766458Sdfr } 29866458Sdfr if (pa != (vm_offset_t)-1) 29966458Sdfr OF_release_phys(pa, PAGE_SIZE_4M); 30066458Sdfr return 0; 30166458Sdfr} 30266458Sdfr 30366458Sdfrstatic vm_offset_t 30466458Sdfrinit_heap(void) 30566458Sdfr{ 30666458Sdfr if ((pmemh = OF_finddevice("/memory")) == (phandle_t)-1) 30766458Sdfr OF_exit(); 30866458Sdfr if (OF_getprop(pmemh, "available", memslices, sizeof(memslices)) <= 0) 30966458Sdfr OF_exit(); 31066458Sdfr 31166458Sdfr /* There is no need for continuous physical heap memory. */ 31266458Sdfr heapva = (vm_offset_t)OF_claim((void *)HEAPVA, HEAPSZ, 32); 31366458Sdfr return heapva; 31466458Sdfr} 31566458Sdfr 31666458Sdfrstatic void 31766458Sdfrtlb_init(void) 31866458Sdfr{ 31966458Sdfr phandle_t child; 32066458Sdfr phandle_t root; 32166458Sdfr char buf[128]; 32266458Sdfr u_int bootcpu; 32366458Sdfr u_int cpu; 32466458Sdfr 32566458Sdfr bootcpu = UPA_CR_GET_MID(ldxa(0, ASI_UPA_CONFIG_REG)); 32666458Sdfr if ((root = OF_peer(0)) == -1) 32766458Sdfr panic("main: OF_peer"); 32866458Sdfr for (child = OF_child(root); child != 0; child = OF_peer(child)) { 32966458Sdfr if (child == -1) 33066458Sdfr panic("main: OF_child"); 33166458Sdfr if (OF_getprop(child, "device_type", buf, sizeof(buf)) > 0 && 33266458Sdfr strcmp(buf, "cpu") == 0) { 33366458Sdfr if (OF_getprop(child, "upa-portid", &cpu, 334171312Smarcel sizeof(cpu)) == -1 && OF_getprop(child, "portid", 335135262Sphk &cpu, sizeof(cpu)) == -1) 33666458Sdfr panic("main: OF_getprop"); 33766458Sdfr if (cpu == bootcpu) 33866458Sdfr break; 33966458Sdfr } 34066458Sdfr } 34166458Sdfr if (cpu != bootcpu) 34266458Sdfr panic("init_tlb: no node for bootcpu?!?!"); 34366458Sdfr if (OF_getprop(child, "#dtlb-entries", &dtlb_slot_max, 34466458Sdfr sizeof(dtlb_slot_max)) == -1 || 34566458Sdfr OF_getprop(child, "#itlb-entries", &itlb_slot_max, 34666458Sdfr sizeof(itlb_slot_max)) == -1) 34766458Sdfr panic("init_tlb: OF_getprop"); 34866458Sdfr dtlb_store = malloc(dtlb_slot_max * sizeof(*dtlb_store)); 34966458Sdfr itlb_store = malloc(itlb_slot_max * sizeof(*itlb_store)); 35066458Sdfr if (dtlb_store == NULL || itlb_store == NULL) 35166458Sdfr panic("init_tlb: malloc"); 35266458Sdfr} 35366458Sdfr 35466458Sdfrint 35566458Sdfrmain(int (*openfirm)(void *)) 35666458Sdfr{ 35766458Sdfr char bootpath[64]; 35866458Sdfr struct devsw **dp; 35966458Sdfr phandle_t chosenh; 36066458Sdfr 36166458Sdfr /* 36266458Sdfr * Tell the OpenFirmware functions where they find the ofw gate. 36366458Sdfr */ 36466458Sdfr OF_init(openfirm); 36566458Sdfr 36666458Sdfr archsw.arch_getdev = ofw_getdev; 36766458Sdfr archsw.arch_copyin = sparc64_copyin; 36866458Sdfr archsw.arch_copyout = ofw_copyout; 36966458Sdfr archsw.arch_readin = sparc64_readin; 37066458Sdfr archsw.arch_autoload = sparc64_autoload; 37166458Sdfr#ifdef ELF_CRC32 37266458Sdfr archsw.arch_crc32 = sparc64_crc32; 37366458Sdfr#endif 37466458Sdfr 37566458Sdfr init_heap(); 37666458Sdfr setheap((void *)heapva, (void *)(heapva + HEAPSZ)); 37766458Sdfr 37866458Sdfr /* 37966458Sdfr * Probe for a console. 38066458Sdfr */ 38166458Sdfr cons_probe(); 38266458Sdfr 38366458Sdfr tlb_init(); 38466458Sdfr 38566458Sdfr bcache_init(32, 512); 38666458Sdfr 38766458Sdfr /* 38866458Sdfr * Initialize devices. 38966458Sdfr */ 39066458Sdfr for (dp = devsw; *dp != 0; dp++) { 39166458Sdfr if ((*dp)->dv_init != 0) 39266458Sdfr (*dp)->dv_init(); 39366458Sdfr } 39466458Sdfr 39566458Sdfr /* 39666458Sdfr * Set up the current device. 39766458Sdfr */ 39866458Sdfr chosenh = OF_finddevice("/chosen"); 39966458Sdfr OF_getprop(chosenh, "bootpath", bootpath, sizeof(bootpath)); 40066458Sdfr 40166458Sdfr bootdev.d_type = ofw_devicetype(bootpath); 40266458Sdfr switch (bootdev.d_type) { 40366458Sdfr case DEVT_DISK: 40466458Sdfr bootdev.d_dev = &ofwdisk; 40566458Sdfr /* 40666458Sdfr * Sun compatible bootable CD-ROMs have a disk label placed 40766458Sdfr * before the cd9660 data, with the actual filesystem being 40866458Sdfr * in the first partition, while the other partitions contain 40966458Sdfr * pseudo disk labels with embedded boot blocks for different 41066458Sdfr * architectures, which may be followed by UFS filesystems. 41166458Sdfr * The firmware will set the boot path to the partition it 41266458Sdfr * boots from ('f' in the sun4u case), but we want the kernel 41366458Sdfr * to be loaded from the cd9660 fs ('a'), so the boot path 41466458Sdfr * needs to be altered. 41566458Sdfr */ 41666458Sdfr if (strstr(bootpath, "cdrom") != NULL && 41766458Sdfr bootpath[strlen(bootpath) - 2] == ':') { 41866458Sdfr bootpath[strlen(bootpath) - 1] = 'a'; 41966458Sdfr printf("Boot path set to %s\n", bootpath); 42066458Sdfr } 42166458Sdfr strncpy(bootdev.d_kind.ofwdisk.path, bootpath, 64); 42266458Sdfr ofw_parseofwdev(&bootdev, bootpath); 42366458Sdfr break; 42466458Sdfr case DEVT_NET: 42566458Sdfr bootdev.d_dev = &netdev; 42666458Sdfr strncpy(bootdev.d_kind.netif.path, bootpath, 64); 42766458Sdfr bootdev.d_kind.netif.unit = 0; 42866458Sdfr break; 42966458Sdfr } 43066458Sdfr 43166458Sdfr env_setenv("currdev", EV_VOLATILE, ofw_fmtdev(&bootdev), 43266458Sdfr ofw_setcurrdev, env_nounset); 43366458Sdfr env_setenv("loaddev", EV_VOLATILE, ofw_fmtdev(&bootdev), 43466458Sdfr env_noset, env_nounset); 43566458Sdfr 43666458Sdfr printf("\n"); 43766458Sdfr printf("%s, Revision %s\n", bootprog_name, bootprog_rev); 43866458Sdfr printf("(%s, %s)\n", bootprog_maker, bootprog_date); 43966458Sdfr printf("bootpath=\"%s\"\n", bootpath); 44066458Sdfr printf("loaddev=%s\n", getenv("loaddev")); 44166458Sdfr 44266458Sdfr /* Give control to the machine independent loader code. */ 44366458Sdfr interact(); 44466458Sdfr return 1; 44566458Sdfr} 44666458Sdfr 44766458SdfrCOMMAND_SET(reboot, "reboot", "reboot the system", command_reboot); 44866458Sdfr 44966458Sdfrstatic int 45066458Sdfrcommand_reboot(int argc, char *argv[]) 45166458Sdfr{ 45266458Sdfr int i; 45366458Sdfr 45466458Sdfr for (i = 0; devsw[i] != NULL; ++i) 45566458Sdfr if (devsw[i]->dv_cleanup != NULL) 45666458Sdfr (devsw[i]->dv_cleanup)(); 45766458Sdfr 45866458Sdfr printf("Rebooting...\n"); 45966458Sdfr OF_exit(); 46066458Sdfr} 46166458Sdfr 46266458Sdfr/* provide this for panic, as it's not in the startup code */ 46366458Sdfrvoid 46466458Sdfrexit(int code) 46566458Sdfr{ 46666458Sdfr OF_exit(); 46766458Sdfr} 46866458Sdfr 46966458Sdfr#ifdef LOADER_DEBUG 47066458Sdfrtypedef u_int64_t tte_t; 47166458Sdfr 47266458Sdfrconst char *page_sizes[] = { 47366458Sdfr " 8k", " 64k", "512k", " 4m" 47466458Sdfr}; 475141391Sphk 476141391Sphkstatic void 477141391Sphkpmap_print_tte(tte_t tag, tte_t tte) 478141391Sphk{ 479141391Sphk printf("%s %s ", 480141391Sphk page_sizes[(tte & TD_SIZE_MASK) >> TD_SIZE_SHIFT], 481141391Sphk tag & TD_G ? "G" : " "); 482141391Sphk printf(tte & TD_W ? "W " : " "); 483141391Sphk printf(tte & TD_P ? "\e[33mP\e[0m " : " "); 484141391Sphk printf(tte & TD_E ? "E " : " "); 485141391Sphk printf(tte & TD_CV ? "CV " : " "); 486141391Sphk printf(tte & TD_CP ? "CP " : " "); 487141391Sphk printf(tte & TD_L ? "\e[32mL\e[0m " : " "); 48866458Sdfr printf(tte & TD_IE ? "IE " : " "); 48966458Sdfr printf(tte & TD_NFO ? "NFO " : " "); 49066458Sdfr printf("tag=0x%lx pa=0x%lx va=0x%lx ctx=%ld\n", tag, TD_PA(tte), 49166458Sdfr TT_VA(tag), TT_CTX(tag)); 49266458Sdfr} 49366458Sdfrvoid 49466458Sdfrpmap_print_tlb(char which) 49566458Sdfr{ 49666458Sdfr int i; 49766458Sdfr tte_t tte, tag; 49866458Sdfr 49966458Sdfr for (i = 0; i < 64*8; i += 8) { 50066458Sdfr if (which == 'i') { 50166458Sdfr __asm__ __volatile__("ldxa [%1] %2, %0\n" : 50266458Sdfr "=r" (tag) : "r" (i), 50366458Sdfr "i" (ASI_ITLB_TAG_READ_REG)); 50466458Sdfr __asm__ __volatile__("ldxa [%1] %2, %0\n" : 50566458Sdfr "=r" (tte) : "r" (i), 50666458Sdfr "i" (ASI_ITLB_DATA_ACCESS_REG)); 50766458Sdfr } 50866458Sdfr else { 509 __asm__ __volatile__("ldxa [%1] %2, %0\n" : 510 "=r" (tag) : "r" (i), 511 "i" (ASI_DTLB_TAG_READ_REG)); 512 __asm__ __volatile__("ldxa [%1] %2, %0\n" : 513 "=r" (tte) : "r" (i), 514 "i" (ASI_DTLB_DATA_ACCESS_REG)); 515 } 516 if (!(tte & TD_V)) 517 continue; 518 printf("%cTLB-%2u: ", which, i>>3); 519 pmap_print_tte(tag, tte); 520 } 521} 522#endif 523