File:  [DragonFly] / src / lib / libkvm / kvm_sparc.c
Revision 1.3: download - view: text, annotated - select for diffs
Sun Apr 11 21:28:03 2004 UTC (10 years, 7 months ago) by cpressey
Branches: MAIN
CVS tags: HEAD, DragonFly_Stable, DragonFly_Snap29Sep2004, DragonFly_Snap13Sep2004, DragonFly_RELEASE_1_8_Slip, DragonFly_RELEASE_1_8, DragonFly_RELEASE_1_6_Slip, DragonFly_RELEASE_1_6, DragonFly_RELEASE_1_4_Slip, DragonFly_RELEASE_1_4, DragonFly_RELEASE_1_2_Slip, DragonFly_RELEASE_1_2, DragonFly_1_0_REL, DragonFly_1_0_RC1, DragonFly_1_0A_REL
Style(9) cleanup.

- Convert K&R-style function definitions to ANSI style.
- Remove `register' keywords.
- Use stdarg.h instead of varargs.h for variable numbers of arguments.
- #define _KERNEL_STRUCTURES when accessing kernel structures.
- No functional changes.

    1: /*-
    2:  * Copyright (c) 1992, 1993
    3:  *	The Regents of the University of California.  All rights reserved.
    4:  *
    5:  * This code is derived from software developed by the Computer Systems
    6:  * Engineering group at Lawrence Berkeley Laboratory under DARPA contract
    7:  * BG 91-66 and contributed to Berkeley.
    8:  *
    9:  * Redistribution and use in source and binary forms, with or without
   10:  * modification, are permitted provided that the following conditions
   11:  * are met:
   12:  * 1. Redistributions of source code must retain the above copyright
   13:  *    notice, this list of conditions and the following disclaimer.
   14:  * 2. Redistributions in binary form must reproduce the above copyright
   15:  *    notice, this list of conditions and the following disclaimer in the
   16:  *    documentation and/or other materials provided with the distribution.
   17:  * 3. All advertising materials mentioning features or use of this software
   18:  *    must display the following acknowledgement:
   19:  *	This product includes software developed by the University of
   20:  *	California, Berkeley and its contributors.
   21:  * 4. Neither the name of the University nor the names of its contributors
   22:  *    may be used to endorse or promote products derived from this software
   23:  *    without specific prior written permission.
   24:  *
   25:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   26:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   27:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   28:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   29:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   30:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   31:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   32:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   33:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   34:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   35:  * SUCH DAMAGE.
   36:  *
   37:  * @(#)kvm_sparc.c	8.1 (Berkeley) 6/4/93
   38:  * $FreeBSD: src/lib/libkvm/kvm_sparc.c,v 1.3 1999/12/27 07:14:58 peter Exp $
   39:  * $DragonFly: src/lib/libkvm/kvm_sparc.c,v 1.3 2004/04/11 21:28:03 cpressey Exp $
   40:  */
   41: 
   42: /*
   43:  * Sparc machine dependent routines for kvm.  Hopefully, the forthcoming
   44:  * vm code will one day obsolete this module.
   45:  */
   46: 
   47: #include <sys/param.h>
   48: #include <sys/user.h>
   49: #include <sys/proc.h>
   50: #include <sys/stat.h>
   51: #include <unistd.h>
   52: #include <nlist.h>
   53: #include <kvm.h>
   54: 
   55: #include <vm/vm.h>
   56: #include <vm/vm_param.h>
   57: 
   58: #include <limits.h>
   59: 
   60: #include "kvm_private.h"
   61: 
   62: #define NPMEG 128
   63: 
   64: /* XXX from sparc/pmap.c */
   65: #define MAXMEM  (128 * 1024 * 1024)     /* no more than 128 MB phys mem */
   66: #define NPGBANK 16                      /* 2^4 pages per bank (64K / bank) */
   67: #define BSHIFT  4                       /* log2(NPGBANK) */
   68: #define BOFFSET (NPGBANK - 1)
   69: #define BTSIZE  (MAXMEM / NBPG / NPGBANK)
   70: #define HWTOSW(pmap_stod, pg) (pmap_stod[(pg) >> BSHIFT] | ((pg) & BOFFSET))
   71: 
   72: struct vmstate {
   73: 	pmeg_t segmap[NKSEG];
   74: 	int pmeg[NPMEG][NPTESG];
   75: 	int pmap_stod[BTSIZE];              /* dense to sparse */
   76: };
   77: 
   78: void
   79: _kvm_freevtop(kvm_t *kd)
   80: {
   81: 	if (kd->vmst != 0)
   82: 		free(kd->vmst);
   83: }
   84: 
   85: int
   86: _kvm_initvtop(kvm_t *kd)
   87: {
   88: 	int i;
   89: 	int off;
   90: 	struct vmstate *vm;
   91: 	struct stat st;
   92: 	struct nlist nlist[2];
   93: 
   94: 	vm = (struct vmstate *)_kvm_malloc(kd, sizeof(*vm));
   95: 	if (vm == 0)
   96: 		return (-1);
   97: 
   98: 	kd->vmst = vm;
   99: 
  100: 	if (fstat(kd->pmfd, &st) < 0)
  101: 		return (-1);
  102: 	/*
  103: 	 * Read segment table.
  104: 	 */
  105: 	off = st.st_size - ctob(btoc(sizeof(vm->segmap)));
  106: 	errno = 0;
  107: 	if (lseek(kd->pmfd, (off_t)off, 0) == -1 && errno != 0 ||
  108: 	    read(kd->pmfd, (char *)vm->segmap, sizeof(vm->segmap)) < 0) {
  109: 		_kvm_err(kd, kd->program, "cannot read segment map");
  110: 		return (-1);
  111: 	}
  112: 	/*
  113: 	 * Read PMEGs.
  114: 	 */
  115: 	off = st.st_size - ctob(btoc(sizeof(vm->pmeg)) +
  116: 	    btoc(sizeof(vm->segmap)));
  117: 	errno = 0;
  118: 	if (lseek(kd->pmfd, (off_t)off, 0) == -1 && errno != 0 ||
  119: 	    read(kd->pmfd, (char *)vm->pmeg, sizeof(vm->pmeg)) < 0) {
  120: 		_kvm_err(kd, kd->program, "cannot read PMEG table");
  121: 		return (-1);
  122: 	}
  123: 	/*
  124: 	 * Make pmap_stod be an identity map so we can bootstrap it in.
  125: 	 * We assume it's in the first contiguous chunk of physical memory.
  126: 	 */
  127: 	for (i = 0; i < BTSIZE; ++i)
  128: 		vm->pmap_stod[i] = i << 4;
  129: 
  130: 	/*
  131: 	 * It's okay to do this nlist separately from the one kvm_getprocs()
  132: 	 * does, since the only time we could gain anything by combining
  133: 	 * them is if we do a kvm_getprocs() on a dead kernel, which is
  134: 	 * not too common.
  135: 	 */
  136: 	nlist[0].n_name = "_pmap_stod";
  137: 	nlist[1].n_name = 0;
  138: 	if (kvm_nlist(kd, nlist) != 0) {
  139: 		_kvm_err(kd, kd->program, "pmap_stod: no such symbol");
  140: 		return (-1);
  141: 	}
  142: 	if (kvm_read(kd, (u_long)nlist[0].n_value,
  143: 		     (char *)vm->pmap_stod, sizeof(vm->pmap_stod))
  144: 	    != sizeof(vm->pmap_stod)) {
  145: 		_kvm_err(kd, kd->program, "cannot read pmap_stod");
  146: 		return (-1);
  147: 	}
  148: 	return (0);
  149: }
  150: 
  151: #define VA_OFF(va) (va & (NBPG - 1))
  152: 
  153: /*
  154:  * Translate a user virtual address to a physical address.
  155:  */
  156: int
  157: _kvm_uvatop(kvm_t *kd, const struct proc *p, u_long va, u_long *pa)
  158: {
  159: 	int kva, pte;
  160: 	int off, frame;
  161: 	struct vmspace *vms = p->p_vmspace;
  162: 
  163: 	if ((u_long)vms < KERNBASE) {
  164: 		_kvm_err(kd, kd->program, "_kvm_uvatop: corrupt proc");
  165: 		return (0);
  166: 	}
  167: 	if (va >= KERNBASE)
  168: 		return (0);
  169: 	/*
  170: 	 * Get the PTE.  This takes two steps.  We read the
  171: 	 * base address of the table, then we index it.
  172: 	 * Note that the index pte table is indexed by
  173: 	 * virtual segment rather than physical segment.
  174: 	 */
  175: 	kva = (u_long)&vms->vm_pmap.pm_rpte[VA_VSEG(va)];
  176: 	if (kvm_read(kd, kva, (char *)&kva, 4) != 4 || kva == 0)
  177: 		goto invalid;
  178: 	kva += sizeof(vms->vm_pmap.pm_rpte[0]) * VA_VPG(va);
  179: 	if (kvm_read(kd, kva, (char *)&pte, 4) == 4 && (pte & PG_V)) {
  180: 		off = VA_OFF(va);
  181: 		/*
  182: 		 * /dev/mem adheres to the hardware model of physical memory
  183: 		 * (with holes in the address space), while crashdumps
  184: 		 * adhere to the contiguous software model.
  185: 		 */
  186: 		if (ISALIVE(kd))
  187: 			frame = pte & PG_PFNUM;
  188: 		else
  189: 			frame = HWTOSW(kd->vmst->pmap_stod, pte & PG_PFNUM);
  190: 		*pa = (frame << PGSHIFT) | off;
  191: 		return (NBPG - off);
  192: 	}
  193: invalid:
  194: 	_kvm_err(kd, 0, "invalid address (%x)", va);
  195: 	return (0);
  196: }
  197: 
  198: /*
  199:  * Translate a kernel virtual address to a physical address using the
  200:  * mapping information in kd->vm.  Returns the result in pa, and returns
  201:  * the number of bytes that are contiguously available from this
  202:  * physical address.  This routine is used only for crashdumps.
  203:  */
  204: int
  205: _kvm_kvatop(kvm_t *kd, u_long va, u_long *pa)
  206: {
  207: 	struct vmstate *vm;
  208: 	int s;
  209: 	int pte;
  210: 	int off;
  211: 
  212: 	if (va >= KERNBASE) {
  213: 		vm = kd->vmst;
  214: 		s = vm->segmap[VA_VSEG(va) - NUSEG];
  215: 		pte = vm->pmeg[s][VA_VPG(va)];
  216: 		if ((pte & PG_V) != 0) {
  217: 			off = VA_OFF(va);
  218: 			*pa = (HWTOSW(vm->pmap_stod, pte & PG_PFNUM)
  219: 			       << PGSHIFT) | off;
  220: 
  221: 			return (NBPG - off);
  222: 		}
  223: 	}
  224: 	_kvm_err(kd, 0, "invalid address (%x)", va);
  225: 	return (0);
  226: }