Uh oh!
There was an error while loading. Please reload this page.
Honor CBAUD/CIBAUD in TCGETS, TCGETS2 and TCSETS - #312
Merged
Conversation
This comment was marked as resolved.
This comment was marked as resolved.
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
jotpalchforce-pushed
the
termios-baud
branch
2 times, most recently
from
August 20, 2026 09:12
394558a to
ee6805aComparemusl and glibc <= 2.41 store the baud rate as a B* index in CBAUD (and in CIBAUD for a split input rate) and issue plain TCSETS; glibc 2.42+ switched to TCGETS2/TCSETS2 unconditionally. elfuse only read a speed in the termios2 arm, so on a real serial port tcsetattr(B115200) returned 0 and left the host line at whatever speed it last had, and TCGETS reported cfgetospeed() == 0. Host ptys hid this because their rate is meaningless; a guest opening /dev/cu.usbmodem* through the /dev passthrough observes it on the first tcsetattr. TCGETS and TCGETS2 now encode the host rates the way tty_termios_encode_baud_rate() does: CBAUD carries the output rate (B* index, or BOTHER for a rate Linux has no name for) and CIBAUD is set only when the input rate differs. TCGETS2 no longer forces BOTHER, so both requests agree as they do on Linux. TCSETS decodes CBAUD/CIBAUD following drivers/tty/tty_baudrate.c: CIBAUD B0 means "same as output"; B0 in CBAUD (drop DTR/RTS on Linux, not emulated) and a bare BOTHER leave the host speed alone -- on a plain TCSETS the kernel resolves BOTHER from the tty's current c_ospeed since the struct carries no speed fields, and without that rule a tcgetattr/tcsetattr pair on a port set to 74880 via termios2 collapsed the line to B0. tests/test-pty.c gains a slave-side block covering the B115200 round trip, the BOTHER-preserving plain pair at 74880, a split rate through CIBAUD and its re-unification, and TCGETS/TCGETS2 agreement. The TCSETS2 arm now decodes CIBAUD the same way: since TCGETS2 reports a split host rate as CBAUD+CIBAUD indexes rather than the previous blanket BOTHER, an unchanged tcgetattr/tcsetattr pair from a termios2 libc (glibc 2.42) would otherwise collapse the input rate to the output rate.
jotpalch
commented
Aug 20, 2026
ContributorAuthor
Uh oh!
There was an error while loading. Please reload this page.
jserv
commented
Aug 20, 2026
Contributor
Thank @jotpalch for contributing! |
jotpalch
commented
Aug 20, 2026
ContributorAuthor
Thank you! This is my first contribution to your projects and I'm thrilled it landed. The review gates here (commentflow, the commit-log hooks, the EINTR contract checker) taught me a lot along the way. Piece 2 of #310 follows next. |
This was referenced Aug 20, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for freeto join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Note
Piece 1 of #310, sent separately per the discussion there.
Summary
Plain
TCSETSdropped the baud rate andTCGETSreported B0.TCGETS/TCGETS2/TCSETSnow encode and decodeCBAUD/CIBAUDlike the Linux tty core, sotcsetattr(B115200)from a musl or glibc <= 2.41 guest reaches the host line andcfgetospeed()round-trips.Important
What to look at:
apply_linux_cflag_speeds(): the two values that must not touch the host speed:B0inCBAUDand a bareBOTHER. The kernel resolvesBOTHERon a plainTCSETSfrom the tty's currentc_ospeed(drivers/tty/tty_ioctl.cset_termiosstarts fromtty->termios;drivers/tty/tty_baudrate.ctty_termios_baud_rate). An earlier draft decoded it to 0 and collapsed a 74880-baud line to B0 on the nexttcgetattr/tcsetattrpair (see evidence).linux_cflag_speed_bits():CIBAUDis set only when input != output, andTCGETS2now uses the same encoding instead of alwaysBOTHER, matchingtty_termios_encode_baud_rate().TCSETS2decodesCIBAUDsymmetrically (B0 = same as output,BOTHER= numericc_ispeed, else table): sinceTCGETS2now reports a split rate asCBAUD+CIBAUDindexes rather than the old blanketBOTHER, an unchangedtcgetattr/tcsetattrpair from glibc 2.42 would otherwise collapse the input rate to the output rate (found in self-review on the staging fork, Honor CBAUD/CIBAUD in TCGETS, TCGETS2 and TCSETS jotpalch/elfuse#1).Problem
src/syscall/io.cTCSETS arm (io.c:2289-2316at bffd6bd)cfsetispeed/cfsetospeed; only the TCSETS2 arm didTCGETSCBAUD, socfgetospeed()== 0TCSETSwith the rate inCBAUD; glibc 2.42+ switched toTCGETS2/TCSETS2unconditionally (sysdeps/unix/sysv/linux/tcsetattr.c,kernel-features.h__ASSUME_TERMIOS2)/devpassthrough already allows (/dev/cu.usbmodem*)Change
io.c:linux_cflag_speed_bits()(host termios ->CBAUD/CIBAUDbits) andapply_linux_cflag_speeds()(Linuxc_cflag->cfsetospeed/cfsetispeed), used by theTCGETS,TCGETS2andTCSETS/TCSETSW/TCSETSFarms.LINUX_IBSHIFTadded next toLINUX_CBAUD.tests/test-pty.c: slave-side block (5 checks): B115200 round trip; unchanged termios keeps the rate; 74880 set via rawTCSETS2survives a plaintcgetattr/tcsetattrpair; split rate throughCIBAUDand re-unification;TCGETS/TCGETS2agree.Kernel references (Linux v7.2):
include/uapi/asm-generic/termbits.h(CBAUD0x100f,BOTHER0x1000,CIBAUD=CBAUD << 16,B1152000x1002),drivers/tty/tty_baudrate.c(tty_termios_baud_rate,tty_termios_input_baud_rate,tty_termios_encode_baud_rate),drivers/tty/tty_ioctl.c(set_termios,get_termios). x86_64 (Rosetta) guests share theasm-genericlayout.Evidence
Harness: open a macOS pty pair, preset the host side to 9600, hand the slave to a static aarch64 guest that does
tcsetattr(B115200)and reads it back.glibc 2.41 guest, before (bffd6bd) vs after
before:
after:
musl 1.2.5 guest, after
74880 (BOTHER) regression: draft vs final
draft (decoded bare BOTHER to 0):
final:
native macOS build of the same program, same pty (control)
real hardware: ESP32-S3 USB-Serial/JTAG (/dev/cu.usbmodem101), before vs after
before:
after (this PR + piece 2):
Tests
build/elfuse build/test-pty: 63 passed, 0 failed (includes the split-rate TCGETS2/TCSETS2 regression test)make check BAREMETAL_CROSS=aarch64-elf- LINUX_TOOLCHAIN=/opt/homebrew/opt/aarch64-unknown-linux-gnu -j8: rc=0,All 77 tests passed(fixture-dependent musl/dyn-glibc cases skipped as on a stock checkout)clang-format --dry-run -WerrorcleanNot in this PR
TCFLSH,TCSBRK,TIOCM*, ...) -> piece 2 (stacked PR).B0hang-up (drop DTR/RTS) is not emulated; documented in the comment.Summary by cubic
Honor CBAUD/CIBAUD in TCGETS, TCGETS2, and TCSETS so baud rates round-trip correctly. Previously TCSETS ignored baud bits and TCGETS reported B0; now standard, custom (BOTHER), and split input rates are preserved.
Written for commit 3a6c880. Summary will update on new commits.