summaryrefslogtreecommitdiff
path: root/arch/sparc/kernel/sys_sparc_64.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/sparc/kernel/sys_sparc_64.c')
-rw-r--r--arch/sparc/kernel/sys_sparc_64.c59
1 files changed, 58 insertions, 1 deletions
diff --git a/arch/sparc/kernel/sys_sparc_64.c b/arch/sparc/kernel/sys_sparc_64.c
index 1c079e7bab09..9825ca6a6020 100644
--- a/arch/sparc/kernel/sys_sparc_64.c
+++ b/arch/sparc/kernel/sys_sparc_64.c
@@ -28,8 +28,9 @@
#include <linux/random.h>
#include <linux/export.h>
#include <linux/context_tracking.h>
-
+#include <linux/timex.h>
#include <linux/uaccess.h>
+
#include <asm/utrap.h>
#include <asm/unistd.h>
@@ -544,6 +545,62 @@ out_unlock:
return err;
}
+SYSCALL_DEFINE1(sparc_adjtimex, struct timex __user *, txc_p)
+{
+ struct timex txc; /* Local copy of parameter */
+ struct __kernel_timex *kt = (void *)&txc;
+ int ret;
+
+ /* Copy the user data space into the kernel copy
+ * structure. But bear in mind that the structures
+ * may change
+ */
+ if (copy_from_user(&txc, txc_p, sizeof(struct timex)))
+ return -EFAULT;
+
+ /*
+ * override for sparc64 specific timeval type: tv_usec
+ * is 32 bit wide instead of 64-bit in __kernel_timex
+ */
+ kt->time.tv_usec = txc.time.tv_usec;
+ ret = do_adjtimex(kt);
+ txc.time.tv_usec = kt->time.tv_usec;
+
+ return copy_to_user(txc_p, &txc, sizeof(struct timex)) ? -EFAULT : ret;
+}
+
+SYSCALL_DEFINE2(sparc_clock_adjtime, const clockid_t, which_clock,struct timex __user *, txc_p)
+{
+ struct timex txc; /* Local copy of parameter */
+ struct __kernel_timex *kt = (void *)&txc;
+ int ret;
+
+ if (!IS_ENABLED(CONFIG_POSIX_TIMERS)) {
+ 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;
+ }
+
+ /* Copy the user data space into the kernel copy
+ * structure. But bear in mind that the structures
+ * may change
+ */
+ if (copy_from_user(&txc, txc_p, sizeof(struct timex)))
+ return -EFAULT;
+
+ /*
+ * override for sparc64 specific timeval type: tv_usec
+ * is 32 bit wide instead of 64-bit in __kernel_timex
+ */
+ kt->time.tv_usec = txc.time.tv_usec;
+ ret = do_clock_adjtime(which_clock, kt);
+ txc.time.tv_usec = kt->time.tv_usec;
+
+ return copy_to_user(txc_p, &txc, sizeof(struct timex)) ? -EFAULT : ret;
+}
+
SYSCALL_DEFINE5(utrap_install, utrap_entry_t, type,
utrap_handler_t, new_p, utrap_handler_t, new_d,
utrap_handler_t __user *, old_p,