All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH v2 0/3] linux-user: Add support for adjtimex(), sysfs(), and ustat() syscalls
@ 2016-09-05 14:00 Aleksandar Markovic
  2016-09-05 14:00 ` [Qemu-devel] [PATCH v2 1/3] linux-user: Add support for adjtimex() syscall Aleksandar Markovic
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Aleksandar Markovic @ 2016-09-05 14:00 UTC (permalink / raw)
  To: qemu-devel, riku.voipio, peter.maydell, petar.jovanovic,
	miodrag.dinic, aleksandar.markovic

From: Aleksandar Markovic <aleksandar.markovic@imgtec.com>

v1->v2:
    - added "#ifdef TARGET_NR_adjtimex" where appropriate in patch 1/3.

This patch series adds support for three syscalls to the Qemu user mode.

Each patch fixes certain LTP test failures that occur if LTP tests are
executed in Qemu user mode. This improvement will affect all platforms
supported by Qemu. Altogether, there are 10 LTP tests fixed by this series.

Where needed, the support for "-strace" switch is included as well.

For each patch, a minimal test example is created that demonstrates
the correctness of the implementation, and such example is compiled and
tested on arm, i386, mips, mipsel, ppc, sh4, and sparc platforms.

All patches are checked with scripts/checkpatch.pl.

Aleksandar Markovic (3):
  linux-user: Add support for adjtimex() syscall
  linux-user: Add support for sysfs() syscall
  linux-user: Add support for ustat() syscall

 linux-user/strace.c       |   37 +++++++++++
 linux-user/strace.list    |    4 +-
 linux-user/syscall.c      |  157 ++++++++++++++++++++++++++++++++++++++++++++-
 linux-user/syscall_defs.h |   28 ++++++++
 4 files changed, 221 insertions(+), 5 deletions(-)

-- 
1.7.9.5

^ permalink raw reply	[flat|nested] 4+ messages in thread

* [Qemu-devel] [PATCH v2 1/3] linux-user: Add support for adjtimex() syscall
  2016-09-05 14:00 [Qemu-devel] [PATCH v2 0/3] linux-user: Add support for adjtimex(), sysfs(), and ustat() syscalls Aleksandar Markovic
@ 2016-09-05 14:00 ` Aleksandar Markovic
  2016-09-05 14:00 ` [Qemu-devel] [PATCH v2 2/3] linux-user: Add support for sysfs() syscall Aleksandar Markovic
  2016-09-05 14:00 ` [Qemu-devel] [PATCH v2 3/3] linux-user: Add support for ustat() syscall Aleksandar Markovic
  2 siblings, 0 replies; 4+ messages in thread
From: Aleksandar Markovic @ 2016-09-05 14:00 UTC (permalink / raw)
  To: qemu-devel, riku.voipio, peter.maydell, petar.jovanovic,
	miodrag.dinic, aleksandar.markovic

From: Aleksandar Markovic <aleksandar.markovic@imgtec.com>

This patch implements Qemu user mode adjtimex() syscall support.

Syscall adjtimex() reads and optionally sets parameters for a clock
adjustment algorithm used in network synchonization or similar scenarios.

The implementation is based on invocation of host's adjtimex(), and
its key part is in the correspondent case segment of the main switch
statement of the function do_syscall(), in file linux-user/syscalls.c.
Also, support for related structure "timex" is added to the file
linux-user/syscall_defs.h, based on its definition in Linux kernel. All
necessary conversions of the data structures from target to host and from
host to target are covered. Two new functions, target_to_host_timex() and
host_to_target_timex(), are provided for the purpose of such conversions.
Moreover, the relevant support for "-strace" Qemu option is included in
files linux-user/strace.c and linux-user/strace.list.

This patch also fixes failures of LTP tests adjtimex01 and adjtimex02, if
executed in Qemu user mode.

Signed-off-by: Aleksandar Rikalo <aleksandar.rikalo@imgtec.com>
---
 linux-user/strace.c       |   12 ++++++
 linux-user/strace.list    |    2 +-
 linux-user/syscall.c      |   90 ++++++++++++++++++++++++++++++++++++++++++++-
 linux-user/syscall_defs.h |   28 ++++++++++++++
 4 files changed, 130 insertions(+), 2 deletions(-)

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..5643840 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,78 @@ static inline abi_long target_ftruncate64(void *cpu_env, abi_long arg1,
 }
 #endif
 
+#ifdef TARGET_NR_adjtimex
+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;
+}
+#endif
+
 static inline abi_long target_to_host_timespec(struct timespec *host_ts,
                                                abi_ulong target_addr)
 {
@@ -9419,8 +9492,23 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
         break;
 #endif
 #endif
+#ifdef TARGET_NR_adjtimex
     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;
+#endif
 #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
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [Qemu-devel] [PATCH v2 2/3] linux-user: Add support for sysfs() syscall
  2016-09-05 14:00 [Qemu-devel] [PATCH v2 0/3] linux-user: Add support for adjtimex(), sysfs(), and ustat() syscalls Aleksandar Markovic
  2016-09-05 14:00 ` [Qemu-devel] [PATCH v2 1/3] linux-user: Add support for adjtimex() syscall Aleksandar Markovic
@ 2016-09-05 14:00 ` Aleksandar Markovic
  2016-09-05 14:00 ` [Qemu-devel] [PATCH v2 3/3] linux-user: Add support for ustat() syscall Aleksandar Markovic
  2 siblings, 0 replies; 4+ messages in thread
From: Aleksandar Markovic @ 2016-09-05 14:00 UTC (permalink / raw)
  To: qemu-devel, riku.voipio, peter.maydell, petar.jovanovic,
	miodrag.dinic, aleksandar.markovic

From: Aleksandar Markovic <aleksandar.markovic@imgtec.com>

This patch implements Qemu user mode sysfs() syscall support.

Syscall sysfs() involves returning information about the filesystem types
currently present in the kernel, and can operate in three distinct flavors,
depending on its first argument.

The implementation is based on invocation of host's sysfs(), and
its key part is in the correspondent case segment of the main switch
statement of the function do_syscall(), in file linux-user/syscalls.c.
All necessary conversions of data structures from target to host and from
host to target are covered. Based on the value of the first argument, three
cases are distinguished, and such conversions are implemented separately
for each case. Relevant support for "-strace" option is included in files
linux-user/strace.c and linux-user/strace.list.

This patch also fixes failures of LTP tests sysfs01, sysfs02, sysfs03,
sysfs04, sysfs05, and sysfs06, if executed in Qemu user mode.

Signed-off-by: Aleksandar Markovic <aleksandar.markovic@imgtec.com>
---
 linux-user/strace.c    |   25 +++++++++++++++++++++++++
 linux-user/strace.list |    2 +-
 linux-user/syscall.c   |   42 +++++++++++++++++++++++++++++++++++++++++-
 3 files changed, 67 insertions(+), 2 deletions(-)

diff --git a/linux-user/strace.c b/linux-user/strace.c
index 7ddcaf8..a52ff58 100644
--- a/linux-user/strace.c
+++ b/linux-user/strace.c
@@ -2138,6 +2138,31 @@ print_kill(const struct syscallname *name,
 }
 #endif
 
+#if defined(TARGET_NR_sysfs)
+static void
+print_sysfs(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);
+    switch (arg0) {
+    case 1:
+        print_raw_param("%d", arg0, 1);
+        print_string(arg1, 1);
+        break;
+    case 2:
+        print_raw_param("%d", arg0, 0);
+        print_raw_param("%u", arg1, 0);
+        print_pointer(arg2, 1);
+        break;
+    default:
+        print_raw_param("%d", arg0, 1);
+        break;
+    }
+    print_syscall_epilogue(name);
+}
+#endif
+
 /*
  * An array of all of the syscalls we know about
  */
diff --git a/linux-user/strace.list b/linux-user/strace.list
index 9a665a8..e8133b0 100644
--- a/linux-user/strace.list
+++ b/linux-user/strace.list
@@ -1368,7 +1368,7 @@
 { TARGET_NR_sys_epoll_wait, "sys_epoll_wait" , NULL, NULL, NULL },
 #endif
 #ifdef TARGET_NR_sysfs
-{ TARGET_NR_sysfs, "sysfs" , NULL, NULL, NULL },
+{ TARGET_NR_sysfs, "sysfs" , NULL, print_sysfs, NULL },
 #endif
 #ifdef TARGET_NR_sysinfo
 { TARGET_NR_sysinfo, "sysinfo" , NULL, NULL, NULL },
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 5643840..38d69f1 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -9532,7 +9532,47 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
 #endif
 #ifdef TARGET_NR_sysfs
     case TARGET_NR_sysfs:
-        goto unimplemented;
+        switch (arg1) {
+        case 1:
+            {
+                if (arg2 != 0) {
+                    p = lock_user_string(arg2);
+                    if (!p) {
+                        goto efault;
+                    }
+                    ret = get_errno(syscall(__NR_sysfs, arg1, p));
+                    unlock_user(p, arg2, 0);
+                } else {
+                    ret = get_errno(syscall(__NR_sysfs, arg1, NULL));
+                }
+            }
+            break;
+        case 2:
+            {
+                if (arg3 != 0) {
+                    char buf[PATH_MAX];
+                    int len;
+                    memset(buf, 0, PATH_MAX);
+                    ret = get_errno(syscall(__NR_sysfs, arg1, arg2, buf));
+                    len = PATH_MAX;
+                    if (len > strlen(buf)) {
+                        len = strlen(buf);
+                    }
+                    if (copy_to_user(arg3, buf, len) != 0) {
+                        goto efault;
+                    }
+                } else {
+                    ret = get_errno(syscall(__NR_sysfs, arg1, arg2, NULL));
+                }
+            }
+            break;
+        case 3:
+            ret = get_errno(syscall(__NR_sysfs, arg1));
+            break;
+        default:
+            ret = -EINVAL;
+        }
+        break;
 #endif
     case TARGET_NR_personality:
         ret = get_errno(personality(arg1));
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [Qemu-devel] [PATCH v2 3/3] linux-user: Add support for ustat() syscall
  2016-09-05 14:00 [Qemu-devel] [PATCH v2 0/3] linux-user: Add support for adjtimex(), sysfs(), and ustat() syscalls Aleksandar Markovic
  2016-09-05 14:00 ` [Qemu-devel] [PATCH v2 1/3] linux-user: Add support for adjtimex() syscall Aleksandar Markovic
  2016-09-05 14:00 ` [Qemu-devel] [PATCH v2 2/3] linux-user: Add support for sysfs() syscall Aleksandar Markovic
@ 2016-09-05 14:00 ` Aleksandar Markovic
  2 siblings, 0 replies; 4+ messages in thread
From: Aleksandar Markovic @ 2016-09-05 14:00 UTC (permalink / raw)
  To: qemu-devel, riku.voipio, peter.maydell, petar.jovanovic,
	miodrag.dinic, aleksandar.markovic

From: Aleksandar Markovic <aleksandar.markovic@imgtec.com>

This patch implements Qemu user mode ustat() syscall support.

Syscall ustat() returns information about a mounted filesystem.

The implementation is similar to the implementations of statfs(),
fstatfs() and other related syscalls. It is based on invocation of
host's ustat(), and its key part is in the correspondent case segment
of the main switch statement of the function do_syscall(), in file
linux-user/syscalls.c. All necessary conversions of data structures
from target to host and from host to target are covered. Sufficient
support for "-strace" option for this syscall is already present,
and this patch does not change it.

This patch also fixes failures of LTP tests ustat01, and ustat02, if
executed on Qemu-emulated systems.

Signed-off-by: Aleksandar Markovic <aleksandar.markovic@imgtec.com>
---
 linux-user/syscall.c |   25 ++++++++++++++++++++++++-
 1 file changed, 24 insertions(+), 1 deletion(-)

diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 38d69f1..b118bd9 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -48,6 +48,7 @@ int __clone2(int (*fn)(void *), void *child_stack_base,
 #include <sys/shm.h>
 #include <sys/sem.h>
 #include <sys/statfs.h>
+#include <ustat.h>
 #include <utime.h>
 #include <sys/sysinfo.h>
 #include <sys/signalfd.h>
@@ -8098,7 +8099,29 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
         break;
 #ifdef TARGET_NR_ustat
     case TARGET_NR_ustat:
-        goto unimplemented;
+    {
+        struct ustat ust;
+        int cnt;
+        ret = get_errno(ustat(arg1, &ust));
+
+        if (!is_error(ret)) {
+            struct ustat *target_ust;
+
+            if (!lock_user_struct(VERIFY_WRITE, target_ust, arg2, 0)) {
+                goto efault;
+            }
+
+            __put_user(ust.f_tfree, &target_ust->f_tfree);
+            __put_user(ust.f_tinode, &target_ust->f_tinode);
+
+            for (cnt = 0; cnt < 6; cnt++) {
+                __put_user(ust.f_fname[cnt], &target_ust->f_fname[cnt]);
+                __put_user(ust.f_fpack[cnt], &target_ust->f_fpack[cnt]);
+            }
+            unlock_user_struct(target_ust, arg2, 1);
+        }
+        break;
+      }
 #endif
 #ifdef TARGET_NR_dup2
     case TARGET_NR_dup2:
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2016-09-05 14:01 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-09-05 14:00 [Qemu-devel] [PATCH v2 0/3] linux-user: Add support for adjtimex(), sysfs(), and ustat() syscalls Aleksandar Markovic
2016-09-05 14:00 ` [Qemu-devel] [PATCH v2 1/3] linux-user: Add support for adjtimex() syscall Aleksandar Markovic
2016-09-05 14:00 ` [Qemu-devel] [PATCH v2 2/3] linux-user: Add support for sysfs() syscall Aleksandar Markovic
2016-09-05 14:00 ` [Qemu-devel] [PATCH v2 3/3] linux-user: Add support for ustat() syscall Aleksandar Markovic

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.