186560Sjake/*- 286560Sjake * Copyright (c) 1989, 1992, 1993 386560Sjake * The Regents of the University of California. All rights reserved. 486560Sjake * 586560Sjake * This code is derived from software developed by the Computer Systems 686560Sjake * Engineering group at Lawrence Berkeley Laboratory under DARPA contract 786560Sjake * BG 91-66 and contributed to Berkeley. 886560Sjake * 986560Sjake * Redistribution and use in source and binary forms, with or without 1086560Sjake * modification, are permitted provided that the following conditions 1186560Sjake * are met: 1286560Sjake * 1. Redistributions of source code must retain the above copyright 1386560Sjake * notice, this list of conditions and the following disclaimer. 1486560Sjake * 2. Redistributions in binary form must reproduce the above copyright 1586560Sjake * notice, this list of conditions and the following disclaimer in the 1686560Sjake * documentation and/or other materials provided with the distribution. 1786560Sjake * 4. Neither the name of the University nor the names of its contributors 1886560Sjake * may be used to endorse or promote products derived from this software 1986560Sjake * without specific prior written permission. 2086560Sjake * 2186560Sjake * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2286560Sjake * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2386560Sjake * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2486560Sjake * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2586560Sjake * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2686560Sjake * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2786560Sjake * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2886560Sjake * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2986560Sjake * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3086560Sjake * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3186560Sjake * SUCH DAMAGE. 3286560Sjake * 3386560Sjake * from: FreeBSD: src/lib/libkvm/kvm_i386.c,v 1.15 2001/10/10 17:48:43 3486560Sjake */ 3586560Sjake 3686560Sjake#include <sys/cdefs.h> 3786560Sjake__FBSDID("$FreeBSD$"); 3886560Sjake 3986560Sjake#if defined(LIBC_SCCS) && !defined(lint) 4086560Sjake#if 0 4186560Sjakestatic char sccsid[] = "@(#)kvm_hp300.c 8.1 (Berkeley) 6/4/93"; 4286560Sjake#endif 4386560Sjake#endif /* LIBC_SCCS and not lint */ 4486560Sjake 4586560Sjake/* 4686560Sjake * sparc64 machine dependent routines for kvm. 4786560Sjake */ 4886560Sjake 4986560Sjake#include <sys/param.h> 5086560Sjake#include <sys/user.h> 5186560Sjake#include <sys/proc.h> 5286560Sjake#include <sys/stat.h> 5386560Sjake#include <stdlib.h> 5486560Sjake#include <unistd.h> 5586560Sjake#include <nlist.h> 5686560Sjake#include <kvm.h> 5786560Sjake 5886560Sjake#include <vm/vm.h> 5986560Sjake#include <vm/vm_param.h> 6086560Sjake 61105532Stmm#include <machine/kerneldump.h> 6286560Sjake#include <machine/tte.h> 63108300Sjake#include <machine/tlb.h> 6486560Sjake#include <machine/tsb.h> 6586560Sjake 6686560Sjake#include <limits.h> 6786560Sjake 6886560Sjake#include "kvm_private.h" 6986560Sjake 7086560Sjake#ifndef btop 7186560Sjake#define btop(x) (sparc64_btop(x)) 7286560Sjake#define ptob(x) (sparc64_ptob(x)) 7386560Sjake#endif 7486560Sjake 7586560Sjakestruct vmstate { 76105532Stmm off_t vm_tsb_off; 77101653Sjake vm_size_t vm_tsb_mask; 78105532Stmm int vm_nregions; 79105532Stmm struct sparc64_dump_reg *vm_regions; 8086560Sjake}; 8186560Sjake 8286560Sjakevoid 8386560Sjake_kvm_freevtop(kvm_t *kd) 8486560Sjake{ 8586560Sjake if (kd->vmst != 0) { 86105532Stmm free(kd->vmst->vm_regions); 8786560Sjake free(kd->vmst); 8886560Sjake } 8986560Sjake} 9086560Sjake 91105532Stmmstatic int 92105532Stmm_kvm_read_phys(kvm_t *kd, off_t pos, void *buf, size_t size) 93105532Stmm{ 94105532Stmm 95105532Stmm /* XXX This has to be a raw file read, kvm_read is virtual. */ 96105532Stmm if (lseek(kd->pmfd, pos, SEEK_SET) == -1) { 97105532Stmm _kvm_syserr(kd, kd->program, "_kvm_read_phys: lseek"); 98105532Stmm return (0); 99105532Stmm } 100217744Suqs if (read(kd->pmfd, buf, size) != (ssize_t)size) { 101105532Stmm _kvm_syserr(kd, kd->program, "_kvm_read_phys: read"); 102105532Stmm return (0); 103105532Stmm } 104105532Stmm return (1); 105105532Stmm} 106105532Stmm 107105532Stmmstatic int 108105532Stmm_kvm_reg_cmp(const void *a, const void *b) 109105532Stmm{ 110105532Stmm const struct sparc64_dump_reg *ra, *rb; 111105532Stmm 112105532Stmm ra = a; 113105532Stmm rb = b; 114105532Stmm if (ra->dr_pa < rb->dr_pa) 115105532Stmm return (-1); 116105532Stmm else if (ra->dr_pa >= rb->dr_pa + rb->dr_size) 117105532Stmm return (1); 118105532Stmm else 119105532Stmm return (0); 120105532Stmm} 121105532Stmm 122105532Stmm#define KVM_OFF_NOTFOUND 0 123105532Stmm 124105532Stmmstatic off_t 125105532Stmm_kvm_find_off(struct vmstate *vm, vm_offset_t pa, vm_size_t size) 126105532Stmm{ 127105532Stmm struct sparc64_dump_reg *reg, key; 128105532Stmm vm_offset_t o; 129105532Stmm 130105532Stmm key.dr_pa = pa; 131105532Stmm reg = bsearch(&key, vm->vm_regions, vm->vm_nregions, 132105532Stmm sizeof(*vm->vm_regions), _kvm_reg_cmp); 133105532Stmm if (reg == NULL) 134105532Stmm return (KVM_OFF_NOTFOUND); 135105532Stmm o = pa - reg->dr_pa; 136105532Stmm if (o + size > reg->dr_size) 137105532Stmm return (KVM_OFF_NOTFOUND); 138105532Stmm return (reg->dr_offs + o); 139105532Stmm} 140105532Stmm 14186560Sjakeint 14286560Sjake_kvm_initvtop(kvm_t *kd) 14386560Sjake{ 144105532Stmm struct sparc64_dump_hdr hdr; 145105532Stmm struct sparc64_dump_reg *regs; 14686560Sjake struct vmstate *vm; 147105532Stmm size_t regsz; 148101653Sjake vm_offset_t pa; 14986560Sjake 15086560Sjake vm = (struct vmstate *)_kvm_malloc(kd, sizeof(*vm)); 15186560Sjake if (vm == NULL) { 15286560Sjake _kvm_err(kd, kd->program, "cannot allocate vm"); 15386560Sjake return (-1); 15486560Sjake } 15586560Sjake kd->vmst = vm; 15686560Sjake 157105532Stmm if (!_kvm_read_phys(kd, 0, &hdr, sizeof(hdr))) 158105532Stmm goto fail_vm; 159105532Stmm pa = hdr.dh_tsb_pa; 16086560Sjake 161105532Stmm regsz = hdr.dh_nregions * sizeof(*regs); 162105532Stmm regs = _kvm_malloc(kd, regsz); 163105532Stmm if (regs == NULL) { 164105532Stmm _kvm_err(kd, kd->program, "cannot allocate regions"); 165105532Stmm goto fail_vm; 16686560Sjake } 167105532Stmm if (!_kvm_read_phys(kd, sizeof(hdr), regs, regsz)) 168105532Stmm goto fail_regs; 169105532Stmm qsort(regs, hdr.dh_nregions, sizeof(*regs), _kvm_reg_cmp); 170105532Stmm 171105532Stmm vm->vm_tsb_mask = hdr.dh_tsb_mask; 172105532Stmm vm->vm_regions = regs; 173105532Stmm vm->vm_nregions = hdr.dh_nregions; 174105532Stmm vm->vm_tsb_off = _kvm_find_off(vm, hdr.dh_tsb_pa, hdr.dh_tsb_size); 175105532Stmm if (vm->vm_tsb_off == KVM_OFF_NOTFOUND) { 176105532Stmm _kvm_err(kd, kd->program, "tsb not found in dump"); 177105532Stmm goto fail_regs; 17886560Sjake } 17986560Sjake return (0); 180105532Stmm 181105532Stmmfail_regs: 182105532Stmm free(regs); 183105532Stmmfail_vm: 184105532Stmm free(vm); 185105532Stmm return (-1); 18686560Sjake} 18786560Sjake 18888615Sjakeint 189147672Speter_kvm_kvatop(kvm_t *kd, u_long va, off_t *pa) 19086560Sjake{ 19188615Sjake struct tte tte; 192217744Suqs off_t tte_off; 193217744Suqs u_long vpn; 194217744Suqs off_t pa_off; 195217744Suqs u_long pg_off; 196105532Stmm int rest; 19786560Sjake 198105532Stmm pg_off = va & PAGE_MASK; 199108300Sjake if (va >= VM_MIN_DIRECT_ADDRESS) 200108300Sjake pa_off = TLB_DIRECT_TO_PHYS(va) & ~PAGE_MASK; 201108300Sjake else { 202108300Sjake vpn = btop(va); 203108300Sjake tte_off = kd->vmst->vm_tsb_off + 204108300Sjake ((vpn & kd->vmst->vm_tsb_mask) << TTE_SHIFT); 205108300Sjake if (!_kvm_read_phys(kd, tte_off, &tte, sizeof(tte))) 206108300Sjake goto invalid; 207108300Sjake if (!tte_match(&tte, va)) 208108300Sjake goto invalid; 209108300Sjake pa_off = TTE_GET_PA(&tte); 210108300Sjake } 211105532Stmm rest = PAGE_SIZE - pg_off; 212108300Sjake pa_off = _kvm_find_off(kd->vmst, pa_off, rest); 213105532Stmm if (pa_off == KVM_OFF_NOTFOUND) 214105532Stmm goto invalid; 215105532Stmm *pa = pa_off + pg_off; 216105532Stmm return (rest); 21786560Sjake 21886560Sjakeinvalid: 219217744Suqs _kvm_err(kd, 0, "invalid address (%lx)", va); 22086560Sjake return (0); 22186560Sjake} 222