]> git.saurik.com Git - apple/xnu.git/blobdiff - osfmk/x86_64/loose_ends.c
xnu-3789.60.24.tar.gz
[apple/xnu.git] / osfmk / x86_64 / loose_ends.c
index 3d75d8eab4573081aaea2ad4c706d8297e7e3fad..0736226fbb6814dac438f5be4e3e91ab11f1e3bf 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000-2006 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2000-2013 Apple Inc. All rights reserved.
  *
  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
  * 
 #include <libkern/OSAtomic.h>
 #include <sys/kdebug.h>
 
+#if !MACH_KDP
+#include <kdp/kdp_callout.h>
+#endif /* !MACH_KDP */
+
+#include <libkern/OSDebug.h>
+#if CONFIG_DTRACE
+#include <mach/sdt.h>
+#endif
+
 #if 0
 
 #undef KERNEL_DEBUG
@@ -98,7 +107,7 @@ extern void          mapping_set_ref(ppnum_t pn);
 extern void            ovbcopy(const char      *from,
                                char            *to,
                                vm_size_t       nbytes);
-void machine_callstack(natural_t *buf, vm_size_t callstack_max);
+void machine_callstack(uintptr_t *buf, vm_size_t callstack_max);
 
 
 #define value_64bit(value)  ((value) & 0xFFFFFFFF00000000ULL)
@@ -242,76 +251,117 @@ ovbcopy(
  *  Read data from a physical address. Memory should not be cache inhibited.
  */
 
+uint64_t reportphyreaddelayabs;
+uint32_t reportphyreadosbt;
+#if DEVELOPMENT || DEBUG
+uint32_t phyreadpanic = 1;
+#else
+uint32_t phyreadpanic = 0;
+#endif
 
-static inline unsigned int
-ml_phys_read_data(pmap_paddr_t paddr, int size)
-{
-       unsigned int result;
+__private_extern__ uint64_t
+ml_phys_read_data(pmap_paddr_t paddr, int size) {
+       uint64_t result = 0;
+       unsigned char s1;
+       unsigned short s2;
+       boolean_t istate, timeread = FALSE;
+       uint64_t sabs, eabs;
+
+       if (__improbable(!physmap_enclosed(paddr)))
+               panic("%s: 0x%llx out of bounds\n", __FUNCTION__, paddr);
+
+       if (__improbable(reportphyreaddelayabs != 0)) {
+               istate = ml_set_interrupts_enabled(FALSE);
+               sabs = mach_absolute_time();
+               timeread = TRUE;
+       }
 
         switch (size) {
-            unsigned char s1;
-            unsigned short s2;
         case 1:
-            s1 = *(unsigned char *)PHYSMAP_PTOV(paddr);
-            result = s1;
-            break;
+               s1 = *(volatile unsigned char *)PHYSMAP_PTOV(paddr);
+               result = s1;
+               break;
         case 2:
-            s2 = *(unsigned short *)PHYSMAP_PTOV(paddr);
-            result = s2;
-            break;
+               s2 = *(volatile unsigned short *)PHYSMAP_PTOV(paddr);
+               result = s2;
+               break;
         case 4:
-        default:
-            result = *(unsigned int *)PHYSMAP_PTOV(paddr);
-            break;
+               result = *(volatile unsigned int *)PHYSMAP_PTOV(paddr);
+               break;
+       case 8:
+               result = *(volatile unsigned long long *)PHYSMAP_PTOV(paddr);
+               break;
+       default:
+               panic("Invalid size %d for ml_phys_read_data\n", size);
+               break;
         }
 
+       if (__improbable(timeread == TRUE)) {
+               eabs = mach_absolute_time();
+               (void)ml_set_interrupts_enabled(istate);
+
+               if (__improbable((eabs - sabs) > reportphyreaddelayabs)) {
+                       if (phyreadpanic) {
+                               panic_io_port_read();
+                               panic("Read from physical addr 0x%llx took %llu ns, result: 0x%llx (start: %llu, end: %llu), ceiling: %llu", paddr, (eabs - sabs), result, sabs, eabs, reportphyreaddelayabs);
+                       }
+
+                       if (reportphyreadosbt) {
+                               OSReportWithBacktrace("ml_phys_read_data took %lluus\n", (eabs - sabs) / 1000);
+                       }
+#if CONFIG_DTRACE
+                       DTRACE_PHYSLAT3(physread, uint64_t, (eabs - sabs),
+                           pmap_paddr_t, paddr, uint32_t, size);
+#endif
+               }
+       }
+
         return result;
 }
 
 static unsigned long long
-ml_phys_read_long_long(pmap_paddr_t paddr )
-{
-       return *(unsigned long long *)PHYSMAP_PTOV(paddr);
+ml_phys_read_long_long(pmap_paddr_t paddr) {
+       return ml_phys_read_data(paddr, 8);
 }
 
 unsigned int ml_phys_read( vm_offset_t paddr)
 {
-        return ml_phys_read_data((pmap_paddr_t)paddr, 4);
+        return (unsigned int) ml_phys_read_data((pmap_paddr_t)paddr, 4);
 }
 
 unsigned int ml_phys_read_word(vm_offset_t paddr) {
 
-        return ml_phys_read_data((pmap_paddr_t)paddr, 4);
+        return (unsigned int) ml_phys_read_data((pmap_paddr_t)paddr, 4);
 }
 
 unsigned int ml_phys_read_64(addr64_t paddr64)
 {
-        return ml_phys_read_data((pmap_paddr_t)paddr64, 4);
+        return (unsigned int) ml_phys_read_data((pmap_paddr_t)paddr64, 4);
 }
 
 unsigned int ml_phys_read_word_64(addr64_t paddr64)
 {
-        return ml_phys_read_data((pmap_paddr_t)paddr64, 4);
+        return (unsigned int) ml_phys_read_data((pmap_paddr_t)paddr64, 4);
 }
 
 unsigned int ml_phys_read_half(vm_offset_t paddr)
 {
-        return ml_phys_read_data((pmap_paddr_t)paddr, 2);
+        return (unsigned int) ml_phys_read_data((pmap_paddr_t)paddr, 2);
 }
 
 unsigned int ml_phys_read_half_64(addr64_t paddr64)
 {
-        return ml_phys_read_data((pmap_paddr_t)paddr64, 2);
+        return (unsigned int) ml_phys_read_data((pmap_paddr_t)paddr64, 2);
 }
 
 unsigned int ml_phys_read_byte(vm_offset_t paddr)
 {
-        return ml_phys_read_data((pmap_paddr_t)paddr, 1);
+        return (unsigned int) ml_phys_read_data((pmap_paddr_t)paddr, 1);
 }
 
 unsigned int ml_phys_read_byte_64(addr64_t paddr64)
 {
-        return ml_phys_read_data((pmap_paddr_t)paddr64, 1);
+        return (unsigned int) ml_phys_read_data((pmap_paddr_t)paddr64, 1);
 }
 
 unsigned long long ml_phys_read_double(vm_offset_t paddr)
@@ -333,24 +383,32 @@ unsigned long long ml_phys_read_double_64(addr64_t paddr64)
 static inline void
 ml_phys_write_data(pmap_paddr_t paddr, unsigned long data, int size)
 {
+       if (!physmap_enclosed(paddr))
+               panic("%s: 0x%llx out of bounds\n", __FUNCTION__, paddr);
+
         switch (size) {
         case 1:
-           *(unsigned char *)PHYSMAP_PTOV(paddr) = (unsigned char)data;
+           *(volatile unsigned char *)PHYSMAP_PTOV(paddr) = (unsigned char)data;
             break;
         case 2:
-           *(unsigned short *)PHYSMAP_PTOV(paddr) = (unsigned short)data;
+           *(volatile unsigned short *)PHYSMAP_PTOV(paddr) = (unsigned short)data;
             break;
         case 4:
-        default:
-           *(unsigned int *)PHYSMAP_PTOV(paddr) = (unsigned int)data;
+           *(volatile unsigned int *)PHYSMAP_PTOV(paddr) = (unsigned int)data;
             break;
+       default:
+               panic("Invalid size %d for ml_phys_write_data\n", size);
+               break;
         }
 }
 
 static void
 ml_phys_write_long_long(pmap_paddr_t paddr, unsigned long long data)
 {
-       *(unsigned long long *)PHYSMAP_PTOV(paddr) = data;
+       if (!physmap_enclosed(paddr))
+               panic("%s: 0x%llx out of bounds\n", __FUNCTION__, paddr);
+
+       *(volatile unsigned long long *)PHYSMAP_PTOV(paddr) = data;
 }
 
 void ml_phys_write_byte(vm_offset_t paddr, unsigned int data)
@@ -408,9 +466,8 @@ void ml_phys_write_double_64(addr64_t paddr64, unsigned long long data)
  *
  *
  *      Read the memory location at physical address paddr.
- *  This is a part of a device probe, so there is a good chance we will
- *  have a machine check here. So we have to be able to handle that.
- *  We assume that machine checks are enabled both in MSR and HIDs
+ * *Does not* recover from machine checks, unlike the PowerPC implementation.
+ * Should probably be deprecated.
  */
 
 boolean_t
@@ -474,6 +531,13 @@ memcmp(const void *s1, const void *s2, size_t n)
        return (0);
 }
 
+void *
+memmove(void *dst, const void *src, size_t ulen)
+{
+       bcopy(src, dst, ulen);
+       return dst;
+}
+
 /*
  * Abstract:
  * strlen returns the number of characters in "string" preceeding
@@ -482,23 +546,15 @@ memcmp(const void *s1, const void *s2, size_t n)
 
 size_t
 strlen(
-       register const char *string)
+       const char *string)
 {
-       register const char *ret = string;
+       const char *ret = string;
 
        while (*string++ != '\0')
                continue;
        return string - 1 - ret;
 }
 
-uint32_t
-hw_compare_and_store(uint32_t oldval, uint32_t newval, volatile uint32_t *dest)
-{
-       return OSCompareAndSwap((UInt32)oldval,
-                               (UInt32)newval,
-                               (volatile UInt32 *)dest);
-}
-
 #if    MACH_ASSERT
 
 /*
@@ -506,7 +562,7 @@ hw_compare_and_store(uint32_t oldval, uint32_t newval, volatile uint32_t *dest)
  * levels of return pc information.
  */
 void machine_callstack(
-       __unused natural_t      *buf,
+       __unused uintptr_t      *buf,
        __unused vm_size_t      callstack_max)
 {
 }
@@ -525,18 +581,6 @@ void fillPage(ppnum_t pa, unsigned int fill)
                *addr++ = fill;
 }
 
-static inline void __sfence(void)
-{
-    __asm__ volatile("sfence");
-}
-static inline void __mfence(void)
-{
-    __asm__ volatile("mfence");
-}
-static inline void __wbinvd(void)
-{
-    __asm__ volatile("wbinvd");
-}
 static inline void __clflush(void *ptr)
 {
        __asm__ volatile("clflush (%0)" : : "r" (ptr));
@@ -547,14 +591,14 @@ void dcache_incoherent_io_store64(addr64_t pa, unsigned int count)
        addr64_t  linesize = cpuid_info()->cache_linesize;
        addr64_t  bound = (pa + count + linesize - 1) & ~(linesize - 1);
 
-       __mfence();
+       mfence();
 
        while (pa < bound) {
                __clflush(PHYSMAP_PTOV(pa));
                pa += linesize;
        }
 
-       __mfence();
+       mfence();
 }
 
 void dcache_incoherent_io_flush64(addr64_t pa, unsigned int count)
@@ -569,14 +613,14 @@ flush_dcache64(addr64_t addr, unsigned count, int phys)
                dcache_incoherent_io_flush64(addr, count);
        }
        else {
-               uint32_t  linesize = cpuid_info()->cache_linesize;
+               uint64_t  linesize = cpuid_info()->cache_linesize;
                addr64_t  bound = (addr + count + linesize -1) & ~(linesize - 1);
-               __mfence();
+               mfence();
                while (addr < bound) {
                        __clflush((void *) (uintptr_t) addr);
                        addr += linesize;
                }
-               __mfence();
+               mfence();
        }
 }
 
@@ -602,15 +646,22 @@ mapping_set_ref(ppnum_t pn)
   pmap_set_reference(pn);
 }
 
+extern i386_cpu_info_t cpuid_cpu_info;
 void
 cache_flush_page_phys(ppnum_t pa)
 {
        boolean_t       istate;
        unsigned char   *cacheline_addr;
-       int             cacheline_size = cpuid_info()->cache_linesize;
-       int             cachelines_to_flush = PAGE_SIZE/cacheline_size;
+       i386_cpu_info_t *cpuid_infop = cpuid_info();
+       int             cacheline_size;
+       int             cachelines_to_flush;
+
+       cacheline_size = cpuid_infop->cache_linesize;
+       if (cacheline_size == 0)
+               panic("cacheline_size=0 cpuid_infop=%p\n", cpuid_infop);
+       cachelines_to_flush = PAGE_SIZE/cacheline_size;
 
-       __mfence();
+       mfence();
 
        istate = ml_set_interrupts_enabled(FALSE);
 
@@ -622,14 +673,15 @@ cache_flush_page_phys(ppnum_t pa)
 
        (void) ml_set_interrupts_enabled(istate);
 
-       __mfence();
+       mfence();
 }
 
 
 #if !MACH_KDP
 void
-kdp_register_callout(void)
+kdp_register_callout(kdp_callout_fn_t fn, void *arg)
 {
+#pragma unused(fn,arg)
 }
 #endif