hc
2024-11-01 2f529f9b558ca1c1bd74be7437a84e4711743404
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
/*
 * SPDX-License-Identifier: GPL-2.0
 *
 * Copyright (C) 2020 Philippe Gerum  <rpm@xenomai.org>
 * Copyright (c) Siemens AG, 2021
 */
 
#ifndef _COBALT_KERNEL_PIPELINE_VDSO_FALLBACK_H
#define _COBALT_KERNEL_PIPELINE_VDSO_FALLBACK_H
 
#include <cobalt/kernel/clock.h>
#include <cobalt/kernel/timer.h>
#include <xenomai/posix/clock.h>
 
#define is_clock_gettime(__nr)        ((__nr) == __NR_clock_gettime)
 
#ifndef __NR_clock_gettime64
#define is_clock_gettime64(__nr)    0
#else
#define is_clock_gettime64(__nr)    ((__nr) == __NR_clock_gettime64)
#endif
 
static __always_inline bool 
pipeline_handle_vdso_fallback(int nr, struct pt_regs *regs)
{
   struct __kernel_old_timespec __user *u_old_ts;
   struct __kernel_timespec uts, __user *u_uts;
   struct __kernel_old_timespec old_ts;
   struct timespec64 ts64;
   int clock_id, ret = 0;
   unsigned long args[6];
 
   if (!is_clock_gettime(nr) && !is_clock_gettime64(nr))
       return false;
 
   /*
    * We need to fetch the args again because not all archs use the same
    * calling convention for Linux and Xenomai syscalls.
    */
   syscall_get_arguments(current, regs, args);
 
   clock_id = (int)args[0];
   switch (clock_id) {
   case CLOCK_MONOTONIC:
       ns2ts(&ts64, xnclock_read_monotonic(&nkclock));
       break;
   case CLOCK_REALTIME:
       ns2ts(&ts64, xnclock_read_realtime(&nkclock));
       break;
   default:
       return false;
   }
 
   if (is_clock_gettime(nr)) {
       old_ts.tv_sec = (__kernel_old_time_t)ts64.tv_sec;
       old_ts.tv_nsec = ts64.tv_nsec;
       u_old_ts = (struct __kernel_old_timespec __user *)args[1];
       if (raw_copy_to_user(u_old_ts, &old_ts, sizeof(old_ts)))
           ret = -EFAULT;
   } else if (is_clock_gettime64(nr)) {
       uts.tv_sec = ts64.tv_sec;
       uts.tv_nsec = ts64.tv_nsec;
       u_uts = (struct __kernel_timespec __user *)args[1];
       if (raw_copy_to_user(u_uts, &uts, sizeof(uts)))
           ret = -EFAULT;
   }
 
   __xn_status_return(regs, ret);
 
   return true;
}
 
#endif /* !_COBALT_KERNEL_PIPELINE_VDSO_FALLBACK_H */