Re: OProfile cannot be loaded as module...

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



David Daney wrote:
arch/mips/oprofile/common.c defines several symbols (op_model_mipsxx and op_model_rm9000) with __attribute__((weak)). It then assumes that ELF linking conventions will prevail and there will be no problems if they are undefined.

The problem is if you try to load oprofile as a module. The kernel module linker evidentially does not understand weak symbols and refuses to load the module because they are undefined.

Perhaps a single

extern struct op_mips_model plat_op_model;

That must be defined by each different implementation. Deciding one which implementation would then be done at compile time instead of runtime.

I don't have a patch for this yet, but that is what I am thinking of doing.


Ok, attached is my untested (but it compiles for some architectures) patch.

David Daney
diff --git a/arch/mips/oprofile/common.c b/arch/mips/oprofile/common.c
--- a/arch/mips/oprofile/common.c
+++ b/arch/mips/oprofile/common.c
@@ -14,20 +14,17 @@
 
 #include "op_impl.h"
 
-extern struct op_mips_model op_model_mipsxx __attribute__((weak));
-extern struct op_mips_model op_model_rm9000 __attribute__((weak));
-
-static struct op_mips_model *model;
+extern struct op_mips_model *plat_op_model;
 
 static struct op_counter_config ctr[20];
 
 static int op_mips_setup(void)
 {
 	/* Pre-compute the values to stuff in the hardware registers.  */
-	model->reg_setup(ctr);
+	plat_op_model->reg_setup(ctr);
 
 	/* Configure the registers on all cpus.  */
-	on_each_cpu(model->cpu_setup, 0, 0, 1);
+	on_each_cpu(plat_op_model->cpu_setup, 0, 0, 1);
 
         return 0;
 }
@@ -36,7 +33,7 @@ static int op_mips_create_files(struct s
 {
 	int i;
 
-	for (i = 0; i < model->num_counters; ++i) {
+	for (i = 0; i < plat_op_model->num_counters; ++i) {
 		struct dentry *dir;
 		char buf[3];
 
@@ -58,7 +55,7 @@ static int op_mips_create_files(struct s
 
 static int op_mips_start(void)
 {
-	on_each_cpu(model->cpu_start, NULL, 0, 1);
+	on_each_cpu(plat_op_model->cpu_start, NULL, 0, 1);
 
 	return 0;
 }
@@ -66,49 +63,33 @@ static int op_mips_start(void)
 static void op_mips_stop(void)
 {
 	/* Disable performance monitoring for all counters.  */
-	on_each_cpu(model->cpu_stop, NULL, 0, 1);
+	on_each_cpu(plat_op_model->cpu_stop, NULL, 0, 1);
 }
 
 int __init oprofile_arch_init(struct oprofile_operations *ops)
 {
-	struct op_mips_model *lmodel = NULL;
 	int res;
 
 	printk(KERN_INFO "oprofile: In oprofile_arch_init.\n");
 
-	switch (current_cpu_data.cputype) {
-	case CPU_24K:
-		lmodel = &op_model_mipsxx;
-		break;
-
-	case CPU_RM9000:
-		lmodel = &op_model_rm9000;
-		break;
-	};
-
-	if (!lmodel)
-		return -ENODEV;
-
-	res = lmodel->init();
+	res = plat_op_model->init();
 	if (res)
 		return res;
 
-	model = lmodel;
-
 	ops->create_files	= op_mips_create_files;
 	ops->setup		= op_mips_setup;
 	//ops->shutdown         = op_mips_shutdown;
 	ops->start		= op_mips_start;
 	ops->stop		= op_mips_stop;
-	ops->cpu_type		= lmodel->cpu_type;
+	ops->cpu_type		= plat_op_model->cpu_type;
 
 	printk(KERN_INFO "oprofile: using %s performance monitoring.\n",
-	       lmodel->cpu_type);
+	       plat_op_model->cpu_type);
 
 	return 0;
 }
 
 void oprofile_arch_exit(void)
 {
-	model->exit();
+	plat_op_model->exit();
 }
diff --git a/arch/mips/oprofile/op_model_mipsxx.c b/arch/mips/oprofile/op_model_mipsxx.c
--- a/arch/mips/oprofile/op_model_mipsxx.c
+++ b/arch/mips/oprofile/op_model_mipsxx.c
@@ -23,7 +23,7 @@
 
 #define M_COUNTER_OVERFLOW		(1UL    << 31)
 
-struct op_mips_model op_model_mipsxx;
+static struct op_mips_model op_model_mipsxx;
 
 static struct mipsxx_register_config {
 	unsigned int control[4];
@@ -205,7 +205,7 @@ static void mipsxx_exit(void)
 	perf_irq = null_perf_irq;
 }
 
-struct op_mips_model op_model_mipsxx = {
+static struct op_mips_model op_model_mipsxx = {
 	.reg_setup	= mipsxx_reg_setup,
 	.cpu_setup	= mipsxx_cpu_setup,
 	.init		= mipsxx_init,
@@ -213,3 +213,5 @@ struct op_mips_model op_model_mipsxx = {
 	.cpu_start	= mipsxx_cpu_start,
 	.cpu_stop	= mipsxx_cpu_stop,
 };
+
+struct op_mips_model *plat_op_model = &op_model_mipsxx;
diff --git a/arch/mips/oprofile/op_model_rm9000.c b/arch/mips/oprofile/op_model_rm9000.c
--- a/arch/mips/oprofile/op_model_rm9000.c
+++ b/arch/mips/oprofile/op_model_rm9000.c
@@ -126,7 +126,7 @@ static void rm9000_exit(void)
 	free_irq(rm9000_perfcount_irq, NULL);
 }
 
-struct op_mips_model op_model_rm9000 = {
+static struct op_mips_model op_model_rm9000 = {
 	.reg_setup	= rm9000_reg_setup,
 	.cpu_setup	= rm9000_cpu_setup,
 	.init		= rm9000_init,
@@ -136,3 +136,5 @@ struct op_mips_model op_model_rm9000 = {
 	.cpu_type	= "mips/rm9000",
 	.num_counters	= 2
 };
+
+struct op_mips_model *plat_op_model = &op_model_rm9000;

[Index of Archives]     [Linux MIPS Home]     [LKML Archive]     [Linux ARM Kernel]     [Linux ARM]     [Linux]     [Git]     [Yosemite News]     [Linux SCSI]     [Linux Hams]

  Powered by Linux