From 2dce1bd3f9af386d1f73839007648e6739d22930 Mon Sep 17 00:00:00 2001
From: Sascha Wildner <saw@online.de>
Date: Sun, 26 Jun 2011 02:11:50 +0200
Subject: [PATCH 12/18] kernel: Add implementations of lapic_{enable,disable,reenable}_pmc().

Donated-by:  aggelos
Reviewed-by: sephe
---
 sys/platform/pc32/apic/lapic.c |   75 ++++++++++++++++++++++++++++++++++++++++
 sys/platform/pc32/apic/lapic.h |    5 ++-
 sys/platform/pc64/apic/lapic.c |   75 ++++++++++++++++++++++++++++++++++++++++
 sys/platform/pc64/apic/lapic.h |    5 ++-
 4 files changed, 158 insertions(+), 2 deletions(-)

diff --git a/sys/platform/pc32/apic/lapic.c b/sys/platform/pc32/apic/lapic.c
index 4c39d27..0d1849f 100644
--- a/sys/platform/pc32/apic/lapic.c
+++ b/sys/platform/pc32/apic/lapic.c
@@ -763,6 +763,81 @@ lapic_fixup_noioapic(void)
 	lapic->lvt_lint1 = temp;
 }
 
+#ifdef HWPMC_HOOKS
+static void
+lapic_enable_pmc_oncpu(void *dummy __unused)
+{
+	uint32_t value;
+
+	value = lapic->lvt_pcint;
+	value &= ~(APIC_LVT_MASKED | APIC_LVT_TRIG_MASK |
+	    APIC_LVT_POLARITY_MASK | APIC_LVT_DM_MASK | APIC_LVT_VECTOR);
+	value |= APIC_LVT_DM_NMI | APIC_LVT_LEVELTRIG;
+	lapic->lvt_pcint = value;
+}
+
+int
+lapic_enable_pmc(void)
+{
+	if (!lapic_enable)
+		return 0;
+#ifdef SMP
+	lwkt_cpusync_simple(smp_active_mask, lapic_enable_pmc_oncpu, NULL);
+#else
+	lapic_enable_pmc_oncpu(NULL);
+#endif
+	return 1;
+}
+
+static void
+lapic_disable_pmc_oncpu(void *dummy __unused)
+{
+	uint32_t value;
+
+	value = lapic->lvt_pcint;
+	value |= APIC_LVT_MASKED;
+	lapic->lvt_pcint = value;
+}
+
+void
+lapic_disable_pmc(void)
+{
+	if (!lapic_enable)
+		return;
+#ifdef SMP
+	lwkt_cpusync_simple(smp_active_mask, lapic_disable_pmc_oncpu, NULL);
+#else
+	lapic_disable_pmc_oncpu(NULL);
+#endif
+}
+
+void
+lapic_reenable_pmc(void)
+{
+	uint32_t value;
+
+	value = lapic->lvt_pcint;
+	value &= ~APIC_LVT_MASKED;
+	lapic->lvt_pcint = value;
+}
+#else /* !HWPMC_HOOKS */
+int
+lapic_enable_pmc(void)
+{
+	return 0;
+}
+
+void
+lapic_disable_pmc(void)
+{
+}
+
+void
+lapic_reenable_pmc(void)
+{
+}
+#endif /* HWPMC_HOOKS */
+
 static void
 lapic_sysinit(void *dummy __unused)
 {
diff --git a/sys/platform/pc32/apic/lapic.h b/sys/platform/pc32/apic/lapic.h
index 3d59556..6d1169a 100644
--- a/sys/platform/pc32/apic/lapic.h
+++ b/sys/platform/pc32/apic/lapic.h
@@ -23,7 +23,6 @@
  * SUCH DAMAGE.
  *
  * $FreeBSD: src/sys/i386/include/mpapic.h,v 1.14.2.2 2000/09/30 02:49:34 ps Exp $
- * $DragonFly: src/sys/platform/pc32/apic/mpapic.h,v 1.12 2008/06/07 11:37:23 mneumann Exp $
  */
 
 #ifndef _ARCH_APIC_LAPIC_H_
@@ -70,6 +69,10 @@ void	lapic_map(vm_paddr_t);
 int	lapic_unused_apic_id(int);
 void	lapic_fixup_noioapic(void);
 
+int	lapic_enable_pmc(void);
+void	lapic_disable_pmc(void);
+void	lapic_reenable_pmc(void);
+
 #ifdef SMP
 
 #ifndef _MACHINE_SMP_H_
diff --git a/sys/platform/pc64/apic/lapic.c b/sys/platform/pc64/apic/lapic.c
index da6eada..493a0f0 100644
--- a/sys/platform/pc64/apic/lapic.c
+++ b/sys/platform/pc64/apic/lapic.c
@@ -825,6 +825,81 @@ lapic_fixup_noioapic(void)
 	lapic->lvt_lint1 = temp;
 }
 
+#ifdef HWPMC_HOOKS
+static void
+lapic_enable_pmc_oncpu(void *dummy __unused)
+{
+	uint32_t value;
+
+	value = lapic->lvt_pcint;
+	value &= ~(APIC_LVT_MASKED | APIC_LVT_TRIG_MASK |
+	    APIC_LVT_POLARITY_MASK | APIC_LVT_DM_MASK | APIC_LVT_VECTOR);
+	value |= APIC_LVT_DM_NMI | APIC_LVT_LEVELTRIG;
+	lapic->lvt_pcint = value;
+}
+
+int
+lapic_enable_pmc(void)
+{
+	if (!lapic_enable)
+		return 0;
+#ifdef SMP
+	lwkt_cpusync_simple(smp_active_mask, lapic_enable_pmc_oncpu, NULL);
+#else
+	lapic_enable_pmc_oncpu(NULL);
+#endif
+	return 1;
+}
+
+static void
+lapic_disable_pmc_oncpu(void *dummy __unused)
+{
+	uint32_t value;
+
+	value = lapic->lvt_pcint;
+	value |= APIC_LVT_MASKED;
+	lapic->lvt_pcint = value;
+}
+
+void
+lapic_disable_pmc(void)
+{
+	if (!lapic_enable)
+		return;
+#ifdef SMP
+	lwkt_cpusync_simple(smp_active_mask, lapic_disable_pmc_oncpu, NULL);
+#else
+	lapic_disable_pmc_oncpu(NULL);
+#endif
+}
+
+void
+lapic_reenable_pmc(void)
+{
+	uint32_t value;
+
+	value = lapic->lvt_pcint;
+	value &= ~APIC_LVT_MASKED;
+	lapic->lvt_pcint = value;
+}
+#else /* !HWPMC_HOOKS */
+int
+lapic_enable_pmc(void)
+{
+	return 0;
+}
+
+void
+lapic_disable_pmc(void)
+{
+}
+
+void
+lapic_reenable_pmc(void)
+{
+}
+#endif /* HWPMC_HOOKS */
+
 static void
 lapic_sysinit(void *dummy __unused)
 {
diff --git a/sys/platform/pc64/apic/lapic.h b/sys/platform/pc64/apic/lapic.h
index 23cf52c..096c08a 100644
--- a/sys/platform/pc64/apic/lapic.h
+++ b/sys/platform/pc64/apic/lapic.h
@@ -24,7 +24,6 @@
  * SUCH DAMAGE.
  *
  * $FreeBSD: src/sys/i386/include/mpapic.h,v 1.14.2.2 2000/09/30 02:49:34 ps Exp $
- * $DragonFly: src/sys/platform/pc64/apic/mpapic.h,v 1.1 2008/08/29 17:07:12 dillon Exp $
  */
 
 #ifndef _ARCH_APIC_LAPIC_H_
@@ -71,6 +70,10 @@ void	lapic_map(vm_paddr_t);
 int	lapic_unused_apic_id(int);
 void	lapic_fixup_noioapic(void);
 
+int	lapic_enable_pmc(void);
+void	lapic_disable_pmc(void);
+void	lapic_reenable_pmc(void);
+
 #ifdef SMP
 
 #ifndef _MACHINE_SMP_H_
-- 
1.7.0.5

