Index: sys/dev/hwpmc/hwpmc_core.c =================================================================== --- sys/dev/hwpmc/hwpmc_core.c (revision 209857) +++ sys/dev/hwpmc/hwpmc_core.c (working copy) @@ -147,6 +147,7 @@ int core_ri, n, npmc; struct pmc_cpu *pc; struct core_cpu *cc; + uint64_t msr = 0; KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), ("[core,%d] insane cpu number (%d)", __LINE__, cpu)); @@ -166,11 +167,14 @@ npmc = md->pmd_classdep[PMC_MDEP_CLASS_INDEX_IAP].pcd_num; core_ri = md->pmd_classdep[PMC_MDEP_CLASS_INDEX_IAP].pcd_ri; - for (n = 0; n < npmc; n++) - wrmsr(IAP_EVSEL0 + n, 0); + for (n = 0; n < npmc; n++) { + msr = rdmsr(IAP_EVSEL0 + n); + wrmsr(IAP_EVSEL0 + n, msr & ~IAP_EVSEL_MASK); + } if (core_cputype != PMC_CPU_INTEL_CORE) { - wrmsr(IAF_CTRL, 0); + msr = rdmsr(IAF_CTRL); + wrmsr(IAF_CTRL, msr & ~IAF_CTRL_MASK); npmc += md->pmd_classdep[PMC_MDEP_CLASS_INDEX_IAF].pcd_num; } @@ -374,6 +378,7 @@ { struct pmc *pm; struct core_cpu *iafc; + uint64_t msr = 0; KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), ("[core,%d] illegal CPU value %d", __LINE__, cpu)); @@ -387,12 +392,15 @@ iafc->pc_iafctrl |= pm->pm_md.pm_iaf.pm_iaf_ctrl; - wrmsr(IAF_CTRL, iafc->pc_iafctrl); + msr = rdmsr(IAF_CTRL); + wrmsr(IAF_CTRL, msr | (iafc->pc_iafctrl & IAF_CTRL_MASK)); do { iafc->pc_resync = 0; iafc->pc_globalctrl |= (1ULL << (ri + IAF_OFFSET)); - wrmsr(IA_GLOBAL_CTRL, iafc->pc_globalctrl); + msr = rdmsr(IA_GLOBAL_CTRL); + wrmsr(IA_GLOBAL_CTRL, msr | (iafc->pc_globalctrl & + IAF_GLOBAL_CTRL_MASK)); } while (iafc->pc_resync != 0); PMCDBG(MDP,STA,1,"iafctrl=%x(%x) globalctrl=%jx(%jx)", @@ -407,6 +415,7 @@ { uint32_t fc; struct core_cpu *iafc; + uint64_t msr = 0; PMCDBG(MDP,STO,1,"iaf-stop cpu=%d ri=%d", cpu, ri); @@ -425,12 +434,15 @@ iafc->pc_iafctrl &= ~fc; PMCDBG(MDP,STO,1,"iaf-stop iafctrl=%x", iafc->pc_iafctrl); - wrmsr(IAF_CTRL, iafc->pc_iafctrl); + msr = rdmsr(IAF_CTRL); + wrmsr(IAF_CTRL, msr | (iafc->pc_iafctrl & IAF_CTRL_MASK)); do { iafc->pc_resync = 0; iafc->pc_globalctrl &= ~(1ULL << (ri + IAF_OFFSET)); - wrmsr(IA_GLOBAL_CTRL, iafc->pc_globalctrl); + msr = rdmsr(IA_GLOBAL_CTRL); + wrmsr(IA_GLOBAL_CTRL, msr | (iafc->pc_globalctrl & + IAF_GLOBAL_CTRL_MASK)); } while (iafc->pc_resync != 0); PMCDBG(MDP,STO,1,"iafctrl=%x(%x) globalctrl=%jx(%jx)", @@ -445,6 +457,7 @@ { struct core_cpu *cc; struct pmc *pm; + uint64_t msr; KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), ("[core,%d] illegal cpu value %d", __LINE__, cpu)); @@ -460,9 +473,11 @@ if (PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm))) v = iaf_reload_count_to_perfctr_value(v); - wrmsr(IAF_CTRL, 0); /* Turn off fixed counters */ - wrmsr(IAF_CTR0 + ri, v); - wrmsr(IAF_CTRL, cc->pc_iafctrl); + msr = rdmsr(IAF_CTRL); + wrmsr(IAF_CTRL, msr & ~IAF_CTRL_MASK); + wrmsr(IAF_CTR0 + ri, v & ((1ULL << core_iaf_width) - 1)); + msr = rdmsr(IAF_CTRL); + wrmsr(IAF_CTRL, msr | (cc->pc_iafctrl & IAF_CTRL_MASK)); PMCDBG(MDP,WRI,1, "iaf-write cpu=%d ri=%d msr=0x%x v=%jx iafctrl=%jx " "pmc=%jx", cpu, ri, IAF_RI_TO_MSR(ri), v, @@ -1879,6 +1894,7 @@ { struct pmc *pm; struct core_cpu *cc; + uint64_t msr; KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), ("[core,%d] illegal cpu value %d", __LINE__, cpu)); @@ -1894,7 +1910,8 @@ PMCDBG(MDP,STO,1, "iap-stop cpu=%d ri=%d", cpu, ri); - wrmsr(IAP_EVSEL0 + ri, 0); /* stop hw */ + msr = rdmsr(IAP_EVSEL0 + ri); + wrmsr(IAP_EVSEL0 + ri, msr & IAP_EVSEL_MASK); /* stop hw */ if (core_cputype == PMC_CPU_INTEL_CORE) return (0); @@ -1937,7 +1954,7 @@ * a stopped state when the pcd_write() entry point is called. */ - wrmsr(IAP_PMC0 + ri, v); + wrmsr(IAP_PMC0 + ri, v & ((1ULL << core_iap_width) - 1)); return (0); } @@ -1987,6 +2004,7 @@ struct pmc *pm; struct core_cpu *cc; int error, found_interrupt, ri; + uint64_t msr = 0; PMCDBG(MDP,INT, 1, "cpu=%d tf=0x%p um=%d", cpu, (void *) tf, TRAPF_USERMODE(tf)); @@ -2018,7 +2036,8 @@ * Stop the counter, reload it but only restart it if * the PMC is not stalled. */ - wrmsr(IAP_EVSEL0 + ri, 0); + msr = rdmsr(IAP_EVSEL0 + ri); + wrmsr(IAP_EVSEL0 + ri, msr & ~IAP_EVSEL_MASK); wrmsr(IAP_PMC0 + ri, v); if (error) Index: sys/dev/hwpmc/hwpmc_core.h =================================================================== --- sys/dev/hwpmc/hwpmc_core.h (revision 209857) +++ sys/dev/hwpmc/hwpmc_core.h (working copy) @@ -67,20 +67,59 @@ /* * Fixed-function counters. */ + #define IAF_MASK 0xF +#define IAF_COUNTER_MASK 0x0000ffffffffffff #define IAF_CTR0 0x309 #define IAF_CTR1 0x30A #define IAF_CTR2 0x30B +/* + * The IAF_CTRL MSR is laid out in the following way. + * + * Bit Position Use + * 63 - 12 Reserved (do not touch) + * 11 Ctr 2 PMI + * 10 Reserved (do not touch) + * 9-8 Ctr 2 Enable + * 7 Ctr 1 PMI + * 6 Reserved (do not touch) + * 5-4 Ctr 1 Enable + * 3 Ctr 0 PMI + * 2 Reserved (do not touch) + * 1-0 Ctr 0 Enable (3: All Levels, 2: User, 1: OS, 0: Disable) + */ + #define IAF_OFFSET 32 #define IAF_CTRL 0x38D +#define IAF_CTRL_MASK 0x0000000000000bbb /* * Programmable counters. */ #define IAP_PMC0 0x0C1 + +/* + * IAP_EVSEL(n) is laid out in the following way. + * + * Bit Position Use + * 63-31 Reserved (do not touch) + * 31-24 Counter Mask + * 23 Invert + * 22 Enable + * 21 Reserved (do not touch) + * 20 APIC Interrupt Enable + * 19 Pin Control + * 18 Edge Detect + * 17 OS + * 16 User + * 15-8 Unit Mask + * 7-0 Event Select + */ + +#define IAP_EVSEL_MASK 0x00000000ffdfffff #define IAP_EVSEL0 0x186 /* @@ -90,6 +129,21 @@ #define IA_GLOBAL_STATUS 0x38E #define IA_GLOBAL_CTRL 0x38F + +/* + * IA_GLOBAL_CTRL is layed out in the following way. + * + * Bit Position Use + * 63-35 Reserved (do not touch) + * 34 IAF Counter 2 Enable + * 33 IAF Counter 1 Enable + * 32 IAF Counter 0 Enable + * 31-0 Depends on programmable counters + */ + +/* The mask is only for the fixed porttion of the register. */ +#define IAF_GLOBAL_CTRL_MASK 0x0000000700000000 + #define IA_GLOBAL_OVF_CTRL 0x390 #define IA_GLOBAL_STATUS_FLAG_CONDCHG (1ULL << 63)