diff --git a/linux-user/strace.c b/linux-user/strace.c
index cc10dc4..7ddcaf8 100644
--- a/linux-user/strace.c
+++ b/linux-user/strace.c
@@ -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,
diff --git a/linux-user/strace.list b/linux-user/strace.list
index aa967a2..9a665a8 100644
--- a/linux-user/strace.list
+++ b/linux-user/strace.list
@@ -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 },
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index ca06943..2190d41 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -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
diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h
index 7835654..afd9191 100644
--- a/linux-user/syscall_defs.h
+++ b/linux-user/syscall_defs.h
@@ -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
