hwpmc_amd.c (153110) | hwpmc_amd.c (174395) |
---|---|
1/*- | 1/*- |
2 * Copyright (c) 2003-2005 Joseph Koshy | 2 * Copyright (c) 2003-2007 Joseph Koshy 3 * Copyright (c) 2007 The FreeBSD Foundation |
3 * All rights reserved. 4 * | 4 * All rights reserved. 5 * |
6 * Portions of this software were developed by A. Joseph Koshy under 7 * sponsorship from the FreeBSD Foundation and Google, Inc. 8 * |
|
5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. --- 8 unchanged lines hidden (view full) --- 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * 26 */ 27 28#include <sys/cdefs.h> | 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. --- 8 unchanged lines hidden (view full) --- 25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28 * SUCH DAMAGE. 29 * 30 */ 31 32#include <sys/cdefs.h> |
29__FBSDID("$FreeBSD: head/sys/dev/hwpmc/hwpmc_amd.c 153110 2005-12-05 11:58:35Z ru $"); | 33__FBSDID("$FreeBSD: head/sys/dev/hwpmc/hwpmc_amd.c 174395 2007-12-07 08:20:17Z jkoshy $"); |
30 31/* Support for the AMD K7 and later processors */ 32 33#include <sys/param.h> 34#include <sys/lock.h> 35#include <sys/malloc.h> 36#include <sys/mutex.h> 37#include <sys/pmc.h> 38#include <sys/smp.h> 39#include <sys/systm.h> 40 | 34 35/* Support for the AMD K7 and later processors */ 36 37#include <sys/param.h> 38#include <sys/lock.h> 39#include <sys/malloc.h> 40#include <sys/mutex.h> 41#include <sys/pmc.h> 42#include <sys/smp.h> 43#include <sys/systm.h> 44 |
45#include <machine/cpu.h> |
|
41#include <machine/cpufunc.h> 42#include <machine/md_var.h> | 46#include <machine/cpufunc.h> 47#include <machine/md_var.h> |
43#include <machine/pmc_mdep.h> | |
44#include <machine/specialreg.h> 45 46#ifdef DEBUG 47enum pmc_class amd_pmc_class; 48#endif 49 50/* AMD K7 & K8 PMCs */ 51struct amd_descr { --- 610 unchanged lines hidden (view full) --- 662/* 663 * Interrupt handler. This function needs to return '1' if the 664 * interrupt was this CPU's PMCs or '0' otherwise. It is not allowed 665 * to sleep or do anything a 'fast' interrupt handler is not allowed 666 * to do. 667 */ 668 669static int | 48#include <machine/specialreg.h> 49 50#ifdef DEBUG 51enum pmc_class amd_pmc_class; 52#endif 53 54/* AMD K7 & K8 PMCs */ 55struct amd_descr { --- 610 unchanged lines hidden (view full) --- 666/* 667 * Interrupt handler. This function needs to return '1' if the 668 * interrupt was this CPU's PMCs or '0' otherwise. It is not allowed 669 * to sleep or do anything a 'fast' interrupt handler is not allowed 670 * to do. 671 */ 672 673static int |
670amd_intr(int cpu, uintptr_t eip, int usermode) | 674amd_intr(int cpu, struct trapframe *tf) |
671{ 672 int i, error, retval, ri; 673 uint32_t config, evsel, perfctr; 674 struct pmc *pm; 675 struct pmc_cpu *pc; 676 struct pmc_hw *phw; 677 pmc_value_t v; 678 679 KASSERT(cpu >= 0 && cpu < mp_ncpus, 680 ("[amd,%d] out of range CPU %d", __LINE__, cpu)); 681 | 675{ 676 int i, error, retval, ri; 677 uint32_t config, evsel, perfctr; 678 struct pmc *pm; 679 struct pmc_cpu *pc; 680 struct pmc_hw *phw; 681 pmc_value_t v; 682 683 KASSERT(cpu >= 0 && cpu < mp_ncpus, 684 ("[amd,%d] out of range CPU %d", __LINE__, cpu)); 685 |
682 PMCDBG(MDP,INT,1, "cpu=%d eip=%p um=%d", cpu, (void *) eip, 683 usermode); | 686 PMCDBG(MDP,INT,1, "cpu=%d tf=0x%p um=%d", cpu, (void *) tf, 687 TRAPF_USERMODE(tf)); |
684 685 retval = 0; 686 687 pc = pmc_pcpu[cpu]; 688 689 /* 690 * look for all PMCs that have interrupted: 691 * - skip over the TSC [PMC#0] 692 * - look for a running, sampling PMC which has overflowed 693 * and which has a valid 'struct pmc' association 694 * 695 * If found, we call a helper to process the interrupt. 696 * 697 * If multiple PMCs interrupt at the same time, the AMD64 698 * processor appears to deliver as many NMIs as there are | 688 689 retval = 0; 690 691 pc = pmc_pcpu[cpu]; 692 693 /* 694 * look for all PMCs that have interrupted: 695 * - skip over the TSC [PMC#0] 696 * - look for a running, sampling PMC which has overflowed 697 * and which has a valid 'struct pmc' association 698 * 699 * If found, we call a helper to process the interrupt. 700 * 701 * If multiple PMCs interrupt at the same time, the AMD64 702 * processor appears to deliver as many NMIs as there are |
699 * outstanding PMC interrupts. Thus we need to only process 700 * one interrupt at a time. | 703 * outstanding PMC interrupts. So we process only one NMI 704 * interrupt at a time. |
701 */ 702 703 for (i = 0; retval == 0 && i < AMD_NPMCS-1; i++) { 704 705 ri = i + 1; /* row index; TSC is at ri == 0 */ 706 707 if (!AMD_PMC_HAS_OVERFLOWED(i)) 708 continue; 709 710 phw = pc->pc_hwpmcs[ri]; 711 712 KASSERT(phw != NULL, ("[amd,%d] null PHW pointer", __LINE__)); 713 714 if ((pm = phw->phw_pmc) == NULL || 715 pm->pm_state != PMC_STATE_RUNNING || 716 !PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm))) { 717 continue; 718 } 719 | 705 */ 706 707 for (i = 0; retval == 0 && i < AMD_NPMCS-1; i++) { 708 709 ri = i + 1; /* row index; TSC is at ri == 0 */ 710 711 if (!AMD_PMC_HAS_OVERFLOWED(i)) 712 continue; 713 714 phw = pc->pc_hwpmcs[ri]; 715 716 KASSERT(phw != NULL, ("[amd,%d] null PHW pointer", __LINE__)); 717 718 if ((pm = phw->phw_pmc) == NULL || 719 pm->pm_state != PMC_STATE_RUNNING || 720 !PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm))) { 721 continue; 722 } 723 |
720 retval = 1; /* found an interrupting PMC */ | 724 retval = 1; /* Found an interrupting PMC. */ |
721 | 725 |
722 /* stop the PMC, reload count */ | 726 /* Stop the PMC, reload count. */ |
723 evsel = AMD_PMC_EVSEL_0 + i; 724 perfctr = AMD_PMC_PERFCTR_0 + i; 725 v = pm->pm_sc.pm_reloadcount; 726 config = rdmsr(evsel); 727 728 KASSERT((config & ~AMD_PMC_ENABLE) == 729 (pm->pm_md.pm_amd.pm_amd_evsel & ~AMD_PMC_ENABLE), 730 ("[amd,%d] config mismatch reg=0x%x pm=0x%x", __LINE__, 731 config, pm->pm_md.pm_amd.pm_amd_evsel)); 732 733 wrmsr(evsel, config & ~AMD_PMC_ENABLE); 734 wrmsr(perfctr, AMD_RELOAD_COUNT_TO_PERFCTR_VALUE(v)); 735 | 727 evsel = AMD_PMC_EVSEL_0 + i; 728 perfctr = AMD_PMC_PERFCTR_0 + i; 729 v = pm->pm_sc.pm_reloadcount; 730 config = rdmsr(evsel); 731 732 KASSERT((config & ~AMD_PMC_ENABLE) == 733 (pm->pm_md.pm_amd.pm_amd_evsel & ~AMD_PMC_ENABLE), 734 ("[amd,%d] config mismatch reg=0x%x pm=0x%x", __LINE__, 735 config, pm->pm_md.pm_amd.pm_amd_evsel)); 736 737 wrmsr(evsel, config & ~AMD_PMC_ENABLE); 738 wrmsr(perfctr, AMD_RELOAD_COUNT_TO_PERFCTR_VALUE(v)); 739 |
736 /* restart the counter if there was no error during logging */ 737 error = pmc_process_interrupt(cpu, pm, eip, usermode); | 740 /* Restart the counter if logging succeeded. */ 741 error = pmc_process_interrupt(cpu, pm, tf, TRAPF_USERMODE(tf)); |
738 if (error == 0) 739 wrmsr(evsel, config | AMD_PMC_ENABLE); 740 } 741 742 atomic_add_int(retval ? &pmc_stats.pm_intr_processed : 743 &pmc_stats.pm_intr_ignored, 1); 744 | 742 if (error == 0) 743 wrmsr(evsel, config | AMD_PMC_ENABLE); 744 } 745 746 atomic_add_int(retval ? &pmc_stats.pm_intr_processed : 747 &pmc_stats.pm_intr_ignored, 1); 748 |
745 return retval; | 749 return (retval); |
746} 747 748/* 749 * describe a PMC 750 */ 751static int 752amd_describe(int cpu, int ri, struct pmc_info *pi, struct pmc **ppmc) 753{ --- 251 unchanged lines hidden --- | 750} 751 752/* 753 * describe a PMC 754 */ 755static int 756amd_describe(int cpu, int ri, struct pmc_info *pi, struct pmc **ppmc) 757{ --- 251 unchanged lines hidden --- |