]> git.saurik.com Git - apple/xnu.git/blobdiff - osfmk/i386/cpu_threads.c
xnu-1699.22.73.tar.gz
[apple/xnu.git] / osfmk / i386 / cpu_threads.c
index 7727eb7eac654bb9bf8482457ce7c4c6bba88bf6..b92a796e9e6e18138f81cbbc1163a6131d231359 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003-2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2003-2010 Apple Inc. All rights reserved.
  *
  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
  * 
  */
 #include <vm/vm_kern.h>
 #include <kern/kalloc.h>
+#include <kern/etimer.h>
 #include <mach/machine.h>
 #include <i386/cpu_threads.h>
 #include <i386/cpuid.h>
 #include <i386/machine_cpu.h>
-#include <i386/lock.h>
-#include <i386/perfmon.h>
 #include <i386/pmCPU.h>
+#include <i386/lock.h>
 
 //#define TOPO_DEBUG           1
 #if TOPO_DEBUG
@@ -43,6 +43,11 @@ void debug_topology_print(void);
 #define DBG(x...)
 #endif /* TOPO_DEBUG */
 
+
+void validate_topology(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)
 
@@ -176,7 +181,8 @@ x86_LLC_info(void)
      */
     topoParms.maxSharingLLC = nCPUsSharing;
 
-    topoParms.nCoresSharingLLC = nCPUsSharing;
+    topoParms.nCoresSharingLLC = nCPUsSharing / (cpuinfo->thread_count /
+                                                cpuinfo->core_count);
     topoParms.nLCPUsSharingLLC = nCPUsSharing;
 
     /*
@@ -187,10 +193,6 @@ x86_LLC_info(void)
        topoParms.nCoresSharingLLC = cpuinfo->core_count;
     if (nCPUsSharing > cpuinfo->thread_count)
        topoParms.nLCPUsSharingLLC = cpuinfo->thread_count;
-
-
-    if (nCPUsSharing > cpuinfo->thread_count)
-       topoParms.maxSharingLLC = cpuinfo->thread_count;
 }
 
 static void
@@ -198,6 +200,8 @@ initTopoParms(void)
 {
     i386_cpu_info_t    *cpuinfo;
 
+    topoParms.stable = FALSE;
+
     cpuinfo = cpuid_info();
 
     /*
@@ -241,6 +245,12 @@ 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);
@@ -316,6 +326,9 @@ x86_cache_list(void)
 
        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;
@@ -342,7 +355,7 @@ static x86_cpu_cache_t *
 x86_match_cache(x86_cpu_cache_t *list, x86_cpu_cache_t *matcher)
 {
     x86_cpu_cache_t    *cur_cache;
-
     cur_cache = list;
     while (cur_cache != NULL) {
        if (cur_cache->maxcpus  == matcher->maxcpus
@@ -863,13 +876,6 @@ cpu_thread_alloc(int cpu)
 
     x86_lcpu_init(cpu);
 
-     /*
-     * Allocate performance counter structure.
-     */
-    simple_unlock(&x86_topo_lock);
-    cpup->lcpu.pmc = pmc_alloc();
-    simple_lock(&x86_topo_lock);
-
     /*
      * Assume that all cpus have the same features.
      */
@@ -1039,6 +1045,180 @@ cpu_thread_halt(void)
     /* NOT REACHED */
 }
 
+/*
+ * Validates that the topology was built correctly.  Must be called only
+ * after the complete topology is built and no other changes are being made.
+ */
+void
+validate_topology(void)
+{
+    x86_pkg_t          *pkg;
+    x86_die_t          *die;
+    x86_core_t         *core;
+    x86_lcpu_t         *lcpu;
+    uint32_t           nDies;
+    uint32_t           nCores;
+    uint32_t           nCPUs;
+
+    /*
+     * XXX
+     *
+     * Right now this only works if the number of CPUs started is the total
+     * number of CPUs.  However, when specifying cpus=n the topology is only
+     * partially constructed and the checks below will fail.
+     *
+     * We should *always* build the complete topology and only start the CPUs
+     * indicated by cpus=n.  Until that happens, this code will not check the
+     * topology if the number of cpus defined is < that described the the
+     * topology parameters.
+     */
+    nCPUs = topoParms.nPackages * topoParms.nLThreadsPerPackage;
+    if (nCPUs > real_ncpus)
+       return;
+
+    pkg = x86_pkgs;
+    while (pkg != NULL) {
+       /*
+        * Make sure that the package has the correct number of dies.
+        */
+       nDies = 0;
+       die = pkg->dies;
+       while (die != NULL) {
+           if (die->package == NULL)
+               panic("Die(%d)->package is NULL",
+                     die->pdie_num);
+           if (die->package != pkg)
+               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",
+               die->pdie_num, pkg->lpkg_num);
+
+           /*
+            * Make sure that the die has the correct number of cores.
+            */
+           DBG("Die(%d)->cores: ", die->pdie_num);
+           nCores = 0;
+           core = die->cores;
+           while (core != NULL) {
+               if (core->die == NULL)
+                   panic("Core(%d)->die is NULL",
+                         core->pcore_num);
+               if (core->die != die)
+                   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);
+               core = core->next_in_die;
+           }
+           DBG("\n");
+
+           if (nCores != topoParms.nLCoresPerDie)
+               panic("Should have %d Cores, but only found %d for Die %d",
+                     topoParms.nLCoresPerDie, nCores, die->pdie_num);
+
+           /*
+            * Make sure that the die has the correct number of CPUs.
+            */
+           DBG("Die(%d)->lcpus: ", die->pdie_num);
+           nCPUs = 0;
+           lcpu = die->lcpus;
+           while (lcpu != NULL) {
+               if (lcpu->die == NULL)
+                   panic("CPU(%d)->die is NULL",
+                         lcpu->cpu_num);
+               if (lcpu->die != die)
+                   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);
+               lcpu = lcpu->next_in_die;
+           }
+           DBG("\n");
+
+           if (nCPUs != topoParms.nLThreadsPerDie)
+               panic("Should have %d Threads, but only found %d for Die %d",
+                     topoParms.nLThreadsPerDie, nCPUs, die->pdie_num);
+
+           nDies += 1;
+           die = die->next_in_pkg;
+       }
+
+       if (nDies != topoParms.nLDiesPerPackage)
+           panic("Should have %d Dies, but only found %d for package %d",
+                 topoParms.nLDiesPerPackage, nDies, pkg->lpkg_num);
+
+       /*
+        * Make sure that the package has the correct number of cores.
+        */
+       nCores = 0;
+       core = pkg->cores;
+       while (core != NULL) {
+           if (core->package == NULL)
+               panic("Core(%d)->package is NULL",
+                     core->pcore_num);
+           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",
+               core->pcore_num, pkg->lpkg_num);
+
+           /*
+            * Make sure that the core has the correct number of CPUs.
+            */
+           nCPUs = 0;
+           lcpu = core->lcpus;
+           DBG("Core(%d)->lcpus: ", core->pcore_num);
+           while (lcpu != NULL) {
+               if (lcpu->core == NULL)
+                   panic("CPU(%d)->core is NULL",
+                         lcpu->cpu_num);
+               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);
+               nCPUs += 1;
+               lcpu = lcpu->next_in_core;
+           }
+           DBG("\n");
+
+           if (nCPUs != topoParms.nLThreadsPerCore)
+               panic("Should have %d Threads, but only found %d for Core %d",
+                     topoParms.nLThreadsPerCore, nCPUs, core->pcore_num);
+           nCores += 1;
+           core = core->next_in_pkg;
+       }
+
+       if (nCores != topoParms.nLCoresPerPackage)
+           panic("Should have %d Cores, but only found %d for package %d",
+                 topoParms.nLCoresPerPackage, nCores, pkg->lpkg_num);
+
+       /*
+        * Make sure that the package has the correct number of CPUs.
+        */
+       nCPUs = 0;
+       lcpu = pkg->lcpus;
+       while (lcpu != NULL) {
+           if (lcpu->package == NULL)
+               panic("CPU(%d)->package is NULL",
+                     lcpu->cpu_num);
+           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",
+               lcpu->cpu_num, pkg->lpkg_num);
+           nCPUs += 1;
+           lcpu = lcpu->next_in_pkg;
+       }
+
+       if (nCPUs != topoParms.nLThreadsPerPackage)
+           panic("Should have %d Threads, but only found %d for package %d",
+                 topoParms.nLThreadsPerPackage, nCPUs, pkg->lpkg_num);
+
+       pkg = pkg->next;
+    }
+}
+
 #if TOPO_DEBUG
 /*
  * Prints out the topology