On 08.03.21 18:02, Florian Bezdeka wrote:
> Implementation is heavily inspired by the sem_timedwait syscall,
> but expecting time64 based timespec / timeout.
> 
> We need two new syscall handlers:
>   - The native one (COBALT_SYSCALL()) to get 32 bit kernels time64
>     aware. This handler is added for 64 bit kernels as well, but not
>     used. As we don't have separate syscall tables for this both
>     worlds we have to add it.
> 
>  - The compat handler (COBALT_SYSCALL32emu()) for x32 or x86
>    applications running on an x86_64 kernel. Otherwise the redirection
>    to the compat / emulation syscalls is broken.
> 
> Signed-off-by: Florian Bezdeka <[email protected]>
> ---
>  include/cobalt/uapi/syscall.h                 |  1 +
>  .../include/asm-generic/xenomai/syscall.h     | 23 +++++++++++++++++++
>  kernel/cobalt/posix/sem.c                     | 13 +++++++++++
>  kernel/cobalt/posix/sem.h                     |  4 ++++
>  kernel/cobalt/posix/syscall32.c               | 13 +++++++++++
>  kernel/cobalt/posix/syscall32.h               |  4 ++++
>  6 files changed, 58 insertions(+)
> 
> diff --git a/include/cobalt/uapi/syscall.h b/include/cobalt/uapi/syscall.h
> index aa3c308d0..9b005da47 100644
> --- a/include/cobalt/uapi/syscall.h
> +++ b/include/cobalt/uapi/syscall.h
> @@ -122,6 +122,7 @@
>  #define sc_cobalt_sendmmsg                   99
>  #define sc_cobalt_clock_adjtime                      100
>  #define sc_cobalt_thread_setschedprio                101
> +#define sc_cobalt_sem_timedwait_time64               102

Maybe just sc_cobalt_sem_timedwait64?

How many additional calls are probably required?

>  
>  #define __NR_COBALT_SYSCALLS                 128 /* Power of 2 */
>  
> diff --git a/kernel/cobalt/include/asm-generic/xenomai/syscall.h 
> b/kernel/cobalt/include/asm-generic/xenomai/syscall.h
> index 91bbf3bfd..40d64b7a1 100644
> --- a/kernel/cobalt/include/asm-generic/xenomai/syscall.h
> +++ b/kernel/cobalt/include/asm-generic/xenomai/syscall.h
> @@ -19,6 +19,7 @@
>  #ifndef _COBALT_ASM_GENERIC_SYSCALL_H
>  #define _COBALT_ASM_GENERIC_SYSCALL_H
>  
> +#include <linux/compat.h>
>  #include <linux/types.h>
>  #include <linux/version.h>
>  #include <linux/uaccess.h>
> @@ -82,6 +83,28 @@ static inline int cobalt_strncpy_from_user(char *dst, 
> const char __user *src,
>       return __xn_strncpy_from_user(dst, src, count);
>  }
>  
> +static inline int cobalt_get_timespec64(struct timespec64 *ts,
> +                             const struct __kernel_timespec __user *uts)
> +{
> +     struct __kernel_timespec kts;
> +     int ret;
> +
> +     ret = cobalt_copy_from_user(&kts, uts, sizeof(kts));
> +     if (ret)
> +             return -EFAULT;
> +
> +     ts->tv_sec = kts.tv_sec;
> +
> +     /* Zero out the padding in compat mode */
> +     if (in_compat_syscall())
> +             kts.tv_nsec &= 0xFFFFFFFFUL;
> +
> +     /* In 32-bit mode, this drops the padding */
> +     ts->tv_nsec = kts.tv_nsec;
> +
> +     return 0;
> +}
> +

Why inline? But that question is likely obsolete when we can avoid the
code duplication below.

>  #if __BITS_PER_LONG == 64
>  
>  /*
> diff --git a/kernel/cobalt/posix/sem.c b/kernel/cobalt/posix/sem.c
> index 827a4751a..3055a456d 100644
> --- a/kernel/cobalt/posix/sem.c
> +++ b/kernel/cobalt/posix/sem.c
> @@ -435,6 +435,19 @@ COBALT_SYSCALL(sem_timedwait, primary,
>       return __cobalt_sem_timedwait(u_sem, ret ? NULL : &ts64);
>  }
>  
> +COBALT_SYSCALL(sem_timedwait_time64, primary,
> +            (struct cobalt_sem_shadow __user *u_sem,
> +             const struct __kernel_timespec __user *u_ts))
> +{
> +     int ret = 1;
> +     struct timespec64 ts64;
> +
> +     if (u_ts)
> +             ret = cobalt_get_timespec64(&ts64, u_ts);
> +
> +     return __cobalt_sem_timedwait(u_sem, ret ? NULL : &ts64);
> +}
> +
>  COBALT_SYSCALL(sem_trywait, primary,
>              (struct cobalt_sem_shadow __user *u_sem))
>  {
> diff --git a/kernel/cobalt/posix/sem.h b/kernel/cobalt/posix/sem.h
> index 658e11f7a..8491b69ba 100644
> --- a/kernel/cobalt/posix/sem.h
> +++ b/kernel/cobalt/posix/sem.h
> @@ -66,6 +66,10 @@ __cobalt_sem_open(struct cobalt_sem_shadow __user *usm,
>  int __cobalt_sem_timedwait(struct cobalt_sem_shadow __user *u_sem,
>                          const struct timespec64 *ts);
>  
> +COBALT_SYSCALL_DECL(sem_timedwait_time64,
> +                 (struct cobalt_sem_shadow __user *u_sem,
> +                  const struct __kernel_timespec __user *u_ts));
> +
>  int __cobalt_sem_destroy(xnhandle_t handle);
>  
>  void cobalt_nsem_reclaim(struct cobalt_process *process);
> diff --git a/kernel/cobalt/posix/syscall32.c b/kernel/cobalt/posix/syscall32.c
> index edac7ea4a..f73bfcda3 100644
> --- a/kernel/cobalt/posix/syscall32.c
> +++ b/kernel/cobalt/posix/syscall32.c
> @@ -135,6 +135,19 @@ COBALT_SYSCALL32emu(sem_timedwait, primary,
>       return __cobalt_sem_timedwait(u_sem, ret ? NULL : &ts64);
>  }
>  
> +COBALT_SYSCALL32emu(sem_timedwait_time64, primary,
> +                 (struct cobalt_sem_shadow __user *u_sem,
> +                  const struct __kernel_timespec __user *u_ts))
> +{
> +     int ret = 1;
> +     struct timespec64 ts64;
> +
> +     if (u_ts)
> +             ret = cobalt_get_timespec64(&ts64, u_ts);
> +
> +     return __cobalt_sem_timedwait(u_sem, ret ? NULL : &ts64);
> +}

Why do we need to code this out twice? I don't spot the difference to
the native implementation yet. Can't we point to it directly?

> +
>  COBALT_SYSCALL32emu(clock_getres, current,
>                   (clockid_t clock_id,
>                    struct old_timespec32 __user *u_ts))
> diff --git a/kernel/cobalt/posix/syscall32.h b/kernel/cobalt/posix/syscall32.h
> index d72fd2022..3612bf751 100644
> --- a/kernel/cobalt/posix/syscall32.h
> +++ b/kernel/cobalt/posix/syscall32.h
> @@ -231,4 +231,8 @@ COBALT_SYSCALL32emu_DECL(sem_timedwait,
>                        (struct cobalt_sem_shadow __user *u_sem,
>                         const struct old_timespec32 __user *u_ts));
>  
> +COBALT_SYSCALL32emu_DECL(sem_timedwait_time64,
> +                      (struct cobalt_sem_shadow __user * u_sem,
> +                       const struct __kernel_timespec __user *u_ts));
> +
>  #endif /* !_COBALT_POSIX_SYSCALL32_H */
> 

Jan

-- 
Siemens AG, T RDA IOT
Corporate Competence Center Embedded Linux

Reply via email to