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@xxxxxxxxxxxxx> --- 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