xref: /netbsd-src/lib/libkvm/kvm_alpha.c (revision 916b154777c03001385d7553acc2d6430fb1a919)
1*916b1547Srin /* $NetBSD: kvm_alpha.c,v 1.29 2023/08/23 14:00:11 rin Exp $ */
25eecfd89Scgd 
35eecfd89Scgd /*
45eecfd89Scgd  * Copyright (c) 1994, 1995 Carnegie-Mellon University.
55eecfd89Scgd  * All rights reserved.
65eecfd89Scgd  *
75eecfd89Scgd  * Author: Chris G. Demetriou
85eecfd89Scgd  *
95eecfd89Scgd  * Permission to use, copy, modify and distribute this software and
105eecfd89Scgd  * its documentation is hereby granted, provided that both the copyright
115eecfd89Scgd  * notice and this permission notice appear in all copies of the
125eecfd89Scgd  * software, derivative works or modified versions, and any portions
135eecfd89Scgd  * thereof, and that both notices appear in supporting documentation.
145eecfd89Scgd  *
155eecfd89Scgd  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
165eecfd89Scgd  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
175eecfd89Scgd  * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
185eecfd89Scgd  *
195eecfd89Scgd  * Carnegie Mellon requests users of this software to return to
205eecfd89Scgd  *
215eecfd89Scgd  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
225eecfd89Scgd  *  School of Computer Science
235eecfd89Scgd  *  Carnegie Mellon University
245eecfd89Scgd  *  Pittsburgh PA 15213-3890
255eecfd89Scgd  *
265eecfd89Scgd  * any improvements or extensions that they make and grant Carnegie the
275eecfd89Scgd  * rights to redistribute these changes.
285eecfd89Scgd  */
295eecfd89Scgd 
30aa9e487dSthorpej #define	__KVM_ALPHA_PRIVATE		/* see <machine/pte.h> */
31aa9e487dSthorpej 
325eecfd89Scgd #include <sys/param.h>
335eecfd89Scgd #include <sys/proc.h>
345eecfd89Scgd #include <sys/stat.h>
354540a28eScgd #include <sys/kcore.h>
36962a341dSjym #include <sys/types.h>
375eecfd89Scgd #include <unistd.h>
385eecfd89Scgd #include <nlist.h>
395eecfd89Scgd #include <kvm.h>
405eecfd89Scgd 
413b8ac18dSmrg #include <uvm/uvm_extern.h>
42962a341dSjym 
43962a341dSjym #include <machine/kcore.h>
44cce919e0Smatt #include <machine/pmap.h>
4555c1d5c2Smatt #include <machine/vmparam.h>
465eecfd89Scgd 
475eecfd89Scgd #include <limits.h>
485eecfd89Scgd #include <db.h>
49395c20eaSmrg #include <stdlib.h>
505eecfd89Scgd 
515eecfd89Scgd #include "kvm_private.h"
525eecfd89Scgd 
53*916b1547Srin __RCSID("$NetBSD: kvm_alpha.c,v 1.29 2023/08/23 14:00:11 rin Exp $");
540deb66dfSmatt 
55cc1db076Snathanw /*ARGSUSED*/
565eecfd89Scgd void
_kvm_freevtop(kvm_t * kd)576dc46b92Sjym _kvm_freevtop(kvm_t *kd)
585eecfd89Scgd {
59cc1db076Snathanw 	return;
605eecfd89Scgd }
615eecfd89Scgd 
62cc1db076Snathanw /*ARGSUSED*/
635eecfd89Scgd int
_kvm_initvtop(kvm_t * kd)646dc46b92Sjym _kvm_initvtop(kvm_t *kd)
655eecfd89Scgd {
665eecfd89Scgd 	return (0);
675eecfd89Scgd }
685eecfd89Scgd 
695eecfd89Scgd int
_kvm_kvatop(kvm_t * kd,vaddr_t va,paddr_t * pa)70962a341dSjym _kvm_kvatop(kvm_t *kd, vaddr_t va, paddr_t *pa)
715eecfd89Scgd {
724540a28eScgd 	cpu_kcore_hdr_t *cpu_kh;
731d7d5ec2Scgd 	alpha_pt_entry_t pte;
74bf8f319dSthorpej 	u_long pteoff, page_off;
75bf8f319dSthorpej 	int rv;
765eecfd89Scgd 
774540a28eScgd 	if (ISALIVE(kd)) {
784540a28eScgd 		_kvm_err(kd, 0, "vatop called in live kernel!");
795eecfd89Scgd 		return(0);
805eecfd89Scgd 	}
8151e3315eScgd 
824540a28eScgd 	cpu_kh = kd->cpu_data;
834540a28eScgd 	page_off = va & (cpu_kh->page_size - 1);
844540a28eScgd 
854540a28eScgd 	if (va >= ALPHA_K0SEG_BASE && va <= ALPHA_K0SEG_END) {
864540a28eScgd 		/*
871d7d5ec2Scgd 		 * Direct-mapped address: just convert it.
884540a28eScgd 		 */
891d7d5ec2Scgd 
904540a28eScgd 		*pa = ALPHA_K0SEG_TO_PHYS(va);
914540a28eScgd 		rv = cpu_kh->page_size - page_off;
924540a28eScgd 	} else if (va >= ALPHA_K1SEG_BASE && va <= ALPHA_K1SEG_END) {
934540a28eScgd 		/*
941d7d5ec2Scgd 		 * Real kernel virtual address: do the translation.
954540a28eScgd 		 */
961d7d5ec2Scgd 
971d7d5ec2Scgd 		/* Find and read the L1 PTE. */
981d7d5ec2Scgd 		pteoff = cpu_kh->lev1map_pa +
99c88048edSthorpej 		    l1pte_index(va) * sizeof(alpha_pt_entry_t);
100a7a2d171Sad 		if (_kvm_pread(kd, kd->pmfd, &pte, sizeof(pte),
10155c7ea7cSthorpej 		    _kvm_pa2off(kd, pteoff)) != sizeof(pte)) {
1021d7d5ec2Scgd 			_kvm_syserr(kd, 0, "could not read L1 PTE");
1031d7d5ec2Scgd 			goto lose;
1041d7d5ec2Scgd 		}
1051d7d5ec2Scgd 
1061d7d5ec2Scgd 		/* Find and read the L2 PTE. */
1071d7d5ec2Scgd 		if ((pte & ALPHA_PTE_VALID) == 0) {
1081d7d5ec2Scgd 			_kvm_err(kd, 0, "invalid translation (invalid L1 PTE)");
1091d7d5ec2Scgd 			goto lose;
1101d7d5ec2Scgd 		}
1111d7d5ec2Scgd 		pteoff = ALPHA_PTE_TO_PFN(pte) * cpu_kh->page_size +
112c88048edSthorpej 		    l2pte_index(va) * sizeof(alpha_pt_entry_t);
113a7a2d171Sad 		if (_kvm_pread(kd, kd->pmfd, &pte, sizeof(pte),
11455c7ea7cSthorpej 		    _kvm_pa2off(kd, pteoff)) != sizeof(pte)) {
1151d7d5ec2Scgd 			_kvm_syserr(kd, 0, "could not read L2 PTE");
1161d7d5ec2Scgd 			goto lose;
1171d7d5ec2Scgd 		}
1181d7d5ec2Scgd 
1191d7d5ec2Scgd 		/* Find and read the L3 PTE. */
1201d7d5ec2Scgd 		if ((pte & ALPHA_PTE_VALID) == 0) {
1211d7d5ec2Scgd 			_kvm_err(kd, 0, "invalid translation (invalid L2 PTE)");
1221d7d5ec2Scgd 			goto lose;
1231d7d5ec2Scgd 		}
1241d7d5ec2Scgd 		pteoff = ALPHA_PTE_TO_PFN(pte) * cpu_kh->page_size +
125c88048edSthorpej 		    l3pte_index(va) * sizeof(alpha_pt_entry_t);
126a7a2d171Sad 		if (_kvm_pread(kd, kd->pmfd, &pte, sizeof(pte),
12755c7ea7cSthorpej 		    _kvm_pa2off(kd, pteoff)) != sizeof(pte)) {
1281d7d5ec2Scgd 			_kvm_syserr(kd, 0, "could not read L3 PTE");
1291d7d5ec2Scgd 			goto lose;
1301d7d5ec2Scgd 		}
1311d7d5ec2Scgd 
1321d7d5ec2Scgd 		/* Fill in the PA. */
1331d7d5ec2Scgd 		if ((pte & ALPHA_PTE_VALID) == 0) {
1341d7d5ec2Scgd 			_kvm_err(kd, 0, "invalid translation (invalid L3 PTE)");
1351d7d5ec2Scgd 			goto lose;
1361d7d5ec2Scgd 		}
1370e2ebc35Sross 		*pa = ALPHA_PTE_TO_PFN(pte) * cpu_kh->page_size + page_off;
1381d7d5ec2Scgd 		rv = cpu_kh->page_size - page_off;
1394540a28eScgd 	} else {
1404540a28eScgd 		/*
1411d7d5ec2Scgd 		 * Bogus address (not in KV space): punt.
1424540a28eScgd 		 */
1431d7d5ec2Scgd 
1441d7d5ec2Scgd 		_kvm_err(kd, 0, "invalid kernel virtual address");
1451d7d5ec2Scgd lose:
1464540a28eScgd 		*pa = -1;
1474540a28eScgd 		rv = 0;
1484540a28eScgd 	}
1494540a28eScgd 
1504540a28eScgd 	return (rv);
1514540a28eScgd }
1524540a28eScgd 
15351e3315eScgd /*
154b976c559Swiz  * Translate a physical address to a file-offset in the crash dump.
15551e3315eScgd  */
15651e3315eScgd off_t
_kvm_pa2off(kvm_t * kd,paddr_t pa)157962a341dSjym _kvm_pa2off(kvm_t *kd, paddr_t pa)
15851e3315eScgd {
1594540a28eScgd 	cpu_kcore_hdr_t *cpu_kh;
1606c0b8a86Scgd 	phys_ram_seg_t *ramsegs;
1616c0b8a86Scgd 	off_t off;
1626c0b8a86Scgd 	int i;
16351e3315eScgd 
1644540a28eScgd 	cpu_kh = kd->cpu_data;
1656c0b8a86Scgd 	ramsegs = (phys_ram_seg_t *)((char *)cpu_kh + ALIGN(sizeof *cpu_kh));
1664540a28eScgd 
1674540a28eScgd 	off = 0;
1686c0b8a86Scgd 	for (i = 0; i < cpu_kh->nmemsegs; i++) {
1696c0b8a86Scgd 		if (pa >= ramsegs[i].start &&
1706c0b8a86Scgd 		    (pa - ramsegs[i].start) < ramsegs[i].size) {
1716c0b8a86Scgd 			off += (pa - ramsegs[i].start);
1726c0b8a86Scgd 			break;
1736c0b8a86Scgd 		}
1746c0b8a86Scgd 		off += ramsegs[i].size;
1756c0b8a86Scgd 	}
1764540a28eScgd 
1776c0b8a86Scgd 	return (kd->dump_off + off);
17851e3315eScgd }
179f6385749Sgwr 
180f6385749Sgwr /*
181f6385749Sgwr  * Machine-dependent initialization for ALL open kvm descriptors,
182f6385749Sgwr  * not just those for a kernel crash dump.  Some architectures
183f6385749Sgwr  * have to deal with these NOT being constants!  (i.e. m68k)
184f6385749Sgwr  */
185f6385749Sgwr int
_kvm_mdopen(kvm_t * kd)1866dc46b92Sjym _kvm_mdopen(kvm_t *kd)
187f6385749Sgwr {
188f6385749Sgwr 
189f6385749Sgwr 	kd->min_uva = VM_MIN_ADDRESS;
190f6385749Sgwr 	kd->max_uva = VM_MAXUSER_ADDRESS;
191f6385749Sgwr 
192f6385749Sgwr 	return (0);
193f6385749Sgwr }
194