diff --git a/libc-test/build.rs b/libc-test/build.rs index 30ab41202e94..a02eb4c11fba 100644 --- a/libc-test/build.rs +++ b/libc-test/build.rs @@ -3542,6 +3542,8 @@ fn test_linux(target: &str) { "linux/netlink.h", // FIXME: requires Linux >= 5.6: [!musl]: "linux/openat2.h", + "linux/ptp_clock.h", + // FIXME: requires Linux >= 5.6: [!musl]: "linux/ptrace.h", "linux/quota.h", "linux/random.h", @@ -3679,6 +3681,9 @@ fn test_linux(target: &str) { if musl && ty == "seccomp_notif_sizes" { return true; } + if musl && ty == "ptp_sys_offset_extended" { + return true; + } // LFS64 types have been removed in musl 1.2.4+ if musl && (ty.ends_with("64") || ty.ends_with("64_t")) { @@ -3839,7 +3844,8 @@ fn test_linux(target: &str) { } if musl { // FIXME: Requires >= 5.0 kernel headers - if name == "SECCOMP_GET_NOTIF_SIZES" + if name == "PTP_SYS_OFFSET_EXTENDED" + || name == "SECCOMP_GET_NOTIF_SIZES" || name == "SECCOMP_FILTER_FLAG_NEW_LISTENER" || name == "SECCOMP_FILTER_FLAG_TSYNC_ESRCH" || name == "SECCOMP_USER_NOTIF_FLAG_CONTINUE" // requires >= 5.5 @@ -3854,6 +3860,15 @@ fn test_linux(target: &str) { || name.starts_with("RTEXT_FILTER_") || name.starts_with("SO_J1939") || name.starts_with("SCM_J1939") + || name == "PTP_CLOCK_GETCAPS2" + || name == "PTP_ENABLE_PPS2" + || name == "PTP_EXTTS_REQUEST2" + || name == "PTP_PEROUT_REQUEST2" + || name == "PTP_PIN_GETFUNC2" + || name == "PTP_PIN_SETFUNC2" + || name == "PTP_SYS_OFFSET2" + || name == "PTP_SYS_OFFSET_PRECISE2" + || name == "PTP_SYS_OFFSET_EXTENDED2" { return true; } @@ -4362,7 +4377,11 @@ fn test_linux(target: &str) { // `__exit_status` type is a patch which is absent in musl (struct_ == "utmpx" && field == "ut_exit" && musl) || // `can_addr` is an anonymous union - (struct_ == "sockaddr_can" && field == "can_addr") + (struct_ == "sockaddr_can" && field == "can_addr") || + // `anonymous_1` is an anonymous union + (struct_ == "ptp_perout_request" && field == "anonymous_1") || + // `anonymous_2` is an anonymous union + (struct_ == "ptp_perout_request" && field == "anonymous_2") }); cfg.volatile_item(|i| { @@ -4420,7 +4439,11 @@ fn test_linux(target: &str) { // the `ifc_ifcu` field is an anonymous union (struct_ == "ifconf" && field == "ifc_ifcu") || // glibc uses a single array `uregs` instead of individual fields. - (struct_ == "user_regs" && arm) + (struct_ == "user_regs" && arm) || + // `anonymous_1` is an anonymous union + (struct_ == "ptp_perout_request" && field == "anonymous_1") || + // `anonymous_2` is an anonymous union + (struct_ == "ptp_perout_request" && field == "anonymous_2") }); cfg.skip_roundtrip(move |s| match s { diff --git a/libc-test/semver/linux.txt b/libc-test/semver/linux.txt index 0bee4e68c16a..45201fe557ab 100644 --- a/libc-test/semver/linux.txt +++ b/libc-test/semver/linux.txt @@ -1997,6 +1997,29 @@ PTHREAD_INHERIT_SCHED PTHREAD_EXPLICIT_SCHED PTHREAD_STACK_MIN PTHREAD_ONCE_INIT +PTP_CLOCK_GETCAPS +PTP_CLOCK_GETCAPS2 +PTP_ENABLE_PPS +PTP_ENABLE_PPS2 +PTP_EXTTS_REQUEST +PTP_EXTTS_REQUEST2 +PTP_MAX_SAMPLES +PTP_PEROUT_REQUEST +PTP_PEROUT_REQUEST2 +PTP_PF_EXTTS +PTP_PF_NONE +PTP_PF_PEROUT +PTP_PF_PHYSYNC +PTP_PIN_GETFUNC +PTP_PIN_GETFUNC2 +PTP_PIN_SETFUNC +PTP_PIN_SETFUNC2 +PTP_SYS_OFFSET +PTP_SYS_OFFSET2 +PTP_SYS_OFFSET_EXTENDED +PTP_SYS_OFFSET_EXTENDED2 +PTP_SYS_OFFSET_PRECISE +PTP_SYS_OFFSET_PRECISE2 PTRACE_ATTACH PTRACE_CONT PTRACE_DETACH diff --git a/src/unix/linux_like/linux/mod.rs b/src/unix/linux_like/linux/mod.rs index 779faa81ff16..7e89a5e92f65 100644 --- a/src/unix/linux_like/linux/mod.rs +++ b/src/unix/linux_like/linux/mod.rs @@ -651,6 +651,51 @@ s! { pub val: ::c_int, } + // linux/ptp_clock.h + pub struct ptp_clock_time { + pub sec: ::__s64, + pub nsec: ::__u32, + pub reserved: ::__u32, + } + + pub struct ptp_clock_caps { + pub max_adj: ::c_int, + pub n_alarm: ::c_int, + pub n_ext_ts: ::c_int, + pub n_per_out: ::c_int, + pub pps: ::c_int, + pub n_pins: ::c_int, + pub cross_timestamping: ::c_int, + pub adjust_phase: ::c_int, + pub rsv: [::c_int; 12], + } + + pub struct ptp_extts_request { + pub index: ::c_uint, + pub flags: ::c_uint, + pub rsv: [::c_uint; 2], + } + + pub struct ptp_sys_offset_extended { + pub n_samples: ::c_uint, + pub rsv: [::c_uint; 3], + pub ts: [[ptp_clock_time; 3]; PTP_MAX_SAMPLES as usize], + } + + pub struct ptp_sys_offset_precise { + pub device: ptp_clock_time, + pub sys_realtime: ptp_clock_time, + pub sys_monoraw: ptp_clock_time, + pub rsv: [::c_uint; 4], + } + + pub struct ptp_extts_event { + pub t: ptp_clock_time, + index: ::c_uint, + flags: ::c_uint, + rsv: [::c_uint; 2], + } + // linux/sctp.h pub struct sctp_initmsg { @@ -892,6 +937,23 @@ s_no_extra_traits! { } } +s! { + // linux/ptp_clock.h + pub struct ptp_sys_offset { + pub n_samples: ::c_uint, + pub rsv: [::c_uint; 3], + pub ts: [ptp_clock_time; 2 * PTP_MAX_SAMPLES as usize + 1], + } + + pub struct ptp_pin_desc { + pub name: [::c_char; 64], + pub index: ::c_uint, + pub func: ::c_uint, + pub chan: ::c_uint, + pub rsv: [::c_uint; 5], + } +} + s_no_extra_traits! { // linux/net_tstamp.h #[allow(missing_debug_implementations)] @@ -921,6 +983,34 @@ cfg_if! { } } +cfg_if! { + if #[cfg(libc_union)] { + s_no_extra_traits! { + // linux/ptp_clock.h + #[allow(missing_debug_implementations)] + pub union __c_anonymous_ptp_perout_request_1 { + pub start: ptp_clock_time, + pub phase: ptp_clock_time, + } + + #[allow(missing_debug_implementations)] + pub union __c_anonymous_ptp_perout_request_2 { + pub on: ptp_clock_time, + pub rsv: [::c_uint; 4], + } + + #[allow(missing_debug_implementations)] + pub struct ptp_perout_request { + pub anonymous_1: __c_anonymous_ptp_perout_request_1, + pub period: ptp_clock_time, + pub index: ::c_uint, + pub flags: ::c_uint, + pub anonymous_2: __c_anonymous_ptp_perout_request_2, + } + } + } +} + cfg_if! { if #[cfg(feature = "extra_traits")] { impl PartialEq for sockaddr_nl { @@ -3643,6 +3733,43 @@ pub const HWTSTAMP_FILTER_PTP_V2_SYNC: ::c_uint = 13; pub const HWTSTAMP_FILTER_PTP_V2_DELAY_REQ: ::c_uint = 14; pub const HWTSTAMP_FILTER_NTP_ALL: ::c_uint = 15; +// linux/ptp_clock.h +pub const PTP_MAX_SAMPLES: ::c_uint = 25; // Maximum allowed offset measurement samples. + +const PTP_CLK_MAGIC: u32 = b'=' as u32; + +pub const PTP_CLOCK_GETCAPS: ::c_uint = ioctl::_IOR::(PTP_CLK_MAGIC, 1); +pub const PTP_EXTTS_REQUEST: ::c_uint = ioctl::_IOW::(PTP_CLK_MAGIC, 2); +pub const PTP_PEROUT_REQUEST: ::c_uint = ioctl::_IOW::(PTP_CLK_MAGIC, 3); +pub const PTP_ENABLE_PPS: ::c_uint = ioctl::_IOW::<::c_int>(PTP_CLK_MAGIC, 4); +pub const PTP_SYS_OFFSET: ::c_uint = ioctl::_IOW::(PTP_CLK_MAGIC, 5); +pub const PTP_PIN_GETFUNC: ::c_uint = ioctl::_IOWR::(PTP_CLK_MAGIC, 6); +pub const PTP_PIN_SETFUNC: ::c_uint = ioctl::_IOW::(PTP_CLK_MAGIC, 7); +pub const PTP_SYS_OFFSET_PRECISE: ::c_uint = + ioctl::_IOWR::(PTP_CLK_MAGIC, 8); +pub const PTP_SYS_OFFSET_EXTENDED: ::c_uint = + ioctl::_IOWR::(PTP_CLK_MAGIC, 9); + +pub const PTP_CLOCK_GETCAPS2: ::c_uint = ioctl::_IOR::(PTP_CLK_MAGIC, 10); +pub const PTP_EXTTS_REQUEST2: ::c_uint = ioctl::_IOW::(PTP_CLK_MAGIC, 11); +pub const PTP_PEROUT_REQUEST2: ::c_uint = ioctl::_IOW::(PTP_CLK_MAGIC, 12); +pub const PTP_ENABLE_PPS2: ::c_uint = ioctl::_IOW::<::c_int>(PTP_CLK_MAGIC, 13); +pub const PTP_SYS_OFFSET2: ::c_uint = ioctl::_IOW::(PTP_CLK_MAGIC, 14); +pub const PTP_PIN_GETFUNC2: ::c_uint = ioctl::_IOWR::(PTP_CLK_MAGIC, 15); +pub const PTP_PIN_SETFUNC2: ::c_uint = ioctl::_IOW::(PTP_CLK_MAGIC, 16); +pub const PTP_SYS_OFFSET_PRECISE2: ::c_uint = + ioctl::_IOWR::(PTP_CLK_MAGIC, 17); +pub const PTP_SYS_OFFSET_EXTENDED2: ::c_uint = + ioctl::_IOWR::(PTP_CLK_MAGIC, 18); +pub const PTP_MASK_CLEAR_ALL: ::c_uint = ioctl::_IO(PTP_CLK_MAGIC, 19); +pub const PTP_MASK_EN_SINGLE: ::c_uint = ioctl::_IOW::<::c_uint>(PTP_CLK_MAGIC, 20); + +// enum ptp_pin_function +pub const PTP_PF_NONE: ::c_uint = 0; +pub const PTP_PF_EXTTS: ::c_uint = 1; +pub const PTP_PF_PEROUT: ::c_uint = 2; +pub const PTP_PF_PHYSYNC: ::c_uint = 3; + // linux/tls.h pub const TLS_TX: ::c_int = 1; pub const TLS_RX: ::c_int = 2; @@ -5697,3 +5824,88 @@ cfg_if! { pub use self::non_exhaustive::*; } } + +mod ioctl { + const _IOC_NRBITS: u32 = 8; + const _IOC_TYPEBITS: u32 = 8; + + // https://github.com/search?q=repo%3Atorvalds%2Flinux+%22%23define+_IOC_NONE%22&type=code + cfg_if! { + if #[cfg(any( + any(target_arch = "powerpc", target_arch = "powerpc64"), + any(target_arch = "sparc", target_arch = "sparc64"), + any(target_arch = "mips", target_arch = "mips64"), + ))] + { + // https://github.com/torvalds/linux/blob/b311c1b497e51a628aa89e7cb954481e5f9dced2/arch/powerpc/include/uapi/asm/ioctl.h + // https://github.com/torvalds/linux/blob/b311c1b497e51a628aa89e7cb954481e5f9dced2/arch/sparc/include/uapi/asm/ioctl.h + // https://github.com/torvalds/linux/blob/b311c1b497e51a628aa89e7cb954481e5f9dced2/arch/mips/include/uapi/asm/ioctl.h + + const _IOC_SIZEBITS: u32 = 13; + const _IOC_DIRBITS: u32 = 3; + + const _IOC_NONE: u32 = 1; + const _IOC_READ: u32 = 2; + const _IOC_WRITE: u32 = 4; + } else { + // https://github.com/torvalds/linux/blob/b311c1b497e51a628aa89e7cb954481e5f9dced2/include/uapi/asm-generic/ioctl.h + + const _IOC_SIZEBITS: u32 = 14; + const _IOC_DIRBITS: u32 = 2; + + const _IOC_NONE: u32 = 0; + const _IOC_WRITE: u32 = 1; + const _IOC_READ: u32 = 2; + } + } + + const _IOC_NRMASK: u32 = (1 << _IOC_NRBITS) - 1; + const _IOC_TYPEMASK: u32 = (1 << _IOC_TYPEBITS) - 1; + const _IOC_SIZEMASK: u32 = (1 << _IOC_SIZEBITS) - 1; + const _IOC_DIRMASK: u32 = (1 << _IOC_DIRBITS) - 1; + + const _IOC_NRSHIFT: u32 = 0; + const _IOC_TYPESHIFT: u32 = _IOC_NRSHIFT + _IOC_NRBITS; + const _IOC_SIZESHIFT: u32 = _IOC_TYPESHIFT + _IOC_TYPEBITS; + const _IOC_DIRSHIFT: u32 = _IOC_SIZESHIFT + _IOC_SIZEBITS; + + // adopted from https://github.com/torvalds/linux/blob/8a696a29c6905594e4abf78eaafcb62165ac61f1/rust/kernel/ioctl.rs + + /// Build an ioctl number, analogous to the C macro of the same name. + #[inline(always)] + const fn _IOC(dir: u32, ty: u32, nr: u32, size: usize) -> u32 { + debug_assert!(dir <= _IOC_DIRMASK); + debug_assert!(ty <= _IOC_TYPEMASK); + debug_assert!(nr <= _IOC_NRMASK); + debug_assert!(size <= (_IOC_SIZEMASK as usize)); + + (dir << _IOC_DIRSHIFT) + | (ty << _IOC_TYPESHIFT) + | (nr << _IOC_NRSHIFT) + | ((size as u32) << _IOC_SIZESHIFT) + } + + /// Build an ioctl number for an argumentless ioctl. + #[inline(always)] + pub const fn _IO(ty: u32, nr: u32) -> u32 { + _IOC(_IOC_NONE, ty, nr, 0) + } + + /// Build an ioctl number for an read-only ioctl. + #[inline(always)] + pub const fn _IOR(ty: u32, nr: u32) -> u32 { + _IOC(_IOC_READ, ty, nr, core::mem::size_of::()) + } + + /// Build an ioctl number for an write-only ioctl. + #[inline(always)] + pub const fn _IOW(ty: u32, nr: u32) -> u32 { + _IOC(_IOC_WRITE, ty, nr, core::mem::size_of::()) + } + + /// Build an ioctl number for a read-write ioctl. + #[inline(always)] + pub const fn _IOWR(ty: u32, nr: u32) -> u32 { + _IOC(_IOC_READ | _IOC_WRITE, ty, nr, core::mem::size_of::()) + } +}