[PATCH v3 2/2] powerpc/powernv: Add ultravisor message log interface
Claudio Carvalho
cclaudio at linux.ibm.com
Wed Aug 28 13:56:46 AEST 2019
The ultravisor (UV) provides an in-memory console which follows the OPAL
in-memory console structure.
This patch extends the OPAL msglog code to initialize the UV memory
console and provide the "/sys/firmware/ultravisor/msglog" interface
for userspace to view the UV message log.
Signed-off-by: Claudio Carvalho <cclaudio at linux.ibm.com>
---
This patch applies on top of the "kvmppc: Paravirtualize KVM to support
ultravisor" patch series submitted by Claudio Carvalho.
---
arch/powerpc/include/asm/ultravisor.h | 8 ++++
arch/powerpc/platforms/powernv/opal-msglog.c | 36 ++++++++++++++++++
arch/powerpc/platforms/powernv/ultravisor.c | 40 ++++++++++++++++++++
3 files changed, 84 insertions(+)
diff --git a/arch/powerpc/include/asm/ultravisor.h b/arch/powerpc/include/asm/ultravisor.h
index d7aa97aa7834..62932d403847 100644
--- a/arch/powerpc/include/asm/ultravisor.h
+++ b/arch/powerpc/include/asm/ultravisor.h
@@ -12,6 +12,14 @@
#include <asm/ultravisor-api.h>
#include <asm/firmware.h>
+/* /sys/firmware/ultravisor */
+extern struct kobject *ultravisor_kobj;
+
+/* /ibm,ultravisor/ibm,uv-firmware */
+extern struct device_node *uv_firmware_node;
+
+void ultra_msglog_init(void);
+void ultra_msglog_sysfs_init(void);
int early_init_dt_scan_ultravisor(unsigned long node, const char *uname,
int depth, void *data);
diff --git a/arch/powerpc/platforms/powernv/opal-msglog.c b/arch/powerpc/platforms/powernv/opal-msglog.c
index 0e8eb62c8afe..7c6b2001e62f 100644
--- a/arch/powerpc/platforms/powernv/opal-msglog.c
+++ b/arch/powerpc/platforms/powernv/opal-msglog.c
@@ -11,6 +11,7 @@
#include <linux/of.h>
#include <linux/types.h>
#include <asm/barrier.h>
+#include <asm/ultravisor.h>
/* OPAL in-memory console. Defined in OPAL source at core/console.c */
struct memcons {
@@ -28,6 +29,7 @@ struct memcons {
};
static struct memcons *opal_memcons = NULL;
+static struct memcons *ultra_memcons;
static ssize_t memcons_copy(struct memcons *mc, char *to, loff_t pos,
size_t count)
@@ -104,6 +106,18 @@ static struct bin_attribute opal_msglog_attr = {
.read = opal_msglog_read
};
+static ssize_t ultra_msglog_read(struct file *file, struct kobject *kobj,
+ struct bin_attribute *bin_attr, char *to,
+ loff_t pos, size_t count)
+{
+ return memcons_copy(ultra_memcons, to, pos, count);
+}
+
+static struct bin_attribute ultra_msglog_attr = {
+ .attr = {.name = "msglog", .mode = 0400},
+ .read = ultra_msglog_read
+};
+
static struct memcons *memcons_load_from_dt(struct device_node *node,
const char *mc_prop_name)
{
@@ -159,3 +173,25 @@ void __init opal_msglog_sysfs_init(void)
if (sysfs_create_bin_file(opal_kobj, &opal_msglog_attr) != 0)
pr_warn("OPAL: sysfs file creation failed\n");
}
+
+void __init ultra_msglog_init(void)
+{
+ ultra_memcons = memcons_load_from_dt(uv_firmware_node, "memcons");
+ if (!ultra_memcons) {
+ pr_warn("Ultravisor: memcons failed to load from DT\n");
+ return;
+ }
+
+ ultra_msglog_attr.size = memcons_get_size(ultra_memcons);
+}
+
+void __init ultra_msglog_sysfs_init(void)
+{
+ if (!ultra_memcons) {
+ pr_warn("Ultravisor: msglog initialisation failed, not creating sysfs entry\n");
+ return;
+ }
+
+ if (sysfs_create_bin_file(ultravisor_kobj, &ultra_msglog_attr) != 0)
+ pr_warn("Ultravisor: sysfs msglog file creation failed\n");
+}
diff --git a/arch/powerpc/platforms/powernv/ultravisor.c b/arch/powerpc/platforms/powernv/ultravisor.c
index 02ac57b4bded..4ec63b7c0c78 100644
--- a/arch/powerpc/platforms/powernv/ultravisor.c
+++ b/arch/powerpc/platforms/powernv/ultravisor.c
@@ -8,9 +8,14 @@
#include <linux/init.h>
#include <linux/printk.h>
#include <linux/of_fdt.h>
+#include <linux/of.h>
#include <asm/ultravisor.h>
#include <asm/firmware.h>
+#include <asm/machdep.h>
+
+struct kobject *ultravisor_kobj;
+struct device_node *uv_firmware_node;
int __init early_init_dt_scan_ultravisor(unsigned long node, const char *uname,
int depth, void *data)
@@ -22,3 +27,38 @@ int __init early_init_dt_scan_ultravisor(unsigned long node, const char *uname,
pr_debug("Ultravisor detected!\n");
return 1;
}
+
+static int __init ultra_sysfs_init(void)
+{
+ ultravisor_kobj = kobject_create_and_add("ultravisor", firmware_kobj);
+ if (!ultravisor_kobj) {
+ pr_warn("kobject_create_and_add ultravisor failed\n");
+ return -ENOMEM;
+ }
+
+ return 0;
+}
+
+static int __init ultra_init(void)
+{
+ int rc;
+
+ if (!firmware_has_feature(FW_FEATURE_ULTRAVISOR))
+ goto out;
+
+ uv_firmware_node = of_find_compatible_node(NULL, NULL,
+ "ibm,uv-firmware");
+ if (!uv_firmware_node) {
+ pr_err("ibm,uv-firmware node not found\n");
+ return -ENODEV;
+ }
+
+ ultra_msglog_init();
+
+ rc = ultra_sysfs_init();
+ if (rc == 0)
+ ultra_msglog_sysfs_init();
+out:
+ return 0;
+}
+machine_subsys_initcall(powernv, ultra_init);
--
2.20.1
More information about the Linuxppc-dev
mailing list