]> git.saurik.com Git - apple/xnu.git/blobdiff - osfmk/i386/Diagnostics.c
xnu-4903.221.2.tar.gz
[apple/xnu.git] / osfmk / i386 / Diagnostics.c
index 88a86c31bb816aca08e0a58f5495719b4a561960..90eeb41922c63e687852db2efe8c8f2db790b3fc 100644 (file)
 #include <i386/misc_protos.h>
 #include <i386/cpuid.h>
 
+#if MONOTONIC
+#include <kern/monotonic.h>
+#endif /* MONOTONIC */
+
 #define PERMIT_PERMCHECK (0)
 
 diagWork        dgWork;
@@ -94,6 +98,9 @@ typedef struct {
        uint64_t cpu_insns;
        uint64_t cpu_ucc;
        uint64_t cpu_urc;
+#if    DIAG_ALL_PMCS
+       uint64_t gpmcs[4];
+#endif /* DIAG_ALL_PMCS */
 } core_energy_stat_t;
 
 typedef struct {
@@ -150,6 +157,7 @@ diagCall64(x86_saved_state_t * state)
 
                        lastRuptClear = mach_absolute_time();   /* Get the time of clear */
                        rval = 1;       /* Normal return */
+                       (void) ml_set_interrupts_enabled(FALSE);
                        break;
                }
 
@@ -175,6 +183,7 @@ diagCall64(x86_saved_state_t * state)
                                                                         * slot */
                }
                rval = 1;
+               (void) ml_set_interrupts_enabled(FALSE);
                break;
 
        case dgPowerStat:
@@ -218,7 +227,21 @@ diagCall64(x86_saved_state_t * state)
                rdmsr64_carefully(MSR_IA32_RING_PERF_STATUS, &pkes.ring_ratio_instantaneous);
 
                pkes.IA_frequency_clipping_cause = ~0ULL;
-               rdmsr64_carefully(MSR_IA32_IA_PERF_LIMIT_REASONS, &pkes.IA_frequency_clipping_cause);
+
+               uint32_t ia_perf_limits = MSR_IA32_IA_PERF_LIMIT_REASONS;
+               /* Should perhaps be a generic register map module for these
+                * registers with identical functionality that were renumbered.
+                */
+               switch (cpuid_cpufamily()) {
+               case CPUFAMILY_INTEL_SKYLAKE:
+               case CPUFAMILY_INTEL_KABYLAKE:
+                       ia_perf_limits = MSR_IA32_IA_PERF_LIMIT_REASONS_SKL;
+                       break;
+               default:
+                       break;
+               }
+
+               rdmsr64_carefully(ia_perf_limits, &pkes.IA_frequency_clipping_cause);
 
                pkes.GT_frequency_clipping_cause = ~0ULL;
                rdmsr64_carefully(MSR_IA32_GT_PERF_LIMIT_REASONS, &pkes.GT_frequency_clipping_cause);
@@ -258,16 +281,22 @@ diagCall64(x86_saved_state_t * state)
 
                        cest.citime_total = cpu_data_ptr[i]->cpu_itime_total;
                        cest.crtime_total = cpu_data_ptr[i]->cpu_rtime_total;
-                       cest.cpu_idle_exits = cpu_data_ptr[i]->cpu_idle_exits;
-                       cest.cpu_insns = cpu_data_ptr[i]->cpu_cur_insns;
-                       cest.cpu_ucc = cpu_data_ptr[i]->cpu_cur_ucc;
-                       cest.cpu_urc = cpu_data_ptr[i]->cpu_cur_urc;
-                       (void) ml_set_interrupts_enabled(TRUE);
+                       cest.cpu_idle_exits = cpu_data_ptr[i]->cpu_idle_exits;
+#if MONOTONIC
+                       cest.cpu_insns = cpu_data_ptr[i]->cpu_monotonic.mtc_counts[MT_CORE_INSTRS];
+                       cest.cpu_ucc = cpu_data_ptr[i]->cpu_monotonic.mtc_counts[MT_CORE_CYCLES];
+                       cest.cpu_urc = cpu_data_ptr[i]->cpu_monotonic.mtc_counts[MT_CORE_REFCYCLES];
+#endif /* MONOTONIC */
+#if DIAG_ALL_PMCS
+                       bcopy(&cpu_data_ptr[i]->cpu_gpmcs[0], &cest.gpmcs[0], sizeof(cest.gpmcs));
+#endif /* DIAG_ALL_PMCS */
+                       (void) ml_set_interrupts_enabled(TRUE);
 
                        copyout(&cest, curpos, sizeof(cest));
                        curpos += sizeof(cest);
                }
                rval = 1;
+               (void) ml_set_interrupts_enabled(FALSE);
        }
                break;
        case dgEnaPMC:
@@ -285,7 +314,7 @@ diagCall64(x86_saved_state_t * state)
                rval = 1;
        }
        break;
-#if    DEBUG
+#if    DEVELOPMENT || DEBUG
        case dgGzallocTest:
        {
                (void) ml_set_interrupts_enabled(TRUE);
@@ -294,25 +323,28 @@ diagCall64(x86_saved_state_t * state)
                        kfree(ptr, 1024);
                        *ptr = 0x42;
                }
+               (void) ml_set_interrupts_enabled(FALSE);
        }
        break;
 #endif
 
-#if PERMIT_PERMCHECK   
+#if DEVELOPMENT || DEBUG
        case    dgPermCheck:
        {
                (void) ml_set_interrupts_enabled(TRUE);
                if (diagflag)
                        rval = pmap_permissions_verify(kernel_pmap, kernel_map, 0, ~0ULL);
+               (void) ml_set_interrupts_enabled(FALSE);
        }
                break;
-#endif /* PERMIT_PERMCHECK */
+#endif /* DEVELOPMENT || DEBUG */
        default:                /* Handle invalid ones */
                rval = 0;       /* Return an exception */
        }
 
        regs->rax = rval;
 
+       assert(ml_get_interrupts_enabled() == FALSE);
        return rval;
 }
 
@@ -341,16 +373,30 @@ void cpu_powerstats(__unused void *arg) {
        cdp->cpu_c7res = ((uint64_t)ch << 32) | cl;
 
        if (diag_pmc_enabled) {
+#if MONOTONIC
+               mt_update_fixed_counts();
+#else /* MONOTONIC */
                uint64_t insns = read_pmc(FIXED_PMC0);
                uint64_t ucc = read_pmc(FIXED_PMC1);
                uint64_t urc = read_pmc(FIXED_PMC2);
+#endif /* !MONOTONIC */
+#if DIAG_ALL_PMCS
+               int i;
+
+               for (i = 0; i < 4; i++) {
+                       cdp->cpu_gpmcs[i] = read_pmc(i);
+               }
+#endif /* DIAG_ALL_PMCS */
+#if !MONOTONIC
                cdp->cpu_cur_insns = insns;
                cdp->cpu_cur_ucc = ucc;
                cdp->cpu_cur_urc = urc;
+#endif /* !MONOTONIC */
        }
 }
 
 void cpu_pmc_control(void *enablep) {
+#if !MONOTONIC
        boolean_t enable = *(boolean_t *)enablep;
        cpu_data_t      *cdp = current_cpu_datap();
 
@@ -365,4 +411,7 @@ void cpu_pmc_control(void *enablep) {
                set_cr4((get_cr4() & ~CR4_PCE));
        }
        cdp->cpu_fixed_pmcs_enabled = enable;
+#else /* !MONOTONIC */
+#pragma unused(enablep)
+#endif /* MONOTONIC */
 }