lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite for Android: free password hash cracker in your pocket
[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Date:	Thu, 11 Sep 2008 17:05:36 -0400
From:	Elad Lahav <elad_lahav@...rs.sourceforge.net>
To:	linux-kernel@...r.kernel.org
Subject: [PATCH] Initial support for Niagara T1 performance counters

The patch handles performance counter overflow traps, which are
currently being ignored.
A trap with type 0x4f is generated by either a level-15 interrupt, or,
if the processor interrupt level is smaller than 15, by the overflow of
a performance counter (either the low or high parts). Currently, the
kernel ignores the former, and handles only the latter. The patch checks
the previous value of PIL and, if smaller than 15, increments a 64-bit
per-cpu counter. The counter is used to count both types of overflows,
being divided into two 32 bit values. The counter is exported, so that
kernel modules can use it to keep track of 64-bit performance counter
values.
A sample module, which uses the overflow counters, can be found on:
http://www.cs.uwaterloo.ca/~elahav/pcount.c
The module uses a procfs entry (/proc/pcount) that enables users to both
programme the counters (start, stop, reset, configure event), as well as
get a snapshot of the current value of all counters.

Notes:
1. I have tried to be as unintrusive as possible. The code is only
enabled if a config option is turned on, and the option is marked as
EXPERIMENTAL.
2. The way in which the previous PIL value is extracted from the stored
TSTATE register is based on my interpretation of the code in etrap.S. I
hope it is correct (seems to be working, though).
3. I'm not sure about the need to manually reset the PCR overflow flags
- see comment in the code (again, seems to be working).


Signed-off-by: Elad Lahav <elad_lahav@...rs.sourceforge.net>
---
diff -r -u linux-2.6.26.5/arch/sparc64/Kconfig linux-2.6.26.5-t1pc/arch/sparc64/Kconfig
--- linux-2.6.26.5/arch/sparc64/Kconfig	2008-09-08 13:40:20.000000000 -0400
+++ linux-2.6.26.5-t1pc/arch/sparc64/Kconfig	2008-09-11 10:24:47.000000000 -0400
@@ -397,6 +397,15 @@

  	  NOTE: This option WILL override the PROM bootargs setting!

+config T1_PERF_COUNTERS
+	bool "Support for performance counters on the Niagara T1 (EXPERIMENTAL)"
+	depends on EXPERIMENTAL && SPARC64
+	default n
+	help
+	  Each virtual processor on the T1 has its own performance counter
+	  unit, composed of two 32 bit counters.
+	  Say Y to enable support for programming and reading these counters.
+
  source "net/Kconfig"

  source "drivers/Kconfig"
diff -r -u linux-2.6.26.5/arch/sparc64/kernel/irq.c 
linux-2.6.26.5-t1pc/arch/sparc64/kernel/irq.c
--- linux-2.6.26.5/arch/sparc64/kernel/irq.c	2008-09-08 13:40:20.000000000 -0400
+++ linux-2.6.26.5-t1pc/arch/sparc64/kernel/irq.c	2008-09-11 16:19:44.000000000 -0400
@@ -703,6 +703,53 @@
  	__asm__ __volatile__("mov %0, %%sp" : : "r" (orig_sp));
  }

+#ifdef CONFIG_T1_PERF_COUNTERS
+/**
+ * pic_overflows holds two 32 bit values. The lower one keeps track of the
+ * overflows of the programmable counter (PIC.l), and the higher of the
+ * overflows of the instruction counter (PIC.h).
+ */
+DEFINE_PER_CPU(u64, pic_overflows);
+EXPORT_PER_CPU_SYMBOL(pic_overflows);
+
+/**
+ * Handles a performance counter overflow trap.
+ * The trap occurs when either the high or the low halves of the counter (or
+ * both) overflow. This is indicated by a disrupting trap on SOFTINT 15 (0x4f),
+ * whike PIL < 15.
+ */
+static void handle_pic_overflow(void)
+{
+	u64 pcr;
+
+	/*
+	 * Get the current value of the control register.
+	 */
+	__asm__ __volatile__("rd %%pcr, %0" : "=r" (pcr));
+
+	/*
+	 * Check the overflow flags.
+	 * Bit 9 is set if the high half of the counter has overflowed.
+	 * Bit 8 is set if the low half of the counter has overflowed.
+	 */
+	if (pcr & (1ULL << 9))
+		__get_cpu_var(pic_overflows) += (1ULL << 32);
+	if (pcr & (1ULL << 8))
+		__get_cpu_var(pic_overflows)++;
+
+	/*
+	 * Reset the overflow flags.
+	 * TODO: The manual does not mention that the overflow flags need to be
+	 * reset manually. This is probably safe, though, as this function is
+	 * called with PIL=15, so that another overflow trap cannot happen in
+	 * the meantime.
+	 */
+	pcr &= ~(3ULL << 8);
+	__asm__ __volatile__("wr %0, %%g0, %%pcr" : : "r"(pcr));
+}
+
+#endif /* CONFIG_T1_PERF_COUNTERS */
+
  void handler_irq(int irq, struct pt_regs *regs)
  {
  	unsigned long pstate, bucket_pa;
@@ -714,6 +761,28 @@
  	old_regs = set_irq_regs(regs);
  	irq_enter();

+#ifdef CONFIG_T1_PERF_COUNTERS
+	/*
+	 * SOFTINT 15 is shared with the PIC overflow trap.
+	 * This is indicated by the PIL register having a value < 15 (i.e.,
+	 * an interrupt of level 15 is blocked).
+	 */
+	if (irq == 15) {
+		unsigned long pil;
+
+		/*
+		 * PIL is set to 15 by the trap entry routine.
+		 * To find out the value of PIL when the trap was taken, we
+		 * need to look into bits 20-23 of the saved TSTATE register.
+		 */
+		pil = (regs->tstate & (0xf << 20)) >> 20;
+		if (pil < 15) {
+			handle_pic_overflow();
+			goto exit_irq;
+		}
+	}
+#endif /* CONFIG_T1_PERF_COUNTERS */
+
  	/* Grab an atomic snapshot of the pending IVECs.  */
  	__asm__ __volatile__("rdpr	%%pstate, %0\n\t"
  			     "wrpr	%0, %3, %%pstate\n\t"
@@ -745,6 +814,7 @@

  	restore_hardirq_stack(orig_sp);

+exit_irq:
  	irq_exit();
  	set_irq_regs(old_regs);
  }
diff -r -u linux-2.6.26.5/include/asm-sparc64/irq.h 
linux-2.6.26.5-t1pc/include/asm-sparc64/irq.h
--- linux-2.6.26.5/include/asm-sparc64/irq.h	2008-09-08 13:40:20.000000000 -0400
+++ linux-2.6.26.5-t1pc/include/asm-sparc64/irq.h	2008-09-11 10:37:40.000000000 -0400
@@ -94,4 +94,8 @@
  extern void *softirq_stack[NR_CPUS];
  #define __ARCH_HAS_DO_SOFTIRQ

+#ifdef CONFIG_T1_PERF_COUNTERS
+DECLARE_PER_CPU(u64, pic_overflows);
+#endif /* CONFIG_T1_PERF_COUNTERS */
+
  #endif

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ