From patchwork Tue Sep 20 19:56:40 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nicolas Pitre X-Patchwork-Id: 76627 Delivered-To: patch@linaro.org Received: by 10.140.106.72 with SMTP id d66csp1660802qgf; Tue, 20 Sep 2016 12:57:30 -0700 (PDT) X-Received: by 10.98.10.145 with SMTP id 17mr40624738pfk.144.1474401450855; Tue, 20 Sep 2016 12:57:30 -0700 (PDT) Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id l79si31249594pfi.243.2016.09.20.12.57.30; Tue, 20 Sep 2016 12:57:30 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753874AbcITT5I (ORCPT + 27 others); Tue, 20 Sep 2016 15:57:08 -0400 Received: from alt42.smtp-out.videotron.ca ([23.233.128.29]:8559 "EHLO alt42.smtp-out.videotron.ca" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752869AbcITT4r (ORCPT ); Tue, 20 Sep 2016 15:56:47 -0400 Received: from yoda.home ([96.23.157.65]) by Videotron with SMTP id mR9obBDSmcMN9mR9pbGpmx; Tue, 20 Sep 2016 15:56:46 -0400 X-Authority-Analysis: v=2.1 cv=YqOvP9sX c=1 sm=1 tr=0 a=keA3yYpnlypCNW5BNWqu+w==:117 a=keA3yYpnlypCNW5BNWqu+w==:17 a=L9H7d07YOLsA:10 a=9cW_t1CCXrUA:10 a=s5jvgZ67dGcA:10 a=GW1xBdLrtEIA:10 a=KKAkSRfTAAAA:8 a=n8CnRwfVG-Bsn8Iujn8A:9 a=YTurM7c5C5fLzAtj:21 a=twfA3-tS0Zic60_J:21 a=cvBusfyB2V15izCimMoJ:22 Received: from xanadu.home (xanadu.home [192.168.2.2]) by yoda.home (Postfix) with ESMTP id AE9C02DA0579; Tue, 20 Sep 2016 15:56:44 -0400 (EDT) From: Nicolas Pitre To: John Stultz Cc: Thomas Gleixner , Richard Cochran , Josh Triplett , netdev@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH 2/2] posix-timers: make it configurable Date: Tue, 20 Sep 2016 15:56:40 -0400 Message-Id: <1474401400-18491-3-git-send-email-nicolas.pitre@linaro.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1474401400-18491-1-git-send-email-nicolas.pitre@linaro.org> References: <1474401400-18491-1-git-send-email-nicolas.pitre@linaro.org> X-CMAE-Envelope: MS4wfN2MqS57tBUWu5apnIusqw43Fuf+PALwsp9wB787CLu4ZIziSCvIF3LbGCBw+/janaXgP8vLLSWMfyqmOeV6/AYJq25rnRaBsJ/b7POC6patgbkENR6+ LCzJkQ/Ece4X9rgTP9xNr8J03nswNIby4D292ESf4U2BZzCci9WeHKqWL0HB2YFv2Vxqcm4aP8/4XhGLf+O2458JqyKW1RvxTG3F7oP3jryEgbyD+ZOlCG8g RwVwvl8JVdTkqj95B3c3TKS699G1pVst0aunmMlL7DbkjPEfQ9XKeedRqbJXQB2Kln7vN5HZCpA/O3+G4WcJ40v4/f/JPL7YXvi1p3Mei+THgjZZcyN7dCVW +KblhJuy Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Many embedded systems typically don't need them. This removes about 22KB from the kernel binary size on ARM when configured out. Corresponding syscalls are routed to a stub logging the attempt to use those syscalls which should be enough of a clue if they were disabled without proper consideration. They are: timer_create, timer_gettime: timer_getoverrun, timer_settime, timer_delete, clock_adjtime. The clock_settime, clock_gettime, clock_getres and clock_nanosleep syscalls are replaced by simple wrappers compatible with CLOCK_REALTIME, CLOCK_MONOTONIC and CLOCK_BOOTTIME only. Signed-off-by: Nicolas Pitre --- drivers/ptp/Kconfig | 2 +- include/linux/posix-timers.h | 28 +++++++++- include/linux/sched.h | 10 ++++ init/Kconfig | 17 +++++++ kernel/signal.c | 4 ++ kernel/time/Kconfig | 1 + kernel/time/Makefile | 10 +++- kernel/time/posix-stubs.c | 118 +++++++++++++++++++++++++++++++++++++++++++ 8 files changed, 185 insertions(+), 5 deletions(-) create mode 100644 kernel/time/posix-stubs.c -- 2.7.4 diff --git a/drivers/ptp/Kconfig b/drivers/ptp/Kconfig index f34b3748c0..940fa10907 100644 --- a/drivers/ptp/Kconfig +++ b/drivers/ptp/Kconfig @@ -10,7 +10,7 @@ config PTP_1588_CLOCK_SELECTED config PTP_1588_CLOCK tristate "PTP clock support" default PTP_1588_CLOCK_SELECTED - depends on NET + depends on NET && POSIX_TIMERS select PPS select NET_PTP_CLASSIFY help diff --git a/include/linux/posix-timers.h b/include/linux/posix-timers.h index 62d44c1760..2288c5c557 100644 --- a/include/linux/posix-timers.h +++ b/include/linux/posix-timers.h @@ -118,6 +118,8 @@ struct k_clock { extern struct k_clock clock_posix_cpu; extern struct k_clock clock_posix_dynamic; +#ifdef CONFIG_POSIX_TIMERS + void posix_timers_register_clock(const clockid_t clock_id, struct k_clock *new_clock); /* function to call to trigger timer event */ @@ -131,8 +133,30 @@ void posix_cpu_timers_exit_group(struct task_struct *task); void set_process_cpu_timer(struct task_struct *task, unsigned int clock_idx, cputime_t *newval, cputime_t *oldval); -long clock_nanosleep_restart(struct restart_block *restart_block); - void update_rlimit_cpu(struct task_struct *task, unsigned long rlim_new); +#else + +#include + +static inline void posix_timers_register_clock(const clockid_t clock_id, + struct k_clock *new_clock) {} +static inline int posix_timer_event(struct k_itimer *timr, int si_private) +{ return 0; } +static inline void run_posix_cpu_timers(struct task_struct *task) {} +static inline void posix_cpu_timers_exit(struct task_struct *task) +{ + add_device_randomness((const void*) &task->se.sum_exec_runtime, + sizeof(unsigned long long)); +} +static inline void posix_cpu_timers_exit_group(struct task_struct *task) {} +static inline void set_process_cpu_timer(struct task_struct *task, + unsigned int clock_idx, cputime_t *newval, cputime_t *oldval) {} +static inline void update_rlimit_cpu(struct task_struct *task, + unsigned long rlim_new) {} + +#endif + +long clock_nanosleep_restart(struct restart_block *restart_block); + #endif diff --git a/include/linux/sched.h b/include/linux/sched.h index 54182d52a0..39a1d6d3f5 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -2924,8 +2924,13 @@ static inline void exit_thread(struct task_struct *tsk) extern void exit_files(struct task_struct *); extern void __cleanup_sighand(struct sighand_struct *); +#ifdef CONFIG_POSIX_TIMERS extern void exit_itimers(struct signal_struct *); extern void flush_itimer_signals(void); +#else +static inline void exit_itimers(struct signal_struct *s) {} +static inline void flush_itimer_signals(void) {} +#endif extern void do_group_exit(int); @@ -3382,7 +3387,12 @@ static __always_inline bool need_resched(void) * Thread group CPU time accounting. */ void thread_group_cputime(struct task_struct *tsk, struct task_cputime *times); +#ifdef CONFIG_POSIX_TIMERS void thread_group_cputimer(struct task_struct *tsk, struct task_cputime *times); +#else +static inline void thread_group_cputimer(struct task_struct *tsk, + struct task_cputime *times) {} +#endif /* * Reevaluate whether the task has signals pending delivery. diff --git a/init/Kconfig b/init/Kconfig index a117738afd..3fdea723dd 100644 --- a/init/Kconfig +++ b/init/Kconfig @@ -1449,6 +1449,23 @@ config SYSCTL_SYSCALL If unsure say N here. +config POSIX_TIMERS + bool "Posix Clocks & timers" if EXPERT + default y + help + This includes native support for POSIX timers to the kernel. + Most embedded systems may have no use for them and therefore they + can be configured out to reduce the size of the kernel image. + + When this option is disabled, the following syscalls won't be + available: timer_create, timer_gettime: timer_getoverrun, + timer_settime, timer_delete, clock_adjtime. Furthermore, the + clock_settime, clock_gettime, clock_getres and clock_nanosleep + syscalls will be limited to CLOCK_REALTIME and CLOCK_MONOTONIC + only. + + If unsure say y. + config KALLSYMS bool "Load all symbols for debugging/ksymoops" if EXPERT default y diff --git a/kernel/signal.c b/kernel/signal.c index af21afc00d..ea75065e29 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -427,6 +427,7 @@ void flush_signals(struct task_struct *t) spin_unlock_irqrestore(&t->sighand->siglock, flags); } +#ifdef CONFIG_POSIX_TIMERS static void __flush_itimer_signals(struct sigpending *pending) { sigset_t signal, retain; @@ -460,6 +461,7 @@ void flush_itimer_signals(void) __flush_itimer_signals(&tsk->signal->shared_pending); spin_unlock_irqrestore(&tsk->sighand->siglock, flags); } +#endif void ignore_signals(struct task_struct *t) { @@ -611,6 +613,7 @@ int dequeue_signal(struct task_struct *tsk, sigset_t *mask, siginfo_t *info) */ current->jobctl |= JOBCTL_STOP_DEQUEUED; } +#ifdef CONFIG_POSIX_TIMERS if ((info->si_code & __SI_MASK) == __SI_TIMER && info->si_sys_private) { /* * Release the siglock to ensure proper locking order @@ -622,6 +625,7 @@ int dequeue_signal(struct task_struct *tsk, sigset_t *mask, siginfo_t *info) do_schedule_next_timer(info); spin_lock(&tsk->sighand->siglock); } +#endif return signr; } diff --git a/kernel/time/Kconfig b/kernel/time/Kconfig index 62824f2fe4..a3817ef652 100644 --- a/kernel/time/Kconfig +++ b/kernel/time/Kconfig @@ -195,3 +195,4 @@ config HIGH_RES_TIMERS endmenu endif + diff --git a/kernel/time/Makefile b/kernel/time/Makefile index 49eca0beed..fc26c308f5 100644 --- a/kernel/time/Makefile +++ b/kernel/time/Makefile @@ -1,6 +1,12 @@ -obj-y += time.o timer.o hrtimer.o itimer.o posix-timers.o posix-cpu-timers.o +obj-y += time.o timer.o hrtimer.o itimer.o obj-y += timekeeping.o ntp.o clocksource.o jiffies.o timer_list.o -obj-y += timeconv.o timecounter.o posix-clock.o alarmtimer.o +obj-y += timeconv.o timecounter.o alarmtimer.o + +ifeq ($(CONFIG_POSIX_TIMERS),y) + obj-y += posix-timers.o posix-cpu-timers.o posix-clock.o +else + obj-y += posix-stubs.o +endif obj-$(CONFIG_GENERIC_CLOCKEVENTS) += clockevents.o tick-common.o ifeq ($(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST),y) diff --git a/kernel/time/posix-stubs.c b/kernel/time/posix-stubs.c new file mode 100644 index 0000000000..fe857bd4a0 --- /dev/null +++ b/kernel/time/posix-stubs.c @@ -0,0 +1,118 @@ +/* + * Dummy stubs used when CONFIG_POSIX_TIMERS=n + * + * Created by: Nicolas Pitre, July 2016 + * Copyright: (C) 2016 Linaro Limited + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +asmlinkage long sys_ni_posix_timers(void) +{ + pr_err_once("process %d (%s) attempted a POSIX timer syscall " + "while CONFIG_POSIX_TIMERS is not set\n", + current->pid, current->comm); + return -ENOSYS; +} + +#define SYS_NI(name) SYSCALL_ALIAS(sys_##name, sys_ni_posix_timers) + +SYS_NI(timer_create); +SYS_NI(timer_gettime); +SYS_NI(timer_getoverrun); +SYS_NI(timer_settime); +SYS_NI(timer_delete); +SYS_NI(clock_adjtime); + +/* + * We preserve minimal support for CLOCK_REALTIME and CLOCK_MONOTONIC + * as it is easy to remain compatible with little code. CLOCK_BOOTTIME + * is also included for convenience as at least systemd uses it. + */ + +SYSCALL_DEFINE2(clock_settime, const clockid_t, which_clock, + const struct timespec __user *, tp) +{ + struct timespec new_tp; + + if (which_clock != CLOCK_REALTIME) + return -EINVAL; + if (copy_from_user(&new_tp, tp, sizeof (*tp))) + return -EFAULT; + return do_sys_settimeofday(&new_tp, NULL); +} + +SYSCALL_DEFINE2(clock_gettime, const clockid_t, which_clock, + struct timespec __user *,tp) +{ + struct timespec kernel_tp; + + switch (which_clock) { + case CLOCK_REALTIME: ktime_get_real_ts(&kernel_tp); break; + case CLOCK_MONOTONIC: ktime_get_ts(&kernel_tp); break; + case CLOCK_BOOTTIME: get_monotonic_boottime(&kernel_tp); break; + default: return -EINVAL; + } + if (copy_to_user(tp, &kernel_tp, sizeof (kernel_tp))) + return -EFAULT; + return 0; +} + +SYSCALL_DEFINE2(clock_getres, const clockid_t, which_clock, struct timespec __user *, tp) +{ + struct timespec rtn_tp = { + .tv_sec = 0, + .tv_nsec = hrtimer_resolution, + }; + + switch (which_clock) { + case CLOCK_REALTIME: + case CLOCK_MONOTONIC: + case CLOCK_BOOTTIME: + if (copy_to_user(tp, &rtn_tp, sizeof(rtn_tp))) + return -EFAULT; + return 0; + default: + return -EINVAL; + } +} + +SYSCALL_DEFINE4(clock_nanosleep, const clockid_t, which_clock, int, flags, + const struct timespec __user *, rqtp, + struct timespec __user *, rmtp) +{ + struct timespec t; + + switch (which_clock) { + case CLOCK_REALTIME: + case CLOCK_MONOTONIC: + case CLOCK_BOOTTIME: + if (copy_from_user(&t, rqtp, sizeof (struct timespec))) + return -EFAULT; + if (!timespec_valid(&t)) + return -EINVAL; + return hrtimer_nanosleep(&t, rmtp, flags & TIMER_ABSTIME ? + HRTIMER_MODE_ABS : HRTIMER_MODE_REL, + which_clock); + default: + return -EINVAL; + } +} + +#ifdef CONFIG_COMPAT +long clock_nanosleep_restart(struct restart_block *restart_block) +{ + return hrtimer_nanosleep_restart(restart_block); +} +#endif