1 /*- 2 * Copyright (c) 1989, 1992 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * This code is derived from software developed by the Computer Systems 6 * Engineering group at Lawrence Berkeley Laboratory under DARPA contract 7 * BG 91-66 and contributed to Berkeley. Modified for MIPS by Ralph Campbell. 8 * 9 * %sccs.include.redist.c% 10 */ 11 12 #if defined(LIBC_SCCS) && !defined(lint) 13 static char sccsid[] = "@(#)kvm_mips.c 5.2 (Berkeley) 05/15/93"; 14 #endif /* LIBC_SCCS and not lint */ 15 /* 16 * MIPS machine dependent routines for kvm. Hopefully, the forthcoming 17 * vm code will one day obsolete this module. 18 */ 19 20 #include <sys/param.h> 21 #include <sys/user.h> 22 #include <sys/proc.h> 23 #include <sys/stat.h> 24 #include <unistd.h> 25 #include <nlist.h> 26 #include <kvm.h> 27 28 #include <vm/vm.h> 29 #include <vm/vm_param.h> 30 31 #include <limits.h> 32 #include <db.h> 33 34 #include "kvm_private.h" 35 36 #include <machine/machConst.h> 37 #include <machine/pte.h> 38 #include <machine/pmap.h> 39 40 struct vmstate { 41 pt_entry_t *Sysmap; 42 u_int Sysmapsize; 43 }; 44 45 #define KREAD(kd, addr, p)\ 46 (kvm_read(kd, addr, (char *)(p), sizeof(*(p))) != sizeof(*(p))) 47 48 void 49 _kvm_freevtop(kd) 50 kvm_t *kd; 51 { 52 if (kd->vmst != 0) 53 free(kd->vmst); 54 } 55 56 int 57 _kvm_initvtop(kd) 58 kvm_t *kd; 59 { 60 struct vmstate *vm; 61 struct nlist nlist[3]; 62 63 vm = (struct vmstate *)_kvm_malloc(kd, sizeof(*vm)); 64 if (vm == 0) 65 return (-1); 66 kd->vmst = vm; 67 68 nlist[0].n_name = "Sysmap"; 69 nlist[1].n_name = "Sysmapsize"; 70 nlist[2].n_name = 0; 71 72 if (kvm_nlist(kd, nlist) != 0) { 73 _kvm_err(kd, kd->program, "bad namelist"); 74 return (-1); 75 } 76 if (KREAD(kd, (u_long)nlist[0].n_value, &vm->Sysmap)) { 77 _kvm_err(kd, kd->program, "cannot read Sysmap"); 78 return (-1); 79 } 80 if (KREAD(kd, (u_long)nlist[1].n_value, &vm->Sysmapsize)) { 81 _kvm_err(kd, kd->program, "cannot read mmutype"); 82 return (-1); 83 } 84 return (0); 85 } 86 87 /* 88 * Translate a kernel virtual address to a physical address. 89 */ 90 int 91 _kvm_kvatop(kd, va, pa) 92 kvm_t *kd; 93 u_long va; 94 u_long *pa; 95 { 96 register struct vmstate *vm; 97 u_long pte, addr, offset; 98 99 if (ISALIVE(kd)) { 100 _kvm_err(kd, 0, "vatop called in live kernel!"); 101 return((off_t)0); 102 } 103 vm = kd->vmst; 104 offset = va & PGOFSET; 105 /* 106 * If we are initializing (kernel segment table pointer not yet set) 107 * then return pa == va to avoid infinite recursion. 108 */ 109 if (vm->Sysmap == 0) { 110 *pa = va; 111 return (NBPG - offset); 112 } 113 if (va < KERNBASE || 114 va >= VM_MIN_KERNEL_ADDRESS + vm->Sysmapsize * NBPG) 115 goto invalid; 116 if (va < VM_MIN_KERNEL_ADDRESS) { 117 *pa = MACH_CACHED_TO_PHYS(va); 118 return (NBPG - offset); 119 } 120 addr = (u_long)(vm->Sysmap + ((va - VM_MIN_KERNEL_ADDRESS) >> PGSHIFT)); 121 /* 122 * Can't use KREAD to read kernel segment table entries. 123 * Fortunately it is 1-to-1 mapped so we don't have to. 124 */ 125 if (lseek(kd->pmfd, (off_t)addr, 0) < 0 || 126 read(kd->pmfd, (char *)&pte, sizeof(pte)) < 0) 127 goto invalid; 128 if (!(pte & PG_V)) 129 goto invalid; 130 *pa = (pte & PG_FRAME) | offset; 131 return (NBPG - offset); 132 133 invalid: 134 _kvm_err(kd, 0, "invalid address (%x)", va); 135 return (0); 136 } 137 138 /* 139 * Translate a user virtual address to a physical address. 140 */ 141 int 142 _kvm_uvatop(kd, p, va, pa) 143 kvm_t *kd; 144 const struct proc *p; 145 u_long va; 146 u_long *pa; 147 { 148 register struct vmspace *vms = p->p_vmspace; 149 u_long kva, offset; 150 151 if (va >= KERNBASE) 152 goto invalid; 153 154 /* read the address of the first level table */ 155 kva = (u_long)&vms->vm_pmap.pm_segtab; 156 if (kvm_read(kd, kva, (char *)&kva, sizeof(kva)) != sizeof(kva)) 157 goto invalid; 158 if (kva == 0) 159 goto invalid; 160 161 /* read the address of the second level table */ 162 kva += (va >> SEGSHIFT) * sizeof(caddr_t); 163 if (kvm_read(kd, kva, (char *)&kva, sizeof(kva)) != sizeof(kva)) 164 goto invalid; 165 if (kva == 0) 166 goto invalid; 167 168 /* read the pte from the second level table */ 169 kva += (va >> PGSHIFT) & (NPTEPG - 1); 170 if (kvm_read(kd, kva, (char *)&kva, sizeof(kva)) != sizeof(kva)) 171 goto invalid; 172 if (!(kva & PG_V)) 173 goto invalid; 174 offset = va & PGOFSET; 175 *pa = (kva & PG_FRAME) | offset; 176 return (NBPG - offset); 177 178 invalid: 179 _kvm_err(kd, 0, "invalid address (%x)", va); 180 return (0); 181 } 182