1 /* $NetBSD: kvm_powerpc.c,v 1.13 2014/01/27 21:00:01 matt 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 #include <sys/types.h> 75 76 #include <uvm/uvm_extern.h> 77 78 #include <db.h> 79 #include <limits.h> 80 #include <kvm.h> 81 #include <stdlib.h> 82 #include <unistd.h> 83 84 #include "kvm_private.h" 85 86 #include <sys/kcore.h> 87 #include <machine/kcore.h> 88 89 #include <powerpc/spr.h> 90 #include <powerpc/oea/spr.h> 91 #include <powerpc/oea/bat.h> 92 #include <powerpc/oea/pte.h> 93 94 __RCSID("$NetBSD: kvm_powerpc.c,v 1.13 2014/01/27 21:00:01 matt Exp $"); 95 96 static int _kvm_match_601bat(kvm_t *, vaddr_t, paddr_t *, int *); 97 static int _kvm_match_bat(kvm_t *, vaddr_t, paddr_t *, int *); 98 static int _kvm_match_sr(kvm_t *, vaddr_t, paddr_t *, int *); 99 static struct pte *_kvm_scan_pteg(struct pteg *, uint32_t, uint32_t, int); 100 101 void 102 _kvm_freevtop(kvm_t *kd) 103 { 104 if (kd->vmst != 0) 105 free(kd->vmst); 106 } 107 108 /*ARGSUSED*/ 109 int 110 _kvm_initvtop(kvm_t *kd) 111 { 112 113 return 0; 114 } 115 116 #define BAT601_SIZE(b) ((((b) << 17) | ~BAT601_BLPI) + 1) 117 118 static int 119 _kvm_match_601bat(kvm_t *kd, vaddr_t va, paddr_t *pa, int *off) 120 { 121 cpu_kcore_hdr_t *cpu_kh; 122 u_long pgoff; 123 size_t size; 124 int i, nbat; 125 126 cpu_kh = kd->cpu_data; 127 nbat = 4; 128 for (i=0 ; i<nbat ; i++) { 129 if (!BAT601_VALID_P(cpu_kh->dbatu[i])) 130 continue; 131 if (BAT601_VA_MATCH_P(cpu_kh->dbatu[i], cpu_kh->dbatl[i], va)) { 132 size = BAT601_SIZE(cpu_kh->dbatu[i] & BAT601_BSM); 133 pgoff = va & (size-1); 134 *pa = (cpu_kh->dbatl[i] & BAT601_PBN) + pgoff; 135 *off = size - pgoff; 136 return 1; 137 } 138 } 139 return 0; 140 } 141 142 #undef BAT601_SIZE 143 144 #define BAT_SIZE(b) ((((b) << 15) | ~BAT_EPI) + 1) 145 146 static int 147 _kvm_match_bat(kvm_t *kd, vaddr_t va, paddr_t *pa, int *off) 148 { 149 cpu_kcore_hdr_t *cpu_kh; 150 u_long pgoff; 151 size_t size; 152 int i, nbat; 153 154 cpu_kh = kd->cpu_data; 155 /* 156 * Assume that we're looking for data and check only the dbats. 157 */ 158 nbat = 8; 159 for (i=0 ; i<nbat ; i++) { 160 if ( ((cpu_kh->dbatu[i] & BAT_Vs) != 0) 161 && (BAT_VA_MATCH_P(cpu_kh->dbatu[i], va))) { 162 size = BAT_SIZE(cpu_kh->dbatu[i] & BAT_BL); 163 pgoff = va & (size-1); 164 *pa = (cpu_kh->dbatl[i] & BAT_RPN) + pgoff; 165 *off = size - pgoff; 166 return 1; 167 } 168 } 169 return 0; 170 } 171 172 #undef BAT_SIZE 173 174 #define SR_VSID_HASH_MASK 0x0007ffff 175 176 static struct pte * 177 _kvm_scan_pteg(struct pteg *pteg, uint32_t vsid, uint32_t api, int secondary) 178 { 179 struct pte *pte; 180 u_long ptehi; 181 int i; 182 183 for (i=0 ; i<8 ; i++) { 184 pte = &pteg->pt[i]; 185 ptehi = (u_long) pte->pte_hi; 186 if ((ptehi & PTE_VALID) == 0) 187 continue; 188 if ((ptehi & PTE_HID) != secondary) 189 continue; 190 if (((ptehi & PTE_VSID) >> PTE_VSID_SHFT) != vsid) 191 continue; 192 if (((ptehi & PTE_API) >> PTE_API_SHFT) != api) 193 continue; 194 return pte; 195 } 196 return NULL; 197 } 198 199 #define HASH_MASK 0x0007ffff 200 201 static int 202 _kvm_match_sr(kvm_t *kd, vaddr_t va, paddr_t *pa, int *off) 203 { 204 cpu_kcore_hdr_t *cpu_kh; 205 struct pteg pteg; 206 struct pte *pte; 207 uint32_t sr, pgoff, vsid, pgidx, api, hash; 208 uint32_t htaborg, htabmask, mhash; 209 paddr_t pteg_vaddr; 210 211 cpu_kh = kd->cpu_data; 212 213 sr = cpu_kh->sr[(va >> 28) & 0xf]; 214 if ((sr & SR_TYPE) != 0) { 215 /* Direct-store segment (shouldn't be) */ 216 return 0; 217 } 218 219 pgoff = va & ADDR_POFF; 220 vsid = sr & SR_VSID; 221 pgidx = (va & ADDR_PIDX) >> ADDR_PIDX_SHFT; 222 api = pgidx >> 10; 223 hash = (vsid & HASH_MASK) ^ pgidx; 224 225 htaborg = cpu_kh->sdr1 & 0xffff0000; 226 htabmask = cpu_kh->sdr1 & 0x1ff; 227 228 mhash = (hash >> 10) & htabmask; 229 230 pteg_vaddr = ( htaborg & 0xfe000000) | ((hash & 0x3ff) << 6) 231 | ((htaborg & 0x01ff0000) | (mhash << 16)); 232 233 if (_kvm_pread(kd, kd->pmfd, (void *) &pteg, sizeof(pteg), 234 _kvm_pa2off(kd, pteg_vaddr)) != sizeof(pteg)) { 235 _kvm_syserr(kd, 0, "could not read primary PTEG"); 236 return 0; 237 } 238 239 if ((pte = _kvm_scan_pteg(&pteg, vsid, api, 0)) != NULL) { 240 *pa = (pte->pte_lo & PTE_RPGN) | pgoff; 241 *off = NBPG - pgoff; 242 return 1; 243 } 244 245 hash = (~hash) & HASH_MASK; 246 mhash = (hash >> 10) & htabmask; 247 248 pteg_vaddr = ( htaborg & 0xfe000000) | ((hash & 0x3ff) << 6) 249 | ((htaborg & 0x01ff0000) | (mhash << 16)); 250 251 if (_kvm_pread(kd, kd->pmfd, (void *) &pteg, sizeof(pteg), 252 _kvm_pa2off(kd, pteg_vaddr)) != sizeof(pteg)) { 253 _kvm_syserr(kd, 0, "could not read secondary PTEG"); 254 return 0; 255 } 256 257 if ((pte = _kvm_scan_pteg(&pteg, vsid, api, 0)) != NULL) { 258 *pa = (pte->pte_lo & PTE_RPGN) | pgoff; 259 *off = NBPG - pgoff; 260 return 1; 261 } 262 263 return 0; 264 } 265 266 /* 267 * Translate a KVA to a PA 268 */ 269 int 270 _kvm_kvatop(kvm_t *kd, vaddr_t va, paddr_t *pa) 271 { 272 cpu_kcore_hdr_t *cpu_kh; 273 int offs; 274 uint32_t pvr; 275 276 if (ISALIVE(kd)) { 277 _kvm_err(kd, 0, "vatop called in live kernel!"); 278 return 0; 279 } 280 281 cpu_kh = kd->cpu_data; 282 283 pvr = (cpu_kh->pvr >> 16); 284 if (MPC745X_P(pvr)) 285 pvr = MPC7450; 286 287 switch (pvr) { 288 case MPC601: 289 /* Check for a BAT hit first */ 290 if (_kvm_match_601bat(kd, va, pa, &offs)) { 291 return offs; 292 } 293 294 /* No BAT hit; check page tables */ 295 if (_kvm_match_sr(kd, va, pa, &offs)) { 296 return offs; 297 } 298 break; 299 300 case MPC603: 301 case MPC603e: 302 case MPC603ev: 303 case MPC604: 304 case MPC604ev: 305 case MPC750: 306 case IBM750FX: 307 case MPC7400: 308 case MPC7450: 309 case MPC7410: 310 case MPC8240: 311 case MPC8245: 312 /* Check for a BAT hit first */ 313 if (_kvm_match_bat(kd, va, pa, &offs)) { 314 return offs; 315 } 316 317 /* No BAT hit; check page tables */ 318 if (_kvm_match_sr(kd, va, pa, &offs)) { 319 return offs; 320 } 321 break; 322 323 default: 324 _kvm_err(kd, 0, "Unsupported CPU type (pvr 0x%08lx)!", 325 (unsigned long) cpu_kh->pvr); 326 break; 327 } 328 329 /* No hit -- no translation */ 330 *pa = (paddr_t)~0UL; 331 return 0; 332 } 333 334 off_t 335 _kvm_pa2off(kvm_t *kd, paddr_t pa) 336 { 337 cpu_kcore_hdr_t *cpu_kh; 338 phys_ram_seg_t *ram; 339 off_t off; 340 void *e; 341 342 cpu_kh = kd->cpu_data; 343 e = (char *) kd->cpu_data + kd->cpu_dsize; 344 ram = (void *)((char *)(void *)cpu_kh + ALIGN(sizeof *cpu_kh)); 345 off = kd->dump_off; 346 do { 347 if (pa >= ram->start && (pa - ram->start) < ram->size) { 348 return off + (pa - ram->start); 349 } 350 ram++; 351 off += ram->size; 352 } while ((void *) ram < e && ram->size); 353 354 _kvm_err(kd, 0, "pa2off failed for pa %#" PRIxPADDR "\n", pa); 355 return (off_t) -1; 356 } 357 358 /* 359 * Machine-dependent initialization for ALL open kvm descriptors, 360 * not just those for a kernel crash dump. Some architectures 361 * have to deal with these NOT being constants! (i.e. m68k) 362 */ 363 int 364 _kvm_mdopen(kvm_t *kd) 365 { 366 uintptr_t max_uva; 367 extern struct ps_strings *__ps_strings; 368 369 #if 0 /* XXX - These vary across powerpc machines... */ 370 kd->usrstack = USRSTACK; 371 kd->min_uva = VM_MIN_ADDRESS; 372 kd->max_uva = VM_MAXUSER_ADDRESS; 373 #endif 374 /* This is somewhat hack-ish, but it works. */ 375 max_uva = (uintptr_t) (__ps_strings + 1); 376 kd->usrstack = max_uva; 377 kd->max_uva = max_uva; 378 kd->min_uva = 0; 379 380 return (0); 381 } 382