Skip to contentSkip to conversation

powerpc/powernv: Expose OPAL firmware symbol map

PATCH In review Benjamin Herrenschmidt 2 participants 2 messages Dec 5, 2014 PowerPC

lore
Share & tools
lore
#0 lore raw

PATCH v2 1/1 powerpc/powernv: Expose OPAL firmware symbol map

Newer versions of OPAL will provide this, so let's expose it to user space so tools like perf can use it to properly decode samples in firmware space.

---

v2. Use memory_read_from_buffer()

arch/powerpc/platforms/powernv/opal.c +38 -0
index 06d9076..98f50e8 100644
@@ -61,6 +61,8 @@ static DEFINE_SPINLOCK(opal_notifier_lock);
 static uint64_t last_notified_mask = 0x0ul;
 static atomic_t opal_notifier_hold = ATOMIC_INIT(0);
 static uint32_t opal_heartbeat;
+static void *opal_symmap;
+static uint64_t opal_symmap_size;
 
 static void opal_reinit_cores(void)
 {
@@ -608,6 +610,40 @@ static int opal_sysfs_init(void)
 	return 0;
 }
 
+static ssize_t symbol_map_read(struct file *fp, struct kobject *kobj,
+			       struct bin_attribute *bin_attr,
+			       char *buf, loff_t off, size_t count)
+{
+	return memory_read_from_buffer(buf, count, &off,
+				       opal_symmap, opal_symmap_size);
+}
+
+static BIN_ATTR_RO(symbol_map, 0);
+
+static void opal_export_symmap(void)
+{
+	const __be64 *syms;
+	unsigned int size;
+	struct device_node *fw;
+	int rc;
+
+	fw = of_find_node_by_path("/ibm,opal/firmware");
+	if (!fw)
+		return;
+	syms = of_get_property(fw, "symbol-map", &size);
+	if (!syms || size != 2 * sizeof(__be64))
+		return;
+
+	opal_symmap = __va(be64_to_cpu(syms[0]));
+	opal_symmap_size = be64_to_cpu(syms[1]);
+
+	/* Setup attributes */
+	bin_attr_symbol_map.size = opal_symmap_size;
+	rc = sysfs_create_bin_file(opal_kobj, &bin_attr_symbol_map);
+	if (rc)
+		pr_warn("Error %d creating OPAL symbols file\n", rc);
+}
+
 static void __init opal_dump_region_init(void)
 {
 	void *addr;
@@ -738,6 +774,8 @@ static int __init opal_init(void)
 	/* Create "opal" kobject under /sys/firmware */
 	rc = opal_sysfs_init();
 	if (rc == 0) {
+		/* Export symbol map to userspace */
+		opal_export_symmap();
 		/* Setup dump region interface */
 		opal_dump_region_init();
 		/* Setup error log interface */
#1 lore raw
Quoted 9 lines · Benjamin Herrenschmidt

Newer versions of OPAL will provide this, so let's expose it to user space so tools like perf can use it to properly decode samples in firmware space.

arch/powerpc/platforms/powernv/opal.c +0 -0
index 06d9076..98f50e8 100644

arch/powerpc/platforms/powernv/opal.c static DEFINE_SPINLOCK(opal_notifier_lock); · line 65

Quoted 5 lines
arch/powerpc/platforms/powernv/opal.c +2 -0
@@ -61,6 +61,8 @@ static DEFINE_SPINLOCK(opal_notifier_lock);
 static uint64_t last_notified_mask = 0x0ul;
 static atomic_t opal_notifier_hold = ATOMIC_INIT(0);
 static uint32_t opal_heartbeat;
+static void *opal_symmap;
+static uint64_t opal_symmap_size;

We shouldn't need these.

The bin_attribute has a size (you set it), you just need to use it in symbol_map_read().

And the attribute also has a private pointer, which you can use for opal_symmap.

arch/powerpc/platforms/powernv/opal.c static int opal_sysfs_init(void) · line 618

Quoted 10 lines
arch/powerpc/platforms/powernv/opal.c +6 -0
@@ -608,6 +610,40 @@ static int opal_sysfs_init(void)
 	return 0;
 }
 
+static ssize_t symbol_map_read(struct file *fp, struct kobject *kobj,
+			       struct bin_attribute *bin_attr,
+			       char *buf, loff_t off, size_t count)
+{
+	return memory_read_from_buffer(buf, count, &off,
+				       opal_symmap, opal_symmap_size);

So this would be:

	return memory_read_from_buffer(buf, count, &off,
				       bin_attr->private, bin_attr->size);
Quoted 10 lines
arch/powerpc/platforms/powernv/opal.c +10 -0
+}
+
+static BIN_ATTR_RO(symbol_map, 0);
+
+static void opal_export_symmap(void)
+{
+	const __be64 *syms;
+	unsigned int size;
+	struct device_node *fw;
+	int rc;

arch/powerpc/platforms/powernv/opal.c static int opal_sysfs_init(void) · line 638

Quoted 10 lines
arch/powerpc/platforms/powernv/opal.c +10 -0
+
+	fw = of_find_node_by_path("/ibm,opal/firmware");
+	if (!fw)
+		return;
+	syms = of_get_property(fw, "symbol-map", &size);
+	if (!syms || size != 2 * sizeof(__be64))
+		return;
+
+	opal_symmap = __va(be64_to_cpu(syms[0]));
+	opal_symmap_size = be64_to_cpu(syms[1]);

I was going to tell you to use of_property_read_u64_index(), but it doesn't exist - we can add it one day and clean this up then.

arch/powerpc/platforms/powernv/opal.c static int opal_sysfs_init(void) · line 644

Quoted 5 lines
arch/powerpc/platforms/powernv/opal.c +5 -0
+	/* Setup attributes */
+	bin_attr_symbol_map.size = opal_symmap_size;
+	rc = sysfs_create_bin_file(opal_kobj, &bin_attr_symbol_map);
+	if (rc)
+		pr_warn("Error %d creating OPAL symbols file\n", rc);

Can you prefix it please, so:

	pr_warn("opal: Error .."

Or add to the very top of the file:

#define pr_fmt(fmt) "opal: " fmt

cheers