kvm_arm.c revision 1.3 1 1.3 chris /* $NetBSD: kvm_arm.c,v 1.3 2008/01/01 14:10:37 chris Exp $ */
2 1.1 bjh21
3 1.1 bjh21 /*-
4 1.1 bjh21 * Copyright (C) 1996 Wolfgang Solfrank.
5 1.1 bjh21 * Copyright (C) 1996 TooLs GmbH.
6 1.1 bjh21 * All rights reserved.
7 1.1 bjh21 *
8 1.1 bjh21 * Redistribution and use in source and binary forms, with or without
9 1.1 bjh21 * modification, are permitted provided that the following conditions
10 1.1 bjh21 * are met:
11 1.1 bjh21 * 1. Redistributions of source code must retain the above copyright
12 1.1 bjh21 * notice, this list of conditions and the following disclaimer.
13 1.1 bjh21 * 2. Redistributions in binary form must reproduce the above copyright
14 1.1 bjh21 * notice, this list of conditions and the following disclaimer in the
15 1.1 bjh21 * documentation and/or other materials provided with the distribution.
16 1.1 bjh21 * 3. All advertising materials mentioning features or use of this software
17 1.1 bjh21 * must display the following acknowledgement:
18 1.1 bjh21 * This product includes software developed by TooLs GmbH.
19 1.1 bjh21 * 4. The name of TooLs GmbH may not be used to endorse or promote products
20 1.1 bjh21 * derived from this software without specific prior written permission.
21 1.1 bjh21 *
22 1.1 bjh21 * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
23 1.1 bjh21 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24 1.1 bjh21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25 1.1 bjh21 * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 1.1 bjh21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
27 1.1 bjh21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
28 1.1 bjh21 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29 1.1 bjh21 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
30 1.1 bjh21 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
31 1.1 bjh21 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 1.1 bjh21 *
33 1.1 bjh21 * from: kvm_powerpc.c,v 1.3 1997/09/19 04:00:23 thorpej Exp
34 1.1 bjh21 */
35 1.1 bjh21
36 1.1 bjh21 /*
37 1.1 bjh21 * arm32 machine dependent routines for kvm.
38 1.1 bjh21 */
39 1.1 bjh21
40 1.3 chris #include <sys/cdefs.h>
41 1.3 chris #if defined(LIBC_SCCS) && !defined(lint)
42 1.3 chris __RCSID("$NetBSD: kvm_arm.c,v 1.3 2008/01/01 14:10:37 chris Exp $");
43 1.3 chris #endif /* LIBC_SCCS and not lint */
44 1.3 chris
45 1.1 bjh21 #include <sys/param.h>
46 1.2 matt #include <sys/exec.h>
47 1.3 chris #include <sys/kcore.h>
48 1.3 chris #include <arm/kcore.h>
49 1.3 chris #include <arm/arm32/pte.h>
50 1.1 bjh21
51 1.1 bjh21 #include <stdlib.h>
52 1.1 bjh21 #include <db.h>
53 1.1 bjh21 #include <limits.h>
54 1.1 bjh21 #include <kvm.h>
55 1.1 bjh21
56 1.3 chris #include <unistd.h>
57 1.3 chris
58 1.1 bjh21 #include "kvm_private.h"
59 1.1 bjh21
60 1.1 bjh21 void
61 1.3 chris _kvm_freevtop(kvm_t * kd)
62 1.1 bjh21 {
63 1.1 bjh21 if (kd->vmst != 0)
64 1.1 bjh21 free(kd->vmst);
65 1.1 bjh21 }
66 1.1 bjh21
67 1.1 bjh21 int
68 1.3 chris _kvm_initvtop(kvm_t * kd)
69 1.1 bjh21 {
70 1.1 bjh21 return 0;
71 1.1 bjh21 }
72 1.1 bjh21
73 1.1 bjh21 int
74 1.3 chris _kvm_kvatop(kvm_t * kd, u_long va, u_long * pa)
75 1.1 bjh21 {
76 1.3 chris cpu_kcore_hdr_t *cpu_kh;
77 1.3 chris pd_entry_t pde;
78 1.3 chris pt_entry_t pte;
79 1.3 chris uint32_t pde_pa, pte_pa;
80 1.3 chris
81 1.3 chris if (ISALIVE(kd)) {
82 1.3 chris _kvm_err(kd, 0, "vatop called in live kernel!");
83 1.3 chris return (0);
84 1.3 chris }
85 1.3 chris cpu_kh = kd->cpu_data;
86 1.3 chris
87 1.3 chris if (cpu_kh->version != 1) {
88 1.3 chris _kvm_err(kd, 0, "unsupported kcore structure version");
89 1.3 chris return 0;
90 1.3 chris }
91 1.3 chris if (cpu_kh->flags != 0) {
92 1.3 chris _kvm_err(kd, 0, "kcore flags not supported");
93 1.3 chris return 0;
94 1.3 chris }
95 1.3 chris /*
96 1.3 chris * work out which L1 table we need
97 1.3 chris */
98 1.3 chris if (va >= (cpu_kh->UserL1TableSize << 17))
99 1.3 chris pde_pa = cpu_kh->PAKernelL1Table;
100 1.3 chris else
101 1.3 chris pde_pa = cpu_kh->PAUserL1Table;
102 1.3 chris
103 1.3 chris /*
104 1.3 chris * work out the offset into the L1 Table
105 1.3 chris */
106 1.3 chris pde_pa += ((va >> 20) * sizeof(pd_entry_t));
107 1.3 chris
108 1.3 chris if (pread(kd->pmfd, (void *) &pde, sizeof(pd_entry_t),
109 1.3 chris _kvm_pa2off(kd, pde_pa)) != sizeof(pd_entry_t)) {
110 1.3 chris _kvm_syserr(kd, 0, "could not read L1 entry");
111 1.3 chris return (0);
112 1.3 chris }
113 1.3 chris /*
114 1.3 chris * next work out what kind of record it is
115 1.3 chris */
116 1.3 chris switch (pde & L1_TYPE_MASK) {
117 1.3 chris case L1_TYPE_S:
118 1.3 chris *pa = (pde & L1_S_FRAME) | (va & L1_S_OFFSET);
119 1.3 chris return L1_S_SIZE - (va & L1_S_OFFSET);
120 1.3 chris case L1_TYPE_C:
121 1.3 chris pte_pa = (pde & L1_C_ADDR_MASK)
122 1.3 chris | ((va & 0xff000) >> 10);
123 1.3 chris break;
124 1.3 chris case L1_TYPE_F:
125 1.3 chris pte_pa = (pde & L1_S_ADDR_MASK)
126 1.3 chris | ((va & 0xffc00) >> 8);
127 1.3 chris break;
128 1.3 chris default:
129 1.3 chris _kvm_syserr(kd, 0, "L1 entry is invalid");
130 1.3 chris return (0);
131 1.3 chris }
132 1.3 chris
133 1.3 chris /*
134 1.3 chris * locate the pte and load it
135 1.3 chris */
136 1.3 chris if (pread(kd->pmfd, (void *) &pte, sizeof(pt_entry_t),
137 1.3 chris _kvm_pa2off(kd, pte_pa)) != sizeof(pt_entry_t)) {
138 1.3 chris _kvm_syserr(kd, 0, "could not read L2 entry");
139 1.3 chris return (0);
140 1.3 chris }
141 1.3 chris switch (pte & L2_TYPE_MASK) {
142 1.3 chris case L2_TYPE_L:
143 1.3 chris *pa = (pte & L2_L_FRAME) | (va & L2_L_OFFSET);
144 1.3 chris return (L2_L_SIZE - (va & L2_L_OFFSET));
145 1.3 chris case L2_TYPE_S:
146 1.3 chris *pa = (pte & L2_S_FRAME) | (va & L2_S_OFFSET);
147 1.3 chris return (L2_S_SIZE - (va & L2_S_OFFSET));
148 1.3 chris case L2_TYPE_T:
149 1.3 chris *pa = (pte & L2_T_FRAME) | (va & L2_T_OFFSET);
150 1.3 chris return (L2_T_SIZE - (va & L2_T_OFFSET));
151 1.3 chris default:
152 1.3 chris _kvm_syserr(kd, 0, "L2 entry is invalid");
153 1.3 chris return (0);
154 1.3 chris }
155 1.3 chris
156 1.1 bjh21 _kvm_err(kd, 0, "vatop not yet implemented!");
157 1.1 bjh21 return 0;
158 1.1 bjh21 }
159 1.1 bjh21
160 1.1 bjh21 off_t
161 1.3 chris _kvm_pa2off(kvm_t * kd, u_long pa)
162 1.1 bjh21 {
163 1.3 chris cpu_kcore_hdr_t *cpu_kh;
164 1.3 chris phys_ram_seg_t *ramsegs;
165 1.3 chris off_t off;
166 1.3 chris int i;
167 1.3 chris
168 1.3 chris cpu_kh = kd->cpu_data;
169 1.3 chris ramsegs = (void *) ((char *) (void *) cpu_kh + cpu_kh->omemsegs);
170 1.3 chris
171 1.3 chris off = 0;
172 1.3 chris for (i = 0; i < cpu_kh->nmemsegs; i++) {
173 1.3 chris if (pa >= ramsegs[i].start &&
174 1.3 chris (pa - ramsegs[i].start) < ramsegs[i].size) {
175 1.3 chris off += (pa - ramsegs[i].start);
176 1.3 chris break;
177 1.3 chris }
178 1.3 chris off += ramsegs[i].size;
179 1.3 chris }
180 1.3 chris return (kd->dump_off + off);
181 1.1 bjh21 }
182 1.1 bjh21
183 1.1 bjh21 /*
184 1.1 bjh21 * Machine-dependent initialization for ALL open kvm descriptors,
185 1.1 bjh21 * not just those for a kernel crash dump. Some architectures
186 1.2 matt * have to deal with these NOT being constants! (i.e. arm)
187 1.1 bjh21 */
188 1.1 bjh21 int
189 1.3 chris _kvm_mdopen(kvm_t * kd)
190 1.1 bjh21 {
191 1.3 chris uintptr_t max_uva;
192 1.2 matt extern struct ps_strings *__ps_strings;
193 1.1 bjh21
194 1.3 chris #if 0 /* XXX - These vary across arm machines... */
195 1.1 bjh21 kd->usrstack = USRSTACK;
196 1.1 bjh21 kd->min_uva = VM_MIN_ADDRESS;
197 1.1 bjh21 kd->max_uva = VM_MAXUSER_ADDRESS;
198 1.2 matt #endif
199 1.2 matt /* This is somewhat hack-ish, but it works. */
200 1.2 matt max_uva = (uintptr_t) (__ps_strings + 1);
201 1.2 matt kd->usrstack = max_uva;
202 1.3 chris kd->max_uva = max_uva;
203 1.3 chris kd->min_uva = 0;
204 1.1 bjh21
205 1.1 bjh21 return (0);
206 1.1 bjh21 }
207