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