diff --git a/libc-test/build.rs b/libc-test/build.rs index da12acade8f00..1586a8a520ce0 100644 --- a/libc-test/build.rs +++ b/libc-test/build.rs @@ -3522,6 +3522,8 @@ fn test_linux(target: &str) { "linux/netlink.h", // FIXME: requires Linux >= 5.6: [!musl]: "linux/openat2.h", + "linux/ptp_clock.h", + // FIXME: some items require Linux >= 5.6: [!musl]: "linux/ptrace.h", "linux/quota.h", "linux/random.h", @@ -3670,6 +3672,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")) { @@ -3850,7 +3855,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 @@ -3865,6 +3871,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; } @@ -4382,7 +4397,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| { @@ -4456,7 +4475,11 @@ fn test_linux(target: &str) { // either fsid_t or int[2] type (struct_ == "fanotify_event_info_fid" && field == "fsid") || // `handle` is a VLA - (struct_ == "fanotify_event_info_fid" && field == "handle") + (struct_ == "fanotify_event_info_fid" && field == "handle") || + // `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 402241df1d033..bd334a5751361 100644 --- a/libc-test/semver/linux.txt +++ b/libc-test/semver/linux.txt @@ -2061,6 +2061,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/ioctl.rs b/src/unix/linux_like/linux/ioctl.rs new file mode 100644 index 0000000000000..4dd0c095c9ea2 --- /dev/null +++ b/src/unix/linux_like/linux/ioctl.rs @@ -0,0 +1,85 @@ +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 { + // TODO the `garando_syntax` crate (used by ctest2 in the CI test suite) + // cannot currently parse these `debug_assert!`s + // + // 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::()) +} diff --git a/src/unix/linux_like/linux/mod.rs b/src/unix/linux_like/linux/mod.rs index 616e2e7c7d466..c59345b4f6c5d 100644 --- a/src/unix/linux_like/linux/mod.rs +++ b/src/unix/linux_like/linux/mod.rs @@ -821,6 +821,41 @@ 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_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 { @@ -1036,6 +1071,52 @@ s! { pub get_args: __u16, pub name: [c_char; ::IFNAMSIZ], } + + // linux/ptp_clock.h + pub struct ptp_sys_offset { + pub n_samples: ::c_uint, + pub rsv: [::c_uint; 3], + pub ts: [ptp_clock_time; 51], + } + + 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], + } + + 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, + #[cfg(any(target_arch = "sparc", target_arch = "sparc64"))] + pub adjust_phase: ::c_int, + #[cfg(any(target_arch = "sparc", target_arch = "sparc64"))] + pub rsv: [::c_int; 12], + #[cfg(any(target_env = "musl", target_env = "ohos"))] + pub rsv: [::c_int; 13], + #[cfg(not(any( + any(target_arch = "sparc", target_arch = "sparc64"), + any(target_env = "musl", target_env = "ohos"), + )))] + pub adjust_phase: ::c_int, + #[cfg(not(any( + any(target_arch = "sparc", target_arch = "sparc64"), + any(target_env = "musl", target_env = "ohos"), + )))] + pub max_phase_adj: ::c_int, + #[cfg(not(any( + any(target_arch = "sparc", target_arch = "sparc64"), + any(target_env = "musl", target_env = "ohos"), + )))] + pub rsv: [::c_int; 11], + } } cfg_if! { @@ -1283,6 +1364,30 @@ s_no_extra_traits! { } } +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 { @@ -4112,6 +4217,41 @@ 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); + +// 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; @@ -6189,3 +6329,5 @@ expand_align!(); mod non_exhaustive; pub use self::non_exhaustive::*; + +mod ioctl;