clear-pkgs-linux-iot-lts2018/0910-trusty-Enable-dynamic-...

211 lines
6.4 KiB
Diff

From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: "Zhong,Fangjian" <fangjian.zhong@intel.com>
Date: Tue, 6 Jun 2017 00:15:01 +0000
Subject: [PATCH] trusty: Enable dynamic timer
Enable the dynamic timer support for Trusty scheduling.
Besides periodic timer, Trusty now supports both dynamic timer
and periodic timer. Proxy timer drives the Trusty OS scheduling
in fixed periodical intervals. Dynamic timer is similar to
tickless mode which will not schedule if Trusty OS is idle.
This patch will consult Trusty OS for the timer mode to use
and enable the specified timer to drive Trusty scheduling.
Change-Id: Ic972c40d768cb59a8326842c698fafbe45af906c
Signed-off-by: Zhong,Fangjian <fangjian.zhong@intel.com>
---
drivers/trusty/trusty.c | 91 ++++++++++++++++++++++++++++++++---
include/linux/trusty/smcall.h | 17 +++++++
2 files changed, 100 insertions(+), 8 deletions(-)
diff --git a/drivers/trusty/trusty.c b/drivers/trusty/trusty.c
index 93c73882b00c..647031dacb4e 100644
--- a/drivers/trusty/trusty.c
+++ b/drivers/trusty/trusty.c
@@ -25,9 +25,10 @@
#include <linux/trusty/sm_err.h>
#include <linux/trusty/trusty.h>
-#define TRUSTY_VMCALL_SMC 0x74727500
+#define TRUSTY_VMCALL_SMC 0x74727500
#define TRUSTY_LKTIMER_INTERVAL 10 /* 10 ms */
#define TRUSTY_LKTIMER_VECTOR 0x31 /* INT_PIT */
+#define TRUSTY_STOP_TIMER 0xFFFFFFFF
enum lktimer_mode {
ONESHOT_TIMER,
@@ -52,6 +53,12 @@ struct trusty_smc_interface {
ulong args[5];
};
+static struct timer_list *lk_timer;
+
+static ulong (*smc_func)(ulong r0, ulong r1, ulong r2, ulong r3);
+static ulong smc_dynamic_timer(ulong r0, ulong r1, ulong r2, ulong r3);
+static ulong smc_periodic_timer(ulong r0, ulong r1, ulong r2, ulong r3);
+
static void trusty_lktimer_work_func(struct work_struct *work)
{
int ret;
@@ -72,7 +79,7 @@ static void trusty_lktimer_work_func(struct work_struct *work)
if (ret != SM_ERR_NOP_DONE)
dev_err(s->dev, "%s: SMC_SC_NOP failed %d", __func__, ret);
- dev_notice_once(s->dev, "LK OS proxy timer works\n");
+ dev_notice_once(s->dev, "LK OS timer works\n");
}
static void trusty_lktimer_func(unsigned long data)
@@ -92,6 +99,7 @@ static void trusty_init_lktimer(struct trusty_state *s)
{
INIT_WORK(&s->timer_work, trusty_lktimer_work_func);
setup_timer(&s->timer, trusty_lktimer_func, (unsigned long)s);
+ lk_timer = &s->timer;
}
/* note that this function is not thread-safe */
@@ -108,6 +116,39 @@ static void trusty_configure_lktimer(struct trusty_state *s,
mod_timer(&s->timer, jiffies + msecs_to_jiffies(s->timer_interval));
}
+static void trusty_init_smc_function(void)
+{
+ smc_func = smc_periodic_timer;
+}
+
+static void trusty_set_timer_mode(struct trusty_state *s, struct device *dev)
+{
+ int ret;
+
+ ret = trusty_fast_call32(dev, SMC_FC_TIMER_MODE, 0, 0, 0);
+
+ if (ret == 0) {
+ smc_func = smc_dynamic_timer;
+ } else {
+ smc_func = smc_periodic_timer;
+ /*
+ * If bit 31 set indicates periodic timer is used
+ * bit 15:0 indicates interval
+ */
+ if ((ret & 0x80000000) && (ret & 0x0FFFF)) {
+ trusty_configure_lktimer(s,
+ PERIODICAL_TIMER,
+ ret & 0x0FFFF);
+ } else {
+ /* set periodical timer with default interval */
+ trusty_configure_lktimer(s,
+ PERIODICAL_TIMER,
+ TRUSTY_LKTIMER_INTERVAL);
+ }
+ }
+
+}
+
/*
* this should be called when removing trusty dev and
* when LK/Trusty crashes, to disable proxy timer.
@@ -119,12 +160,45 @@ static void trusty_del_lktimer(struct trusty_state *s)
}
static inline ulong smc(ulong r0, ulong r1, ulong r2, ulong r3)
+{
+ return smc_func(r0, r1, r2, r3);
+}
+
+static ulong smc_dynamic_timer(ulong r0, ulong r1, ulong r2, ulong r3)
{
__asm__ __volatile__(
"vmcall; \n"
- :"=D"(r0)
- :"a"(TRUSTY_VMCALL_SMC), "D"(r0), "S"(r1), "d"(r2), "b"(r3)
+ : "=D"(r0), "=S"(r1), "=d"(r2), "=b"(r3)
+ : "a"(TRUSTY_VMCALL_SMC), "D"(r0), "S"(r1), "d"(r2), "b"(r3)
);
+
+ if (((r0 == SM_ERR_NOP_INTERRUPTED) ||
+ (r0 == SM_ERR_INTERRUPTED)) &&
+ (r1 != 0)) {
+ struct trusty_state *s;
+
+ if (lk_timer != NULL) {
+ s = container_of(lk_timer, struct trusty_state, timer);
+ if (r1 != TRUSTY_STOP_TIMER)
+ trusty_configure_lktimer(s, ONESHOT_TIMER, r1);
+ else
+ trusty_configure_lktimer(s, ONESHOT_TIMER, 0);
+ } else {
+ pr_err("Trusty timer has not been initialized yet!\n");
+ }
+ }
+
+ return r0;
+}
+
+static inline ulong smc_periodic_timer(ulong r0, ulong r1, ulong r2, ulong r3)
+{
+ __asm__ __volatile__(
+ "vmcall; \n"
+ : "=D"(r0), "=S"(r1), "=d"(r2), "=b"(r3)
+ : "a"(TRUSTY_VMCALL_SMC), "D"(r0), "S"(r1), "d"(r2), "b"(r3)
+ );
+
return r0;
}
@@ -472,19 +546,20 @@ static int trusty_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, s);
s->dev = &pdev->dev;
+ trusty_init_smc_function();
+ trusty_init_lktimer(s);
+ trusty_set_timer_mode(s, &pdev->dev);
+
trusty_init_version(s, &pdev->dev);
ret = trusty_init_api_version(s, &pdev->dev);
if (ret < 0)
goto err_api_version;
- trusty_init_lktimer(s);
- trusty_configure_lktimer(s,
- PERIODICAL_TIMER, TRUSTY_LKTIMER_INTERVAL);
-
return 0;
err_api_version:
+ trusty_del_lktimer(s);
if (s->version_str) {
device_remove_file(&pdev->dev, &dev_attr_trusty_version);
kfree(s->version_str);
diff --git a/include/linux/trusty/smcall.h b/include/linux/trusty/smcall.h
index 1160890a3d90..974b7b3e753d 100644
--- a/include/linux/trusty/smcall.h
+++ b/include/linux/trusty/smcall.h
@@ -123,6 +123,23 @@
#define TRUSTY_API_VERSION_CURRENT (2)
#define SMC_FC_API_VERSION SMC_FASTCALL_NR(SMC_ENTITY_SECURE_MONITOR, 11)
+/**
+ * SMC_FC_TIMER_MODE - Find and set timer mode
+ * Returns timer mode from trusty.
+ *
+ * Return value stands for:
+ * Bit 31 :
+ * If this bit is set, trusty uses periodic timer, Android trusty driver
+ * injects timer interrupt to trusty with specified interval.
+ * If this bit is clear, trusty uses dynamic timer, Android trusty
+ * driver injects timer interrupt to trusty on demand.
+ * Bit 15:0 :
+ * If bit 31 is set, Android trusty driver injects timer interrupt to
+ * trusty with interval specified by this field in milliseconds.
+ * If bit 31 is clear, this field is ignored.
+ */
+#define SMC_FC_TIMER_MODE SMC_FASTCALL_NR(SMC_ENTITY_SECURE_MONITOR, 12)
+
/* TRUSTED_OS entity calls */
#define SMC_SC_VIRTIO_GET_DESCR SMC_STDCALL_NR(SMC_ENTITY_TRUSTED_OS, 20)
#define SMC_SC_VIRTIO_START SMC_STDCALL_NR(SMC_ENTITY_TRUSTED_OS, 21)
--
https://clearlinux.org