freebsd-dev/sys/i386/include/pmc_mdep.h
John Baldwin 7612087747 Adjust the handling of the local APIC PMC interrupt vector:
- Provide lapic_disable_pmc(), lapic_enable_pmc(), and lapic_reenable_pmc()
  routines in the local APIC code that the hwpmc(4) driver can use to
  manage the local APIC PMC interrupt vector.
- Do not enable the local APIC PMC interrupt vector by default when
  HWPMC_HOOKS is enabled.  Instead, the hwpmc(4) driver explicitly
  enables the interrupt when it is succesfully initialized and disables
  the interrupt when it is unloaded.  This avoids enabling the interrupt
  on unsupported CPUs which may result in spurious NMIs.

Reported by:	rnoland
Reviewed by:	jkoshy
Approved by:	re (kib)
MFC after:	2 weeks
2009-08-14 20:57:21 +00:00

161 lines
5.3 KiB
C

/*-
* Copyright (c) 2003-2005,2008 Joseph Koshy
* Copyright (c) 2007 The FreeBSD Foundation
* All rights reserved.
*
* Portions of this software were developed by A. Joseph Koshy under
* sponsorship from the FreeBSD Foundation and Google, Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/
#ifndef _MACHINE_PMC_MDEP_H
#define _MACHINE_PMC_MDEP_H 1
#ifdef _KERNEL
struct pmc_mdep;
#endif
/*
* On the i386 platform we support the following PMCs.
*
* TSC The timestamp counter
* K7 AMD Athlon XP/MP and other 32 bit processors.
* K8 AMD Athlon64 and Opteron PMCs in 32 bit mode.
* PIV Intel P4/HTT and P4/EMT64
* PPRO Intel Pentium Pro, Pentium-II, Pentium-III, Celeron and
* Pentium-M processors
* PENTIUM Intel Pentium MMX.
* IAP Intel Core/Core2/Atom programmable PMCs.
* IAF Intel fixed-function PMCs.
*/
#include <dev/hwpmc/hwpmc_amd.h> /* K7 and K8 */
#include <dev/hwpmc/hwpmc_core.h>
#include <dev/hwpmc/hwpmc_piv.h>
#include <dev/hwpmc/hwpmc_ppro.h>
#include <dev/hwpmc/hwpmc_pentium.h>
#include <dev/hwpmc/hwpmc_tsc.h>
/*
* Intel processors implementing V2 and later of the Intel performance
* measurement architecture have PMCs of the following classes: TSC,
* IAF and IAP.
*/
#define PMC_MDEP_CLASS_INDEX_TSC 0
#define PMC_MDEP_CLASS_INDEX_K7 1
#define PMC_MDEP_CLASS_INDEX_K8 1
#define PMC_MDEP_CLASS_INDEX_P4 1
#define PMC_MDEP_CLASS_INDEX_P5 1
#define PMC_MDEP_CLASS_INDEX_P6 1
#define PMC_MDEP_CLASS_INDEX_IAP 1
#define PMC_MDEP_CLASS_INDEX_IAF 2
/*
* Architecture specific extensions to <sys/pmc.h> structures.
*/
union pmc_md_op_pmcallocate {
struct pmc_md_amd_op_pmcallocate pm_amd;
struct pmc_md_iaf_op_pmcallocate pm_iaf;
struct pmc_md_iap_op_pmcallocate pm_iap;
struct pmc_md_p4_op_pmcallocate pm_p4;
struct pmc_md_pentium_op_pmcallocate pm_pentium;
struct pmc_md_ppro_op_pmcallocate pm_ppro;
uint64_t __pad[4];
};
/* Logging */
#define PMCLOG_READADDR PMCLOG_READ32
#define PMCLOG_EMITADDR PMCLOG_EMIT32
#ifdef _KERNEL
/* MD extension for 'struct pmc' */
union pmc_md_pmc {
struct pmc_md_amd_pmc pm_amd;
struct pmc_md_iaf_pmc pm_iaf;
struct pmc_md_iap_pmc pm_iap;
struct pmc_md_p4_pmc pm_p4;
struct pmc_md_pentium_pmc pm_pentium;
struct pmc_md_ppro_pmc pm_ppro;
};
struct pmc;
struct pmc_mdep;
#define PMC_TRAPFRAME_TO_PC(TF) ((TF)->tf_eip)
#define PMC_TRAPFRAME_TO_FP(TF) ((TF)->tf_ebp)
/*
* The layout of the stack frame on entry into the NMI handler depends on
* whether a privilege level change (and consequent stack switch) was
* required for entry.
*
* When processing an interrupt when in user mode, the processor switches
* stacks, and saves the user mode stack pointer on the kernel stack. The
* user mode stack pointer is then available to the interrupt handler
* at frame->tf_esp.
*
* When processing an interrupt while in kernel mode, the processor
* continues to use the existing (kernel) stack. Therefore we determine
* the stack pointer for the interrupted kernel procedure by adding an
* offset to the current frame pointer.
*/
#define PMC_TRAPFRAME_TO_USER_SP(TF) ((TF)->tf_esp)
#define PMC_TRAPFRAME_TO_KERNEL_SP(TF) ((uintptr_t) &((TF)->tf_esp))
#define PMC_IN_KERNEL_STACK(S,START,END) \
((S) >= (START) && (S) < (END))
#define PMC_IN_KERNEL(va) (((va) >= USRSTACK) && \
((va) < VM_MAX_KERNEL_ADDRESS))
#define PMC_IN_USERSPACE(va) ((va) <= VM_MAXUSER_ADDRESS)
#define PMC_IN_TRAP_HANDLER(PC) \
((PC) >= (uintptr_t) start_exceptions && \
(PC) < (uintptr_t) end_exceptions)
#define PMC_AT_FUNCTION_PROLOGUE_PUSH_BP(I) \
(((I) & 0x00ffffff) == 0xe58955) /* pushl %ebp; movl %esp,%ebp */
#define PMC_AT_FUNCTION_PROLOGUE_MOV_SP_BP(I) \
(((I) & 0x0000ffff) == 0xe589) /* movl %esp,%ebp */
#define PMC_AT_FUNCTION_EPILOGUE_RET(I) \
(((I) & 0xFF) == 0xC3) /* ret */
/*
* Prototypes
*/
void start_exceptions(void), end_exceptions(void);
struct pmc_mdep *pmc_amd_initialize(void);
void pmc_amd_finalize(struct pmc_mdep *_md);
struct pmc_mdep *pmc_intel_initialize(void);
void pmc_intel_finalize(struct pmc_mdep *_md);
#endif /* _KERNEL */
#endif /* _MACHINE_PMC_MDEP_H */