fix(kernel): FileTableVerb::Resize no-op + ProcUptime soft-float

Two fixes on the clean base (all boot-investigation diagnostics removed):

1. ProcScheme::kcall now accepts FileTableVerb::Resize on filetable
   handles as a no-op instead of returning EBADF. After the upstream
   'move fd allocation into userspace' relibc refactor, FILETABLE
   pre-syncs its size via a Resize call before growing; the kernel
   already grows posix_fdtbl on insert. Returning EBADF broke add_posix
   once a process's fd table grew (notably the bootstrap process manager
   proxying child thread ops), making the child's regs/env dup fail and
   its ld.so panic, crashing initfs daemons (randd) at boot.

2. ProcUptime uses integer arithmetic instead of f64 (the kernel is
   built with +soft-float; f64 in format!() breaks the build).
This commit is contained in:
2026-07-15 15:27:42 +09:00
parent 2086faecb0
commit b5a7bf5581
+32 -7
View File
@@ -975,14 +975,34 @@ impl KernelScheme for ProcScheme {
handle.clone()
};
let verb_raw: u8 = (*metadata.first().ok_or(Error::new(EINVAL))?)
.try_into()
.map_err(|_| Error::new(EINVAL))?;
// After the upstream "move fd allocation into userspace" relibc refactor,
// FILETABLE.add_posix pre-syncs the kernel table size by issuing a
// FileTableVerb::Resize call on the filetable handle before it grows.
// The kernel already grows posix_fdtbl automatically on insert (see
// Context::insert_file / bulk_add_files_posix), so accept this as a
// no-op instead of rejecting the non-OpenViaDup filetable handle with
// EBADF. Returning EBADF broke add_posix for any process whose fd table
// grew — notably the bootstrap process manager while proxying a child's
// thread ops — making the child's regs/env dup fail and its ld.so panic
// ("failed to open handle for process registers"), crashing initfs
// daemons (randd) at boot.
if matches!(
handle.kind,
ContextHandle::Filetable { .. } | ContextHandle::NewFiletable { .. }
) && verb_raw == FileTableVerb::Resize as u8
{
return Ok(0);
}
let ContextHandle::OpenViaDup = handle.kind else {
return Err(Error::new(EBADF));
};
let verb: u8 = (*metadata.first().ok_or(Error::new(EINVAL))?)
.try_into()
.map_err(|_| Error::new(EINVAL))?;
let verb = ProcSchemeVerb::try_from_raw(verb).ok_or(Error::new(EINVAL))?;
let verb = ProcSchemeVerb::try_from_raw(verb_raw).ok_or(Error::new(EINVAL))?;
match verb {
ProcSchemeVerb::Iopl => context::current()
@@ -2000,9 +2020,14 @@ impl ContextHandle {
read_from(buf, output.as_bytes(), offset)
}
ContextHandle::ProcUptime => {
let uptime_s = crate::time::monotonic(token) as f64 / crate::time::NANOS_PER_SEC as f64;
let idle_s = 0.0f64;
let output = format!("{:.2} {:.2}\n", uptime_s, idle_s);
// Red Bear fix: kernel is built with `+soft-float` (no SSE), so
// f64 in format!() triggers "SSE register return with SSE
// disabled" build error. Use integer arithmetic and emit
// seconds.milliseconds without f64 division. Idle always 0.
let nanos = crate::time::monotonic(token);
let uptime_s = nanos / crate::time::NANOS_PER_SEC;
let uptime_ms = (nanos % crate::time::NANOS_PER_SEC) / 1_000_000;
let output = format!("{}.{:02} 0.00\n", uptime_s, uptime_ms);
read_from(buf, output.as_bytes(), offset)
}
ContextHandle::ProcLoadavg => {