Commit 817b9b14 authored by Philippe Gerum's avatar Philippe Gerum
Browse files

cobalt/kernel: add clock_adjtime() syscall

parent 9d8010f8
......@@ -53,6 +53,8 @@ struct xnclock {
xnticks_t (*read_monotonic)(struct xnclock *clock);
int (*set_time)(struct xnclock *clock,
const struct timespec *ts);
int (*adjust_time)(struct xnclock *clock,
struct timex *tx);
xnsticks_t (*ns_to_ticks)(struct xnclock *clock,
xnsticks_t ns);
xnsticks_t (*ticks_to_ns)(struct xnclock *clock,
......@@ -252,6 +254,15 @@ static inline int xnclock_set_time(struct xnclock *clock,
#endif /* !CONFIG_XENO_OPT_EXTCLOCK */
static inline int xnclock_adjust_time(struct xnclock *clock,
struct timex *tx)
{
if (clock->ops.adjust_time == NULL)
return -EOPNOTSUPP;
return clock->ops.adjust_time(clock, tx);
}
static inline xnticks_t xnclock_get_offset(struct xnclock *clock)
{
return clock->wallclock_offset;
......
......@@ -104,6 +104,12 @@ int sys32_get_timeval(struct timeval *tv,
int sys32_put_timeval(struct compat_timeval __user *ctv,
const struct timeval *tv);
int sys32_get_timex(struct timex *tx,
const struct compat_timex __user *ctx);
int sys32_put_timex(struct compat_timex __user *ctx,
const struct timex *tx);
ssize_t sys32_get_fdset(fd_set *fds, const compat_fd_set __user *cfds,
size_t cfdsize);
......
......@@ -120,6 +120,7 @@
#define sc_cobalt_ftrace_puts 97
#define sc_cobalt_recvmmsg 98
#define sc_cobalt_sendmmsg 99
#define sc_cobalt_clock_adjtime 100
#define __NR_COBALT_SYSCALLS 128 /* Power of 2 */
......
......@@ -221,6 +221,27 @@ int __cobalt_clock_settime(clockid_t clock_id, const struct timespec *ts)
return 0;
}
int __cobalt_clock_adjtime(clockid_t clock_id, struct timex *tx)
{
int _ret, ret = 0;
switch (clock_id) {
case CLOCK_REALTIME:
case CLOCK_MONOTONIC:
case CLOCK_MONOTONIC_RAW:
case CLOCK_HOST_REALTIME:
return -EOPNOTSUPP;
default:
_ret = do_ext_clock(clock_id, adjust_time, ret, tx);
if (_ret || ret)
return _ret ?: ret;
}
trace_cobalt_clock_adjtime(clock_id, tx);
return 0;
}
COBALT_SYSCALL(clock_settime, current,
(clockid_t clock_id, const struct timespec __user *u_ts))
{
......@@ -232,6 +253,22 @@ COBALT_SYSCALL(clock_settime, current,
return __cobalt_clock_settime(clock_id, &ts);
}
COBALT_SYSCALL(clock_adjtime, current,
(clockid_t clock_id, struct timex __user *u_tx))
{
struct timex tx;
int ret;
if (cobalt_copy_from_user(&tx, u_tx, sizeof(tx)))
return -EFAULT;
ret = __cobalt_clock_adjtime(clock_id, &tx);
if (ret)
return ret;
return cobalt_copy_to_user(u_tx, &tx, sizeof(tx));
}
int __cobalt_clock_nanosleep(clockid_t clock_id, int flags,
const struct timespec *rqt,
struct timespec *rmt)
......
......@@ -88,6 +88,9 @@ int __cobalt_clock_gettime(clockid_t clock_id,
int __cobalt_clock_settime(clockid_t clock_id,
const struct timespec *ts);
int __cobalt_clock_adjtime(clockid_t clock_id,
struct timex *tx);
int __cobalt_clock_nanosleep(clockid_t clock_id, int flags,
const struct timespec *rqt,
struct timespec *rmt);
......@@ -101,6 +104,9 @@ COBALT_SYSCALL_DECL(clock_gettime,
COBALT_SYSCALL_DECL(clock_settime,
(clockid_t clock_id, const struct timespec __user *u_ts));
COBALT_SYSCALL_DECL(clock_adjtime,
(clockid_t clock_id, struct timex __user *u_tx));
COBALT_SYSCALL_DECL(clock_nanosleep,
(clockid_t clock_id, int flags,
const struct timespec __user *u_rqt,
......
......@@ -16,6 +16,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <linux/err.h>
#include <linux/memory.h>
#include <linux/module.h>
#include <cobalt/kernel/compat.h>
#include <asm/xenomai/syscall.h>
......@@ -79,6 +80,68 @@ int sys32_put_timeval(struct compat_timeval __user *ctv,
}
EXPORT_SYMBOL_GPL(sys32_put_timeval);
int sys32_get_timex(struct timex *tx,
const struct compat_timex __user *ctx)
{
memset(tx, 0, sizeof(*tx));
if (!access_rok(ctx, sizeof(*ctx)) ||
__xn_get_user(tx->modes, &ctx->modes) ||
__xn_get_user(tx->offset, &ctx->offset) ||
__xn_get_user(tx->freq, &ctx->freq) ||
__xn_get_user(tx->maxerror, &ctx->maxerror) ||
__xn_get_user(tx->esterror, &ctx->esterror) ||
__xn_get_user(tx->status, &ctx->status) ||
__xn_get_user(tx->constant, &ctx->constant) ||
__xn_get_user(tx->precision, &ctx->precision) ||
__xn_get_user(tx->tolerance, &ctx->tolerance) ||
__xn_get_user(tx->time.tv_sec, &ctx->time.tv_sec) ||
__xn_get_user(tx->time.tv_usec, &ctx->time.tv_usec) ||
__xn_get_user(tx->tick, &ctx->tick) ||
__xn_get_user(tx->ppsfreq, &ctx->ppsfreq) ||
__xn_get_user(tx->jitter, &ctx->jitter) ||
__xn_get_user(tx->shift, &ctx->shift) ||
__xn_get_user(tx->stabil, &ctx->stabil) ||
__xn_get_user(tx->jitcnt, &ctx->jitcnt) ||
__xn_get_user(tx->calcnt, &ctx->calcnt) ||
__xn_get_user(tx->errcnt, &ctx->errcnt) ||
__xn_get_user(tx->stbcnt, &ctx->stbcnt))
return -EFAULT;
return 0;
}
EXPORT_SYMBOL_GPL(sys32_get_timex);
int sys32_put_timex(struct compat_timex __user *ctx,
const struct timex *tx)
{
if (!access_wok(ctx, sizeof(*ctx)) ||
__xn_put_user(tx->modes, &ctx->modes) ||
__xn_put_user(tx->offset, &ctx->offset) ||
__xn_put_user(tx->freq, &ctx->freq) ||
__xn_put_user(tx->maxerror, &ctx->maxerror) ||
__xn_put_user(tx->esterror, &ctx->esterror) ||
__xn_put_user(tx->status, &ctx->status) ||
__xn_put_user(tx->constant, &ctx->constant) ||
__xn_put_user(tx->precision, &ctx->precision) ||
__xn_put_user(tx->tolerance, &ctx->tolerance) ||
__xn_put_user(tx->time.tv_sec, &ctx->time.tv_sec) ||
__xn_put_user(tx->time.tv_usec, &ctx->time.tv_usec) ||
__xn_put_user(tx->tick, &ctx->tick) ||
__xn_put_user(tx->ppsfreq, &ctx->ppsfreq) ||
__xn_put_user(tx->jitter, &ctx->jitter) ||
__xn_put_user(tx->shift, &ctx->shift) ||
__xn_put_user(tx->stabil, &ctx->stabil) ||
__xn_put_user(tx->jitcnt, &ctx->jitcnt) ||
__xn_put_user(tx->calcnt, &ctx->calcnt) ||
__xn_put_user(tx->errcnt, &ctx->errcnt) ||
__xn_put_user(tx->stbcnt, &ctx->stbcnt))
return -EFAULT;
return 0;
}
EXPORT_SYMBOL_GPL(sys32_put_timex);
ssize_t sys32_get_fdset(fd_set *fds, const compat_fd_set __user *cfds,
size_t cfdsize)
{
......
......@@ -162,6 +162,23 @@ COBALT_SYSCALL32emu(clock_settime, current,
return __cobalt_clock_settime(clock_id, &ts);
}
COBALT_SYSCALL32emu(clock_adjtime, current,
(clockid_t clock_id, struct compat_timex __user *u_tx))
{
struct timex tx;
int ret;
ret = sys32_get_timex(&tx, u_tx);
if (ret)
return ret;
ret = __cobalt_clock_adjtime(clock_id, &tx);
if (ret)
return ret;
return sys32_put_timex(u_tx, &tx);
}
COBALT_SYSCALL32emu(clock_nanosleep, nonrestartable,
(clockid_t clock_id, int flags,
const struct compat_timespec __user *u_rqt,
......
......@@ -57,6 +57,10 @@ COBALT_SYSCALL32emu_DECL(clock_settime,
(clockid_t clock_id,
const struct compat_timespec __user *u_ts));
COBALT_SYSCALL32emu_DECL(clock_adjtime,
(clockid_t clock_id,
struct compat_timex __user *u_tx));
COBALT_SYSCALL32emu_DECL(clock_nanosleep,
(clockid_t clock_id, int flags,
const struct compat_timespec __user *u_rqt,
......
......@@ -160,7 +160,8 @@
__cobalt_symbolic_syscall(extend), \
__cobalt_symbolic_syscall(ftrace_puts), \
__cobalt_symbolic_syscall(recvmmsg), \
__cobalt_symbolic_syscall(sendmmsg))
__cobalt_symbolic_syscall(sendmmsg), \
__cobalt_symbolic_syscall(clock_adjtime))
DECLARE_EVENT_CLASS(syscall_entry,
TP_PROTO(unsigned int nr),
......@@ -749,6 +750,26 @@ DEFINE_EVENT(cobalt_clock_timespec, cobalt_clock_settime,
TP_ARGS(clk_id, time)
);
TRACE_EVENT(cobalt_clock_adjtime,
TP_PROTO(clockid_t clk_id, struct timex *tx),
TP_ARGS(clk_id, tx),
TP_STRUCT__entry(
__field(clockid_t, clk_id)
__field(struct timex *, tx)
),
TP_fast_assign(
__entry->clk_id = clk_id;
__entry->tx = tx;
),
TP_printk("clock_id=%d timex=%p",
__entry->clk_id,
__entry->tx
)
);
#define cobalt_print_timer_flags(__flags) \
__print_flags(__flags, "|", \
{TIMER_ABSTIME, "TIMER_ABSTIME"})
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment