From bba186064e905d6fbed6d18cc2f66f4ec78e2c1d Mon Sep 17 00:00:00 2001 From: Julian Seward Date: Mon, 30 Dec 2019 11:03:19 +0100 Subject: [PATCH] Bug 409206 - Support for Linux PPS and PTP ioctls. Patches from Miroslav Lichvar . --- coregrind/m_syswrap/syswrap-linux.c | 150 ++++++++++++++++++++++++++++++++++++ include/vki/vki-linux.h | 118 ++++++++++++++++++++++++++++ 2 files changed, 268 insertions(+) diff --git a/coregrind/m_syswrap/syswrap-linux.c b/coregrind/m_syswrap/syswrap-linux.c index 4655d09f2..fd958e488 100644 --- a/coregrind/m_syswrap/syswrap-linux.c +++ b/coregrind/m_syswrap/syswrap-linux.c @@ -9474,6 +9474,100 @@ PRE(sys_ioctl) PRE_MEM_WRITE("ioctl(VKI_PERF_EVENT_IOC_ID)", (Addr)ARG3, sizeof(__vki_u64)); break; + /* Pulse Per Second (PPS) */ + case VKI_PPS_GETPARAMS: { + struct vki_pps_kparams *data = (struct vki_pps_kparams *)(Addr)ARG3; + PRE_MEM_WRITE("ioctl(PPS_GETPARAMS)", (Addr)data, sizeof(*data)); + break; + } + case VKI_PPS_SETPARAMS: { + struct vki_pps_kparams *data = (struct vki_pps_kparams *)(Addr)ARG3; + PRE_FIELD_READ("ioctl(PPS_SETPARAMS).mode", data->mode); + PRE_FIELD_READ("ioctl(PPS_SETPARAMS).assert_off_tu.sec", + data->assert_off_tu.sec); + PRE_FIELD_READ("ioctl(PPS_SETPARAMS).assert_off_tu.nsec", + data->assert_off_tu.nsec); + PRE_FIELD_READ("ioctl(PPS_SETPARAMS).clear_off_tu.sec", + data->clear_off_tu.sec); + PRE_FIELD_READ("ioctl(PPS_SETPARAMS).clear_off_tu.nsec", + data->clear_off_tu.nsec); + break; + } + case VKI_PPS_GETCAP: + PRE_MEM_WRITE("ioctl(PPS_GETCAP)", (Addr)ARG3, sizeof(int)); + break; + case VKI_PPS_FETCH: { + struct vki_pps_fdata *data = (struct vki_pps_fdata *)(Addr)ARG3; + PRE_FIELD_READ("ioctl(PPS_FETCH).timeout", data->timeout); + PRE_FIELD_WRITE("ioctl(PPS_FETCH).info", data->info); + break; + } + case VKI_PPS_KC_BIND: { + struct vki_pps_bind_args *data = (struct vki_pps_bind_args *)(Addr)ARG3; + PRE_MEM_READ("ioctl(PPS_KC_BIND)", (Addr)data, sizeof(*data)); + break; + } + + /* PTP Hardware Clock */ + case VKI_PTP_CLOCK_GETCAPS: { + struct vki_ptp_clock_caps *data = + (struct vki_ptp_clock_caps *)(Addr)ARG3; + PRE_MEM_WRITE("ioctl(PTP_CLOCK_GETCAPS)", (Addr)data, sizeof(*data)); + break; + } + case VKI_PTP_EXTTS_REQUEST: { + struct vki_ptp_extts_request *data = + (struct vki_ptp_extts_request *)(Addr)ARG3; + PRE_MEM_READ("ioctl(PTP_EXTTS_REQUEST)", (Addr)data, sizeof(*data)); + break; + } + case VKI_PTP_PEROUT_REQUEST: { + struct vki_ptp_perout_request *data = + (struct vki_ptp_perout_request *)(Addr)ARG3; + PRE_MEM_READ("ioctl(PTP_PEROUT_REQUEST)", (Addr)data, sizeof(*data)); + break; + } + case VKI_PTP_ENABLE_PPS: + break; + case VKI_PTP_SYS_OFFSET: { + struct vki_ptp_sys_offset *data = + (struct vki_ptp_sys_offset *)(Addr)ARG3; + PRE_FIELD_READ("ioctl(PTP_SYS_OFFSET).n_samples", data->n_samples); + if (data->n_samples <= VKI_PTP_MAX_SAMPLES) + PRE_MEM_WRITE("ioctl(PTP_SYS_OFFSET).ts", (Addr)data->ts, + (2 * data->n_samples + 1) * sizeof(data->ts[0])); + break; + } + case VKI_PTP_PIN_GETFUNC: { + struct vki_ptp_pin_desc *data = (struct vki_ptp_pin_desc *)(Addr)ARG3; + PRE_FIELD_READ("ioctl(PTP_PIN_GETFUNC).index", data->index); + PRE_MEM_WRITE("ioctl(PTP_PIN_GETFUNC)", (Addr)data, sizeof(*data)); + break; + } + case VKI_PTP_PIN_SETFUNC: { + struct vki_ptp_pin_desc *data = (struct vki_ptp_pin_desc *)(Addr)ARG3; + PRE_FIELD_READ("ioctl(PTP_PIN_SETFUNC).index", data->index); + PRE_FIELD_READ("ioctl(PTP_PIN_SETFUNC).func", data->func); + PRE_FIELD_READ("ioctl(PTP_PIN_SETFUNC).chan", data->chan); + break; + } + case VKI_PTP_SYS_OFFSET_PRECISE: { + struct vki_ptp_sys_offset_precise *data = + (struct vki_ptp_sys_offset_precise *)(Addr)ARG3; + PRE_MEM_WRITE("ioctl(PTP_SYS_OFFSET_PRECISE)", (Addr)data, sizeof(*data)); + break; + } + case VKI_PTP_SYS_OFFSET_EXTENDED: { + struct vki_ptp_sys_offset_extended *data = + (struct vki_ptp_sys_offset_extended *)(Addr)ARG3; + PRE_FIELD_READ("ioctl(PTP_SYS_OFFSET_EXTENDED).n_samples", data->n_samples); + PRE_FIELD_READ("ioctl(PTP_SYS_OFFSET_EXTENDED).rsv", data->rsv); + if (data->n_samples <= VKI_PTP_MAX_SAMPLES) + PRE_MEM_WRITE("ioctl(PTP_SYS_OFFSET_EXTENDED).ts", (Addr)data->ts, + 3 * data->n_samples * sizeof(data->ts[0][0])); + break; + } + default: /* EVIOC* are variable length and return size written on success */ switch (ARG2 & ~(_VKI_IOC_SIZEMASK << _VKI_IOC_SIZESHIFT)) { @@ -11471,6 +11565,62 @@ POST(sys_ioctl) POST_MEM_WRITE((Addr)ARG3, sizeof(__vki_u64)); break; + /* Pulse Per Second (PPS) */ + case VKI_PPS_GETPARAMS: { + struct vki_pps_kparams *data = (struct vki_pps_kparams *)(Addr)ARG3; + POST_MEM_WRITE((Addr)data, sizeof(*data)); + break; + } + case VKI_PPS_GETCAP: + POST_MEM_WRITE((Addr)ARG3, sizeof(int)); + break; + case VKI_PPS_FETCH: { + struct vki_pps_fdata *data = (struct vki_pps_fdata *)(Addr)ARG3; + POST_FIELD_WRITE(data->info); + break; + } + case VKI_PPS_SETPARAMS: + case VKI_PPS_KC_BIND: + break; + + /* PTP Hardware Clock */ + case VKI_PTP_CLOCK_GETCAPS: { + struct vki_ptp_clock_caps *data = + (struct vki_ptp_clock_caps *)(Addr)ARG3; + POST_MEM_WRITE((Addr)data, sizeof(*data)); + break; + } + case VKI_PTP_SYS_OFFSET: { + struct vki_ptp_sys_offset *data = + (struct vki_ptp_sys_offset *)(Addr)ARG3; + POST_MEM_WRITE((Addr)data->ts, + (2 * data->n_samples + 1) * sizeof(data->ts[0])); + break; + } + case VKI_PTP_PIN_GETFUNC: { + struct vki_ptp_pin_desc *data = (struct vki_ptp_pin_desc *)(Addr)ARG3; + POST_MEM_WRITE((Addr)data, sizeof(*data)); + break; + } + case VKI_PTP_SYS_OFFSET_PRECISE: { + struct vki_ptp_sys_offset_precise *data = + (struct vki_ptp_sys_offset_precise *)(Addr)ARG3; + POST_MEM_WRITE((Addr)data, sizeof(*data)); + break; + } + case VKI_PTP_SYS_OFFSET_EXTENDED: { + struct vki_ptp_sys_offset_extended *data = + (struct vki_ptp_sys_offset_extended *)(Addr)ARG3; + POST_MEM_WRITE((Addr)data->ts, + 3 * data->n_samples * sizeof(data->ts[0][0])); + break; + } + case VKI_PTP_EXTTS_REQUEST: + case VKI_PTP_PEROUT_REQUEST: + case VKI_PTP_ENABLE_PPS: + case VKI_PTP_PIN_SETFUNC: + break; + default: /* EVIOC* are variable length and return size written on success */ switch (ARG2 & ~(_VKI_IOC_SIZEMASK << _VKI_IOC_SIZESHIFT)) { diff --git a/include/vki/vki-linux.h b/include/vki/vki-linux.h index 6903c77db..99127eb43 100644 --- a/include/vki/vki-linux.h +++ b/include/vki/vki-linux.h @@ -5132,6 +5132,124 @@ struct vki_bpf_btf_info { __vki_u32 id; } __attribute__((aligned(8))); +//---------------------------------------------------------------------- +// From linux-5.1/include/uapi/linux/pps.h +//---------------------------------------------------------------------- + +struct vki_pps_ktime { + __vki_s64 sec; + __vki_s32 nsec; + __vki_u32 flags; +}; + +struct vki_pps_kinfo { + __vki_u32 assert_sequence; + __vki_u32 clear_sequence; + struct vki_pps_ktime assert_tu; + struct vki_pps_ktime clear_tu; + int current_mode; +}; + +struct vki_pps_kparams { + int api_version; + int mode; + struct vki_pps_ktime assert_off_tu; + struct vki_pps_ktime clear_off_tu; +}; + +struct vki_pps_fdata { + struct vki_pps_kinfo info; + struct vki_pps_ktime timeout; +}; + +struct vki_pps_bind_args { + int tsformat; + int edge; + int consumer; +}; + +#define VKI_PPS_GETPARAMS _VKI_IOR('p', 0xa1, struct vki_pps_kparams *) +#define VKI_PPS_SETPARAMS _VKI_IOW('p', 0xa2, struct vki_pps_kparams *) +#define VKI_PPS_GETCAP _VKI_IOR('p', 0xa3, int *) +#define VKI_PPS_FETCH _VKI_IOWR('p', 0xa4, struct vki_pps_fdata *) +#define VKI_PPS_KC_BIND _VKI_IOW('p', 0xa5, struct vki_pps_bind_args *) + +//---------------------------------------------------------------------- +// From linux-5.1/include/uapi/linux/ptp_clock.h +//---------------------------------------------------------------------- + +struct vki_ptp_clock_time { + __vki_s64 sec; + __vki_u32 nsec; + __vki_u32 reserved; +}; + +struct vki_ptp_clock_caps { + int max_adj; + int n_alarm; + int n_ext_ts; + int n_per_out; + int pps; + int n_pins; + int cross_timestamping; + int rsv[13]; +}; + +struct vki_ptp_extts_request { + unsigned int index; + unsigned int flags; + unsigned int rsv[2]; +}; + +struct vki_ptp_perout_request { + struct vki_ptp_clock_time start; + struct vki_ptp_clock_time period; + unsigned int index; + unsigned int flags; + unsigned int rsv[4]; +}; + +#define VKI_PTP_MAX_SAMPLES 25 + +struct vki_ptp_sys_offset { + unsigned int n_samples; + unsigned int rsv[3]; + struct vki_ptp_clock_time ts[2 * VKI_PTP_MAX_SAMPLES + 1]; +}; + +struct vki_ptp_sys_offset_extended { + unsigned int n_samples; + unsigned int rsv[3]; + struct vki_ptp_clock_time ts[VKI_PTP_MAX_SAMPLES][3]; +}; + +struct vki_ptp_sys_offset_precise { + struct vki_ptp_clock_time device; + struct vki_ptp_clock_time sys_realtime; + struct vki_ptp_clock_time sys_monoraw; + unsigned int rsv[4]; +}; + +struct vki_ptp_pin_desc { + char name[64]; + unsigned int index; + unsigned int func; + unsigned int chan; + unsigned int rsv[5]; +}; + +#define VKI_PTP_CLOCK_GETCAPS _VKI_IOR('=', 1, struct vki_ptp_clock_caps) +#define VKI_PTP_EXTTS_REQUEST _VKI_IOW('=', 2, struct vki_ptp_extts_request) +#define VKI_PTP_PEROUT_REQUEST _VKI_IOW('=', 3, struct vki_ptp_perout_request) +#define VKI_PTP_ENABLE_PPS _VKI_IOW('=', 4, int) +#define VKI_PTP_SYS_OFFSET _VKI_IOW('=', 5, struct vki_ptp_sys_offset) +#define VKI_PTP_PIN_GETFUNC _VKI_IOWR('=', 6, struct vki_ptp_pin_desc) +#define VKI_PTP_PIN_SETFUNC _VKI_IOW('=', 7, struct vki_ptp_pin_desc) +#define VKI_PTP_SYS_OFFSET_PRECISE \ + _VKI_IOWR('=', 8, struct vki_ptp_sys_offset_precise) +#define VKI_PTP_SYS_OFFSET_EXTENDED \ + _VKI_IOWR('=', 9, struct vki_ptp_sys_offset_extended) + /*--------------------------------------------------------------------*/ /*--- end ---*/ /*--------------------------------------------------------------------*/ -- 2.11.4.GIT