1 1.18 matt /* $NetBSD: kvm_m68k_cmn.c,v 1.18 2014/03/04 06:38:08 matt Exp $ */ 2 1.1 gwr 3 1.1 gwr /*- 4 1.1 gwr * Copyright (c) 1989, 1992, 1993 5 1.1 gwr * The Regents of the University of California. All rights reserved. 6 1.1 gwr * 7 1.1 gwr * This code is derived from software developed by the Computer Systems 8 1.1 gwr * Engineering group at Lawrence Berkeley Laboratory under DARPA contract 9 1.1 gwr * BG 91-66 and contributed to Berkeley. 10 1.1 gwr * 11 1.1 gwr * Redistribution and use in source and binary forms, with or without 12 1.1 gwr * modification, are permitted provided that the following conditions 13 1.1 gwr * are met: 14 1.1 gwr * 1. Redistributions of source code must retain the above copyright 15 1.1 gwr * notice, this list of conditions and the following disclaimer. 16 1.1 gwr * 2. Redistributions in binary form must reproduce the above copyright 17 1.1 gwr * notice, this list of conditions and the following disclaimer in the 18 1.1 gwr * documentation and/or other materials provided with the distribution. 19 1.12 agc * 3. Neither the name of the University nor the names of its contributors 20 1.12 agc * may be used to endorse or promote products derived from this software 21 1.12 agc * without specific prior written permission. 22 1.12 agc * 23 1.12 agc * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 24 1.12 agc * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 1.12 agc * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 1.12 agc * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 27 1.12 agc * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 1.12 agc * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 1.12 agc * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 1.12 agc * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 1.12 agc * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 1.12 agc * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 1.12 agc * SUCH DAMAGE. 34 1.12 agc */ 35 1.12 agc 36 1.12 agc /*- 37 1.12 agc * Copyright (c) 1997 Jason R. Thorpe. All rights reserved. 38 1.12 agc * 39 1.12 agc * This code is derived from software developed by the Computer Systems 40 1.12 agc * Engineering group at Lawrence Berkeley Laboratory under DARPA contract 41 1.12 agc * BG 91-66 and contributed to Berkeley. 42 1.12 agc * 43 1.12 agc * Redistribution and use in source and binary forms, with or without 44 1.12 agc * modification, are permitted provided that the following conditions 45 1.12 agc * are met: 46 1.12 agc * 1. Redistributions of source code must retain the above copyright 47 1.12 agc * notice, this list of conditions and the following disclaimer. 48 1.12 agc * 2. Redistributions in binary form must reproduce the above copyright 49 1.12 agc * notice, this list of conditions and the following disclaimer in the 50 1.12 agc * documentation and/or other materials provided with the distribution. 51 1.1 gwr * 3. All advertising materials mentioning features or use of this software 52 1.1 gwr * must display the following acknowledgement: 53 1.1 gwr * This product includes software developed by the University of 54 1.1 gwr * California, Berkeley and its contributors. 55 1.1 gwr * 4. Neither the name of the University nor the names of its contributors 56 1.1 gwr * may be used to endorse or promote products derived from this software 57 1.1 gwr * without specific prior written permission. 58 1.1 gwr * 59 1.1 gwr * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 60 1.1 gwr * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 61 1.1 gwr * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 62 1.1 gwr * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 63 1.1 gwr * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 64 1.1 gwr * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 65 1.1 gwr * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 66 1.1 gwr * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 67 1.1 gwr * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 68 1.1 gwr * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 69 1.1 gwr * SUCH DAMAGE. 70 1.1 gwr */ 71 1.1 gwr 72 1.4 mikel #include <sys/cdefs.h> 73 1.1 gwr #if defined(LIBC_SCCS) && !defined(lint) 74 1.1 gwr #if 0 75 1.1 gwr static char sccsid[] = "@(#)kvm_hp300.c 8.1 (Berkeley) 6/4/93"; 76 1.1 gwr #else 77 1.18 matt __RCSID("$NetBSD: kvm_m68k_cmn.c,v 1.18 2014/03/04 06:38:08 matt Exp $"); 78 1.1 gwr #endif 79 1.1 gwr #endif /* LIBC_SCCS and not lint */ 80 1.1 gwr 81 1.1 gwr /* 82 1.1 gwr * Common m68k machine dependent routines for kvm. 83 1.1 gwr * 84 1.1 gwr * Note: This file has to build on ALL m68k machines, 85 1.6 briggs * so do NOT include any <machine / *.h> files here. 86 1.1 gwr */ 87 1.1 gwr 88 1.17 christos #include <sys/param.h> 89 1.1 gwr #include <sys/types.h> 90 1.1 gwr #include <sys/kcore.h> 91 1.1 gwr 92 1.1 gwr #include <unistd.h> 93 1.1 gwr #include <limits.h> 94 1.1 gwr #include <nlist.h> 95 1.1 gwr #include <kvm.h> 96 1.1 gwr #include <db.h> 97 1.1 gwr 98 1.1 gwr #include <m68k/cpu.h> 99 1.1 gwr #include <m68k/kcore.h> 100 1.18 matt #include <m68k/m68k.h> 101 1.1 gwr 102 1.1 gwr #include "kvm_private.h" 103 1.1 gwr #include "kvm_m68k.h" 104 1.1 gwr 105 1.14 jym int _kvm_cmn_initvtop(kvm_t *); 106 1.14 jym void _kvm_cmn_freevtop(kvm_t *); 107 1.15 jym int _kvm_cmn_kvatop(kvm_t *, vaddr_t, paddr_t *); 108 1.15 jym off_t _kvm_cmn_pa2off(kvm_t *, paddr_t); 109 1.1 gwr 110 1.1 gwr struct kvm_ops _kvm_ops_cmn = { 111 1.1 gwr _kvm_cmn_initvtop, 112 1.1 gwr _kvm_cmn_freevtop, 113 1.1 gwr _kvm_cmn_kvatop, 114 1.1 gwr _kvm_cmn_pa2off }; 115 1.1 gwr 116 1.15 jym static int vatop_030(kvm_t *, uint32_t, vaddr_t, paddr_t *); 117 1.15 jym static int vatop_040(kvm_t *, uint32_t, vaddr_t, paddr_t *); 118 1.1 gwr 119 1.2 thorpej #define _kvm_btop(v, a) (((unsigned)(a)) >> (v)->pgshift) 120 1.1 gwr 121 1.1 gwr void 122 1.14 jym _kvm_cmn_freevtop(kvm_t *kd) 123 1.1 gwr { 124 1.2 thorpej /* No private state information to keep. */ 125 1.1 gwr } 126 1.1 gwr 127 1.1 gwr int 128 1.14 jym _kvm_cmn_initvtop(kvm_t *kd) 129 1.1 gwr { 130 1.2 thorpej /* No private state information to keep. */ 131 1.1 gwr return (0); 132 1.1 gwr } 133 1.1 gwr 134 1.1 gwr int 135 1.15 jym _kvm_cmn_kvatop(kvm_t *kd, vaddr_t va, paddr_t *pa) 136 1.1 gwr { 137 1.2 thorpej cpu_kcore_hdr_t *h = kd->cpu_data; 138 1.2 thorpej struct m68k_kcore_hdr *m = &h->un._m68k; 139 1.15 jym int (*vtopf)(kvm_t *, uint32_t, vaddr_t, paddr_t *); 140 1.1 gwr 141 1.1 gwr if (ISALIVE(kd)) { 142 1.1 gwr _kvm_err(kd, 0, "vatop called in live kernel!"); 143 1.1 gwr return (0); 144 1.1 gwr } 145 1.1 gwr 146 1.2 thorpej /* 147 1.5 kleink * 68040 and 68060 use same translation functions, 148 1.2 thorpej * as do 68030, 68851, HP MMU. 149 1.2 thorpej */ 150 1.2 thorpej if (m->mmutype == MMU_68040 || m->mmutype == MMU_68060) 151 1.2 thorpej vtopf = vatop_040; 152 1.2 thorpej else 153 1.1 gwr vtopf = vatop_030; 154 1.1 gwr 155 1.2 thorpej return ((*vtopf)(kd, m->sysseg_pa, va, pa)); 156 1.1 gwr } 157 1.1 gwr 158 1.1 gwr /* 159 1.11 wiz * Translate a physical address to a file-offset in the crash dump. 160 1.1 gwr */ 161 1.1 gwr off_t 162 1.14 jym _kvm_cmn_pa2off(kvm_t *kd, u_long pa) 163 1.1 gwr { 164 1.2 thorpej cpu_kcore_hdr_t *h = kd->cpu_data; 165 1.2 thorpej struct m68k_kcore_hdr *m = &h->un._m68k; 166 1.2 thorpej phys_ram_seg_t *rsp; 167 1.2 thorpej off_t off; 168 1.2 thorpej int i; 169 1.1 gwr 170 1.1 gwr off = 0; 171 1.2 thorpej rsp = m->ram_segs; 172 1.2 thorpej for (i = 0; i < M68K_NPHYS_RAM_SEGS && rsp[i].size != 0; i++) { 173 1.2 thorpej if (pa >= rsp[i].start && 174 1.2 thorpej pa < (rsp[i].start + rsp[i].size)) { 175 1.3 scottr pa -= rsp[i].start; 176 1.1 gwr break; 177 1.1 gwr } 178 1.3 scottr off += rsp[i].size; 179 1.1 gwr } 180 1.2 thorpej return (kd->dump_off + off + pa); 181 1.1 gwr } 182 1.1 gwr 183 1.1 gwr /***************************************************************** 184 1.1 gwr * Local stuff... 185 1.1 gwr */ 186 1.1 gwr 187 1.1 gwr static int 188 1.15 jym vatop_030(kvm_t *kd, uint32_t stpa, vaddr_t va, paddr_t *pa) 189 1.1 gwr { 190 1.2 thorpej cpu_kcore_hdr_t *h = kd->cpu_data; 191 1.2 thorpej struct m68k_kcore_hdr *m = &h->un._m68k; 192 1.2 thorpej struct vmstate *vm = kd->vmst; 193 1.15 jym paddr_t addr; 194 1.14 jym uint32_t ste, pte; 195 1.2 thorpej u_int p, offset; 196 1.1 gwr 197 1.2 thorpej offset = va & vm->pgofset; 198 1.1 gwr 199 1.1 gwr /* 200 1.2 thorpej * We may be called before address translation is initialized. 201 1.2 thorpej * This is typically used to find the dump magic number. This 202 1.2 thorpej * means we do not yet have the kernel page tables available, 203 1.2 thorpej * so we must to a simple relocation. 204 1.1 gwr */ 205 1.2 thorpej if (va < m->relocend) { 206 1.2 thorpej *pa = (va - h->kernbase) + m->reloc; 207 1.2 thorpej return (h->page_size - offset); 208 1.1 gwr } 209 1.1 gwr 210 1.2 thorpej addr = stpa + ((va >> m->sg_ishift) * sizeof(u_int32_t)); 211 1.2 thorpej 212 1.1 gwr /* 213 1.1 gwr * Can't use KREAD to read kernel segment table entries. 214 1.9 simonb * Fortunately it is 1-to-1 mapped so we don't have to. 215 1.1 gwr */ 216 1.2 thorpej if (stpa == m->sysseg_pa) { 217 1.13 ad if (_kvm_pread(kd, kd->pmfd, &ste, sizeof(ste), 218 1.8 thorpej _kvm_cmn_pa2off(kd, addr)) != sizeof(ste)) 219 1.1 gwr goto invalid; 220 1.1 gwr } else if (KREAD(kd, addr, &ste)) 221 1.1 gwr goto invalid; 222 1.2 thorpej if ((ste & m->sg_v) == 0) { 223 1.1 gwr _kvm_err(kd, 0, "invalid segment (%x)", ste); 224 1.2 thorpej return(0); 225 1.1 gwr } 226 1.2 thorpej p = _kvm_btop(vm, va & m->sg_pmask); 227 1.2 thorpej addr = (ste & m->sg_frame) + (p * sizeof(u_int32_t)); 228 1.1 gwr 229 1.1 gwr /* 230 1.1 gwr * Address from STE is a physical address so don't use kvm_read. 231 1.1 gwr */ 232 1.13 ad if (_kvm_pread(kd, kd->pmfd, &pte, sizeof(pte), 233 1.13 ad _kvm_cmn_pa2off(kd, addr)) != sizeof(pte)) 234 1.1 gwr goto invalid; 235 1.2 thorpej addr = pte & m->pg_frame; 236 1.2 thorpej if ((pte & m->pg_v) == 0) { 237 1.1 gwr _kvm_err(kd, 0, "page not valid"); 238 1.1 gwr return (0); 239 1.1 gwr } 240 1.1 gwr *pa = addr + offset; 241 1.9 simonb 242 1.2 thorpej return (h->page_size - offset); 243 1.1 gwr invalid: 244 1.10 he _kvm_err(kd, 0, "invalid address (%lx)", va); 245 1.1 gwr return (0); 246 1.1 gwr } 247 1.1 gwr 248 1.1 gwr static int 249 1.15 jym vatop_040(kvm_t *kd, uint32_t stpa, vaddr_t va, paddr_t *pa) 250 1.1 gwr { 251 1.2 thorpej cpu_kcore_hdr_t *h = kd->cpu_data; 252 1.2 thorpej struct m68k_kcore_hdr *m = &h->un._m68k; 253 1.2 thorpej struct vmstate *vm = kd->vmst; 254 1.15 jym paddr_t addr; 255 1.14 jym uint32_t stpa2; 256 1.14 jym uint32_t ste, pte; 257 1.7 briggs u_int offset; 258 1.2 thorpej 259 1.2 thorpej offset = va & vm->pgofset; 260 1.1 gwr 261 1.1 gwr /* 262 1.2 thorpej * We may be called before address translation is initialized. 263 1.2 thorpej * This is typically used to find the dump magic number. This 264 1.2 thorpej * means we do not yet have the kernel page tables available, 265 1.2 thorpej * so we must to a simple relocation. 266 1.1 gwr */ 267 1.2 thorpej if (va < m->relocend) { 268 1.2 thorpej *pa = (va - h->kernbase) + m->reloc; 269 1.2 thorpej return (h->page_size - offset); 270 1.1 gwr } 271 1.1 gwr 272 1.2 thorpej addr = stpa + ((va >> m->sg40_shift1) * sizeof(u_int32_t)); 273 1.2 thorpej 274 1.1 gwr /* 275 1.1 gwr * Can't use KREAD to read kernel segment table entries. 276 1.9 simonb * Fortunately it is 1-to-1 mapped so we don't have to. 277 1.1 gwr */ 278 1.2 thorpej if (stpa == m->sysseg_pa) { 279 1.13 ad if (_kvm_pread(kd, kd->pmfd, &ste, sizeof(ste), 280 1.8 thorpej _kvm_cmn_pa2off(kd, addr)) != sizeof(ste)) 281 1.1 gwr goto invalid; 282 1.1 gwr } else if (KREAD(kd, addr, &ste)) 283 1.1 gwr goto invalid; 284 1.2 thorpej if ((ste & m->sg_v) == 0) { 285 1.1 gwr _kvm_err(kd, 0, "invalid level 1 descriptor (%x)", 286 1.1 gwr ste); 287 1.1 gwr return((off_t)0); 288 1.1 gwr } 289 1.2 thorpej stpa2 = (ste & m->sg40_addr1); 290 1.2 thorpej addr = stpa2 + (((va & m->sg40_mask2) >> m->sg40_shift2) * 291 1.2 thorpej sizeof(u_int32_t)); 292 1.2 thorpej 293 1.1 gwr /* 294 1.1 gwr * Address from level 1 STE is a physical address, 295 1.1 gwr * so don't use kvm_read. 296 1.1 gwr */ 297 1.13 ad if (_kvm_pread(kd, kd->pmfd, &ste, sizeof(ste), 298 1.13 ad _kvm_cmn_pa2off(kd, addr)) != sizeof(ste)) 299 1.1 gwr goto invalid; 300 1.2 thorpej if ((ste & m->sg_v) == 0) { 301 1.1 gwr _kvm_err(kd, 0, "invalid level 2 descriptor (%x)", 302 1.1 gwr ste); 303 1.1 gwr return((off_t)0); 304 1.1 gwr } 305 1.2 thorpej stpa2 = (ste & m->sg40_addr2); 306 1.2 thorpej addr = stpa2 + (((va & m->sg40_mask3) >> m->sg40_shift3) * 307 1.2 thorpej sizeof(u_int32_t)); 308 1.1 gwr 309 1.1 gwr /* 310 1.1 gwr * Address from STE is a physical address so don't use kvm_read. 311 1.1 gwr */ 312 1.13 ad if (_kvm_pread(kd, kd->pmfd, &pte, sizeof(pte), 313 1.13 ad _kvm_cmn_pa2off(kd, addr)) != sizeof(pte)) 314 1.1 gwr goto invalid; 315 1.2 thorpej addr = pte & m->pg_frame; 316 1.2 thorpej if ((pte & m->pg_v) == 0) { 317 1.1 gwr _kvm_err(kd, 0, "page not valid"); 318 1.1 gwr return (0); 319 1.1 gwr } 320 1.1 gwr *pa = addr + offset; 321 1.9 simonb 322 1.2 thorpej return (h->page_size - offset); 323 1.2 thorpej 324 1.1 gwr invalid: 325 1.10 he _kvm_err(kd, 0, "invalid address (%lx)", va); 326 1.1 gwr return (0); 327 1.1 gwr } 328