All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] Add support for profiling Loongson 2E
@ 2007-07-24  9:20 Dajie Tan
  2007-07-24 14:40 ` Ralf Baechle
  0 siblings, 1 reply; 7+ messages in thread
From: Dajie Tan @ 2007-07-24  9:20 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: linux-mips

Hello,

This patch adds support for profiling Loongson 2E. It's been tested on
FuLong mini PC(loongson2e inside).


=======================================================================

diff -urN b/arch/mips/lemote/lm2e/irq.c a/arch/mips/lemote/lm2e/irq.c
--- b/arch/mips/lemote/lm2e/irq.c	2007-07-24 12:57:38.000000000 +0800
+++ a/arch/mips/lemote/lm2e/irq.c	2007-07-19 08:20:50.000000000 +0800
@@ -82,6 +82,8 @@

 	if (pending & CAUSEF_IP7) {
 		do_IRQ(MIPS_CPU_IRQ_BASE + 7);
+ 	} else if (pending & CAUSEF_IP6) { 	/* performance counter
overflowe at IP6 */
+ 		do_IRQ(MIPS_CPU_IRQ_BASE + 6);
 	} else if (pending & CAUSEF_IP5) {
 		i8259_irqdispatch();
 	} else if (pending & CAUSEF_IP2) {
diff -urN b/arch/mips/oprofile/Makefile a/arch/mips/oprofile/Makefile
--- b/arch/mips/oprofile/Makefile	2007-07-24 12:58:48.000000000 +0800
+++ a/arch/mips/oprofile/Makefile	2007-07-19 08:20:53.000000000 +0800
@@ -15,4 +15,5 @@
 oprofile-$(CONFIG_CPU_R10000)		+= op_model_mipsxx.o
 oprofile-$(CONFIG_CPU_SB1)		+= op_model_mipsxx.o
 oprofile-$(CONFIG_CPU_RM9000)		+= op_model_rm9000.o
+oprofile-$(CONFIG_CPU_LOONGSON2)		+= op_model_loongson2e.o

diff -urN b/arch/mips/oprofile/common.c a/arch/mips/oprofile/common.c
--- b/arch/mips/oprofile/common.c	2007-07-24 12:59:33.000000000 +0800
+++ a/arch/mips/oprofile/common.c	2007-07-24 08:10:27.000000000 +0800
@@ -16,6 +16,7 @@

 extern struct op_mips_model op_model_mipsxx_ops __attribute__((weak));
 extern struct op_mips_model op_model_rm9000_ops __attribute__((weak));
+extern struct op_mips_model op_model_loongson2e_ops __attribute__((weak));

 static struct op_mips_model *model;

@@ -93,6 +94,10 @@
 		lmodel = &op_model_rm9000_ops;
 		break;

+	case CPU_LOONGSON2:
+		lmodel = &op_model_loongson2e_ops;
+		break;
+
 	};

 	if (!lmodel)
diff -urN b/arch/mips/oprofile/op_model_loongson2e.c
a/arch/mips/oprofile/op_model_loongson2e.c
--- b/arch/mips/oprofile/op_model_loongson2e.c	1970-01-01
08:00:00.000000000 +0800
+++ a/arch/mips/oprofile/op_model_loongson2e.c	2007-07-24
13:03:01.000000000 +0800
@@ -0,0 +1,170 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2007 by Dajie Tan <jiankemeng@gmail.com>
+ */
+
+#include <linux/init.h>
+#include <linux/oprofile.h>
+#include <linux/interrupt.h>
+#include <linux/smp.h>
+
+#include "op_impl.h"
+
+#define GODSON2E_PERFCTL_EXL			(1UL    <<  0)
+#define GODSON2E_PERFCTL_KERNEL			(1UL    <<  1)
+#define GODSON2E_PERFCTL_SUPERVISOR		(1UL    <<  2)
+#define GODSON2E_PERFCTL_USER			(1UL    <<  3)
+#define GODSON2E_PERFCTL_INTERRUPT_ENABLE	(1UL    <<  4)
+#define GODSON2E_PERFCTL_OVERFLOW		(1ULL	<< 31)
+
+#define GODSON2E_COUNTER1_EVENT(event)	((event) << 5)
+#define GODSON2E_COUNTER2_EVENT(event)	((event) << 9)
+
+
+/* IP6 --- performance counter overflow */
+static int loongson2e_pmc_irq = MIPS_CPU_IRQ_BASE + 6;
+
+
+static struct loongson2e_register_config {
+	unsigned int control;
+	unsigned int reset_counter1;
+	unsigned int reset_counter2;
+	int c1_enabled;
+	int c2_enabled;
+} reg;
+
+/* Compute all of the registers in preparation for enabling profiling.  */
+
+static void loongson2e_reg_setup(struct op_counter_config *ctr)
+{
+	unsigned int control = 0;
+
+	/* Compute the performance counter control word.  */
+	/* For now count kernel and user mode */
+	if (ctr[0].enabled)
+		control |= GODSON2E_COUNTER1_EVENT(ctr[0].event) |
+		           GODSON2E_PERFCTL_INTERRUPT_ENABLE;
+	else
+		control |= GODSON2E_COUNTER1_EVENT(0xe);
+
+	if (ctr[1].enabled)
+		control |= GODSON2E_COUNTER2_EVENT(ctr[1].event) |
+		           GODSON2E_PERFCTL_INTERRUPT_ENABLE;
+	else
+		control |= GODSON2E_COUNTER2_EVENT(0x3);
+
+	if (ctr[0].kernel || ctr[1].kernel)
+		control |= GODSON2E_PERFCTL_KERNEL;
+	else
+		control &= ~GODSON2E_PERFCTL_KERNEL;
+
+	if (ctr[0].user || ctr[1].user)
+		control |= GODSON2E_PERFCTL_USER;
+	else
+		control &= ~GODSON2E_PERFCTL_USER;
+
+	if (ctr[0].exl || ctr[1].exl)
+		control |= GODSON2E_PERFCTL_EXL;
+	else
+		control &= ~GODSON2E_PERFCTL_EXL;
+
+	reg.control = control;
+
+	reg.c1_enabled = ctr[0].enabled;
+	reg.c2_enabled = ctr[1].enabled;
+	reg.reset_counter1 = ctr[0].count ? 0x80000000 - ctr[0].count : 0;
+	reg.reset_counter2 = ctr[1].count ? 0x80000000 - ctr[1].count : 0;
+}
+
+static void loongson2e_cpu_setup (void *args)
+{
+	uint64_t perfcount;
+	perfcount = ((uint64_t) reg.reset_counter2 << 32) | reg.reset_counter1;
+	write_c0_pmc_count(perfcount);
+}
+
+static void loongson2e_cpu_start(void *args)
+{
+	/* Start all counters */
+	write_c0_pmc_control(reg.control);
+}
+
+static void loongson2e_cpu_stop(void *args)
+{
+	/* Stop all counters */
+	write_c0_pmc_control(0);
+}
+
+
+static irqreturn_t loongson2e_pmc_handler(int irq, void * dev_id)
+{
+	uint32_t counter1, counter2;
+	uint64_t counters;
+	uint64_t tmp = 0x0;
+	struct pt_regs *regs = get_irq_regs();
+
+	/*
+	 * Godson2e combines two 32-bit performance counters into a single
+	 * 64-bit coprocessor zero register.  To avoid a race updating the
+	 * registers we need to stop the counters while we're messing with
+	 * them ...
+	 */
+
+	write_c0_pmc_control(tmp);
+
+	counters = read_c0_pmc_count();
+	counter1 = counters;
+	counter2 = counters >> 32;
+
+	if (reg.c2_enabled && counter2 & GODSON2E_PERFCTL_OVERFLOW) {
+		oprofile_add_sample(regs, 1);
+		counter2 = reg.reset_counter2;
+	}
+
+	if (reg.c1_enabled && counter1 & GODSON2E_PERFCTL_OVERFLOW) {
+		oprofile_add_sample(regs, 0);
+		counter1 = reg.reset_counter1;
+	}
+
+	counters = ((uint64_t)counter2 << 32) | counter1;
+
+	write_c0_pmc_count(counters);
+	write_c0_pmc_control(reg.control);
+
+	return IRQ_HANDLED;
+}
+
+static int __init loongson2e_init(void)
+{
+	uint64_t tmp = 0;
+	write_c0_pmc_control(0);
+	write_c0_pmc_count(tmp);
+
+	return request_irq(loongson2e_pmc_irq, loongson2e_pmc_handler,
+	                   IRQF_DISABLED, "Perfcounter", NULL);
+}
+
+static void loongson2e_exit(void)
+{
+	uint64_t tmp = 0;
+	write_c0_pmc_control(0);
+	write_c0_pmc_count(tmp);
+
+	free_irq(loongson2e_pmc_irq, NULL);
+}
+
+struct op_mips_model op_model_loongson2e_ops = {
+	.reg_setup	= loongson2e_reg_setup,
+	.cpu_setup	= loongson2e_cpu_setup,
+	.init		= loongson2e_init,
+	.exit		= loongson2e_exit,
+	.cpu_start	= loongson2e_cpu_start,
+	.cpu_stop	= loongson2e_cpu_stop,
+	.cpu_type	= "mips/loongson2e",
+	.num_counters	= 2
+};
+
+
diff -urN b/include/asm-mips/mipsregs.h a/include/asm-mips/mipsregs.h
--- b/include/asm-mips/mipsregs.h	2007-07-24 13:02:29.000000000 +0800
+++ a/include/asm-mips/mipsregs.h	2007-07-19 08:22:44.000000000 +0800
@@ -594,6 +594,58 @@
 	: "r" (val), "i" (counter));				\
 } while (0)

+
+/*
+ * Macros to access the loongson2e system control coprocessor
+ */
+#define __read_64bit_c0_pmc_split(source, sel)				\
+({									\
+	unsigned long long val;						\
+	unsigned long flags;						\
+									\
+	local_irq_save(flags);						\
+	if (sel == 0)							\
+		__asm__ __volatile__(					\
+			".set\tmips64\n\t"				\
+			"dmfc0\t%M0, " #source "\n\t"			\
+			"dsll\t%L0, %M0, 32\n\t"			\
+			"dsra\t%M0, %M0, 32\n\t"			\
+			"dsra\t%L0, %L0, 32\n\t"			\
+			".set\tmips0"					\
+			: "=r" (val));					\
+	else								\
+		__asm__ __volatile__(					\
+			".set\tmips64\n\t"				\
+			"dmfc0\t%M0, " #source ", " #sel "\n\t"		\
+			"dsll\t%L0, %M0, 32\n\t"			\
+			"dsra\t%M0, %M0, 32\n\t"			\
+			"dsra\t%L0, %L0, 32\n\t"			\
+			".set\tmips0"					\
+			: "=r" (val));					\
+	local_irq_restore(flags);					\
+									\
+	val;								\
+})
+
+#define __read_64bit_c0_pmc(source, sel)				\
+({ unsigned long long __res;						\
+	if (sizeof(unsigned long) == 4)					\
+		__res = __read_64bit_c0_pmc_split(source, sel);		\
+	else if (sel == 0)						\
+		__asm__ __volatile__(					\
+			".set\tmips3\n\t"				\
+			"dmfc0\t%0, " #source "\n\t"			\
+			".set\tmips0"					\
+			: "=r" (__res));				\
+	else								\
+		__asm__ __volatile__(					\
+			".set\tmips64\n\t"				\
+			"dmfc0\t%0, " #source ", " #sel "\n\t"		\
+			".set\tmips0"					\
+			: "=r" (__res));				\
+	__res;								\
+})
+
 /*
  * Macros to access the system control coprocessor
  */
@@ -896,6 +948,14 @@
 #define read_c0_framemask()	__read_32bit_c0_register($21, 0)
 #define write_c0_framemask(val)	__write_32bit_c0_register($21, 0, val)

+/* Loongson2e PMC control register */
+#define read_c0_pmc_control()	__read_32bit_c0_register($24, 0)
+#define write_c0_pmc_control(val) __write_32bit_c0_register($24, 0, val)
+
+/* Loongson2e PMC counter register */
+#define read_c0_pmc_count()	__read_64bit_c0_pmc($25, 0)
+#define write_c0_pmc_count(val)	__write_64bit_c0_register($25, 0, val)
+
 /* RM9000 PerfControl performance counter control register */
 #define read_c0_perfcontrol()	__read_32bit_c0_register($22, 0)
 #define write_c0_perfcontrol(val) __write_32bit_c0_register($22, 0, val)
diff -urN b/drivers/oprofile/cpu_buffer.c a/drivers/oprofile/cpu_buffer.c
--- b/drivers/oprofile/cpu_buffer.c	2007-07-24 13:00:54.000000000 +0800
+++ a/drivers/oprofile/cpu_buffer.c	2007-07-19 08:22:15.000000000 +0800
@@ -148,6 +148,10 @@
            unsigned long pc, unsigned long event)
 {
 	struct op_sample * entry = &cpu_buf->buffer[cpu_buf->head_pos];
+
+	if(!entry)
+		return;
+
 	entry->eip = pc;
 	entry->event = event;
 	increment_head(cpu_buf);

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH] Add support for profiling Loongson 2E
  2007-07-24  9:20 [PATCH] Add support for profiling Loongson 2E Dajie Tan
@ 2007-07-24 14:40 ` Ralf Baechle
  2007-07-25  3:41   ` Dajie Tan
  0 siblings, 1 reply; 7+ messages in thread
From: Ralf Baechle @ 2007-07-24 14:40 UTC (permalink / raw)
  To: Dajie Tan; +Cc: linux-mips, phil.el, levon, oprofile-list

On Tue, Jul 24, 2007 at 01:20:27PM +0400, Dajie Tan wrote:

> This patch adds support for profiling Loongson 2E. It's been tested on
> FuLong mini PC(loongson2e inside).

First of all, your patch has been garbled when mailing.


[.. Lots of arch/mips code deleted ...]

No complaints upto this point.  But:

> diff -urN b/drivers/oprofile/cpu_buffer.c a/drivers/oprofile/cpu_buffer.c
> --- b/drivers/oprofile/cpu_buffer.c	2007-07-24 13:00:54.000000000 +0800
> +++ a/drivers/oprofile/cpu_buffer.c	2007-07-19 08:22:15.000000000 +0800
> @@ -148,6 +148,10 @@
>            unsigned long pc, unsigned long event)
> {
> 	struct op_sample * entry = &cpu_buf->buffer[cpu_buf->head_pos];
> +
> +	if(!entry)
> +		return;
> +
> 	entry->eip = pc;
> 	entry->event = event;
> 	increment_head(cpu_buf);

Why do you need this change?  It almost looks as if you're papering over
a bug where add_sample should not be called at all.

  Ralf

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH] Add support for profiling Loongson 2E
  2007-07-24 14:40 ` Ralf Baechle
@ 2007-07-25  3:41   ` Dajie Tan
  2007-07-25 12:52     ` John Levon
  0 siblings, 1 reply; 7+ messages in thread
From: Dajie Tan @ 2007-07-25  3:41 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: inux-mips, phil.el, levon, oprofile-list

> Why do you need this change?  It almost looks as if you're papering over
> a bug where add_sample should not be called at all.

Yeah,this change is to enhance the robust of oprofile. When using
performace counter manually(writting control register in a module, no
need to use the oprofile),I usually make kernel panic if I do not
initialize the oprofile and enable the overflow interrupt carelessly.
So, this change can avoid this panic. :D

2007/7/24, Ralf Baechle <ralf@linux-mips.org>:
> On Tue, Jul 24, 2007 at 01:20:27PM +0400, Dajie Tan wrote:
>
> > This patch adds support for profiling Loongson 2E. It's been tested on
> > FuLong mini PC(loongson2e inside).
>
> First of all, your patch has been garbled when mailing.
>
>
> [.. Lots of arch/mips code deleted ...]
>
> No complaints upto this point.  But:
>
> > diff -urN b/drivers/oprofile/cpu_buffer.c a/drivers/oprofile/cpu_buffer.c
> > --- b/drivers/oprofile/cpu_buffer.c   2007-07-24 13:00:54.000000000 +0800
> > +++ a/drivers/oprofile/cpu_buffer.c   2007-07-19 08:22:15.000000000 +0800
> > @@ -148,6 +148,10 @@
> >            unsigned long pc, unsigned long event)
> > {
> >       struct op_sample * entry = &cpu_buf->buffer[cpu_buf->head_pos];
> > +
> > +     if(!entry)
> > +             return;
> > +
> >       entry->eip = pc;
> >       entry->event = event;
> >       increment_head(cpu_buf);
>
> Why do you need this change?  It almost looks as if you're papering over
> a bug where add_sample should not be called at all.
>
>   Ralf
>


-- 
为天地立心
为生民立命
为往圣继绝学
为万世开太平

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH] Add support for profiling Loongson 2E
  2007-07-25  3:41   ` Dajie Tan
@ 2007-07-25 12:52     ` John Levon
  2007-07-26  1:14       ` Dajie Tan
  0 siblings, 1 reply; 7+ messages in thread
From: John Levon @ 2007-07-25 12:52 UTC (permalink / raw)
  To: Dajie Tan; +Cc: Ralf Baechle, inux-mips, phil.el, oprofile-list

On Wed, Jul 25, 2007 at 07:41:21AM +0400, Dajie Tan wrote:

> >Why do you need this change?  It almost looks as if you're papering over
> >a bug where add_sample should not be called at all.
> 
> Yeah,this change is to enhance the robust of oprofile. When using
> performace counter manually(writting control register in a module, no
> need to use the oprofile),I usually make kernel panic if I do not
> initialize the oprofile and enable the overflow interrupt carelessly.
> So, this change can avoid this panic. :D

This panic is good and should stay. It shows that you've made a mistake.

john

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH] Add support for profiling Loongson 2E
  2007-07-25 12:52     ` John Levon
@ 2007-07-26  1:14       ` Dajie Tan
  2007-07-26  4:48         ` Fuxin Zhang
  2007-07-26 11:17         ` Ralf Baechle
  0 siblings, 2 replies; 7+ messages in thread
From: Dajie Tan @ 2007-07-26  1:14 UTC (permalink / raw)
  To: John Levon; +Cc: Ralf Baechle, linux-mips, phil.el, oprofile-list

2007/7/25, John Levon <levon@movementarian.org>:
> On Wed, Jul 25, 2007 at 07:41:21AM +0400, Dajie Tan wrote:
>
> > >Why do you need this change?  It almost looks as if you're papering over
> > >a bug where add_sample should not be called at all.
> >
> > Yeah,this change is to enhance the robust of oprofile. When using
> > performace counter manually(writting control register in a module, no
> > need to use the oprofile),I usually make kernel panic if I do not
> > initialize the oprofile and enable the overflow interrupt carelessly.
> > So, this change can avoid this panic. :D
>
> This panic is good and should stay. It shows that you've made a mistake.
>
> john
>

This panic is caused by accessing a null pointer.Do you think that
accessing a null
pointer is allowed in a robust system ?

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH] Add support for profiling Loongson 2E
  2007-07-26  1:14       ` Dajie Tan
@ 2007-07-26  4:48         ` Fuxin Zhang
  2007-07-26 11:17         ` Ralf Baechle
  1 sibling, 0 replies; 7+ messages in thread
From: Fuxin Zhang @ 2007-07-26  4:48 UTC (permalink / raw)
  To: Dajie Tan; +Cc: John Levon, Ralf Baechle, linux-mips, phil.el, oprofile-list



Dajie Tan 写道:
>> > Yeah,this change is to enhance the robust of oprofile. When using
>> > performace counter manually(writting control register in a module, no
>> > need to use the oprofile),I usually make kernel panic if I do not
>> > initialize the oprofile and enable the overflow interrupt carelessly.
>> > So, this change can avoid this panic. :D
>>
>> This panic is good and should stay. It shows that you've made a mistake.
>>
>> john
>>
>
> This panic is caused by accessing a null pointer.Do you think that
> accessing a null
> pointer is allowed in a robust system ?
I think you don't really understand Ralf and John's responses. The 
problem should not be workarounded in that position.
Your code should ensure that overflow interrupt will not be enabled when 
oprofile is not enabled, or something like this. If everyone choose to 
'fix' problems via patching generic code, it would be a maintainence 
headache. Why other platform s won't have your problem?

It is not to say that the panic is ok, but it is your problem if others 
are not suffering the same panic, and should be fixed in your code.
>
>
>
>

-- 
------------------------------------------------
Fuxin Zhang

Vice Researcher
Microprocessor Research Center, Institute of Computing Technolgy
Chiese Academy of China
Beijing, 100080
Email: fxzhang@ict.ac.cn
http://www.ict.ac.cn

------------------------------------------------
 

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH] Add support for profiling Loongson 2E
  2007-07-26  1:14       ` Dajie Tan
  2007-07-26  4:48         ` Fuxin Zhang
@ 2007-07-26 11:17         ` Ralf Baechle
  1 sibling, 0 replies; 7+ messages in thread
From: Ralf Baechle @ 2007-07-26 11:17 UTC (permalink / raw)
  To: Dajie Tan; +Cc: John Levon, linux-mips, phil.el, oprofile-list

On Thu, Jul 26, 2007 at 05:14:14AM +0400, Dajie Tan wrote:

> >> Yeah,this change is to enhance the robust of oprofile. When using
> >> performace counter manually(writting control register in a module, no
> >> need to use the oprofile),I usually make kernel panic if I do not
> >> initialize the oprofile and enable the overflow interrupt carelessly.
> >> So, this change can avoid this panic. :D
> >
> >This panic is good and should stay. It shows that you've made a mistake.
> >
> >john
> >
> 
> This panic is caused by accessing a null pointer.Do you think that
> accessing a null
> pointer is allowed in a robust system ?

Of course it isn't.  From the perspective of us kernel maintainers patches
that add such checks are a red flag which raise concerns about the
correctness of the caller of the function.  So if a patch like this is
submitted the first thing that is likely to happen is that we will ask
why the check is needed.  It does not mean such a patch is fundamentally
a no-no but the code will be looked at a little harder.

  Ralf

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2007-07-26 11:17 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2007-07-24  9:20 [PATCH] Add support for profiling Loongson 2E Dajie Tan
2007-07-24 14:40 ` Ralf Baechle
2007-07-25  3:41   ` Dajie Tan
2007-07-25 12:52     ` John Levon
2007-07-26  1:14       ` Dajie Tan
2007-07-26  4:48         ` Fuxin Zhang
2007-07-26 11:17         ` Ralf Baechle

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.