xref: /xnu-8020.121.3/osfmk/kdp/ml/arm/kdp_vm.c (revision fdd8201d7b966f0c3ea610489d29bd841d358941)
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 
49 pmap_t          kdp_pmap = 0;
50 boolean_t       kdp_trans_off;
51 boolean_t       kdp_read_io = 0;
52 
53 pmap_paddr_t    kdp_vtophys(pmap_t pmap, vm_offset_t va);
54 
55 /*
56  * kdp_vtophys
57  */
58 pmap_paddr_t
kdp_vtophys(pmap_t pmap,vm_offset_t va)59 kdp_vtophys(
60 	pmap_t pmap,
61 	vm_offset_t va)
62 {
63 	pmap_paddr_t    pa;
64 
65 	/* Ensure that the provided va resides within the provided pmap range. */
66 	if (!pmap || ((pmap != kernel_pmap) && ((va < pmap->min) || (va >= pmap->max)))) {
67 #ifdef KDP_VTOPHYS_DEBUG
68 		printf("kdp_vtophys(%08x, %016lx) not in range %08x .. %08x\n", (unsigned int) pmap,
69 		    (unsigned long) va,
70 		    (unsigned int) (pmap ? pmap->min : 0),
71 		    (unsigned int) (pmap ? pmap->max : 0));
72 #endif
73 		return 0;   /* Just return if no translation */
74 	}
75 
76 	pa = pmap_find_pa(pmap, va);  /* Get the physical address */
77 	return pa;
78 }
79 
80 /*
81  * kdp_machine_vm_read
82  *
83  * Verify that src is valid, and physically copy len bytes from src to
84  * dst, translating if necessary. If translation is enabled
85  * (kdp_trans_off is 0), a non-zero kdp_pmap specifies the pmap to use
86  * when translating src.
87  */
88 
89 mach_vm_size_t
kdp_machine_vm_read(mach_vm_address_t src,caddr_t dst,mach_vm_size_t len)90 kdp_machine_vm_read( mach_vm_address_t src, caddr_t dst, mach_vm_size_t len)
91 {
92 	addr64_t        cur_virt_src, cur_virt_dst;
93 	addr64_t        cur_phys_src, cur_phys_dst;
94 	mach_vm_size_t  resid, cnt;
95 	pmap_t          pmap;
96 
97 #ifdef KDP_VM_READ_DEBUG
98 	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]);
99 #endif
100 
101 	cur_virt_src = (addr64_t) src;
102 	cur_virt_dst = (addr64_t) dst;
103 
104 	if (kdp_trans_off) {
105 		kdp_readphysmem64_req_t rq;
106 		mach_vm_size_t ret;
107 
108 		rq.address = src;
109 		rq.nbytes = (uint32_t)len;
110 		ret = kdp_machine_phys_read(&rq, dst, 0 /* unused */);
111 		return ret;
112 	} else {
113 		resid = len;
114 
115 		if (kdp_pmap) {
116 			pmap = kdp_pmap;        /* If special pmap, use it */
117 		} else {
118 			pmap = kernel_pmap;     /* otherwise, use kernel's */
119 		}
120 		while (resid != 0) {
121 			/*
122 			 * Always translate the destination using the
123 			 * kernel_pmap.
124 			 */
125 			if ((cur_phys_dst = kdp_vtophys(kernel_pmap, cur_virt_dst)) == 0) {
126 				goto exit;
127 			}
128 
129 			if ((cur_phys_src = kdp_vtophys(pmap, cur_virt_src)) == 0) {
130 				goto exit;
131 			}
132 
133 			/* Attempt to ensure that there are valid translations for src and dst. */
134 			if (!kdp_read_io && ((!pmap_valid_address(cur_phys_dst)) || (!pmap_valid_address(cur_phys_src)))) {
135 				goto exit;
136 			}
137 
138 			cnt = ARM_PGBYTES - (cur_virt_src & PAGE_MASK); /* Get length left on
139 			                                                 * page */
140 			if (cnt > (ARM_PGBYTES - (cur_virt_dst & PAGE_MASK))) {
141 				cnt = ARM_PGBYTES - (cur_virt_dst & PAGE_MASK);
142 			}
143 
144 			if (cnt > resid) {
145 				cnt = resid;
146 			}
147 
148 #ifdef KDP_VM_READ_DEBUG
149 			kprintf("kdp_machine_vm_read2: pmap %08X, virt %016LLX, phys %016LLX\n",
150 			    pmap, cur_virt_src, cur_phys_src);
151 #endif
152 			bcopy_phys(cur_phys_src, cur_phys_dst, cnt);
153 
154 			cur_virt_src += cnt;
155 			cur_virt_dst += cnt;
156 			resid -= cnt;
157 		}
158 	}
159 exit:
160 #ifdef KDP_VM_READ_DEBUG
161 	kprintf("kdp_machine_vm_read: ret %08X\n", len - resid);
162 #endif
163 	return len - resid;
164 }
165 
166 mach_vm_size_t
kdp_machine_phys_read(kdp_readphysmem64_req_t * rq,caddr_t dst,uint16_t lcpu __unused)167 kdp_machine_phys_read(kdp_readphysmem64_req_t *rq, caddr_t dst, uint16_t lcpu __unused)
168 {
169 	mach_vm_address_t src = rq->address;
170 	mach_vm_size_t    len = rq->nbytes;
171 
172 	addr64_t        cur_virt_dst;
173 	addr64_t        cur_phys_src, cur_phys_dst;
174 	mach_vm_size_t  resid = len;
175 	mach_vm_size_t  cnt = 0, cnt_src, cnt_dst;
176 
177 #ifdef KDP_VM_READ_DEBUG
178 	kprintf("kdp_phys_read src %x dst %p len %x\n", src, dst, len);
179 #endif
180 
181 	cur_virt_dst = (addr64_t) dst;
182 	cur_phys_src = (addr64_t) src;
183 
184 	while (resid != 0) {
185 		if ((cur_phys_dst = kdp_vtophys(kernel_pmap, cur_virt_dst)) == 0) {
186 			goto exit;
187 		}
188 
189 		/* Get length left on page */
190 
191 		cnt_src = ARM_PGBYTES - (cur_phys_src & PAGE_MASK);
192 		cnt_dst = ARM_PGBYTES - (cur_phys_dst & PAGE_MASK);
193 		if (cnt_src > cnt_dst) {
194 			cnt = cnt_dst;
195 		} else {
196 			cnt = cnt_src;
197 		}
198 		if (cnt > resid) {
199 			cnt = resid;
200 		}
201 
202 		bcopy_phys(cur_phys_src, cur_phys_dst, cnt);    /* Copy stuff over */
203 		cur_phys_src += cnt;
204 		cur_virt_dst += cnt;
205 		resid -= cnt;
206 	}
207 
208 exit:
209 	return len - resid;
210 }
211 
212 /*
213  * kdp_vm_write
214  */
215 mach_vm_size_t
kdp_machine_vm_write(caddr_t src,mach_vm_address_t dst,mach_vm_size_t len)216 kdp_machine_vm_write( caddr_t src, mach_vm_address_t dst, mach_vm_size_t len)
217 {
218 	addr64_t        cur_virt_src, cur_virt_dst;
219 	addr64_t        cur_phys_src, cur_phys_dst;
220 	mach_vm_size_t  resid, cnt, cnt_src, cnt_dst;
221 
222 #ifdef KDP_VM_WRITE_DEBUG
223 	printf("kdp_vm_write: src %x dst %x len %x - %08X %08X\n", src, dst, len, ((unsigned long *) src)[0], ((unsigned long *) src)[1]);
224 #endif
225 
226 	cur_virt_src = (addr64_t) src;
227 	cur_virt_dst = (addr64_t) dst;
228 
229 	resid = len;
230 
231 	while (resid != 0) {
232 		if ((cur_phys_dst = kdp_vtophys(kernel_pmap, cur_virt_dst)) == 0) {
233 			goto exit;
234 		}
235 
236 		if ((cur_phys_src = kdp_vtophys(kernel_pmap, cur_virt_src)) == 0) {
237 			goto exit;
238 		}
239 
240 		/* Attempt to ensure that there are valid translations for src and dst. */
241 		/* No support for enabling writes for an invalid translation at the moment. */
242 		if ((!pmap_valid_address(cur_phys_dst)) || (!pmap_valid_address(cur_phys_src))) {
243 			goto exit;
244 		}
245 
246 		cnt_src = ((cur_phys_src + ARM_PGBYTES) & (-ARM_PGBYTES)) - cur_phys_src;
247 		cnt_dst = ((cur_phys_dst + ARM_PGBYTES) & (-ARM_PGBYTES)) - cur_phys_dst;
248 
249 		if (cnt_src > cnt_dst) {
250 			cnt = cnt_dst;
251 		} else {
252 			cnt = cnt_src;
253 		}
254 		if (cnt > resid) {
255 			cnt = resid;
256 		}
257 
258 #ifdef KDP_VM_WRITE_DEBUG
259 		printf("kdp_vm_write: cur_phys_src %x cur_phys_src %x len %x - %08X %08X\n", src, dst, cnt);
260 #endif
261 		bcopy_phys(cur_phys_src, cur_phys_dst, cnt);    /* Copy stuff over */
262 		flush_dcache64(cur_phys_dst, (unsigned int)cnt, TRUE);
263 		invalidate_icache64(cur_phys_dst, (unsigned int)cnt, TRUE);
264 
265 		cur_virt_src += cnt;
266 		cur_virt_dst += cnt;
267 		resid -= cnt;
268 	}
269 exit:
270 	return len - resid;
271 }
272 
273 mach_vm_size_t
kdp_machine_phys_write(kdp_writephysmem64_req_t * rq __unused,caddr_t src __unused,uint16_t lcpu __unused)274 kdp_machine_phys_write(kdp_writephysmem64_req_t *rq __unused, caddr_t src __unused,
275     uint16_t lcpu __unused)
276 {
277 	return 0; /* unimplemented */
278 }
279 
280 void
kern_collectth_state_size(uint64_t * tstate_count,uint64_t * tstate_size)281 kern_collectth_state_size(uint64_t * tstate_count, uint64_t * tstate_size)
282 {
283 	uint64_t    count = ml_get_max_cpu_number() + 1;
284 
285 	*tstate_count = count;
286 	*tstate_size  = sizeof(struct thread_command)
287 	    + (sizeof(arm_state_hdr_t)
288 #if defined(__arm64__)
289 	    + ARM_THREAD_STATE64_COUNT * sizeof(uint32_t));
290 #else
291 	    + ARM_THREAD_STATE32_COUNT * sizeof(uint32_t));
292 #endif
293 }
294 
295 void
kern_collectth_state(thread_t thread __unused,void * buffer,uint64_t size,void ** iter)296 kern_collectth_state(thread_t thread __unused, void *buffer, uint64_t size, void ** iter)
297 {
298 	cpu_data_entry_t *cpuentryp = *iter;
299 	if (cpuentryp == NULL) {
300 		cpuentryp = &CpuDataEntries[0];
301 	}
302 
303 	if (cpuentryp == &CpuDataEntries[ml_get_max_cpu_number()]) {
304 		*iter = NULL;
305 	} else {
306 		*iter = cpuentryp + 1;
307 	}
308 
309 	struct cpu_data *cpudatap = cpuentryp->cpu_data_vaddr;
310 
311 	struct thread_command *tc = (struct thread_command *)buffer;
312 	arm_state_hdr_t *hdr = (arm_state_hdr_t *)(void *)(tc + 1);
313 #if defined(__arm64__)
314 	hdr->flavor = ARM_THREAD_STATE64;
315 	hdr->count = ARM_THREAD_STATE64_COUNT;
316 	arm_thread_state64_t *state = (arm_thread_state64_t *)(void *)(hdr + 1);
317 #else
318 	hdr->flavor = ARM_THREAD_STATE;
319 	hdr->count = ARM_THREAD_STATE_COUNT;
320 	arm_thread_state_t *state = (arm_thread_state_t *)(void *)(hdr + 1);
321 #endif
322 
323 	tc->cmd = LC_THREAD;
324 	tc->cmdsize = (uint32_t) size;
325 
326 	if ((cpudatap != NULL) && (cpudatap->halt_status == CPU_HALTED_WITH_STATE)) {
327 		*state = cpudatap->halt_state;
328 		return;
329 	}
330 
331 	processor_t processor = PERCPU_GET_RELATIVE(processor, cpu_data, cpudatap);
332 	if ((cpudatap == NULL) || (processor->active_thread == NULL)) {
333 		bzero(state, hdr->count * sizeof(uint32_t));
334 		return;
335 	}
336 
337 #if defined(__arm64__)
338 	void *kpcb = processor->active_thread->machine.kpcb;
339 	if (kpcb != NULL) {
340 		arm_saved_state_t *saved_state = (arm_saved_state_t *)kpcb;
341 
342 		state->fp   = saved_state->ss_64.fp;
343 		state->lr   = saved_state->ss_64.lr;
344 		state->sp   = saved_state->ss_64.sp;
345 		state->pc   = saved_state->ss_64.pc;
346 		state->cpsr = saved_state->ss_64.cpsr;
347 		bcopy(&saved_state->ss_64.x[0], &state->x[0], sizeof(state->x));
348 	} else {
349 		vm_offset_t kstackptr = (vm_offset_t) processor->active_thread->machine.kstackptr;
350 		arm_kernel_saved_state_t *saved_state = (arm_kernel_saved_state_t *) kstackptr;
351 
352 		state->fp   = saved_state->fp;
353 		state->lr   = saved_state->lr;
354 		state->sp   = saved_state->sp;
355 		state->pc   = saved_state->pc;
356 		state->cpsr = PSR64_KERNEL_DEFAULT;
357 	}
358 
359 #else /* __arm64__ */
360 	vm_offset_t kstackptr = (vm_offset_t) processor->active_thread->machine.kstackptr;
361 	arm_saved_state_t *saved_state = (arm_saved_state_t *) kstackptr;
362 
363 	state->lr   = saved_state->lr;
364 	state->sp   = saved_state->sp;
365 	state->pc   = saved_state->pc;
366 	state->cpsr = saved_state->cpsr;
367 	bcopy(&saved_state->r[0], &state->r[0], sizeof(state->r));
368 
369 #endif /* !__arm64__ */
370 }
371 
372 /*
373  * kdp_core_start_addr
374  *
375  * return the address where the kernel core file starts
376  *
377  * The kernel start address is VM_MIN_KERNEL_AND_KEXT_ADDRESS
378  * unless the physical aperture has been relocated below
379  * VM_MIN_KERNEL_AND_KEXT_ADDRESS as in the case of
380  * ARM_LARGE_MEMORY systems
381  *
382  */
383 vm_map_offset_t
kdp_core_start_addr()384 kdp_core_start_addr()
385 {
386 #if defined(__arm64__)
387 	extern const vm_map_address_t physmap_base;
388 	return MIN(physmap_base, VM_MIN_KERNEL_AND_KEXT_ADDRESS);
389 #else /* !defined(__arm64__) */
390 	return VM_MIN_KERNEL_AND_KEXT_ADDRESS;
391 #endif /* !defined(__arm64__) */
392 }
393