summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--meta-tlk/recipes-kernel/linux/files/uptime-allow-the-optional-limiting-of-kernel-runtime.patch251
-rw-r--r--meta-tlk/recipes-kernel/linux/linux-intel_%.bbappend3
2 files changed, 254 insertions, 0 deletions
diff --git a/meta-tlk/recipes-kernel/linux/files/uptime-allow-the-optional-limiting-of-kernel-runtime.patch b/meta-tlk/recipes-kernel/linux/files/uptime-allow-the-optional-limiting-of-kernel-runtime.patch
new file mode 100644
index 00000000..aa143059
--- /dev/null
+++ b/meta-tlk/recipes-kernel/linux/files/uptime-allow-the-optional-limiting-of-kernel-runtime.patch
@@ -0,0 +1,251 @@
1From a21e483b57c8c31beaa5063268ec35da375daf04 Mon Sep 17 00:00:00 2001
2From: Bruce Ashfield <bruce.ashfield@windriver.com>
3Date: Tue, 12 Jul 2011 10:26:50 -0400
4Subject: [PATCH] uptime: allow the optional limiting of kernel runtime
5
6Introduce the ability to limit the limit the uptime of a kernel.
7When enabled, these options set a maximum uptime on the kernel, and
8(optionally) trigger a clean reboot at expiration.
9
10This functionality may appear to be very close to the softdog watchdog
11implementation. It is. But can't be the softdog for several reasons:
12
13 - The soft watchdog should be available while this functionality is active
14 - The duration range is different between this and the softdog. The
15 timeout available here is potentially quite a bit longer.
16 - At expiration, there are different expiration requirements and actions.
17 - This functionality is specific to a particular use case and should
18 not impact mainline functionality
19
20To cleanly restart the kernel after one minute of uptime, the following
21config items would be required:
22
23 CONFIG_UPTIME_LIMITED_KERNEL=y
24 CONFIG_UPTIME_LIMIT_DURATION=1
25 CONFIG_UPTIME_LIMIT_KERNEL_REBOOT=y
26
27Signed-off-by: Bruce Ashfield <bruce.ashfield@windriver.com>
28
29diff --git a/init/Kconfig b/init/Kconfig
30index cac3f096050d..77d6d5fa1b1d 100644
31--- a/init/Kconfig
32+++ b/init/Kconfig
33@@ -1376,6 +1376,31 @@ menuconfig EXPERT
34 environments which can tolerate a "non-standard" kernel.
35 Only use this if you really know what you are doing.
36
37+config UPTIME_LIMITED_KERNEL
38+ bool "Create a kernel with uptime limitations"
39+ default n
40+ help
41+ Limit the amount of time a kernel can run. The associated UPTIME_LIMIT*
42+ kernel config options should be used to tune the behaviour.
43+
44+config UPTIME_LIMIT_DURATION
45+ int "Kernel uptime limit in minutes"
46+ depends on UPTIME_LIMITED_KERNEL
47+ range 0 14400
48+ default 0
49+ help
50+ Define the uptime limitation on a kernel in minutes. Once
51+ the defined time expires the kernel will emit a warning, cease
52+ to be usable and eventually restart. The valid range is 0 (disable)
53+ to 14400 (10 days)
54+
55+config UPTIME_LIMIT_KERNEL_REBOOT
56+ bool "Reboot a time limited kernel at expiration"
57+ depends on UPTIME_LIMITED_KERNEL
58+ default y
59+ help
60+ Reboot an uptime limited kernel at expiration.
61+
62 config UID16
63 bool "Enable 16-bit UID system calls" if EXPERT
64 depends on HAVE_UID16 && MULTIUSER
65diff --git a/kernel/Makefile b/kernel/Makefile
66index e2ec54e2b952..6b7bdddd624b 100644
67--- a/kernel/Makefile
68+++ b/kernel/Makefile
69@@ -45,6 +45,7 @@ obj-$(CONFIG_FREEZER) += freezer.o
70 obj-$(CONFIG_PROFILING) += profile.o
71 obj-$(CONFIG_STACKTRACE) += stacktrace.o
72 obj-y += time/
73+obj-$(CONFIG_UPTIME_LIMITED_KERNEL) += uptime_limit.o
74 obj-$(CONFIG_FUTEX) += futex.o
75 ifeq ($(CONFIG_COMPAT),y)
76 obj-$(CONFIG_FUTEX) += futex_compat.o
77diff --git a/kernel/uptime_limit.c b/kernel/uptime_limit.c
78new file mode 100644
79index 000000000000..b6a1a5e4f9d9
80--- /dev/null
81+++ b/kernel/uptime_limit.c
82@@ -0,0 +1,166 @@
83+/*
84+ * uptime_limit.c
85+ *
86+ * This file contains the functions which can limit kernel uptime
87+ *
88+ * Copyright (C) 2011 Bruce Ashfield (bruce.ashfield@windriver.com)
89+ *
90+ * This program is free software; you can redistribute it and/or modify
91+ * it under the terms of the GNU General Public License as published by
92+ * the Free Software Foundation; either version 2 of the License, or
93+ * (at your option) any later version.
94+ *
95+ * This program is distributed in the hope that it will be useful,
96+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
97+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
98+ * GNU General Public License for more details.
99+ *
100+ * You should have received a copy of the GNU General Public License
101+ * along with this program; if not, write to the Free Software
102+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
103+ *
104+ *
105+ * This functionality is somewhat close to the softdog watchdog
106+ * implementation, but it cannot be used directly for several reasons:
107+ *
108+ * - The soft watchdog should be available while this functionality is active
109+ * - The duration range is different between this and the softdog. The
110+ * timeout available here is potentially quite a bit longer.
111+ * - At expiration, there are different expiration requirements and actions.
112+ * - This functionality is specific to a particular use case and should
113+ * not impact mainline functionality
114+ *
115+ */
116+#include <linux/kernel.h>
117+#include <linux/reboot.h>
118+#include <linux/timer.h>
119+#include <linux/delay.h>
120+#include <linux/kthread.h>
121+
122+#define UPTIME_LIMIT_IN_SECONDS (CONFIG_UPTIME_LIMIT_DURATION * 60)
123+#define MIN(X, Y) ((X) <= (Y) ? (X) : (Y))
124+#define TEN_MINUTES_IN_SECONDS 600
125+
126+enum uptime_expiration_type {
127+ uptime_no_action,
128+ uptime_reboot
129+};
130+
131+static enum uptime_expiration_type uptime_expiration_action = uptime_no_action;
132+static struct timer_list timelimit_timer;
133+static struct task_struct *uptime_worker_task;
134+
135+static void timelimit_expire(unsigned long timeout_seconds)
136+{
137+ char msg[128];
138+ int msglen = 127;
139+
140+ if (timeout_seconds) {
141+ if (timeout_seconds >= 60)
142+ snprintf(msg, msglen,
143+ "Uptime: kernel validity duration has %d %s remaining\n",
144+ (int) timeout_seconds / 60, "minute(s)");
145+ else
146+ snprintf(msg, msglen,
147+ "Uptime: kernel validity duration has %d %s remaining\n",
148+ (int) timeout_seconds, "seconds");
149+
150+ printk(KERN_CRIT "%s", msg);
151+
152+ timelimit_timer.expires = jiffies + timeout_seconds * HZ;
153+ timelimit_timer.data = 0;
154+ add_timer_on(&timelimit_timer, cpumask_first(cpu_online_mask));
155+ } else {
156+ printk(KERN_CRIT "Uptime: Kernel validity timeout has expired\n");
157+#ifdef CONFIG_UPTIME_LIMIT_KERNEL_REBOOT
158+ uptime_expiration_action = uptime_reboot;
159+ wake_up_process(uptime_worker_task);
160+ }
161+#endif
162+}
163+
164+/*
165+ * This thread starts and then immediately goes to sleep. When it is woken
166+ * up, it carries out the instructions left in uptime_expiration_action. If
167+ * no action was specified it simply goes back to sleep.
168+ */
169+static int uptime_worker(void *unused)
170+{
171+ set_current_state(TASK_INTERRUPTIBLE);
172+
173+ while (!kthread_should_stop()) {
174+ schedule();
175+
176+ if (kthread_should_stop())
177+ break;
178+
179+ if (uptime_expiration_action == uptime_reboot) {
180+ printk(KERN_CRIT "Uptime: restarting machine\n");
181+ kernel_restart(NULL);
182+ }
183+
184+ set_current_state(TASK_INTERRUPTIBLE);
185+ }
186+ __set_current_state(TASK_RUNNING);
187+
188+ return 0;
189+}
190+
191+static int timeout_enable(int cpu)
192+{
193+ int err = 0;
194+ int warning_limit;
195+
196+ /*
197+ * Create an uptime worker thread. This thread is required since the
198+ * safe version of kernel restart cannot be called from a
199+ * non-interruptible context. Which means we cannot call it directly
200+ * from a timer callback. So we arrange for the timer expiration to
201+ * wakeup a thread, which performs the action.
202+ */
203+ uptime_worker_task = kthread_create(uptime_worker,
204+ (void *)(unsigned long)cpu,
205+ "uptime_worker/%d", cpu);
206+ if (IS_ERR(uptime_worker_task)) {
207+ printk(KERN_ERR "Uptime: task for cpu %i failed\n", cpu);
208+ err = PTR_ERR(uptime_worker_task);
209+ goto out;
210+ }
211+ /* bind to cpu0 to avoid migration and hot plug nastiness */
212+ kthread_bind(uptime_worker_task, cpu);
213+ wake_up_process(uptime_worker_task);
214+
215+ /* Create the timer that will wake the uptime thread at expiration */
216+ init_timer(&timelimit_timer);
217+ timelimit_timer.function = timelimit_expire;
218+ /*
219+ * Fire two timers. One warning timeout and the final timer
220+ * which will carry out the expiration action. The warning timer will
221+ * expire at the minimum of half the original time or ten minutes.
222+ */
223+ warning_limit = MIN(UPTIME_LIMIT_IN_SECONDS/2, TEN_MINUTES_IN_SECONDS);
224+ timelimit_timer.expires = jiffies + warning_limit * HZ;
225+ timelimit_timer.data = UPTIME_LIMIT_IN_SECONDS - warning_limit;
226+
227+ add_timer_on(&timelimit_timer, cpumask_first(cpu_online_mask));
228+out:
229+ return err;
230+}
231+
232+static int __init timelimit_init(void)
233+{
234+ int err = 0;
235+
236+ printk(KERN_INFO "Uptime: system uptime restrictions enabled\n");
237+
238+ /*
239+ * Enable the timeout thread for cpu 0 only, assuming that the
240+ * uptime limit is non-zero, to protect against any cpu
241+ * migration issues.
242+ */
243+ if (UPTIME_LIMIT_IN_SECONDS)
244+ err = timeout_enable(0);
245+
246+ return err;
247+}
248+device_initcall(timelimit_init);
249--
2502.10.1
251
diff --git a/meta-tlk/recipes-kernel/linux/linux-intel_%.bbappend b/meta-tlk/recipes-kernel/linux/linux-intel_%.bbappend
new file mode 100644
index 00000000..47c62efe
--- /dev/null
+++ b/meta-tlk/recipes-kernel/linux/linux-intel_%.bbappend
@@ -0,0 +1,3 @@
1FILESEXTRAPATHS_prepend := "${THISDIR}/files:"
2SRC_URI_append = " file://time-limited-kernel.cfg \
3 file://uptime-allow-the-optional-limiting-of-kernel-runtime.patch"