]> git.saurik.com Git - apple/xnu.git/blame - osfmk/kdp/ml/arm/kdp_vm.c
xnu-4903.241.1.tar.gz
[apple/xnu.git] / osfmk / kdp / ml / arm / kdp_vm.c
CommitLineData
5ba3f43e
A
1/*
2 * Copyright (c) 2000-2007 Apple Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28#include <mach/mach_types.h>
29#include <mach/vm_attributes.h>
30#include <mach/vm_param.h>
31
32#include <vm/pmap.h>
33
34#include <mach/thread_status.h>
35#include <mach-o/loader.h>
36#include <mach/vm_region.h>
37#include <mach/vm_statistics.h>
38
39#include <vm/vm_kern.h>
40#include <vm/vm_object.h>
41#include <vm/vm_protos.h>
42#include <kdp/kdp_core.h>
43#include <kdp/kdp_udp.h>
44#include <kdp/kdp_internal.h>
45#include <arm/misc_protos.h>
46#include <arm/caches_internal.h>
47#include <arm/cpu_data_internal.h>
48
49pmap_t kdp_pmap = 0;
50boolean_t kdp_trans_off;
51boolean_t kdp_read_io = 0;
52
53pmap_paddr_t kdp_vtophys(pmap_t pmap, vm_offset_t va);
54
55/*
56 * kdp_vtophys
57 */
58pmap_paddr_t
59kdp_vtophys(
60 pmap_t pmap,
61 vm_offset_t va)
62{
63 pmap_paddr_t pa;
64 ppnum_t pp;
65
66 /* Ensure that the provided va resides within the provided pmap range. */
67 if(!pmap || ((pmap != kernel_pmap) && ((va < pmap->min) || (va >= pmap->max))))
68 {
69#ifdef KDP_VTOPHYS_DEBUG
70 printf("kdp_vtophys(%08x, %016lx) not in range %08x .. %08x\n", (unsigned int) pmap,
71 (unsigned long) va,
72 (unsigned int) (pmap ? pmap->min : 0),
73 (unsigned int) (pmap ? pmap->max : 0));
74#endif
75 return 0; /* Just return if no translation */
76 }
77
78 pp = pmap_find_phys(pmap, va); /* Get the page number */
79 if (!pp)
80 return 0; /* Just return if no translation */
81
82 pa = ((pmap_paddr_t) pp << PAGE_SHIFT) | (va & PAGE_MASK); /* Insert page offset */
83 return (pa);
84}
85
86
87/*
88 * kdp_machine_vm_read
89 *
90 * Verify that src is valid, and physically copy len bytes from src to
91 * dst, translating if necessary. If translation is enabled
92 * (kdp_trans_off is 0), a non-zero kdp_pmap specifies the pmap to use
93 * when translating src.
94 */
95
96mach_vm_size_t
97kdp_machine_vm_read( mach_vm_address_t src, caddr_t dst, mach_vm_size_t len)
98{
99 addr64_t cur_virt_src, cur_virt_dst;
100 addr64_t cur_phys_src, cur_phys_dst;
101 mach_vm_size_t resid, cnt;
102 pmap_t pmap;
103
104#ifdef KDP_VM_READ_DEBUG
105 kprintf("kdp_machine_vm_read1: src %x dst %x len %x - %08X %08X\n", src, dst, len, ((unsigned long *) src)[0], ((unsigned long *) src)[1]);
106#endif
107
108 cur_virt_src = (addr64_t) src;
109 cur_virt_dst = (addr64_t) dst;
110
111 if (kdp_trans_off) {
112 kdp_readphysmem64_req_t rq;
113 mach_vm_size_t ret;
114
115 rq.address = src;
116 rq.nbytes = (uint32_t)len;
117 ret = kdp_machine_phys_read(&rq, dst, 0 /* unused */);
118 return ret;
119 } else {
120
121 resid = len;
122
123 if (kdp_pmap)
124 pmap = kdp_pmap; /* If special pmap, use it */
125 else
126 pmap = kernel_pmap; /* otherwise, use kernel's */
127
128 while (resid != 0) {
129 /*
130 * Always translate the destination using the
131 * kernel_pmap.
132 */
133 if ((cur_phys_dst = kdp_vtophys(kernel_pmap, cur_virt_dst)) == 0)
134 goto exit;
135
136 if ((cur_phys_src = kdp_vtophys(pmap, cur_virt_src)) == 0)
137 goto exit;
138
139 /* Attempt to ensure that there are valid translations for src and dst. */
140 if (!kdp_read_io && ((!pmap_valid_address(cur_phys_dst)) || (!pmap_valid_address(cur_phys_src))))
141 goto exit;
142
143 cnt = ARM_PGBYTES - (cur_virt_src & PAGE_MASK); /* Get length left on
144 * page */
145 if (cnt > (ARM_PGBYTES - (cur_virt_dst & PAGE_MASK)))
146 cnt = ARM_PGBYTES - (cur_virt_dst & PAGE_MASK);
147
148 if (cnt > resid)
149 cnt = resid;
150
151#ifdef KDP_VM_READ_DEBUG
152 kprintf("kdp_machine_vm_read2: pmap %08X, virt %016LLX, phys %016LLX\n",
153 pmap, cur_virt_src, cur_phys_src);
154#endif
155 bcopy_phys(cur_phys_src, cur_phys_dst, cnt);
156
157 cur_virt_src += cnt;
158 cur_virt_dst += cnt;
159 resid -= cnt;
160 }
161 }
162exit:
163#ifdef KDP_VM_READ_DEBUG
164 kprintf("kdp_machine_vm_read: ret %08X\n", len - resid);
165#endif
166 return (len - resid);
167}
168
169mach_vm_size_t
170kdp_machine_phys_read(kdp_readphysmem64_req_t *rq, caddr_t dst, uint16_t lcpu __unused)
171{
172 mach_vm_address_t src = rq->address;
173 mach_vm_size_t len = rq->nbytes;
174
175 addr64_t cur_virt_dst;
176 addr64_t cur_phys_src, cur_phys_dst;
177 mach_vm_size_t resid = len;
178 mach_vm_size_t cnt = 0, cnt_src, cnt_dst;
179
180#ifdef KDP_VM_READ_DEBUG
181 kprintf("kdp_phys_read src %x dst %p len %x\n", src, dst, len);
182#endif
183
184 cur_virt_dst = (addr64_t) dst;
185 cur_phys_src = (addr64_t) src;
186
187 while (resid != 0) {
188
189 if ((cur_phys_dst = kdp_vtophys(kernel_pmap, cur_virt_dst)) == 0)
190 goto exit;
191
192 /* Get length left on page */
193
194 cnt_src = ARM_PGBYTES - (cur_phys_src & PAGE_MASK);
195 cnt_dst = ARM_PGBYTES - (cur_phys_dst & PAGE_MASK);
196 if (cnt_src > cnt_dst)
197 cnt = cnt_dst;
198 else
199 cnt = cnt_src;
200 if (cnt > resid)
201 cnt = resid;
202
203 bcopy_phys(cur_phys_src, cur_phys_dst, cnt); /* Copy stuff over */
204 cur_phys_src += cnt;
205 cur_virt_dst += cnt;
206 resid -= cnt;
207 }
208
209exit:
210 return (len - resid);
211}
212
213/*
214 * kdp_vm_write
215 */
216mach_vm_size_t
217kdp_machine_vm_write( caddr_t src, mach_vm_address_t dst, mach_vm_size_t len)
218{
219 addr64_t cur_virt_src, cur_virt_dst;
220 addr64_t cur_phys_src, cur_phys_dst;
221 mach_vm_size_t resid, cnt, cnt_src, cnt_dst;
222
223#ifdef KDP_VM_WRITE_DEBUG
224 printf("kdp_vm_write: src %x dst %x len %x - %08X %08X\n", src, dst, len, ((unsigned long *) src)[0], ((unsigned long *) src)[1]);
225#endif
226
227 cur_virt_src = (addr64_t) src;
228 cur_virt_dst = (addr64_t) dst;
229
230 resid = len;
231
232 while (resid != 0) {
233 if ((cur_phys_dst = kdp_vtophys(kernel_pmap, cur_virt_dst)) == 0)
234 goto exit;
235
236 if ((cur_phys_src = kdp_vtophys(kernel_pmap, cur_virt_src)) == 0)
237 goto exit;
238
239 /* Attempt to ensure that there are valid translations for src and dst. */
240 /* No support for enabling writes for an invalid translation at the moment. */
241 if ((!pmap_valid_address(cur_phys_dst)) || (!pmap_valid_address(cur_phys_src)))
242 goto exit;
243
244 cnt_src = ((cur_phys_src + ARM_PGBYTES) & (-ARM_PGBYTES)) - cur_phys_src;
245 cnt_dst = ((cur_phys_dst + ARM_PGBYTES) & (-ARM_PGBYTES)) - cur_phys_dst;
246
247 if (cnt_src > cnt_dst)
248 cnt = cnt_dst;
249 else
250 cnt = cnt_src;
251 if (cnt > resid)
252 cnt = resid;
253
254#ifdef KDP_VM_WRITE_DEBUG
255 printf("kdp_vm_write: cur_phys_src %x cur_phys_src %x len %x - %08X %08X\n", src, dst, cnt);
256#endif
257 bcopy_phys(cur_phys_src, cur_phys_dst, cnt); /* Copy stuff over */
258 flush_dcache64(cur_phys_dst, (unsigned int)cnt, TRUE);
259 invalidate_icache64(cur_phys_dst, (unsigned int)cnt, TRUE);
260
261 cur_virt_src += cnt;
262 cur_virt_dst += cnt;
263 resid -= cnt;
264 }
265exit:
266 return (len - resid);
267}
268
269mach_vm_size_t
270kdp_machine_phys_write(kdp_writephysmem64_req_t *rq __unused, caddr_t src __unused,
271 uint16_t lcpu __unused)
272{
273 return 0; /* unimplemented */
274}
275
276void
277kern_collectth_state_size(uint64_t * tstate_count, uint64_t * tstate_size)
278{
279 uint64_t count = ml_get_max_cpu_number() + 1;
280
281 *tstate_count = count;
282 *tstate_size = sizeof(struct thread_command)
283 + (sizeof(arm_state_hdr_t)
284#if defined(__arm64__)
285 + ARM_THREAD_STATE64_COUNT * sizeof(uint32_t));
286#else
287 + ARM_THREAD_STATE32_COUNT * sizeof(uint32_t));
288#endif
289}
290
291void
292kern_collectth_state(thread_t thread __unused, void *buffer, uint64_t size, void ** iter)
293{
294 cpu_data_entry_t *cpuentryp = *iter;
295 if (cpuentryp == NULL)
296 cpuentryp = &CpuDataEntries[0];
297
298 if (cpuentryp == &CpuDataEntries[ml_get_max_cpu_number()])
299 *iter = NULL;
300 else
301 *iter = cpuentryp + 1;
302
303 struct cpu_data *cpudatap = cpuentryp->cpu_data_vaddr;
304
305 struct thread_command *tc = (struct thread_command *)buffer;
306 arm_state_hdr_t *hdr = (arm_state_hdr_t *)(void *)(tc + 1);
307#if defined(__arm64__)
308 hdr->flavor = ARM_THREAD_STATE64;
309 hdr->count = ARM_THREAD_STATE64_COUNT;
310 arm_thread_state64_t *state = (arm_thread_state64_t *)(void *)(hdr + 1);
311#else
312 hdr->flavor = ARM_THREAD_STATE;
313 hdr->count = ARM_THREAD_STATE_COUNT;
314 arm_thread_state_t *state = (arm_thread_state_t *)(void *)(hdr + 1);
315#endif
316
317 tc->cmd = LC_THREAD;
318 tc->cmdsize = (uint32_t) size;
319
320 if ((cpudatap != NULL) && (cpudatap->halt_status == CPU_HALTED_WITH_STATE)) {
321 *state = cpudatap->halt_state;
322 return;
323 }
324
325 if ((cpudatap == NULL) || (cpudatap->cpu_processor == NULL) || (cpudatap->cpu_processor->active_thread == NULL)) {
326 bzero(state, hdr->count * sizeof(uint32_t));
327 return;
328 }
329
330 vm_offset_t kstackptr = (vm_offset_t) cpudatap->cpu_processor->active_thread->machine.kstackptr;
331 arm_saved_state_t *saved_state = (arm_saved_state_t *) kstackptr;
332
333#if defined(__arm64__)
334
335 state->fp = saved_state->ss_64.fp;
336 state->lr = saved_state->ss_64.lr;
337 state->sp = saved_state->ss_64.sp;
338 state->pc = saved_state->ss_64.pc;
339 state->cpsr = saved_state->ss_64.cpsr;
340 bcopy(&saved_state->ss_64.x[0], &state->x[0], sizeof(state->x));
341
342#else /* __arm64__ */
343
344 state->lr = saved_state->lr;
345 state->sp = saved_state->sp;
346 state->pc = saved_state->pc;
347 state->cpsr = saved_state->cpsr;
348 bcopy(&saved_state->r[0], &state->r[0], sizeof(state->r));
349
350#endif /* !__arm64__ */
351
352
353}
354
355