]> git.saurik.com Git - apple/xnu.git/blobdiff - osfmk/i386/cpu_threads.c
xnu-2050.48.11.tar.gz
[apple/xnu.git] / osfmk / i386 / cpu_threads.c
index b92a796e9e6e18138f81cbbc1163a6131d231359..c36eb89b6def29ccb5dd0de4c247d2f95d212bb1 100644 (file)
 #include <i386/pmCPU.h>
 #include <i386/lock.h>
 
-//#define TOPO_DEBUG           1
-#if TOPO_DEBUG
-void debug_topology_print(void);
-#define DBG(x...)      kprintf("DBG: " x)
-#else
-#define DBG(x...)
-#endif /* TOPO_DEBUG */
-
+#define DIVISOR_GUARD(denom)                           \
+       if ((denom) == 0) {                             \
+               kprintf("%s: %d Zero divisor: " #denom, \
+                       __FILE__, __LINE__);            \
+       }
 
-void validate_topology(void);
+static void debug_topology_print(void);
 
-/* Only for 32bit values */
-#define bit(n)                 (1U << (n))
-#define bitmask(h,l)   ((bit(h)|(bit(h)-1)) & ~(bit(l)-1))
-#define bitfield(x,h,l)        (((x) & bitmask(h,l)) >> l)
+boolean_t      topo_dbg = FALSE;
 
 x86_pkg_t      *x86_pkgs               = NULL;
 uint32_t       num_Lx_caches[MAX_CACHE_DEPTH]  = { 0 };
@@ -67,6 +61,15 @@ x86_topology_parameters_t    topoParms;
 
 decl_simple_lock_data(, x86_topo_lock);
  
+static struct cpu_cache {
+       int     level;  int     type;
+} cpu_caches [LCACHE_MAX] = {
+       [L1D] = {       1,      CPU_CACHE_TYPE_DATA },
+       [L1I] = {       1,      CPU_CACHE_TYPE_INST },
+       [L2U] = { 2,    CPU_CACHE_TYPE_UNIF },
+       [L3U] = { 3,    CPU_CACHE_TYPE_UNIF },
+};
+
 static boolean_t
 cpu_is_hyperthreaded(void)
 {
@@ -107,66 +110,30 @@ x86_cache_alloc(void)
 static void
 x86_LLC_info(void)
 {
-    uint32_t           index;
-    uint32_t           cache_info[4];
-    uint32_t           cache_level     = 0;
+    int                        cache_level     = 0;
     uint32_t           nCPUsSharing    = 1;
     i386_cpu_info_t    *cpuinfo;
+    struct cpu_cache   *cachep;
+    int                        i;
 
     cpuinfo = cpuid_info();
 
-    do_cpuid(0, cache_info);
-
-    if (cache_info[eax] < 4) {
-       /*
-        * Processor does not support deterministic
-        * cache information. Set LLC sharing to 1, since
-        * we have no better information.
-        */
-       if (cpu_is_hyperthreaded()) {
-           topoParms.nCoresSharingLLC = 1;
-           topoParms.nLCPUsSharingLLC = 2;
-           topoParms.maxSharingLLC = 2;
-       } else {
-           topoParms.nCoresSharingLLC = 1;
-           topoParms.nLCPUsSharingLLC = 1;
-           topoParms.maxSharingLLC = 1;
-       }
-       return;
-    }
-
-    for (index = 0; ; index += 1) {
-       uint32_t                this_level;
-
-       cache_info[eax] = 4;
-       cache_info[ecx] = index;
-       cache_info[ebx] = 0;
-       cache_info[edx] = 0;
-
-       cpuid(cache_info);
+    for (i = 0, cachep = &cpu_caches[0]; i < LCACHE_MAX; i++, cachep++) {
 
-       /*
-        * See if all levels have been queried.
-        */
-       if (bitfield(cache_info[eax], 4, 0) == 0)
-           break;
-
-       /*
-        * Get the current level.
-        */
-       this_level = bitfield(cache_info[eax], 7, 5);
+       if (cachep->type == 0 || cpuid_info()->cache_size[i] == 0)
+           continue;
 
        /*
         * Only worry about it if it's a deeper level than
         * what we've seen before.
         */
-       if (this_level > cache_level) {
-           cache_level = this_level;
+       if (cachep->level > cache_level) {
+           cache_level = cachep->level;
 
            /*
             * Save the number of CPUs sharing this cache.
             */
-           nCPUsSharing = bitfield(cache_info[eax], 25, 14) + 1;
+           nCPUsSharing = cpuinfo->cache_sharing[i];
        }
     }
 
@@ -204,6 +171,8 @@ initTopoParms(void)
 
     cpuinfo = cpuid_info();
 
+    PE_parse_boot_argn("-topo", &topo_dbg, sizeof(topo_dbg));
+
     /*
      * We need to start with getting the LLC information correct.
      */
@@ -212,15 +181,21 @@ initTopoParms(void)
     /*
      * Compute the number of threads (logical CPUs) per core.
      */
+    DIVISOR_GUARD(cpuinfo->core_count);
     topoParms.nLThreadsPerCore = cpuinfo->thread_count / cpuinfo->core_count;
+    DIVISOR_GUARD(cpuinfo->cpuid_cores_per_package);
     topoParms.nPThreadsPerCore = cpuinfo->cpuid_logical_per_package / cpuinfo->cpuid_cores_per_package;
 
     /*
      * Compute the number of dies per package.
      */
+     DIVISOR_GUARD(topoParms.nCoresSharingLLC);
     topoParms.nLDiesPerPackage = cpuinfo->core_count / topoParms.nCoresSharingLLC;
+    DIVISOR_GUARD(topoParms.nPThreadsPerCore);
+    DIVISOR_GUARD(topoParms.maxSharingLLC / topoParms.nPThreadsPerCore);
     topoParms.nPDiesPerPackage = cpuinfo->cpuid_cores_per_package / (topoParms.maxSharingLLC / topoParms.nPThreadsPerCore);
 
+
     /*
      * Compute the number of cores per die.
      */
@@ -245,27 +220,27 @@ initTopoParms(void)
     topoParms.nLThreadsPerPackage = topoParms.nLThreadsPerCore * topoParms.nLCoresPerPackage;
     topoParms.nPThreadsPerPackage = topoParms.nPThreadsPerCore * topoParms.nPCoresPerPackage;
 
-    DBG("\nCache Topology Parameters:\n");
-    DBG("\tLLC Depth:           %d\n", topoParms.LLCDepth);
-    DBG("\tCores Sharing LLC:   %d\n", topoParms.nCoresSharingLLC);
-    DBG("\tThreads Sharing LLC: %d\n", topoParms.nLCPUsSharingLLC);
-    DBG("\tmax Sharing of LLC:  %d\n", topoParms.maxSharingLLC);
-
-    DBG("\nLogical Topology Parameters:\n");
-    DBG("\tThreads per Core:  %d\n", topoParms.nLThreadsPerCore);
-    DBG("\tCores per Die:     %d\n", topoParms.nLCoresPerDie);
-    DBG("\tThreads per Die:   %d\n", topoParms.nLThreadsPerDie);
-    DBG("\tDies per Package:  %d\n", topoParms.nLDiesPerPackage);
-    DBG("\tCores per Package: %d\n", topoParms.nLCoresPerPackage);
-    DBG("\tThreads per Package: %d\n", topoParms.nLThreadsPerPackage);
-
-    DBG("\nPhysical Topology Parameters:\n");
-    DBG("\tThreads per Core: %d\n", topoParms.nPThreadsPerCore);
-    DBG("\tCores per Die:     %d\n", topoParms.nPCoresPerDie);
-    DBG("\tThreads per Die:   %d\n", topoParms.nPThreadsPerDie);
-    DBG("\tDies per Package:  %d\n", topoParms.nPDiesPerPackage);
-    DBG("\tCores per Package: %d\n", topoParms.nPCoresPerPackage);
-    DBG("\tThreads per Package: %d\n", topoParms.nPThreadsPerPackage);
+    TOPO_DBG("\nCache Topology Parameters:\n");
+    TOPO_DBG("\tLLC Depth:           %d\n", topoParms.LLCDepth);
+    TOPO_DBG("\tCores Sharing LLC:   %d\n", topoParms.nCoresSharingLLC);
+    TOPO_DBG("\tThreads Sharing LLC: %d\n", topoParms.nLCPUsSharingLLC);
+    TOPO_DBG("\tmax Sharing of LLC:  %d\n", topoParms.maxSharingLLC);
+
+    TOPO_DBG("\nLogical Topology Parameters:\n");
+    TOPO_DBG("\tThreads per Core:  %d\n", topoParms.nLThreadsPerCore);
+    TOPO_DBG("\tCores per Die:     %d\n", topoParms.nLCoresPerDie);
+    TOPO_DBG("\tThreads per Die:   %d\n", topoParms.nLThreadsPerDie);
+    TOPO_DBG("\tDies per Package:  %d\n", topoParms.nLDiesPerPackage);
+    TOPO_DBG("\tCores per Package: %d\n", topoParms.nLCoresPerPackage);
+    TOPO_DBG("\tThreads per Package: %d\n", topoParms.nLThreadsPerPackage);
+
+    TOPO_DBG("\nPhysical Topology Parameters:\n");
+    TOPO_DBG("\tThreads per Core: %d\n", topoParms.nPThreadsPerCore);
+    TOPO_DBG("\tCores per Die:     %d\n", topoParms.nPCoresPerDie);
+    TOPO_DBG("\tThreads per Die:   %d\n", topoParms.nPThreadsPerDie);
+    TOPO_DBG("\tDies per Package:  %d\n", topoParms.nPDiesPerPackage);
+    TOPO_DBG("\tCores per Package: %d\n", topoParms.nPCoresPerPackage);
+    TOPO_DBG("\tThreads per Package: %d\n", topoParms.nPThreadsPerPackage);
 
     topoParmsInited = TRUE;
 }
@@ -291,50 +266,29 @@ x86_cache_list(void)
     x86_cpu_cache_t    *root   = NULL;
     x86_cpu_cache_t    *cur    = NULL;
     x86_cpu_cache_t    *last   = NULL;
-    uint32_t           index;
-    uint32_t           cache_info[4];
-    uint32_t           nsets;
-
-    do_cpuid(0, cache_info);
-
-    if (cache_info[eax] < 4) {
-       /*
-        * Processor does not support deterministic
-        * cache information. Don't report anything
-        */
-       return NULL;
-    }
-
-    for (index = 0; ; index += 1) {
-       cache_info[eax] = 4;
-       cache_info[ecx] = index;
-       cache_info[ebx] = 0;
-       cache_info[edx] = 0;
-
-       cpuid(cache_info);
+    struct cpu_cache   *cachep;
+    int                        i;
 
-       /*
-        * See if all levels have been queried.
-        */
-       if (bitfield(cache_info[eax], 4, 0) == 0)
-           break;
+    /*
+     * Cons up a list driven not by CPUID leaf 4 (deterministic cache params)
+     * but by the table above plus parameters already cracked from cpuid...
+     */
+    for (i = 0, cachep = &cpu_caches[0]; i < LCACHE_MAX; i++, cachep++) {
 
+       if (cachep->type == 0 || cpuid_info()->cache_size[i] == 0)
+           continue;
+       
        cur = x86_cache_alloc();
-       if (cur == NULL) {
+       if (cur == NULL)
            break;
-       }
 
-       cur->type = bitfield(cache_info[eax], 4, 0);
-       cur->level = bitfield(cache_info[eax], 7, 5);
-       cur->nlcpus = (bitfield(cache_info[eax], 25, 14) + 1);
-       if (cpuid_info()->cpuid_model == 26)
-               cur->nlcpus /= cpu_is_hyperthreaded() ? 1 : 2;
-       cur->maxcpus = (bitfield(cache_info[eax], 25, 14) + 1);
-       cur->line_size = bitfield(cache_info[ebx], 11, 0) + 1;
-       cur->partitions = bitfield(cache_info[ebx], 21, 12) + 1;
-       cur->ways = bitfield(cache_info[ebx], 31, 22) + 1;
-       nsets = bitfield(cache_info[ecx], 31, 0) + 1;
-       cur->cache_size = cur->line_size * cur->ways * cur->partitions * nsets;
+       cur->type       = cachep->type;
+       cur->level      = cachep->level;
+       cur->nlcpus     = 0;
+       cur->maxcpus    = cpuid_info()->cache_sharing[i];
+       cur->partitions = cpuid_info()->cache_partitions[i];
+       cur->cache_size = cpuid_info()->cache_size[i];
+       cur->line_size  = cpuid_info()->cache_linesize;
 
        if (last == NULL) {
            root = cur;
@@ -343,14 +297,12 @@ x86_cache_list(void)
            last->next = cur;
            last = cur;
        }
-
-       cur->nlcpus = 0;
        num_Lx_caches[cur->level - 1] += 1;
     }
-
-    return(root);
+    return root;
 }
 
+
 static x86_cpu_cache_t *
 x86_match_cache(x86_cpu_cache_t *list, x86_cpu_cache_t *matcher)
 {
@@ -361,7 +313,6 @@ x86_match_cache(x86_cpu_cache_t *list, x86_cpu_cache_t *matcher)
        if (cur_cache->maxcpus  == matcher->maxcpus
            && cur_cache->type  == matcher->type
            && cur_cache->level == matcher->level
-           && cur_cache->ways  == matcher->ways
            && cur_cache->partitions == matcher->partitions
            && cur_cache->line_size  == matcher->line_size
            && cur_cache->cache_size == matcher->cache_size)
@@ -1060,6 +1011,9 @@ validate_topology(void)
     uint32_t           nCores;
     uint32_t           nCPUs;
 
+    if (topo_dbg)
+       debug_topology_print();
+
     /*
      * XXX
      *
@@ -1091,13 +1045,13 @@ validate_topology(void)
                panic("Die %d points to package %d, should be %d",
                      die->pdie_num, die->package->lpkg_num, pkg->lpkg_num);
 
-           DBG("Die(%d)->package %d\n",
+           TOPO_DBG("Die(%d)->package %d\n",
                die->pdie_num, pkg->lpkg_num);
 
            /*
             * Make sure that the die has the correct number of cores.
             */
-           DBG("Die(%d)->cores: ", die->pdie_num);
+           TOPO_DBG("Die(%d)->cores: ", die->pdie_num);
            nCores = 0;
            core = die->cores;
            while (core != NULL) {
@@ -1108,10 +1062,10 @@ validate_topology(void)
                    panic("Core %d points to die %d, should be %d",
                          core->pcore_num, core->die->pdie_num, die->pdie_num);
                nCores += 1;
-               DBG("%d ", core->pcore_num);
+               TOPO_DBG("%d ", core->pcore_num);
                core = core->next_in_die;
            }
-           DBG("\n");
+           TOPO_DBG("\n");
 
            if (nCores != topoParms.nLCoresPerDie)
                panic("Should have %d Cores, but only found %d for Die %d",
@@ -1120,7 +1074,7 @@ validate_topology(void)
            /*
             * Make sure that the die has the correct number of CPUs.
             */
-           DBG("Die(%d)->lcpus: ", die->pdie_num);
+           TOPO_DBG("Die(%d)->lcpus: ", die->pdie_num);
            nCPUs = 0;
            lcpu = die->lcpus;
            while (lcpu != NULL) {
@@ -1131,10 +1085,10 @@ validate_topology(void)
                    panic("CPU %d points to die %d, should be %d",
                          lcpu->cpu_num, lcpu->die->pdie_num, die->pdie_num);
                nCPUs += 1;
-               DBG("%d ", lcpu->cpu_num);
+               TOPO_DBG("%d ", lcpu->cpu_num);
                lcpu = lcpu->next_in_die;
            }
-           DBG("\n");
+           TOPO_DBG("\n");
 
            if (nCPUs != topoParms.nLThreadsPerDie)
                panic("Should have %d Threads, but only found %d for Die %d",
@@ -1160,7 +1114,7 @@ validate_topology(void)
            if (core->package != pkg)
                panic("Core %d points to package %d, should be %d",
                      core->pcore_num, core->package->lpkg_num, pkg->lpkg_num);
-           DBG("Core(%d)->package %d\n",
+           TOPO_DBG("Core(%d)->package %d\n",
                core->pcore_num, pkg->lpkg_num);
 
            /*
@@ -1168,7 +1122,7 @@ validate_topology(void)
             */
            nCPUs = 0;
            lcpu = core->lcpus;
-           DBG("Core(%d)->lcpus: ", core->pcore_num);
+           TOPO_DBG("Core(%d)->lcpus: ", core->pcore_num);
            while (lcpu != NULL) {
                if (lcpu->core == NULL)
                    panic("CPU(%d)->core is NULL",
@@ -1176,11 +1130,11 @@ validate_topology(void)
                if (lcpu->core != core)
                    panic("CPU %d points to core %d, should be %d",
                          lcpu->cpu_num, lcpu->core->pcore_num, core->pcore_num);
-               DBG("%d ", lcpu->cpu_num);
+               TOPO_DBG("%d ", lcpu->cpu_num);
                nCPUs += 1;
                lcpu = lcpu->next_in_core;
            }
-           DBG("\n");
+           TOPO_DBG("\n");
 
            if (nCPUs != topoParms.nLThreadsPerCore)
                panic("Should have %d Threads, but only found %d for Core %d",
@@ -1205,7 +1159,7 @@ validate_topology(void)
            if (lcpu->package != pkg)
                panic("CPU %d points to package %d, should be %d",
                      lcpu->cpu_num, lcpu->package->lpkg_num, pkg->lpkg_num);
-           DBG("CPU(%d)->package %d\n",
+           TOPO_DBG("CPU(%d)->package %d\n",
                lcpu->cpu_num, pkg->lpkg_num);
            nCPUs += 1;
            lcpu = lcpu->next_in_pkg;
@@ -1219,11 +1173,10 @@ validate_topology(void)
     }
 }
 
-#if TOPO_DEBUG
 /*
  * Prints out the topology
  */
-void
+static void
 debug_topology_print(void)
 {
     x86_pkg_t          *pkg;
@@ -1276,4 +1229,3 @@ debug_topology_print(void)
        pkg = pkg->next;
     }
 }
-#endif /* TOPO_DEBUG */