]> git.saurik.com Git - apple/xnu.git/blob - osfmk/kdp/ml/i386/kdp_x86_common.c
xnu-1699.24.23.tar.gz
[apple/xnu.git] / osfmk / kdp / ml / i386 / kdp_x86_common.c
1 /*
2 * Copyright (c) 2008 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
29 #include <mach/mach_types.h>
30 #include <mach/vm_attributes.h>
31 #include <mach/vm_param.h>
32 #include <libsa/types.h>
33
34 #include <vm/vm_map.h>
35 #include <i386/pmap.h>
36 #include <i386/mp.h>
37 #include <i386/misc_protos.h>
38 #include <i386/pio.h>
39 #include <i386/proc_reg.h>
40
41 #include <kdp/kdp_internal.h>
42 #include <mach/vm_map.h>
43
44 #include <vm/vm_protos.h>
45 #include <vm/vm_kern.h>
46
47 #include <machine/pal_routines.h>
48
49 // #define KDP_VM_READ_DEBUG 1
50 // #define KDP_VM_WRITE_DEBUG 1
51
52 boolean_t kdp_read_io;
53 boolean_t kdp_trans_off;
54
55 static addr64_t kdp_vtophys(pmap_t pmap, addr64_t va);
56
57 pmap_t kdp_pmap = 0;
58
59 static addr64_t
60 kdp_vtophys(
61 pmap_t pmap,
62 addr64_t va)
63 {
64 addr64_t pa;
65 ppnum_t pp;
66
67 pp = pmap_find_phys(pmap, va);
68 if(!pp) return 0;
69
70 pa = ((addr64_t)pp << 12) | (va & 0x0000000000000FFFULL);
71
72 return(pa);
73 }
74
75 mach_vm_size_t
76 kdp_machine_vm_read( mach_vm_address_t src, caddr_t dst, mach_vm_size_t len)
77 {
78 addr64_t cur_virt_src = PAL_KDP_ADDR((addr64_t)src);
79 addr64_t cur_virt_dst = PAL_KDP_ADDR((addr64_t)(intptr_t)dst);
80 addr64_t cur_phys_dst, cur_phys_src;
81 mach_vm_size_t resid = len;
82 mach_vm_size_t cnt = 0, cnt_src, cnt_dst;
83 pmap_t src_pmap = kernel_pmap;
84
85 #ifdef KDP_VM_READ_DEBUG
86 printf("kdp_vm_read: src %llx dst %p len %llx\n", src, (void *)dst, len);
87 #endif
88
89 if (kdp_trans_off) {
90 kdp_readphysmem64_req_t rq;
91 mach_vm_size_t ret;
92
93 rq.address = src;
94 rq.nbytes = (uint32_t)len;
95 ret = kdp_machine_phys_read(&rq, dst, KDP_CURRENT_LCPU);
96 return ret;
97 }
98
99 /* If a different pmap has been specified with kdp_pmap, use it to translate the
100 * source (cur_virt_src); otherwise, the source is translated using the
101 * kernel_pmap.
102 */
103 if (kdp_pmap)
104 src_pmap = kdp_pmap;
105
106 while (resid != 0) {
107 if (!(cur_phys_src = kdp_vtophys(src_pmap,
108 cur_virt_src)))
109 goto exit;
110
111 /* Always translate the destination buffer using the kernel_pmap */
112 if(!(cur_phys_dst = kdp_vtophys(kernel_pmap, cur_virt_dst)))
113 goto exit;
114
115 /* Validate physical page numbers unless kdp_read_io is set */
116 if (kdp_read_io == FALSE)
117 if (!pmap_valid_page(i386_btop(cur_phys_dst)) || !pmap_valid_page(i386_btop(cur_phys_src)))
118 goto exit;
119
120 /* Get length left on page */
121 cnt_src = PAGE_SIZE - (cur_phys_src & PAGE_MASK);
122 cnt_dst = PAGE_SIZE - (cur_phys_dst & PAGE_MASK);
123 if (cnt_src > cnt_dst)
124 cnt = cnt_dst;
125 else
126 cnt = cnt_src;
127 if (cnt > resid)
128 cnt = resid;
129
130 /* Do a physical copy */
131 ml_copy_phys(cur_phys_src, cur_phys_dst, (vm_size_t)cnt);
132
133 cur_virt_src += cnt;
134 cur_virt_dst += cnt;
135 resid -= cnt;
136 }
137 exit:
138 return (len - resid);
139 }
140
141 mach_vm_size_t
142 kdp_machine_phys_read(kdp_readphysmem64_req_t *rq, caddr_t dst,
143 uint16_t lcpu)
144 {
145 mach_vm_address_t src = rq->address;
146 mach_vm_size_t len = rq->nbytes;
147
148 addr64_t cur_virt_dst;
149 addr64_t cur_phys_dst, cur_phys_src;
150 mach_vm_size_t resid = len;
151 mach_vm_size_t cnt = 0, cnt_src, cnt_dst;
152
153 if ((lcpu != KDP_CURRENT_LCPU) && (lcpu != cpu_number())) {
154 return (mach_vm_size_t)
155 kdp_x86_xcpu_invoke(lcpu, (kdp_x86_xcpu_func_t)kdp_machine_phys_read, rq, dst);
156 }
157
158 #ifdef KDP_VM_READ_DEBUG
159 printf("kdp_phys_read: src %llx dst %p len %llx\n", src, (void *)dst, len);
160 #endif
161
162 cur_virt_dst = (addr64_t)(intptr_t)dst;
163 cur_phys_src = (addr64_t)src;
164
165 while (resid != 0) {
166
167 if(!(cur_phys_dst = kdp_vtophys(kernel_pmap, cur_virt_dst)))
168 goto exit;
169
170 /* Get length left on page */
171 cnt_src = PAGE_SIZE - (cur_phys_src & PAGE_MASK);
172 cnt_dst = PAGE_SIZE - (cur_phys_dst & PAGE_MASK);
173 if (cnt_src > cnt_dst)
174 cnt = cnt_dst;
175 else
176 cnt = cnt_src;
177 if (cnt > resid)
178 cnt = resid;
179
180 /* Do a physical copy; use ml_copy_phys() in the event this is
181 * a short read with potential side effects.
182 */
183 ml_copy_phys(cur_phys_src, cur_phys_dst, (vm_size_t)cnt);
184 cur_phys_src += cnt;
185 cur_virt_dst += cnt;
186 resid -= cnt;
187 }
188 exit:
189 return (len - resid);
190 }
191
192 /*
193 *
194 */
195 mach_vm_size_t
196 kdp_machine_vm_write( caddr_t src, mach_vm_address_t dst, mach_vm_size_t len)
197 {
198 addr64_t cur_virt_src, cur_virt_dst;
199 addr64_t cur_phys_src, cur_phys_dst;
200 unsigned resid, cnt, cnt_src, cnt_dst;
201
202 #ifdef KDP_VM_WRITE_DEBUG
203 printf("kdp_vm_write: src %p dst %llx len %llx - %08X %08X\n", (void *)src, dst, len, ((unsigned int *)src)[0], ((unsigned int *)src)[1]);
204 #endif
205
206 cur_virt_src = PAL_KDP_ADDR((addr64_t)(intptr_t)src);
207 cur_virt_dst = PAL_KDP_ADDR((addr64_t)dst);
208
209 resid = (unsigned)len;
210
211 while (resid != 0) {
212 if ((cur_phys_dst = kdp_vtophys(kernel_pmap, cur_virt_dst)) == 0)
213 goto exit;
214
215 if ((cur_phys_src = kdp_vtophys(kernel_pmap, cur_virt_src)) == 0)
216 goto exit;
217
218 /* Copy as many bytes as possible without crossing a page */
219 cnt_src = (unsigned)(PAGE_SIZE - (cur_phys_src & PAGE_MASK));
220 cnt_dst = (unsigned)(PAGE_SIZE - (cur_phys_dst & PAGE_MASK));
221
222 if (cnt_src > cnt_dst)
223 cnt = cnt_dst;
224 else
225 cnt = cnt_src;
226 if (cnt > resid)
227 cnt = resid;
228
229 ml_copy_phys(cur_phys_src, cur_phys_dst, cnt); /* Copy stuff over */
230
231 cur_virt_src +=cnt;
232 cur_virt_dst +=cnt;
233 resid -= cnt;
234 }
235 exit:
236 return (len - resid);
237 }
238
239 /*
240 *
241 */
242 mach_vm_size_t
243 kdp_machine_phys_write(kdp_writephysmem64_req_t *rq, caddr_t src,
244 uint16_t lcpu)
245 {
246 mach_vm_address_t dst = rq->address;
247 mach_vm_size_t len = rq->nbytes;
248 addr64_t cur_virt_src;
249 addr64_t cur_phys_src, cur_phys_dst;
250 unsigned resid, cnt, cnt_src, cnt_dst;
251
252 if ((lcpu != KDP_CURRENT_LCPU) && (lcpu != cpu_number())) {
253 return (mach_vm_size_t)
254 kdp_x86_xcpu_invoke(lcpu, (kdp_x86_xcpu_func_t)kdp_machine_phys_write, rq, src);
255 }
256
257 #ifdef KDP_VM_WRITE_DEBUG
258 printf("kdp_phys_write: src %p dst %llx len %llx - %08X %08X\n", (void *)src, dst, len, ((unsigned int *)src)[0], ((unsigned int *)src)[1]);
259 #endif
260
261 cur_virt_src = (addr64_t)(intptr_t)src;
262 cur_phys_dst = (addr64_t)dst;
263
264 resid = (unsigned)len;
265
266 while (resid != 0) {
267 if ((cur_phys_src = kdp_vtophys(kernel_pmap, cur_virt_src)) == 0)
268 goto exit;
269
270 /* Copy as many bytes as possible without crossing a page */
271 cnt_src = (unsigned)(PAGE_SIZE - (cur_phys_src & PAGE_MASK));
272 cnt_dst = (unsigned)(PAGE_SIZE - (cur_phys_dst & PAGE_MASK));
273
274 if (cnt_src > cnt_dst)
275 cnt = cnt_dst;
276 else
277 cnt = cnt_src;
278 if (cnt > resid)
279 cnt = resid;
280
281 ml_copy_phys(cur_phys_src, cur_phys_dst, cnt); /* Copy stuff over */
282
283 cur_virt_src +=cnt;
284 cur_phys_dst +=cnt;
285 resid -= cnt;
286 }
287
288 exit:
289 return (len - resid);
290 }
291
292 int
293 kdp_machine_ioport_read(kdp_readioport_req_t *rq, caddr_t data, uint16_t lcpu)
294 {
295 uint16_t addr = rq->address;
296 uint16_t size = rq->nbytes;
297
298 if ((lcpu != KDP_CURRENT_LCPU) && (lcpu != cpu_number())) {
299 return (int) kdp_x86_xcpu_invoke(lcpu, (kdp_x86_xcpu_func_t)kdp_machine_ioport_read, rq, data);
300 }
301
302 switch (size)
303 {
304 case 1:
305 *((uint8_t *) data) = inb(addr);
306 break;
307 case 2:
308 *((uint16_t *) data) = inw(addr);
309 break;
310 case 4:
311 *((uint32_t *) data) = inl(addr);
312 break;
313 default:
314 return KDPERR_BADFLAVOR;
315 break;
316 }
317
318 return KDPERR_NO_ERROR;
319 }
320
321 int
322 kdp_machine_ioport_write(kdp_writeioport_req_t *rq, caddr_t data, uint16_t lcpu)
323 {
324 uint16_t addr = rq->address;
325 uint16_t size = rq->nbytes;
326
327 if ((lcpu != KDP_CURRENT_LCPU) && (lcpu != cpu_number())) {
328 return (int) kdp_x86_xcpu_invoke(lcpu, (kdp_x86_xcpu_func_t)kdp_machine_ioport_write, rq, data);
329 }
330
331 switch (size)
332 {
333 case 1:
334 outb(addr, *((uint8_t *) data));
335 break;
336 case 2:
337 outw(addr, *((uint16_t *) data));
338 break;
339 case 4:
340 outl(addr, *((uint32_t *) data));
341 break;
342 default:
343 return KDPERR_BADFLAVOR;
344 break;
345 }
346
347 return KDPERR_NO_ERROR;
348 }
349
350 int
351 kdp_machine_msr64_read(kdp_readmsr64_req_t *rq, caddr_t data, uint16_t lcpu)
352 {
353 uint64_t *value = (uint64_t *) data;
354 uint32_t msr = rq->address;
355
356 if ((lcpu != KDP_CURRENT_LCPU) && (lcpu != cpu_number())) {
357 return (int) kdp_x86_xcpu_invoke(lcpu, (kdp_x86_xcpu_func_t)kdp_machine_msr64_read, rq, data);
358 }
359
360 *value = rdmsr64(msr);
361 return KDPERR_NO_ERROR;
362 }
363
364 int
365 kdp_machine_msr64_write(kdp_writemsr64_req_t *rq, caddr_t data, uint16_t lcpu)
366 {
367 uint64_t *value = (uint64_t *) data;
368 uint32_t msr = rq->address;
369
370 if ((lcpu != KDP_CURRENT_LCPU) && (lcpu != cpu_number())) {
371 return (int) kdp_x86_xcpu_invoke(lcpu, (kdp_x86_xcpu_func_t)kdp_machine_msr64_write, rq, data);
372 }
373
374 wrmsr64(msr, *value);
375 return KDPERR_NO_ERROR;
376 }