@@ -919,6 +919,18 @@ print_access(const struct syscallname *name,
}
#endif
+#ifdef TARGET_NR_adjtimex
+static void
+print_adjtimex(const struct syscallname *name,
+ abi_long arg0, abi_long arg1, abi_long arg2,
+ abi_long arg3, abi_long arg4, abi_long arg5)
+{
+ print_syscall_prologue(name);
+ print_pointer(arg0, 1);
+ print_syscall_epilogue(name);
+}
+#endif
+
#ifdef TARGET_NR_brk
static void
print_brk(const struct syscallname *name,
@@ -16,7 +16,7 @@
{ TARGET_NR_add_key, "add_key" , NULL, NULL, NULL },
#endif
#ifdef TARGET_NR_adjtimex
-{ TARGET_NR_adjtimex, "adjtimex" , NULL, NULL, NULL },
+{ TARGET_NR_adjtimex, "adjtimex" , NULL, print_adjtimex, NULL },
#endif
#ifdef TARGET_NR_afs_syscall
{ TARGET_NR_afs_syscall, "afs_syscall" , NULL, NULL, NULL },
@@ -35,6 +35,7 @@
#include <sys/swap.h>
#include <linux/capability.h>
#include <sched.h>
+#include <sys/timex.h>
#ifdef __ia64__
int __clone2(int (*fn)(void *), void *child_stack_base,
size_t stack_size, int flags, void *arg, ...);
@@ -6578,6 +6579,76 @@ static inline abi_long target_ftruncate64(void *cpu_env, abi_long arg1,
}
#endif
+static inline abi_long target_to_host_timex(struct timex *host_buf,
+ abi_long target_addr)
+{
+ struct target_timex *target_buf;
+
+ if (!lock_user_struct(VERIFY_READ, target_buf, target_addr, 1)) {
+ return -TARGET_EFAULT;
+ }
+
+ host_buf->modes = tswap32(target_buf->modes);
+ host_buf->offset = tswapal(target_buf->offset);
+ host_buf->freq = tswapal(target_buf->freq);
+ host_buf->maxerror = tswapal(target_buf->maxerror);
+ host_buf->esterror = tswapal(target_buf->esterror);
+ host_buf->status = tswap32(target_buf->status);
+ host_buf->constant = tswapal(target_buf->constant);
+ host_buf->precision = tswapal(target_buf->precision);
+ host_buf->tolerance = tswapal(target_buf->tolerance);
+ host_buf->time.tv_sec = tswapal(target_buf->time.tv_sec);
+ host_buf->time.tv_usec = tswapal(target_buf->time.tv_usec);
+ host_buf->tick = tswapal(target_buf->tick);
+ host_buf->ppsfreq = tswapal(target_buf->ppsfreq);
+ host_buf->jitter = tswapal(target_buf->jitter);
+ host_buf->shift = tswap32(target_buf->shift);
+ host_buf->stabil = tswapal(target_buf->stabil);
+ host_buf->jitcnt = tswapal(target_buf->jitcnt);
+ host_buf->calcnt = tswapal(target_buf->calcnt);
+ host_buf->errcnt = tswapal(target_buf->errcnt);
+ host_buf->stbcnt = tswapal(target_buf->stbcnt);
+ host_buf->tai = tswap32(target_buf->tai);
+
+ unlock_user_struct(target_buf, target_addr, 0);
+ return 0;
+}
+
+static inline abi_long host_to_target_timex(abi_long target_addr,
+ struct timex *host_buf)
+{
+ struct target_timex *target_buf;
+
+ if (!lock_user_struct(VERIFY_WRITE, target_buf, target_addr, 0)) {
+ return -TARGET_EFAULT;
+ }
+
+ target_buf->modes = tswap32(host_buf->modes);
+ target_buf->offset = tswapal(host_buf->offset);
+ target_buf->freq = tswapal(host_buf->freq);
+ target_buf->maxerror = tswapal(host_buf->maxerror);
+ target_buf->esterror = tswapal(host_buf->esterror);
+ target_buf->status = tswap32(host_buf->status);
+ target_buf->constant = tswapal(host_buf->constant);
+ target_buf->precision = tswapal(host_buf->precision);
+ target_buf->tolerance = tswapal(host_buf->tolerance);
+ target_buf->time.tv_sec = tswapal(host_buf->time.tv_sec);
+ target_buf->time.tv_usec = tswapal(host_buf->time.tv_usec);
+ target_buf->tick = tswapal(host_buf->tick);
+ target_buf->ppsfreq = tswapal(host_buf->ppsfreq);
+ target_buf->jitter = tswapal(host_buf->jitter);
+ target_buf->shift = tswap32(host_buf->shift);
+ target_buf->stabil = tswapal(host_buf->stabil);
+ target_buf->jitcnt = tswapal(host_buf->jitcnt);
+ target_buf->calcnt = tswapal(host_buf->calcnt);
+ target_buf->errcnt = tswapal(host_buf->errcnt);
+ target_buf->stbcnt = tswapal(host_buf->stbcnt);
+ target_buf->tai = tswap32(host_buf->tai);
+
+ unlock_user_struct(target_buf, target_addr, 1);
+ return 0;
+}
+
static inline abi_long target_to_host_timespec(struct timespec *host_ts,
abi_ulong target_addr)
{
@@ -9420,7 +9491,20 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
#endif
#endif
case TARGET_NR_adjtimex:
- goto unimplemented;
+ {
+ struct timex host_buf;
+
+ if (target_to_host_timex(&host_buf, arg1) != 0) {
+ goto efault;
+ }
+ ret = get_errno(adjtimex(&host_buf));
+ if (!is_error(ret) && arg1) {
+ if (host_to_target_timex(arg1, &host_buf) != 0) {
+ goto efault;
+ }
+ }
+ }
+ break;
#ifdef TARGET_NR_create_module
case TARGET_NR_create_module:
#endif
@@ -207,6 +207,34 @@ struct target_itimerspec {
struct target_timespec it_value;
};
+struct target_timex {
+ unsigned int modes; /* Mode selector */
+ abi_long offset; /* Time offset */
+ abi_long freq; /* Frequency offset */
+ abi_long maxerror; /* Maximum error (microseconds) */
+ abi_long esterror; /* Estimated error (microseconds) */
+ int status; /* Clock command/status */
+ abi_long constant; /* PLL (phase-locked loop) time constant */
+ abi_long precision; /* Clock precision (microseconds, ro) */
+ abi_long tolerance; /* Clock freq. tolerance (ppm, ro) */
+ struct target_timeval time; /* Current time */
+ abi_long tick; /* Microseconds between clock ticks */
+ abi_long ppsfreq; /* PPS (pulse per second) frequency */
+ abi_long jitter; /* PPS jitter (ro); nanoseconds */
+ int shift; /* PPS interval duration (seconds) */
+ abi_long stabil; /* PPS stability */
+ abi_long jitcnt; /* PPS jitter limit exceeded (ro) */
+ abi_long calcnt; /* PPS calibration intervals */
+ abi_long errcnt; /* PPS calibration errors */
+ abi_long stbcnt; /* PPS stability limit exceeded */
+ int tai; /* TAI offset */
+
+ /* Further padding bytes to allow for future expansion */
+ int:32; int:32; int:32; int:32;
+ int:32; int:32; int:32; int:32;
+ int:32; int:32; int:32;
+};
+
typedef abi_long target_clock_t;
#define TARGET_HZ 100