]> git.saurik.com Git - apple/xnu.git/blame - osfmk/arm64/loose_ends.c
xnu-6153.141.1.tar.gz
[apple/xnu.git] / osfmk / arm64 / loose_ends.c
CommitLineData
5ba3f43e
A
1/*
2 * Copyright (c) 2007-2016 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_assert.h>
30#include <mach/vm_types.h>
31#include <mach/mach_time.h>
32#include <kern/timer.h>
33#include <kern/clock.h>
34#include <kern/machine.h>
35#include <mach/machine.h>
36#include <mach/machine/vm_param.h>
37#include <mach_kdp.h>
38#include <kdp/kdp_udp.h>
39#if !MACH_KDP
40#include <kdp/kdp_callout.h>
41#endif /* !MACH_KDP */
42#include <arm/cpu_data.h>
43#include <arm/cpu_data_internal.h>
44#include <arm/caches_internal.h>
45
46#include <vm/vm_kern.h>
47#include <vm/vm_map.h>
48#include <vm/pmap.h>
49
50#include <arm/misc_protos.h>
51
52#include <sys/errno.h>
53
54#define INT_SIZE (BYTE_SIZE * sizeof (int))
55
d9a64523
A
56#define BCOPY_PHYS_SRC_IS_PHYS(flags) (((flags) & cppvPsrc) != 0)
57#define BCOPY_PHYS_DST_IS_PHYS(flags) (((flags) & cppvPsnk) != 0)
58#define BCOPY_PHYS_SRC_IS_USER(flags) (((flags) & (cppvPsrc | cppvKmap)) == 0)
59#define BCOPY_PHYS_DST_IS_USER(flags) (((flags) & (cppvPsnk | cppvKmap)) == 0)
60
61static kern_return_t
62bcopy_phys_internal(addr64_t src, addr64_t dst, vm_size_t bytes, int flags)
5ba3f43e
A
63{
64 unsigned int src_index;
65 unsigned int dst_index;
66 vm_offset_t src_offset;
67 vm_offset_t dst_offset;
68 unsigned int wimg_bits_src, wimg_bits_dst;
69 unsigned int cpu_num = 0;
d9a64523
A
70 ppnum_t pn_src;
71 ppnum_t pn_dst;
72 addr64_t end __assert_only;
73 kern_return_t res = KERN_SUCCESS;
74
75 assert(!__improbable(os_add_overflow(src, bytes, &end)));
76 assert(!__improbable(os_add_overflow(dst, bytes, &end)));
77
78 while ((bytes > 0) && (res == KERN_SUCCESS)) {
79 src_offset = src & PAGE_MASK;
80 dst_offset = dst & PAGE_MASK;
81 boolean_t use_copy_window_src = FALSE;
82 boolean_t use_copy_window_dst = FALSE;
83 vm_size_t count = bytes;
84 vm_size_t count2 = bytes;
85 if (BCOPY_PHYS_SRC_IS_PHYS(flags)) {
86 use_copy_window_src = !pmap_valid_address(src);
87 pn_src = (ppnum_t)(src >> PAGE_SHIFT);
88#if !defined(__ARM_COHERENT_IO__) && !__ARM_PTE_PHYSMAP__
89 count = PAGE_SIZE - src_offset;
90 wimg_bits_src = pmap_cache_attributes(pn_src);
0a7de745 91 if ((wimg_bits_src & VM_WIMG_MASK) != VM_WIMG_DEFAULT) {
d9a64523 92 use_copy_window_src = TRUE;
0a7de745 93 }
d9a64523
A
94#else
95 if (use_copy_window_src) {
96 wimg_bits_src = pmap_cache_attributes(pn_src);
97 count = PAGE_SIZE - src_offset;
98 }
5ba3f43e 99#endif
d9a64523
A
100 }
101 if (BCOPY_PHYS_DST_IS_PHYS(flags)) {
102 // write preflighting needed for things like dtrace which may write static read-only mappings
103 use_copy_window_dst = (!pmap_valid_address(dst) || !mmu_kvtop_wpreflight(phystokv((pmap_paddr_t)dst)));
104 pn_dst = (ppnum_t)(dst >> PAGE_SHIFT);
105#if !defined(__ARM_COHERENT_IO__) && !__ARM_PTE_PHYSMAP__
106 count2 = PAGE_SIZE - dst_offset;
107 wimg_bits_dst = pmap_cache_attributes(pn_dst);
0a7de745 108 if ((wimg_bits_dst & VM_WIMG_MASK) != VM_WIMG_DEFAULT) {
d9a64523 109 use_copy_window_dst = TRUE;
0a7de745 110 }
d9a64523
A
111#else
112 if (use_copy_window_dst) {
113 wimg_bits_dst = pmap_cache_attributes(pn_dst);
114 count2 = PAGE_SIZE - dst_offset;
115 }
116#endif
117 }
5ba3f43e 118
d9a64523
A
119 char *tmp_src;
120 char *tmp_dst;
5ba3f43e 121
d9a64523
A
122 if (use_copy_window_src || use_copy_window_dst) {
123 mp_disable_preemption();
124 cpu_num = cpu_number();
125 }
126
127 if (use_copy_window_src) {
128 src_index = pmap_map_cpu_windows_copy(pn_src, VM_PROT_READ, wimg_bits_src);
129 tmp_src = (char*)(pmap_cpu_windows_copy_addr(cpu_num, src_index) + src_offset);
130 } else if (BCOPY_PHYS_SRC_IS_PHYS(flags)) {
131 tmp_src = (char*)phystokv_range((pmap_paddr_t)src, &count);
132 } else {
133 tmp_src = (char*)src;
134 }
135 if (use_copy_window_dst) {
136 dst_index = pmap_map_cpu_windows_copy(pn_dst, VM_PROT_READ | VM_PROT_WRITE, wimg_bits_dst);
137 tmp_dst = (char*)(pmap_cpu_windows_copy_addr(cpu_num, dst_index) + dst_offset);
138 } else if (BCOPY_PHYS_DST_IS_PHYS(flags)) {
139 tmp_dst = (char*)phystokv_range((pmap_paddr_t)dst, &count2);
140 } else {
141 tmp_dst = (char*)dst;
142 }
5ba3f43e 143
0a7de745 144 if (count > count2) {
d9a64523 145 count = count2;
0a7de745
A
146 }
147 if (count > bytes) {
d9a64523 148 count = bytes;
0a7de745 149 }
5ba3f43e 150
0a7de745 151 if (BCOPY_PHYS_SRC_IS_USER(flags)) {
d9a64523 152 res = copyin((user_addr_t)src, tmp_dst, count);
0a7de745 153 } else if (BCOPY_PHYS_DST_IS_USER(flags)) {
d9a64523 154 res = copyout(tmp_src, (user_addr_t)dst, count);
0a7de745 155 } else {
d9a64523 156 bcopy(tmp_src, tmp_dst, count);
0a7de745 157 }
5ba3f43e 158
0a7de745 159 if (use_copy_window_src) {
d9a64523 160 pmap_unmap_cpu_windows_copy(src_index);
0a7de745
A
161 }
162 if (use_copy_window_dst) {
d9a64523 163 pmap_unmap_cpu_windows_copy(dst_index);
0a7de745
A
164 }
165 if (use_copy_window_src || use_copy_window_dst) {
d9a64523 166 mp_enable_preemption();
0a7de745 167 }
5ba3f43e 168
d9a64523
A
169 src += count;
170 dst += count;
171 bytes -= count;
172 }
173 return res;
174}
5ba3f43e 175
d9a64523
A
176void
177bcopy_phys(addr64_t src, addr64_t dst, vm_size_t bytes)
178{
179 bcopy_phys_internal(src, dst, bytes, cppvPsrc | cppvPsnk);
5ba3f43e
A
180}
181
182void
183bzero_phys_nc(addr64_t src64, vm_size_t bytes)
184{
185 bzero_phys(src64, bytes);
186}
187
94ff46dc
A
188extern void *secure_memset(void *, int, size_t);
189
5ba3f43e
A
190/* Zero bytes starting at a physical address */
191void
192bzero_phys(addr64_t src, vm_size_t bytes)
193{
194 unsigned int wimg_bits;
195 unsigned int cpu_num = cpu_number();
d9a64523
A
196 ppnum_t pn;
197 addr64_t end __assert_only;
5ba3f43e 198
d9a64523 199 assert(!__improbable(os_add_overflow(src, bytes, &end)));
5ba3f43e 200
d9a64523
A
201 vm_offset_t offset = src & PAGE_MASK;
202 while (bytes > 0) {
203 vm_size_t count = bytes;
5ba3f43e 204
d9a64523
A
205 boolean_t use_copy_window = !pmap_valid_address(src);
206 pn = (ppnum_t)(src >> PAGE_SHIFT);
94ff46dc 207 wimg_bits = pmap_cache_attributes(pn);
d9a64523
A
208#if !defined(__ARM_COHERENT_IO__) && !__ARM_PTE_PHYSMAP__
209 count = PAGE_SIZE - offset;
0a7de745 210 if ((wimg_bits & VM_WIMG_MASK) != VM_WIMG_DEFAULT) {
d9a64523 211 use_copy_window = TRUE;
0a7de745 212 }
d9a64523
A
213#else
214 if (use_copy_window) {
d9a64523
A
215 count = PAGE_SIZE - offset;
216 }
5ba3f43e 217#endif
d9a64523
A
218 char *buf;
219 unsigned int index;
220 if (use_copy_window) {
221 mp_disable_preemption();
222 cpu_num = cpu_number();
223 index = pmap_map_cpu_windows_copy(pn, VM_PROT_READ | VM_PROT_WRITE, wimg_bits);
224 buf = (char *)(pmap_cpu_windows_copy_addr(cpu_num, index) + offset);
225 } else {
226 buf = (char *)phystokv_range((pmap_paddr_t)src, &count);
227 }
5ba3f43e 228
0a7de745 229 if (count > bytes) {
5ba3f43e 230 count = bytes;
0a7de745 231 }
5ba3f43e 232
94ff46dc
A
233 switch (wimg_bits & VM_WIMG_MASK) {
234 case VM_WIMG_DEFAULT:
235 case VM_WIMG_WCOMB:
236 case VM_WIMG_INNERWBACK:
237 case VM_WIMG_WTHRU:
238 bzero(buf, count);
239 break;
240 default:
241 /* 'dc zva' performed by bzero is not safe for device memory */
242 secure_memset((void*)buf, 0, count);
243 }
5ba3f43e 244
d9a64523
A
245 if (use_copy_window) {
246 pmap_unmap_cpu_windows_copy(index);
247 mp_enable_preemption();
248 }
5ba3f43e
A
249
250 src += count;
251 bytes -= count;
d9a64523 252 offset = 0;
5ba3f43e 253 }
5ba3f43e
A
254}
255
256/*
257 * Read data from a physical address.
258 */
259
260
261static unsigned long long
262ml_phys_read_data(pmap_paddr_t paddr, int size)
263{
264 unsigned int index;
265 unsigned int wimg_bits;
266 ppnum_t pn = (ppnum_t)(paddr >> PAGE_SHIFT);
0a7de745 267 ppnum_t pn_end = (ppnum_t)((paddr + size - 1) >> PAGE_SHIFT);
5ba3f43e
A
268 unsigned long long result = 0;
269 vm_offset_t copywindow_vaddr = 0;
270 unsigned char s1;
271 unsigned short s2;
272 unsigned int s4;
273
0a7de745 274 if (__improbable(pn_end != pn)) {
d9a64523 275 panic("%s: paddr 0x%llx spans a page boundary", __func__, (uint64_t)paddr);
0a7de745 276 }
d9a64523
A
277
278#if defined(__ARM_COHERENT_IO__) || __ARM_PTE_PHYSMAP__
5ba3f43e
A
279 if (pmap_valid_address(paddr)) {
280 switch (size) {
281 case 1:
282 s1 = *(volatile unsigned char *)phystokv(paddr);
283 result = s1;
284 break;
285 case 2:
286 s2 = *(volatile unsigned short *)phystokv(paddr);
287 result = s2;
288 break;
289 case 4:
290 s4 = *(volatile unsigned int *)phystokv(paddr);
291 result = s4;
292 break;
293 case 8:
294 result = *(volatile unsigned long long *)phystokv(paddr);
295 break;
296 default:
297 panic("Invalid size %d for ml_phys_read_data\n", size);
0a7de745 298 break;
5ba3f43e
A
299 }
300 return result;
301 }
302#endif
303
304 mp_disable_preemption();
305 wimg_bits = pmap_cache_attributes(pn);
306 index = pmap_map_cpu_windows_copy(pn, VM_PROT_READ, wimg_bits);
307 copywindow_vaddr = pmap_cpu_windows_copy_addr(cpu_number(), index) | ((uint32_t)paddr & PAGE_MASK);
308
309 switch (size) {
0a7de745
A
310 case 1:
311 s1 = *(volatile unsigned char *)copywindow_vaddr;
312 result = s1;
313 break;
314 case 2:
315 s2 = *(volatile unsigned short *)copywindow_vaddr;
316 result = s2;
317 break;
318 case 4:
319 s4 = *(volatile unsigned int *)copywindow_vaddr;
320 result = s4;
321 break;
322 case 8:
323 result = *(volatile unsigned long long*)copywindow_vaddr;
324 break;
325 default:
326 panic("Invalid size %d for ml_phys_read_data\n", size);
327 break;
5ba3f43e
A
328 }
329
330 pmap_unmap_cpu_windows_copy(index);
331 mp_enable_preemption();
332
333 return result;
334}
335
0a7de745
A
336unsigned int
337ml_phys_read( vm_offset_t paddr)
5ba3f43e 338{
0a7de745 339 return (unsigned int)ml_phys_read_data((pmap_paddr_t)paddr, 4);
5ba3f43e
A
340}
341
0a7de745
A
342unsigned int
343ml_phys_read_word(vm_offset_t paddr)
344{
345 return (unsigned int)ml_phys_read_data((pmap_paddr_t)paddr, 4);
5ba3f43e
A
346}
347
0a7de745
A
348unsigned int
349ml_phys_read_64(addr64_t paddr64)
5ba3f43e 350{
0a7de745 351 return (unsigned int)ml_phys_read_data((pmap_paddr_t)paddr64, 4);
5ba3f43e
A
352}
353
0a7de745
A
354unsigned int
355ml_phys_read_word_64(addr64_t paddr64)
5ba3f43e 356{
0a7de745 357 return (unsigned int)ml_phys_read_data((pmap_paddr_t)paddr64, 4);
5ba3f43e
A
358}
359
0a7de745
A
360unsigned int
361ml_phys_read_half(vm_offset_t paddr)
5ba3f43e 362{
0a7de745 363 return (unsigned int)ml_phys_read_data((pmap_paddr_t)paddr, 2);
5ba3f43e
A
364}
365
0a7de745
A
366unsigned int
367ml_phys_read_half_64(addr64_t paddr64)
5ba3f43e 368{
0a7de745 369 return (unsigned int)ml_phys_read_data((pmap_paddr_t)paddr64, 2);
5ba3f43e
A
370}
371
0a7de745
A
372unsigned int
373ml_phys_read_byte(vm_offset_t paddr)
5ba3f43e 374{
0a7de745 375 return (unsigned int)ml_phys_read_data((pmap_paddr_t)paddr, 1);
5ba3f43e
A
376}
377
0a7de745
A
378unsigned int
379ml_phys_read_byte_64(addr64_t paddr64)
5ba3f43e 380{
0a7de745 381 return (unsigned int)ml_phys_read_data((pmap_paddr_t)paddr64, 1);
5ba3f43e
A
382}
383
0a7de745
A
384unsigned long long
385ml_phys_read_double(vm_offset_t paddr)
5ba3f43e 386{
0a7de745 387 return ml_phys_read_data((pmap_paddr_t)paddr, 8);
5ba3f43e
A
388}
389
0a7de745
A
390unsigned long long
391ml_phys_read_double_64(addr64_t paddr64)
5ba3f43e 392{
0a7de745 393 return ml_phys_read_data((pmap_paddr_t)paddr64, 8);
5ba3f43e
A
394}
395
396
397
398/*
399 * Write data to a physical address.
400 */
401
402static void
403ml_phys_write_data(pmap_paddr_t paddr, unsigned long long data, int size)
404{
405 unsigned int index;
406 unsigned int wimg_bits;
407 ppnum_t pn = (ppnum_t)(paddr >> PAGE_SHIFT);
0a7de745 408 ppnum_t pn_end = (ppnum_t)((paddr + size - 1) >> PAGE_SHIFT);
5ba3f43e
A
409 vm_offset_t copywindow_vaddr = 0;
410
0a7de745 411 if (__improbable(pn_end != pn)) {
d9a64523 412 panic("%s: paddr 0x%llx spans a page boundary", __func__, (uint64_t)paddr);
0a7de745 413 }
d9a64523
A
414
415#if defined(__ARM_COHERENT_IO__) || __ARM_PTE_PHYSMAP__
5ba3f43e
A
416 if (pmap_valid_address(paddr)) {
417 switch (size) {
418 case 1:
419 *(volatile unsigned char *)phystokv(paddr) = (unsigned char)data;
420 return;
421 case 2:
422 *(volatile unsigned short *)phystokv(paddr) = (unsigned short)data;
423 return;
424 case 4:
425 *(volatile unsigned int *)phystokv(paddr) = (unsigned int)data;
426 return;
427 case 8:
428 *(volatile unsigned long long *)phystokv(paddr) = data;
429 return;
430 default:
431 panic("Invalid size %d for ml_phys_write_data\n", size);
432 }
433 }
434#endif
435
436 mp_disable_preemption();
437 wimg_bits = pmap_cache_attributes(pn);
0a7de745 438 index = pmap_map_cpu_windows_copy(pn, VM_PROT_READ | VM_PROT_WRITE, wimg_bits);
5ba3f43e
A
439 copywindow_vaddr = pmap_cpu_windows_copy_addr(cpu_number(), index) | ((uint32_t)paddr & PAGE_MASK);
440
441 switch (size) {
0a7de745
A
442 case 1:
443 *(volatile unsigned char *)(copywindow_vaddr) =
444 (unsigned char)data;
445 break;
446 case 2:
447 *(volatile unsigned short *)(copywindow_vaddr) =
448 (unsigned short)data;
449 break;
450 case 4:
451 *(volatile unsigned int *)(copywindow_vaddr) =
452 (uint32_t)data;
453 break;
454 case 8:
455 *(volatile unsigned long long *)(copywindow_vaddr) =
456 (unsigned long long)data;
457 break;
458 default:
459 panic("Invalid size %d for ml_phys_write_data\n", size);
460 break;
5ba3f43e
A
461 }
462
463 pmap_unmap_cpu_windows_copy(index);
464 mp_enable_preemption();
465}
466
0a7de745
A
467void
468ml_phys_write_byte(vm_offset_t paddr, unsigned int data)
5ba3f43e 469{
0a7de745 470 ml_phys_write_data((pmap_paddr_t)paddr, data, 1);
5ba3f43e
A
471}
472
0a7de745
A
473void
474ml_phys_write_byte_64(addr64_t paddr64, unsigned int data)
5ba3f43e 475{
0a7de745 476 ml_phys_write_data((pmap_paddr_t)paddr64, data, 1);
5ba3f43e
A
477}
478
0a7de745
A
479void
480ml_phys_write_half(vm_offset_t paddr, unsigned int data)
5ba3f43e 481{
0a7de745 482 ml_phys_write_data((pmap_paddr_t)paddr, data, 2);
5ba3f43e
A
483}
484
0a7de745
A
485void
486ml_phys_write_half_64(addr64_t paddr64, unsigned int data)
5ba3f43e 487{
0a7de745 488 ml_phys_write_data((pmap_paddr_t)paddr64, data, 2);
5ba3f43e
A
489}
490
0a7de745
A
491void
492ml_phys_write(vm_offset_t paddr, unsigned int data)
5ba3f43e 493{
0a7de745 494 ml_phys_write_data((pmap_paddr_t)paddr, data, 4);
5ba3f43e
A
495}
496
0a7de745
A
497void
498ml_phys_write_64(addr64_t paddr64, unsigned int data)
5ba3f43e 499{
0a7de745 500 ml_phys_write_data((pmap_paddr_t)paddr64, data, 4);
5ba3f43e
A
501}
502
0a7de745
A
503void
504ml_phys_write_word(vm_offset_t paddr, unsigned int data)
5ba3f43e 505{
0a7de745 506 ml_phys_write_data((pmap_paddr_t)paddr, data, 4);
5ba3f43e
A
507}
508
0a7de745
A
509void
510ml_phys_write_word_64(addr64_t paddr64, unsigned int data)
5ba3f43e 511{
0a7de745 512 ml_phys_write_data((pmap_paddr_t)paddr64, data, 4);
5ba3f43e
A
513}
514
0a7de745
A
515void
516ml_phys_write_double(vm_offset_t paddr, unsigned long long data)
5ba3f43e 517{
0a7de745 518 ml_phys_write_data((pmap_paddr_t)paddr, data, 8);
5ba3f43e
A
519}
520
0a7de745
A
521void
522ml_phys_write_double_64(addr64_t paddr64, unsigned long long data)
5ba3f43e 523{
0a7de745 524 ml_phys_write_data((pmap_paddr_t)paddr64, data, 8);
5ba3f43e
A
525}
526
527
528/*
529 * Set indicated bit in bit string.
530 */
531void
532setbit(int bitno, int *s)
533{
cb323159 534 s[bitno / INT_SIZE] |= 1U << (bitno % INT_SIZE);
5ba3f43e
A
535}
536
537/*
538 * Clear indicated bit in bit string.
539 */
540void
541clrbit(int bitno, int *s)
542{
cb323159 543 s[bitno / INT_SIZE] &= ~(1U << (bitno % INT_SIZE));
5ba3f43e
A
544}
545
546/*
547 * Test if indicated bit is set in bit string.
548 */
549int
550testbit(int bitno, int *s)
551{
cb323159 552 return s[bitno / INT_SIZE] & (1U << (bitno % INT_SIZE));
5ba3f43e
A
553}
554
555/*
556 * Find first bit set in bit string.
557 */
558int
559ffsbit(int *s)
560{
561 int offset;
562
0a7de745
A
563 for (offset = 0; !*s; offset += INT_SIZE, ++s) {
564 ;
565 }
5ba3f43e
A
566 return offset + __builtin_ctz(*s);
567}
568
569int
570ffs(unsigned int mask)
571{
0a7de745 572 if (mask == 0) {
5ba3f43e 573 return 0;
0a7de745 574 }
5ba3f43e
A
575
576 /*
577 * NOTE: cannot use __builtin_ffs because it generates a call to
578 * 'ffs'
579 */
580 return 1 + __builtin_ctz(mask);
581}
582
583int
584ffsll(unsigned long long mask)
585{
0a7de745 586 if (mask == 0) {
5ba3f43e 587 return 0;
0a7de745 588 }
5ba3f43e
A
589
590 /*
591 * NOTE: cannot use __builtin_ffsll because it generates a call to
592 * 'ffsll'
593 */
594 return 1 + __builtin_ctzll(mask);
595}
596
597/*
598 * Find last bit set in bit string.
599 */
600int
601fls(unsigned int mask)
602{
0a7de745 603 if (mask == 0) {
5ba3f43e 604 return 0;
0a7de745 605 }
5ba3f43e 606
0a7de745 607 return (sizeof(mask) << 3) - __builtin_clz(mask);
5ba3f43e
A
608}
609
610int
611flsll(unsigned long long mask)
612{
0a7de745 613 if (mask == 0) {
5ba3f43e 614 return 0;
0a7de745 615 }
5ba3f43e 616
0a7de745 617 return (sizeof(mask) << 3) - __builtin_clzll(mask);
5ba3f43e
A
618}
619
620#undef bcmp
0a7de745 621int
5ba3f43e 622bcmp(
0a7de745
A
623 const void *pa,
624 const void *pb,
625 size_t len)
5ba3f43e
A
626{
627 const char *a = (const char *) pa;
628 const char *b = (const char *) pb;
629
0a7de745 630 if (len == 0) {
5ba3f43e 631 return 0;
0a7de745 632 }
5ba3f43e 633
0a7de745
A
634 do{
635 if (*a++ != *b++) {
5ba3f43e 636 break;
0a7de745
A
637 }
638 } while (--len);
5ba3f43e
A
639
640 /*
641 * Check for the overflow case but continue to handle the non-overflow
642 * case the same way just in case someone is using the return value
643 * as more than zero/non-zero
644 */
0a7de745 645 if ((len & 0xFFFFFFFF00000000ULL) && !(len & 0x00000000FFFFFFFFULL)) {
5ba3f43e 646 return 0xFFFFFFFFL;
0a7de745 647 } else {
5ba3f43e 648 return (int)len;
0a7de745 649 }
5ba3f43e
A
650}
651
652#undef memcmp
653int
654memcmp(const void *s1, const void *s2, size_t n)
655{
656 if (n != 0) {
657 const unsigned char *p1 = s1, *p2 = s2;
658
659 do {
0a7de745
A
660 if (*p1++ != *p2++) {
661 return *--p1 - *--p2;
662 }
5ba3f43e
A
663 } while (--n != 0);
664 }
0a7de745 665 return 0;
5ba3f43e
A
666}
667
668kern_return_t
669copypv(addr64_t source, addr64_t sink, unsigned int size, int which)
670{
0a7de745 671 if ((which & (cppvPsrc | cppvPsnk)) == 0) { /* Make sure that only one is virtual */
d9a64523 672 panic("%s: no more than 1 parameter may be virtual", __func__);
0a7de745 673 }
5ba3f43e 674
d9a64523 675 kern_return_t res = bcopy_phys_internal(source, sink, size, which);
5ba3f43e 676
d9a64523 677#ifndef __ARM_COHERENT_IO__
0a7de745
A
678 if (which & cppvFsrc) {
679 flush_dcache64(source, size, ((which & cppvPsrc) == cppvPsrc));
680 }
d9a64523 681
0a7de745
A
682 if (which & cppvFsnk) {
683 flush_dcache64(sink, size, ((which & cppvPsnk) == cppvPsnk));
684 }
5ba3f43e 685#endif
5ba3f43e 686
d9a64523
A
687 return res;
688}
5ba3f43e
A
689
690#if MACH_ASSERT
691
692extern int copyinframe(vm_address_t fp, char *frame, boolean_t is64bit);
693
694/*
695 * Machine-dependent routine to fill in an array with up to callstack_max
696 * levels of return pc information.
697 */
698void
699machine_callstack(
0a7de745
A
700 uintptr_t * buf,
701 vm_size_t callstack_max)
5ba3f43e
A
702{
703 /* Captures the USER call stack */
0a7de745 704 uint32_t i = 0;
5ba3f43e
A
705
706 struct arm_saved_state *state = find_user_regs(current_thread());
707
708 if (!state) {
0a7de745 709 while (i < callstack_max) {
5ba3f43e 710 buf[i++] = 0;
0a7de745 711 }
5ba3f43e
A
712 } else {
713 if (is_saved_state64(state)) {
714 uint64_t frame[2];
715 buf[i++] = (uintptr_t)get_saved_state_pc(state);
716 frame[0] = get_saved_state_fp(state);
0a7de745
A
717 while (i < callstack_max && frame[0] != 0) {
718 if (copyinframe(frame[0], (void*) frame, TRUE)) {
5ba3f43e 719 break;
0a7de745 720 }
5ba3f43e
A
721 buf[i++] = (uintptr_t)frame[1];
722 }
0a7de745 723 } else {
5ba3f43e
A
724 uint32_t frame[2];
725 buf[i++] = (uintptr_t)get_saved_state_pc(state);
726 frame[0] = (uint32_t)get_saved_state_fp(state);
0a7de745
A
727 while (i < callstack_max && frame[0] != 0) {
728 if (copyinframe(frame[0], (void*) frame, FALSE)) {
5ba3f43e 729 break;
0a7de745 730 }
5ba3f43e
A
731 buf[i++] = (uintptr_t)frame[1];
732 }
733 }
734
0a7de745 735 while (i < callstack_max) {
5ba3f43e 736 buf[i++] = 0;
0a7de745 737 }
5ba3f43e
A
738 }
739}
740
0a7de745 741#endif /* MACH_ASSERT */
5ba3f43e
A
742
743int
744clr_be_bit(void)
745{
746 panic("clr_be_bit");
747 return 0;
748}
749
750boolean_t
751ml_probe_read(
0a7de745
A
752 __unused vm_offset_t paddr,
753 __unused unsigned int *val)
5ba3f43e
A
754{
755 panic("ml_probe_read() unimplemented");
756 return 1;
757}
758
759boolean_t
760ml_probe_read_64(
0a7de745
A
761 __unused addr64_t paddr,
762 __unused unsigned int *val)
5ba3f43e
A
763{
764 panic("ml_probe_read_64() unimplemented");
765 return 1;
766}
767
768
769void
770ml_thread_policy(
0a7de745
A
771 __unused thread_t thread,
772 __unused unsigned policy_id,
773 __unused unsigned policy_info)
5ba3f43e 774{
0a7de745
A
775 // <rdar://problem/7141284>: Reduce print noise
776 // kprintf("ml_thread_policy() unimplemented\n");
5ba3f43e
A
777}
778
cb323159 779__dead2
5ba3f43e 780void
cb323159 781panic_unimplemented(void)
5ba3f43e
A
782{
783 panic("Not yet implemented.");
784}
785
786/* ARM64_TODO <rdar://problem/9198953> */
cb323159 787void abort(void) __dead2;
5ba3f43e
A
788
789void
cb323159 790abort(void)
5ba3f43e
A
791{
792 panic("Abort.");
793}
794
795
796#if !MACH_KDP
797void
798kdp_register_callout(kdp_callout_fn_t fn, void *arg)
799{
800#pragma unused(fn,arg)
801}
802#endif