Home | History | Annotate | Line # | Download | only in libkvm
kvm_powerpc64.c revision 1.1
      1 /*	$NetBSD: kvm_powerpc64.c,v 1.1 2006/07/01 19:21:11 ross Exp $	*/
      2 
      3 /*
      4  * Copyright (c) 2005 Wasabi Systems, Inc.
      5  * All rights reserved.
      6  *
      7  * Written by Allen Briggs for Wasabi Systems, Inc.
      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 for the NetBSD Project by
     20  *      Wasabi Systems, Inc.
     21  * 4. The name of Wasabi Systems, Inc. may not be used to endorse
     22  *    or promote products derived from this software without specific prior
     23  *    written permission.
     24  *
     25  * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
     26  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     27  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     28  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL WASABI SYSTEMS, INC
     29  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     30  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     31  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     32  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     33  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     34  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     35  * POSSIBILITY OF SUCH DAMAGE.
     36  */
     37 /*-
     38  * Copyright (C) 1996 Wolfgang Solfrank.
     39  * Copyright (C) 1996 TooLs GmbH.
     40  * All rights reserved.
     41  *
     42  * Redistribution and use in source and binary forms, with or without
     43  * modification, are permitted provided that the following conditions
     44  * are met:
     45  * 1. Redistributions of source code must retain the above copyright
     46  *    notice, this list of conditions and the following disclaimer.
     47  * 2. Redistributions in binary form must reproduce the above copyright
     48  *    notice, this list of conditions and the following disclaimer in the
     49  *    documentation and/or other materials provided with the distribution.
     50  * 3. All advertising materials mentioning features or use of this software
     51  *    must display the following acknowledgement:
     52  *	This product includes software developed by TooLs GmbH.
     53  * 4. The name of TooLs GmbH may not be used to endorse or promote products
     54  *    derived from this software without specific prior written permission.
     55  *
     56  * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
     57  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     58  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     59  * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     60  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     61  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
     62  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     63  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
     64  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
     65  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     66  */
     67 
     68 /*
     69  * PowerPC machine dependent routines for kvm.
     70  */
     71 
     72 #include <sys/param.h>
     73 #include <sys/exec.h>
     74 
     75 #include <uvm/uvm_extern.h>
     76 
     77 #include <db.h>
     78 #include <limits.h>
     79 #include <kvm.h>
     80 #include <stdlib.h>
     81 #include <unistd.h>
     82 
     83 #include "kvm_private.h"
     84 
     85 #include <sys/kcore.h>
     86 #include <machine/kcore.h>
     87 
     88 #include <powerpc/spr.h>
     89 #include <powerpc/oea/bat.h>
     90 #include <powerpc/oea/pte.h>
     91 
     92 static int	_kvm_match_601bat(kvm_t *kd, u_long va, u_long *pa, int *off);
     93 static int	_kvm_match_bat(kvm_t *kd, u_long va, u_long *pa, int *off);
     94 static int	_kvm_match_sr(kvm_t *kd, u_long va, u_long *pa, int *off);
     95 static struct pte *_kvm_scan_pteg(struct pteg *pteg, uint32_t vsid,
     96 				  uint32_t api, int secondary);
     97 
     98 void
     99 _kvm_freevtop(kd)
    100 	kvm_t *kd;
    101 {
    102 	if (kd->vmst != 0)
    103 		free(kd->vmst);
    104 }
    105 
    106 /*ARGSUSED*/
    107 int
    108 _kvm_initvtop(kd)
    109 	kvm_t *kd;
    110 {
    111 
    112 	return 0;
    113 }
    114 
    115 #define SR_VSID_HASH_MASK	0x0007ffff
    116 
    117 static struct pte *
    118 _kvm_scan_pteg(pteg, vsid, api, secondary)
    119 	struct pteg *pteg;
    120 	uint32_t vsid;
    121 	uint32_t api;
    122 	int secondary;
    123 {
    124 	struct pte	*pte;
    125 	u_long		ptehi;
    126 	int		i;
    127 
    128 	for (i=0 ; i<8 ; i++) {
    129 		pte = &pteg->pt[i];
    130 		ptehi = (u_long) pte->pte_hi;
    131 		if ((ptehi & PTE_VALID) == 0)
    132 			continue;
    133 		if ((ptehi & PTE_HID) != secondary)
    134 			continue;
    135 		if (((ptehi & PTE_VSID) >> PTE_VSID_SHFT) != vsid)
    136 			continue;
    137 		if (((ptehi & PTE_API) >> PTE_API_SHFT) != api)
    138 			continue;
    139 		return pte;
    140 	}
    141 	return NULL;
    142 }
    143 
    144 #define HASH_MASK	0x0007ffff
    145 
    146 static int
    147 _kvm_match_sr(kd, va, pa, off)
    148 	kvm_t *kd;
    149 	u_long va;
    150 	u_long *pa;
    151 	int *off;
    152 {
    153 	cpu_kcore_hdr_t	*cpu_kh;
    154 	struct pteg	pteg;
    155 	struct pte	*pte;
    156 	uint32_t	sr, pgoff, vsid, pgidx, api, hash;
    157 	uint32_t	htaborg, htabmask, mhash;
    158 	u_long		pteg_vaddr;
    159 
    160 	cpu_kh = kd->cpu_data;
    161 
    162 	sr = cpu_kh->sr[(va >> 28) & 0xf];
    163 	if ((sr & SR_TYPE) != 0) {
    164 		/* Direct-store segment (shouldn't be) */
    165 		return 0;
    166 	}
    167 
    168 	pgoff = va & ADDR_POFF;
    169 	vsid = sr & SR_VSID;
    170 	pgidx = (va & ADDR_PIDX) >> ADDR_PIDX_SHFT;
    171 	api = pgidx >> 10;
    172 	hash = (vsid & HASH_MASK) ^ pgidx;
    173 
    174 	htaborg = cpu_kh->sdr1 & 0xffff0000;
    175 	htabmask = cpu_kh->sdr1 & 0x1ff;
    176 
    177 	mhash = (hash >> 10) & htabmask;
    178 
    179 	pteg_vaddr = ( htaborg & 0xfe000000) | ((hash & 0x3ff) << 6)
    180 		   | ((htaborg & 0x01ff0000) | (mhash << 16));
    181 
    182 	if (pread(kd->pmfd, (void *) &pteg, sizeof(pteg),
    183 		  _kvm_pa2off(kd, pteg_vaddr)) != sizeof(pteg)) {
    184 		_kvm_syserr(kd, 0, "could not read primary PTEG");
    185 		return 0;
    186 	}
    187 
    188 	if ((pte = _kvm_scan_pteg(&pteg, vsid, api, 0)) != NULL) {
    189 		*pa = (pte->pte_lo & PTE_RPGN) | pgoff;
    190 		*off = NBPG - pgoff;
    191 		return 1;
    192 	}
    193 
    194 	hash = (~hash) & HASH_MASK;
    195 	mhash = (hash >> 10) & htabmask;
    196 
    197 	pteg_vaddr = ( htaborg & 0xfe000000) | ((hash & 0x3ff) << 6)
    198 		   | ((htaborg & 0x01ff0000) | (mhash << 16));
    199 
    200 	if (pread(kd->pmfd, (void *) &pteg, sizeof(pteg),
    201 		  _kvm_pa2off(kd, pteg_vaddr)) != sizeof(pteg)) {
    202 		_kvm_syserr(kd, 0, "could not read secondary PTEG");
    203 		return 0;
    204 	}
    205 
    206 	if ((pte = _kvm_scan_pteg(&pteg, vsid, api, 0)) != NULL) {
    207 		*pa = (pte->pte_lo & PTE_RPGN) | pgoff;
    208 		*off = NBPG - pgoff;
    209 		return 1;
    210 	}
    211 
    212 	return 0;
    213 }
    214 
    215 /*
    216  * Translate a KVA to a PA
    217  */
    218 int
    219 _kvm_kvatop(kd, va, pa)
    220 	kvm_t *kd;
    221 	u_long va;
    222 	u_long *pa;
    223 {
    224 	cpu_kcore_hdr_t	*cpu_kh;
    225 	int		offs;
    226 	uint32_t	pvr;
    227 
    228 	if (ISALIVE(kd)) {
    229 		_kvm_err(kd, 0, "vatop called in live kernel!");
    230 		return 0;
    231 	}
    232 
    233 	cpu_kh = kd->cpu_data;
    234 
    235 	pvr = (cpu_kh->pvr >> 16);
    236 
    237 	switch (pvr) {
    238 
    239 	if (_kvm_match_sr(kd, va, pa, &offs))
    240 		return offs;
    241 
    242 	/* No hit -- no translation */
    243 	*pa = (u_long)~0UL;
    244 	return 0;
    245 }
    246 
    247 off_t
    248 _kvm_pa2off(kd, pa)
    249 	kvm_t *kd;
    250 	u_long pa;
    251 {
    252 	cpu_kcore_hdr_t	*cpu_kh;
    253 	phys_ram_seg_t	*ram;
    254 	off_t		off;
    255 	void		*e;
    256 
    257 	cpu_kh = kd->cpu_data;
    258 	e = (char *) kd->cpu_data + kd->cpu_dsize;
    259         ram = (void *)((char *)(void *)cpu_kh + ALIGN(sizeof *cpu_kh));
    260 	off = kd->dump_off;
    261 	do {
    262 		if (pa >= ram->start && (pa - ram->start) < ram->size) {
    263 			return off + (pa - ram->start);
    264 		}
    265 		ram++;
    266 		off += ram->size;
    267 	} while ((void *) ram < e && ram->size);
    268 
    269 	_kvm_err(kd, 0, "pa2off failed for pa 0x%08lx\n", pa);
    270 	return (off_t) -1;
    271 }
    272 
    273 /*
    274  * Machine-dependent initialization for ALL open kvm descriptors,
    275  * not just those for a kernel crash dump.  Some architectures
    276  * have to deal with these NOT being constants!  (i.e. m68k)
    277  */
    278 int
    279 _kvm_mdopen(kd)
    280 	kvm_t	*kd;
    281 {
    282 	uintptr_t max_uva;
    283 	extern struct ps_strings *__ps_strings;
    284 
    285 #if 0   /* XXX - These vary across powerpc machines... */
    286 	kd->usrstack = USRSTACK;
    287 	kd->min_uva = VM_MIN_ADDRESS;
    288 	kd->max_uva = VM_MAXUSER_ADDRESS;
    289 #endif
    290 	/* This is somewhat hack-ish, but it works. */
    291 	max_uva = (uintptr_t) (__ps_strings + 1);
    292 	kd->usrstack = max_uva;
    293 	kd->max_uva  = max_uva;
    294 	kd->min_uva  = 0;
    295 
    296 	return (0);
    297 }
    298