clear-pkgs-linux-iot-lts2018/0900-trusty-log-Add-vmm-pan...

209 lines
5.5 KiB
Diff

From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: "Yan, Shaoou" <shaopu.yan@intel.com>
Date: Fri, 9 Dec 2016 05:32:20 +0000
Subject: [PATCH] trusty-log: Add vmm panic notifier for vmm deadloop dumping
register a new vmcall TRUSTY_VMCALL_DUMP_INIT.
Change-Id: Icee169358f30c64da44894dc5816ce5f3020fc70
Tracked-On: OAM-40748
Signed-off-by: syan10 <shaopu.yan@intel.com>
Reviewed-by: Ilkka Koskinen <ilkka.koskinen@intel.com>
---
drivers/trusty/trusty-log.c | 107 ++++++++++++++++++++++++++++++++++++
drivers/trusty/trusty-log.h | 22 ++++++++
2 files changed, 129 insertions(+)
diff --git a/drivers/trusty/trusty-log.c b/drivers/trusty/trusty-log.c
index 112287cd4739..a066481c4f1d 100644
--- a/drivers/trusty/trusty-log.c
+++ b/drivers/trusty/trusty-log.c
@@ -26,6 +26,8 @@
#define TRUSTY_LOG_SIZE (PAGE_SIZE * 2)
#define TRUSTY_LINE_BUFFER_SIZE 256
+static uint64_t g_vmm_debug_buf;
+
struct trusty_log_state {
struct device *dev;
struct device *trusty_dev;
@@ -135,6 +137,72 @@ static int trusty_log_panic_notify(struct notifier_block *nb,
return NOTIFY_OK;
}
+static void trusty_vmm_dump_header(struct deadloop_dump *dump)
+{
+ struct dump_header *header;
+
+ if (!dump)
+ return;
+
+ header = &(dump->header);
+ pr_info("VMM version = %s\n", header->vmm_version);
+ pr_info("Signature = %s\n", header->signature);
+ pr_info("Error_info = %s\n", header->error_info);
+ pr_info("Cpuid = %d\n", header->cpuid);
+}
+
+static void trusty_vmm_dump_data(struct deadloop_dump *dump)
+{
+ struct dump_data *dump_data;
+ int i;
+
+ if (!dump)
+ return;
+
+ dump_data = &(dump->data);
+
+ for (i = 0; i < dump_data->length; i++)
+ pr_info("%c", dump_data->data[i]);
+}
+
+static int trusty_vmm_panic_notify(struct notifier_block *nb,
+ unsigned long action, void *data)
+{
+ struct deadloop_dump *dump_info;
+
+ if (g_vmm_debug_buf) {
+ dump_info = (struct deadloop_dump *)g_vmm_debug_buf;
+
+ if (dump_info->is_valid) {
+ pr_info("trusty-vmm panic start!\n");
+ trusty_vmm_dump_header(dump_info);
+ trusty_vmm_dump_data(dump_info);
+ pr_info("trusty-vmm panic dump end!\n");
+ }
+ }
+
+ return NOTIFY_OK;
+}
+
+static struct notifier_block trusty_vmm_panic_nb = {
+ .notifier_call = trusty_vmm_panic_notify,
+ .priority = 0,
+};
+
+#define TRUSTY_VMCALL_DUMP_INIT 0x74727507
+static int trusty_vmm_dump_init(void *gva)
+{
+ int ret = -1;
+
+ __asm__ __volatile__(
+ "vmcall"
+ : "=a"(ret)
+ : "a"(TRUSTY_VMCALL_DUMP_INIT), "D"(gva)
+ );
+
+ return ret;
+}
+
static bool trusty_supports_logging(struct device *device)
{
int result;
@@ -164,6 +232,7 @@ static int trusty_log_probe(struct platform_device *pdev)
struct trusty_log_state *s;
int result;
phys_addr_t pa;
+ struct deadloop_dump *dump;
dev_dbg(&pdev->dev, "%s\n", __func__);
if (!trusty_supports_logging(pdev->dev.parent)) {
@@ -216,10 +285,45 @@ static int trusty_log_probe(struct platform_device *pdev)
"failed to register panic notifier\n");
goto error_panic_notifier;
}
+
+ /* allocate debug buffer for vmm panic dump */
+ g_vmm_debug_buf = get_zeroed_page(GFP_KERNEL);
+ if (!g_vmm_debug_buf) {
+ result = -ENOMEM;
+ goto error_alloc_vmm;
+ }
+
+ dump = (struct deadloop_dump *)g_vmm_debug_buf;
+ dump->version_of_this_struct = VMM_DUMP_VERSION;
+ dump->size_of_this_struct = sizeof(struct deadloop_dump);
+ dump->is_valid = false;
+
+ /* shared the buffer to vmm by VMCALL */
+ result = trusty_vmm_dump_init(dump);
+ if (result < 0) {
+ dev_err(&pdev->dev,
+ "failed to share the dump buffer to VMM\n");
+ goto error_vmm_panic_notifier;
+ }
+
+ /* register the panic notifier for vmm */
+ result = atomic_notifier_chain_register(&panic_notifier_list,
+ &trusty_vmm_panic_nb);
+ if (result < 0) {
+ dev_err(&pdev->dev,
+ "failed to register vmm panic notifier\n");
+ goto error_vmm_panic_notifier;
+ }
+
platform_set_drvdata(pdev, s);
return 0;
+error_vmm_panic_notifier:
+ free_page(g_vmm_debug_buf);
+error_alloc_vmm:
+ atomic_notifier_chain_unregister(&panic_notifier_list,
+ &s->panic_notifier);
error_panic_notifier:
trusty_call_notifier_unregister(s->trusty_dev, &s->call_notifier);
error_call_notifier:
@@ -241,6 +345,8 @@ static int trusty_log_remove(struct platform_device *pdev)
dev_dbg(&pdev->dev, "%s\n", __func__);
+ atomic_notifier_chain_unregister(&panic_notifier_list,
+ &trusty_vmm_panic_nb);
atomic_notifier_chain_unregister(&panic_notifier_list,
&s->panic_notifier);
trusty_call_notifier_unregister(s->trusty_dev, &s->call_notifier);
@@ -253,6 +359,7 @@ static int trusty_log_remove(struct platform_device *pdev)
}
__free_pages(s->log_pages, get_order(TRUSTY_LOG_SIZE));
kfree(s);
+ free_page(g_vmm_debug_buf);
return 0;
}
diff --git a/drivers/trusty/trusty-log.h b/drivers/trusty/trusty-log.h
index 09f60213e1f6..587bc7aaa145 100644
--- a/drivers/trusty/trusty-log.h
+++ b/drivers/trusty/trusty-log.h
@@ -18,5 +18,27 @@ struct log_rb {
#define TRUSTY_LOG_API_VERSION 1
+#define VMM_DUMP_VERSION 1
+
+struct dump_data {
+ uint32_t length;
+ uint8_t data[0];
+} __packed;
+
+struct dump_header {
+ uint8_t vmm_version[64]; /* version of the vmm */
+ uint8_t signature[16]; /* signature for the dump structure */
+ uint8_t error_info[32]; /* filename:linenum */
+ uint16_t cpuid;
+} __packed;
+
+struct deadloop_dump {
+ uint16_t size_of_this_struct;
+ uint16_t version_of_this_struct;
+ uint32_t is_valid;
+ struct dump_header header;
+ struct dump_data data;
+} __packed;
+
#endif
--
https://clearlinux.org