Feat async - #53
Feat async#53muou000 wants to merge 45 commits into
Conversation
…tion - Integrated `NET_WAIT_QUEUE` into `axnet` for TCP/UDP sockets. - Refactored `sys_epoll_pwait` to use `EpollFuture` and `block_on`. - Replaced sleep-polling with waker-based notification in socket operations. - Added `SigmaskGuard` to ensure signal mask restoration in epoll. - Enabled `multitask` feature for `axnet` and propagated through `axfeat`.
…pport - Ported future module to axtask, including AxWaker, block_on, sleep, and timeout. - Refactored IrqHandler signature to fn(usize) across handler_table, axplat, and axhal. - Implemented register_irq_waker to support asynchronous interrupt-driven task waking. - Migrated axplat and handler_table to local crates/ to enable local patching. - Updated axruntime and platform-specific IRQ dispatchers to support the new handler signature. - Integrated futures-util for advanced async flow control.
…_enable Introduce SpinNoIrq locks to synchronize access to the interrupt enable registers on both RISC-V and LoongArch64. Since set_enable performs non-atomic read-modify-write operations, concurrent calls from multiple threads/cores can overwrite enable states, leading to race conditions. fix(irq): 修复 PLIC 和 PCH-PIC set_enable 中的并发读改写竞态条件 在 RISC-V 和 LoongArch64 的中断启用寄存器上引入 SpinNoIrq 锁进行同步。由于 set_enable 执行的是非原子性的读-改-写操作,多线程/多核的并发调用可能会相互覆盖,导致中断启用配置冲突。
In `IrqIf::unregister`'s `@EX_IRQ` branch, the handler was removed but the PLIC interrupt source remained enabled, potentially causing interrupts to keep retriggering after unregistration. We now call `Self::set_enable(irq, false)` before removing the handler. 在 `IrqIf::unregister` 的 `@EX_IRQ` 分支中,先前只在表中移除了 PLIC 中断处理函数,却没有禁用 PLIC 中断源本身。这导致注销成功后外设中断依然可能被重复触发。 本修改借鉴了 LoongArch 平台上的实现以及对应的注册使能逻辑,在移除处理函数前显式调用 `Self::set_enable(irq, false)`。
To avoid SMP routing issues under multi-hart configurations where PLIC operations (`set_enable`, `claim`, and `complete`) are hardcoded to context 0 (Hart 0), this patch gates S-mode external interrupts (`S_EXT`) during per-CPU initialization so they are only enabled on Hart 0. It also adds clear documentation of the Hart 0 affinity constraint on the corresponding paths. 在多核配置下,PLIC 相关操作(`set_enable`、`claim` 和 `complete`)都是硬编码针对 context 0(Hart 0)的。为了避免 SMP 外部中断路由问题,本修改将 S 模式外部中断(`S_EXT`)在 per-CPU 初始化阶段限制为仅在 Hart 0 上启用。同时在对应路径上添加了清晰的 Hart 0 亲和性限制文档注释。
…nterrupts in a loop To avoid the overhead of repeatedly entering and exiting the trap handler when multiple interrupts are pending on the LoongArch64 platform, this patch updates the `HWI0` interrupt handler to loop over all pending bits in `eiointc::get_pending()`, processing and clearing each one in a single trap invocation. 为了避免在 LoongArch64 平台上出现多个挂起中断时,CPU 频繁进入和退出中断陷阱(Trap)的额外开销,本修改更新了 `HWI0` 外部设备中断处理逻辑。通过 `while` 循环遍历并处理 `eiointc::get_pending()` 中的所有挂起位,从而在同一次中断处理例程中完成所有的中断服务与清除操作。
…aker and wait queue
…t and blk wrappers via Arc
…erOps) Define AsyncBlockDriverOps in axdriver_block and implement it for VirtIoBlkDevWrapper using WaitFuture.await.
…ures and update driver paths
📝 WalkthroughWalkthrough该 PR 新增 Future、轮询和等待队列基础设施,将文件系统、网络 socket、VirtIO I/O 及平台中断处理迁移到异步等待模型,并补充驱动抽象、平台接口、依赖覆盖和启动路径调整。 Changes异步运行时与文件系统
网络、驱动与系统调用
平台与工程配置
Estimated code review effort: 5 (Critical) | ~180 minutes Sequence Diagram(s)sequenceDiagram
participant Syscall as epoll syscall
participant EpollFuture
participant Socket as TCP/UDP socket
participant WaitQueue
participant NetworkTask as network task
Syscall->>EpollFuture: block_on(EpollFuture)
EpollFuture->>Socket: register_poll(waker, events)
Socket->>WaitQueue: register_waker(waker)
NetworkTask->>Socket: poll_interfaces()
NetworkTask->>WaitQueue: notify_all()
WaitQueue-->>EpollFuture: wake waker
EpollFuture-->>Syscall: ready events
Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 3 | ❌ 2❌ Failed checks (1 warning, 1 inconclusive)
✅ Passed checks (3 passed)
✨ Finishing Touches📝 Generate docstrings
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Code Review
This pull request introduces significant changes to support asynchronous I/O operations across the ArceOS filesystem and driver modules. It adds AsyncBlockDriverOps to the block driver trait, updates various modules to use async/await patterns, and integrates axpoll for I/O event polling. However, the implementation of AsyncBlockDriverOps for SharedBlockDevice in arceos/modules/axfs/src/disk.rs contains critical issues, including unsound unsafe code that violates Rust's aliasing rules and a synchronous blocking implementation that undermines the purpose of the async trait.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
| impl AsyncBlockDriverOps for SharedBlockDevice { | ||
| type ReadFuture<'a> = core::pin::Pin<Box<dyn core::future::Future<Output = DevResult> + Send + 'a>>; | ||
| type WriteFuture<'a> = core::pin::Pin<Box<dyn core::future::Future<Output = DevResult> + Send + 'a>>; | ||
|
|
||
| fn read_block_async<'a>(&'a mut self, block_id: u64, buf: &'a mut [u8]) -> Self::ReadFuture<'a> { | ||
| let dev_ptr = Arc::as_ptr(&self.dev) as *mut Mutex<AxBlockDevice>; | ||
| let dev_mut = unsafe { &mut *dev_ptr }; | ||
| let dev_guard = dev_mut.get_mut(); | ||
| let res = dev_guard.read_block(block_id, buf); | ||
| Box::pin(async move { res }) | ||
| } | ||
|
|
||
| fn write_block_async<'a>(&'a mut self, block_id: u64, buf: &'a [u8]) -> Self::WriteFuture<'a> { | ||
| let dev_ptr = Arc::as_ptr(&self.dev) as *mut Mutex<AxBlockDevice>; | ||
| let dev_mut = unsafe { &mut *dev_ptr }; | ||
| let dev_guard = dev_mut.get_mut(); | ||
| let res = dev_guard.write_block(block_id, buf); | ||
| Box::pin(async move { res }) | ||
| } | ||
| } |
There was a problem hiding this comment.
The implementation of AsyncBlockDriverOps for SharedBlockDevice has two major issues:
-
Unsound
unsafecode: The code usesunsafeto get a mutable reference from anArc<Mutex<...>>by casting a*constto a*mut. This is undefined behavior as it violates Rust's aliasing rules. The correct way to get mutable access is by locking the mutex. -
Not actually asynchronous: The implementation calls the synchronous
read_blockandwrite_blockmethods and wraps the result in anasyncblock. This will block the executor's thread until the I/O operation completes, defeating the purpose of async I/O.
A correct implementation should use an async-aware mutex and call an async version of the block I/O methods on the underlying device. If the intention is to provide a synchronous-like async interface for a synchronous driver, the operation should be moved to a blocking thread pool. Given the current implementation, it seems to be a synchronous blocking call wrapped in a future, which is incorrect for an async driver trait.
Here is a sketch of what a correct implementation might look like, assuming an async-aware mutex and an async-enabled underlying device:
impl AsyncBlockDriverOps for SharedBlockDevice {
type ReadFuture<'a> = impl core::future::Future<Output = DevResult> + Send + 'a;
type WriteFuture<'a> = impl core::future::Future<Output = DevResult> + Send + 'a;
fn read_block_async<'a>(&'a mut self, block_id: u64, buf: &'a mut [u8]) -> Self::ReadFuture<'a> {
async move {
let mut dev_guard = self.dev.lock().await; // Using an async mutex
// Assuming the underlying device now implements AsyncBlockDriverOps
dev_guard.read_block_async(block_id, buf).await
}
}
fn write_block_async<'a>(&'a mut self, block_id: u64, buf: &'a [u8]) -> Self::WriteFuture<'a> {
async move {
let mut dev_guard = self.dev.lock().await; // Using an async mutex
dev_guard.write_block_async(block_id, buf).await
}
}
}There was a problem hiding this comment.
Actionable comments posted: 16
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
arceos/modules/axfs/src/fs/tmpfs.rs (1)
349-362: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win
link()在持有dir.entries互斥锁期间对target.metadata()进行await。let mut entries = dir.entries.lock(); ... let node_type = target.metadata().await?.node_type; entries.insert(...);
entries是一个跨越.await点仍持有的MutexGuard。即便当前TmpNode::metadata的实现体本身是同步完成的(几乎不会真正让出),这种“持锁跨 await”的写法本身是脆弱的反模式:一旦未来该 future 的实现变得真正异步(或被其它同类节点类型复用),持锁期间发生任务切换会导致该目录锁被长时间占用,甚至可能与其它需要同一把锁的路径互相阻塞。建议将
target.metadata().await?提到获取entries锁之前执行:♻️ 修复建议
async fn link(&self, name: &str, target: &DirEntry) -> VfsResult<DirEntry> { let dir = inode_as_dir(&self.inode)?; - let mut entries = dir.entries.lock(); - let target = target.downcast::<Self>()?; + let node_type = target.metadata().await?.node_type; + + let mut entries = dir.entries.lock(); if entries.contains_key(name) { return Err(VfsError::AlreadyExists); } let inode = target.inode.clone(); - let node_type = target.metadata().await?.node_type; entries.insert(name.into(), InodeRef::new(self.fs.clone(), inode.ino)); self.new_entry(name, node_type, inode) }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@arceos/modules/axfs/src/fs/tmpfs.rs` around lines 349 - 362, 在 link 方法中将 target.metadata().await?.node_type 的获取移到 dir.entries.lock() 之前,确保 entries 的 MutexGuard 不跨越 await 点;随后再获取锁并执行重复名称检查、插入 InodeRef 和 new_entry,保持现有行为不变。
🧹 Nitpick comments (6)
pulse_core/src/net/mod.rs (1)
956-972: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value
register_poll中intersects与contains使用不一致。Line 959 对
IN | RDHUP使用intersects(任一位匹配即注册),而 Line 962 对OUT使用contains(所有位匹配才注册)。由于OUT是单一位,两者功能等价,但 API 选择不一致容易引起误解。建议统一使用intersects。♻️ 统一使用 intersects
- if events.contains(axpoll::IoEvents::OUT) { + if events.intersects(axpoll::IoEvents::OUT) { s.tx.write_wait_queue.register_waker(cx.waker()); }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@pulse_core/src/net/mod.rs` around lines 956 - 972, 在 register_poll 中将针对 axpoll::IoEvents::OUT 的 events.contains 调用统一改为 events.intersects,保持现有写等待队列注册逻辑不变。arceos/modules/axdriver/Cargo.toml (1)
26-35: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value考虑将
async从virtio-blk解耦为独立 opt-in 特性。
virtio-blk现在强制启用async(L35),用户无法仅使用同步 virtio-blk 而不引入异步依赖。虽然async仅添加AsyncBlockDriverOpstrait 不影响同步操作,但对于最小化构建场景,将async作为可选项更灵活。♻️ 建议将 async 设为 virtio-blk 的可选特性
-virtio-blk = ["block", "virtio", "axdriver_virtio/block", "async"] +virtio-blk = ["block", "virtio", "axdriver_virtio/block"] +virtio-blk-async = ["virtio-blk", "async"]🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@arceos/modules/axdriver/Cargo.toml` around lines 26 - 35, 将 Cargo.toml 中的 virtio-blk 特性与 async 特性解耦,移除 virtio-blk 对 async 的强制依赖,使用户可以仅启用同步 virtio-blk;保留 async 作为独立 opt-in 特性及其 axdriver_block/async 依赖。arceos/modules/axtask/src/future/mod.rs (1)
107-134: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value建议为
WaitFuture添加Drop实现以清理已注册的 waker。
WaitFuture被 drop 时(如select取消、超时等场景),已注册的 waker 仍留在WaitQueue::wakers中,导致临时内存滞留和潜在虚假唤醒。虽然notify_one/notify_all的core::mem::take会最终清理,且register_waker按 task_id 去重可缓解重复注册,但主动清理更可靠。♻️ 建议的 Drop 实现
pub struct WaitFuture<'a> { wq: &'a crate::wait_queue::WaitQueue, registered: bool, } +impl<'a> Drop for WaitFuture<'a> { + fn drop(&mut self) { + if self.registered { + let task_id = crate::current().id().as_u64(); + let mut wakers = self.wq.wakers.lock(); + if let Some(idx) = wakers.iter().position(|(id, _)| *id == task_id) { + wakers.remove(idx); + } + } + } +} + impl<'a> WaitFuture<'a> {🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@arceos/modules/axtask/src/future/mod.rs` around lines 107 - 134, 为 WaitFuture 添加 Drop 实现,在 future 被销毁且已完成 waker 注册时,从关联的 WaitQueue 清理该 waker;未注册时无需执行清理。复用 WaitQueue 现有的 waker 移除机制,确保取消或超时不会留下已注册 waker。arceos/modules/axnet/src/smoltcp_impl/mod.rs (1)
176-192: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win
poll_interfaces中通知逻辑为 O(N*M),建议优化为单次遍历 + 映射查找。对每个已注册等待队列都线性扫描全部 socket 寻找匹配项;由于该函数在网络轮询热路径上频繁调用,socket/等待队列数量增多时开销会明显上升。可改为遍历
sockets.iter_mut()一次,按handle从wq_map(BTreeMap)查找,将复杂度从 O(N*M) 降为 O(N log M)。♻️ 建议重构
- let wq_map = SOCKET_WAIT_QUEUES.lock(); - let mut sockets = self.0.lock(); - for (handle, wq) in wq_map.iter() { - if let Some(socket) = sockets.iter_mut().find(|(h, _)| h == handle).map(|(_, s)| s) { - let can_io = match socket { - Socket::Tcp(s) => s.can_recv() || s.can_send() || !s.is_active(), - Socket::Udp(s) => s.can_recv() || s.can_send(), - _ => false, - }; - if can_io { - wq.notify_all(true); - } - } - } + let wq_map = SOCKET_WAIT_QUEUES.lock(); + let mut sockets = self.0.lock(); + for (handle, socket) in sockets.iter_mut() { + if let Some(wq) = wq_map.get(&handle) { + let can_io = match socket { + Socket::Tcp(s) => s.can_recv() || s.can_send() || !s.is_active(), + Socket::Udp(s) => s.can_recv() || s.can_send(), + _ => false, + }; + if can_io { + wq.notify_all(true); + } + } + }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@arceos/modules/axnet/src/smoltcp_impl/mod.rs` around lines 176 - 192, 优化 poll_interfaces 中的 socket 通知遍历:将当前按等待队列遍历并在线性扫描 sockets 的逻辑,改为单次遍历 sockets.iter_mut(),根据每个 socket 的 handle 使用 wq_map 查找对应等待队列并通知。保留现有各类 Socket 的 can_io 判断及 NET_WAIT_QUEUE.notify_all(true),将复杂度降为 O(N log M)。arceos/modules/axfs/src/highlevel/fs.rs (1)
285-310: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win
read()声明为async fn,但读取路径仍是同步的,未真正获得异步收益。
read()内部用同步的(&file).read_to_end(&mut buf)?(未.await),而同文件的read_prefix()用file.read_at(...).await。若File的Read实现底层是阻塞式的,read()的async fn声明只是形式上的包装,未能避免阻塞执行器线程,与本 PR 异步化的初衷不符。建议
read()也基于read_at/异步 API 实现(例如循环调用file.read_at(...).await直至读满),以与read_prefix保持一致的异步语义。🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@arceos/modules/axfs/src/highlevel/fs.rs` around lines 285 - 310, Update the async read method to avoid the synchronous (&file).read_to_end call. Implement read using File::read_at with awaited reads, looping until EOF while collecting all bytes, consistent with the asynchronous behavior of read_prefix; preserve error propagation and the existing Vec<u8> result.crates/axpoll/src/lib.rs (1)
134-142: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win
PollSet::wake()的真正唤醒行为依赖局部变量inner在函数末尾隐式 Drop 触发,建议加注释说明。代码逻辑正确(
inner.len()只是取值不会阻止其在作用域结束时被 drop,Drop for Inner会遍历并wake()所有条目),但这个控制流比较隐晦,容易被未来的重构(例如为了"性能优化"提前drop/mem::forget)意外破坏。建议加一行注释说明唤醒是由Inner的Drop完成的。📝 建议的注释补充
pub fn wake(&self) -> usize { let mut guard = self.0.lock(); if guard.is_empty() { return 0; } let inner = core::mem::replace(&mut *guard, Inner::new()); drop(guard); + // `inner`'s `Drop` impl wakes all registered wakers when it goes out of scope below. inner.len() }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@crates/axpoll/src/lib.rs` around lines 134 - 142, 在 PollSet::wake 方法中,为局部变量 inner 的生命周期结束位置添加注释,明确说明 Inner 的隐式 Drop 会遍历并唤醒所有条目;保持现有 inner.len() 返回逻辑不变,不引入额外的 drop 或行为修改。
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@arceos/modules/axdriver/src/virtio.rs`:
- Around line 83-98: 为 irq == 0 增加轮询回退:网络设备初始化或 poll_set 返回路径在无 IRQ 时返回 None。同步块
I/O 仅在 self.irq > 0 且 irqs_enabled() 时进入等待,否则执行轮询;异步 I/O 路径同样避免无限等待,并通过可让出 CPU
的轮询回退继续推进。同步更新 VirtIoNetDevInner、块设备等待逻辑及相关异步路径,同时保留 irq > 0 时现有中断注册与唤醒行为。
- Around line 34-42: 更新 VirtioInterruptInfo 及 IRQ 注册流程,除 dev_ptr 外保留设备 Arc
的强引用,注册时通过 Arc::into_raw(inner.clone()) 持有生命周期并确保中断处理使用有效对象;若存在设备移除路径,必须在反注册时停止
IRQ、移除对应记录并将该裸指针恢复为 Arc 以释放引用。
- Around line 557-558: 在处理 MSI-X BAR 的代码中移除 root.bar_info 的 unwrap
调用,改为显式处理缺失或非法 BIR:将其视为 MSI-X 配置失败,并沿现有路径回退到 legacy IRQ,同时保持有效 BarInfo::Memory
情况的处理不变。
In `@arceos/modules/axtask/src/tests.rs`:
- Around line 131-151: Reset the function-local static FINISHED flag to false
before spawning the async task in test_async_task. Keep the existing
acquire/release synchronization and completion assertion unchanged so repeated
test invocations wait for the newly spawned task to finish.
In `@arceos/modules/axtask/src/wait_queue.rs`:
- Around line 267-297: Update notify_one’s waker fallback to remove and wake
only one registered waker, matching the single-task behavior. Preserve the
existing return value semantics: report whether a waker was available, and leave
all other wakers registered for future notifications.
In `@crates/axdriver_block/src/bcm2835sdhci.rs`:
- Around line 63-65: Update the buffer-length validation in write_block so a
buffer smaller than BLOCK_SIZE returns DevError::InvalidParam, matching
read_block’s parameter-validation behavior; leave the normal write path
unchanged.
In `@crates/axdriver_virtio/src/gpu.rs`:
- Around line 20-27: Update try_new to propagate failures from InnerDev::new,
setup_framebuffer, and resolution through its DevResult return type instead of
panicking with unwrap(). Convert each underlying error using the same as_dev_err
error-mapping pattern used by flush(), while preserving the existing
initialization flow.
In `@crates/axdriver_virtio/src/lib.rs`:
- Around line 49-50: Update probe_mmio_device so the NonNull::new conversion for
reg_base propagates None with ? instead of calling unwrap. Preserve the existing
MmioTransport::new error propagation and avoid panicking when reg_base is null.
In `@crates/axdriver_virtio/src/net.rs`:
- Line 19: Remove public visibility from the `inner` field of the net device,
keeping it encapsulated so callers cannot bypass the buffer and queue
bookkeeping initialized by `try_new`. Expose only the narrow delegate methods
required by external callers, such as `enable_interrupts` and `ack_interrupt`,
and preserve their existing behavior.
In `@crates/axfs-ng-vfs/src/node/dir.rs`:
- Around line 216-223: Update Dir::link to acquire and hold self.cache’s lock
before awaiting self.ops.link, then insert the returned entry into the cache
while retaining that same lock. Match the locking and atomicity pattern used by
create_locked and unlink, while preserving name validation and the existing
returned-entry behavior.
In `@crates/axplat-loongarch64-qemu-virt/src/irq/eiointc.rs`:
- Around line 60-63: Update the EIOINTC_IPMAP initialization to write the target
CPU IP as a one-hot mapping instead of zero, using the correct value for CPU
HWI0/IP2 (pin index 0). Apply the same mapping to both register writes covering
all interrupt groups, preserving the existing 256-interrupt setup.
In `@crates/axplat/README.md`:
- Around line 46-48: Update the “How to write a platform package” section
headings so “1. Implement each interface trait” and the nearby “2. Implement
platform bootstrapping code...” use h3 (`###`) rather than h4, preserving the
existing heading text.
In `@crates/axpoll/README.md`:
- Line 28: Update the axpoll README dependency version from 0.3.2 to 0.3.9 and
change the directory path from components/axpoll to crates/axpoll in both
crates/axpoll/README.md (lines 28 and 35) and crates/axpoll/README_CN.md (lines
28 and 35).
In `@crates/axpoll/tests/async.rs`:
- Around line 20-31: 调整 WaitFuture::poll 的操作顺序,先通过 self.ps.register(cx.waker())
注册当前 waker,再检查 ready 状态;ready 为真时返回 Poll::Ready(()),否则返回
Poll::Pending。确保注册后的唤醒不会被遗漏,并保持现有 Future 输出行为不变。
In `@pulse_core/src/mm/loader.rs`:
- Around line 421-429: Remove the synchronous block_on calls from read_elf_range
for File::open, file.read_at, and fs_ctx.read, and refactor the function to
await these filesystem operations directly within its async flow. Preserve the
existing error mappings, short-read fallback, and successful range-read
behavior.
In `@src/main.rs`:
- Around line 121-136: Update the non-testcode startup failure paths around
init_task and the “Failed to create user process” error so they do not enter
permanent axtask::yield_now loops. Observe and handle init_task termination, and
use an explicit recovery, shutdown, or restart strategy when new_uspace or
process creation fails; preserve the existing testcode behavior.
---
Outside diff comments:
In `@arceos/modules/axfs/src/fs/tmpfs.rs`:
- Around line 349-362: 在 link 方法中将 target.metadata().await?.node_type 的获取移到
dir.entries.lock() 之前,确保 entries 的 MutexGuard 不跨越 await 点;随后再获取锁并执行重复名称检查、插入
InodeRef 和 new_entry,保持现有行为不变。
---
Nitpick comments:
In `@arceos/modules/axdriver/Cargo.toml`:
- Around line 26-35: 将 Cargo.toml 中的 virtio-blk 特性与 async 特性解耦,移除 virtio-blk 对
async 的强制依赖,使用户可以仅启用同步 virtio-blk;保留 async 作为独立 opt-in 特性及其 axdriver_block/async
依赖。
In `@arceos/modules/axfs/src/highlevel/fs.rs`:
- Around line 285-310: Update the async read method to avoid the synchronous
(&file).read_to_end call. Implement read using File::read_at with awaited reads,
looping until EOF while collecting all bytes, consistent with the asynchronous
behavior of read_prefix; preserve error propagation and the existing Vec<u8>
result.
In `@arceos/modules/axnet/src/smoltcp_impl/mod.rs`:
- Around line 176-192: 优化 poll_interfaces 中的 socket 通知遍历:将当前按等待队列遍历并在线性扫描
sockets 的逻辑,改为单次遍历 sockets.iter_mut(),根据每个 socket 的 handle 使用 wq_map
查找对应等待队列并通知。保留现有各类 Socket 的 can_io 判断及 NET_WAIT_QUEUE.notify_all(true),将复杂度降为
O(N log M)。
In `@arceos/modules/axtask/src/future/mod.rs`:
- Around line 107-134: 为 WaitFuture 添加 Drop 实现,在 future 被销毁且已完成 waker 注册时,从关联的
WaitQueue 清理该 waker;未注册时无需执行清理。复用 WaitQueue 现有的 waker 移除机制,确保取消或超时不会留下已注册 waker。
In `@crates/axpoll/src/lib.rs`:
- Around line 134-142: 在 PollSet::wake 方法中,为局部变量 inner 的生命周期结束位置添加注释,明确说明 Inner
的隐式 Drop 会遍历并唤醒所有条目;保持现有 inner.len() 返回逻辑不变,不引入额外的 drop 或行为修改。
In `@pulse_core/src/net/mod.rs`:
- Around line 956-972: 在 register_poll 中将针对 axpoll::IoEvents::OUT 的
events.contains 调用统一改为 events.intersects,保持现有写等待队列注册逻辑不变。
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro Plus
Run ID: 90492e09-bba4-4834-97d1-9b609d20dfbf
⛔ Files ignored due to path filters (248)
Cargo.lockis excluded by!**/*.lockarceos/Cargo.lockis excluded by!**/*.lockcrates/axplat/Cargo.lockis excluded by!**/*.lockcrates/axpoll/Cargo.lockis excluded by!**/*.lockvendor/axdriver_block/src/lib.rsis excluded by!vendor/**vendor/axdriver_net/.cargo-checksum.jsonis excluded by!vendor/**vendor/axdriver_virtio/.cargo-checksum.jsonis excluded by!vendor/**vendor/axplat/.cargo-checksum.jsonis excluded by!vendor/**vendor/axplat/Cargo.toml.origis excluded by!vendor/**vendor/axpoll/Cargo.toml.origis excluded by!vendor/**vendor/futures-core/.cargo-checksum.jsonis excluded by!vendor/**vendor/futures-core/.cargo_vcs_info.jsonis excluded by!vendor/**vendor/futures-core/Cargo.lockis excluded by!**/*.lock,!vendor/**vendor/futures-core/Cargo.tomlis excluded by!vendor/**vendor/futures-core/Cargo.toml.origis excluded by!vendor/**vendor/futures-core/LICENSE-APACHEis excluded by!vendor/**vendor/futures-core/LICENSE-MITis excluded by!vendor/**vendor/futures-core/README.mdis excluded by!vendor/**vendor/futures-core/src/future.rsis excluded by!vendor/**vendor/futures-core/src/lib.rsis excluded by!vendor/**vendor/futures-core/src/stream.rsis excluded by!vendor/**vendor/futures-core/src/task/__internal/atomic_waker.rsis excluded by!vendor/**vendor/futures-core/src/task/__internal/mod.rsis excluded by!vendor/**vendor/futures-core/src/task/mod.rsis excluded by!vendor/**vendor/futures-core/src/task/poll.rsis excluded by!vendor/**vendor/futures-macro/.cargo-checksum.jsonis excluded by!vendor/**vendor/futures-macro/.cargo_vcs_info.jsonis excluded by!vendor/**vendor/futures-macro/Cargo.lockis excluded by!**/*.lock,!vendor/**vendor/futures-macro/Cargo.tomlis excluded by!vendor/**vendor/futures-macro/Cargo.toml.origis excluded by!vendor/**vendor/futures-macro/LICENSE-APACHEis excluded by!vendor/**vendor/futures-macro/LICENSE-MITis excluded by!vendor/**vendor/futures-macro/src/executor.rsis excluded by!vendor/**vendor/futures-macro/src/join.rsis excluded by!vendor/**vendor/futures-macro/src/lib.rsis excluded by!vendor/**vendor/futures-macro/src/select.rsis excluded by!vendor/**vendor/futures-macro/src/stream_select.rsis excluded by!vendor/**vendor/futures-task/.cargo-checksum.jsonis excluded by!vendor/**vendor/futures-task/.cargo_vcs_info.jsonis excluded by!vendor/**vendor/futures-task/Cargo.lockis excluded by!**/*.lock,!vendor/**vendor/futures-task/Cargo.tomlis excluded by!vendor/**vendor/futures-task/Cargo.toml.origis excluded by!vendor/**vendor/futures-task/LICENSE-APACHEis excluded by!vendor/**vendor/futures-task/LICENSE-MITis excluded by!vendor/**vendor/futures-task/README.mdis excluded by!vendor/**vendor/futures-task/src/arc_wake.rsis excluded by!vendor/**vendor/futures-task/src/future_obj.rsis excluded by!vendor/**vendor/futures-task/src/lib.rsis excluded by!vendor/**vendor/futures-task/src/noop_waker.rsis excluded by!vendor/**vendor/futures-task/src/spawn.rsis excluded by!vendor/**vendor/futures-task/src/waker.rsis excluded by!vendor/**vendor/futures-task/src/waker_ref.rsis excluded by!vendor/**vendor/futures-util/.cargo-checksum.jsonis excluded by!vendor/**vendor/futures-util/.cargo_vcs_info.jsonis excluded by!vendor/**vendor/futures-util/Cargo.lockis excluded by!**/*.lock,!vendor/**vendor/futures-util/Cargo.tomlis excluded by!vendor/**vendor/futures-util/Cargo.toml.origis excluded by!vendor/**vendor/futures-util/LICENSE-APACHEis excluded by!vendor/**vendor/futures-util/LICENSE-MITis excluded by!vendor/**vendor/futures-util/README.mdis excluded by!vendor/**vendor/futures-util/benches/bilock.rsis excluded by!vendor/**vendor/futures-util/benches/flatten_unordered.rsis excluded by!vendor/**vendor/futures-util/benches/futures_unordered.rsis excluded by!vendor/**vendor/futures-util/benches/select.rsis excluded by!vendor/**vendor/futures-util/src/abortable.rsis excluded by!vendor/**vendor/futures-util/src/async_await/join_mod.rsis excluded by!vendor/**vendor/futures-util/src/async_await/mod.rsis excluded by!vendor/**vendor/futures-util/src/async_await/pending.rsis excluded by!vendor/**vendor/futures-util/src/async_await/poll.rsis excluded by!vendor/**vendor/futures-util/src/async_await/random.rsis excluded by!vendor/**vendor/futures-util/src/async_await/select_mod.rsis excluded by!vendor/**vendor/futures-util/src/async_await/stream_select_mod.rsis excluded by!vendor/**vendor/futures-util/src/compat/compat01as03.rsis excluded by!vendor/**vendor/futures-util/src/compat/compat03as01.rsis excluded by!vendor/**vendor/futures-util/src/compat/executor.rsis excluded by!vendor/**vendor/futures-util/src/compat/mod.rsis excluded by!vendor/**vendor/futures-util/src/fns.rsis excluded by!vendor/**vendor/futures-util/src/future/abortable.rsis excluded by!vendor/**vendor/futures-util/src/future/always_ready.rsis excluded by!vendor/**vendor/futures-util/src/future/either.rsis excluded by!vendor/**vendor/futures-util/src/future/future/catch_unwind.rsis excluded by!vendor/**vendor/futures-util/src/future/future/flatten.rsis excluded by!vendor/**vendor/futures-util/src/future/future/fuse.rsis excluded by!vendor/**vendor/futures-util/src/future/future/map.rsis excluded by!vendor/**vendor/futures-util/src/future/future/mod.rsis excluded by!vendor/**vendor/futures-util/src/future/future/remote_handle.rsis excluded by!vendor/**vendor/futures-util/src/future/future/shared.rsis excluded by!vendor/**vendor/futures-util/src/future/join.rsis excluded by!vendor/**vendor/futures-util/src/future/join_all.rsis excluded by!vendor/**vendor/futures-util/src/future/lazy.rsis excluded by!vendor/**vendor/futures-util/src/future/maybe_done.rsis excluded by!vendor/**vendor/futures-util/src/future/mod.rsis excluded by!vendor/**vendor/futures-util/src/future/option.rsis excluded by!vendor/**vendor/futures-util/src/future/pending.rsis excluded by!vendor/**vendor/futures-util/src/future/poll_fn.rsis excluded by!vendor/**vendor/futures-util/src/future/poll_immediate.rsis excluded by!vendor/**vendor/futures-util/src/future/ready.rsis excluded by!vendor/**vendor/futures-util/src/future/select.rsis excluded by!vendor/**vendor/futures-util/src/future/select_all.rsis excluded by!vendor/**vendor/futures-util/src/future/select_ok.rsis excluded by!vendor/**vendor/futures-util/src/future/try_future/into_future.rsis excluded by!vendor/**vendor/futures-util/src/future/try_future/mod.rsis excluded by!vendor/**vendor/futures-util/src/future/try_future/try_flatten.rsis excluded by!vendor/**vendor/futures-util/src/future/try_future/try_flatten_err.rsis excluded by!vendor/**vendor/futures-util/src/future/try_join.rsis excluded by!vendor/**vendor/futures-util/src/future/try_join_all.rsis excluded by!vendor/**vendor/futures-util/src/future/try_maybe_done.rsis excluded by!vendor/**vendor/futures-util/src/future/try_select.rsis excluded by!vendor/**vendor/futures-util/src/io/allow_std.rsis excluded by!vendor/**vendor/futures-util/src/io/buf_reader.rsis excluded by!vendor/**vendor/futures-util/src/io/buf_writer.rsis excluded by!vendor/**vendor/futures-util/src/io/chain.rsis excluded by!vendor/**vendor/futures-util/src/io/close.rsis excluded by!vendor/**vendor/futures-util/src/io/copy.rsis excluded by!vendor/**vendor/futures-util/src/io/copy_buf.rsis excluded by!vendor/**vendor/futures-util/src/io/copy_buf_abortable.rsis excluded by!vendor/**vendor/futures-util/src/io/cursor.rsis excluded by!vendor/**vendor/futures-util/src/io/empty.rsis excluded by!vendor/**vendor/futures-util/src/io/fill_buf.rsis excluded by!vendor/**vendor/futures-util/src/io/flush.rsis excluded by!vendor/**vendor/futures-util/src/io/into_sink.rsis excluded by!vendor/**vendor/futures-util/src/io/line_writer.rsis excluded by!vendor/**vendor/futures-util/src/io/lines.rsis excluded by!vendor/**vendor/futures-util/src/io/mod.rsis excluded by!vendor/**vendor/futures-util/src/io/read.rsis excluded by!vendor/**vendor/futures-util/src/io/read_exact.rsis excluded by!vendor/**vendor/futures-util/src/io/read_line.rsis excluded by!vendor/**vendor/futures-util/src/io/read_to_end.rsis excluded by!vendor/**vendor/futures-util/src/io/read_to_string.rsis excluded by!vendor/**vendor/futures-util/src/io/read_until.rsis excluded by!vendor/**vendor/futures-util/src/io/read_vectored.rsis excluded by!vendor/**vendor/futures-util/src/io/repeat.rsis excluded by!vendor/**vendor/futures-util/src/io/seek.rsis excluded by!vendor/**vendor/futures-util/src/io/sink.rsis excluded by!vendor/**vendor/futures-util/src/io/split.rsis excluded by!vendor/**vendor/futures-util/src/io/take.rsis excluded by!vendor/**vendor/futures-util/src/io/window.rsis excluded by!vendor/**vendor/futures-util/src/io/write.rsis excluded by!vendor/**vendor/futures-util/src/io/write_all.rsis excluded by!vendor/**vendor/futures-util/src/io/write_all_vectored.rsis excluded by!vendor/**vendor/futures-util/src/io/write_vectored.rsis excluded by!vendor/**vendor/futures-util/src/lib.rsis excluded by!vendor/**vendor/futures-util/src/lock/bilock.rsis excluded by!vendor/**vendor/futures-util/src/lock/mod.rsis excluded by!vendor/**vendor/futures-util/src/lock/mutex.rsis excluded by!vendor/**vendor/futures-util/src/macros.rsis excluded by!vendor/**vendor/futures-util/src/never.rsis excluded by!vendor/**vendor/futures-util/src/sink/buffer.rsis excluded by!vendor/**vendor/futures-util/src/sink/close.rsis excluded by!vendor/**vendor/futures-util/src/sink/drain.rsis excluded by!vendor/**vendor/futures-util/src/sink/err_into.rsis excluded by!vendor/**vendor/futures-util/src/sink/fanout.rsis excluded by!vendor/**vendor/futures-util/src/sink/feed.rsis excluded by!vendor/**vendor/futures-util/src/sink/flush.rsis excluded by!vendor/**vendor/futures-util/src/sink/map_err.rsis excluded by!vendor/**vendor/futures-util/src/sink/mod.rsis excluded by!vendor/**vendor/futures-util/src/sink/send.rsis excluded by!vendor/**vendor/futures-util/src/sink/send_all.rsis excluded by!vendor/**vendor/futures-util/src/sink/unfold.rsis excluded by!vendor/**vendor/futures-util/src/sink/with.rsis excluded by!vendor/**vendor/futures-util/src/sink/with_flat_map.rsis excluded by!vendor/**vendor/futures-util/src/stream/abortable.rsis excluded by!vendor/**vendor/futures-util/src/stream/empty.rsis excluded by!vendor/**vendor/futures-util/src/stream/futures_ordered.rsis excluded by!vendor/**vendor/futures-util/src/stream/futures_unordered/abort.rsis excluded by!vendor/**vendor/futures-util/src/stream/futures_unordered/iter.rsis excluded by!vendor/**vendor/futures-util/src/stream/futures_unordered/mod.rsis excluded by!vendor/**vendor/futures-util/src/stream/futures_unordered/ready_to_run_queue.rsis excluded by!vendor/**vendor/futures-util/src/stream/futures_unordered/task.rsis excluded by!vendor/**vendor/futures-util/src/stream/iter.rsis excluded by!vendor/**vendor/futures-util/src/stream/mod.rsis excluded by!vendor/**vendor/futures-util/src/stream/once.rsis excluded by!vendor/**vendor/futures-util/src/stream/pending.rsis excluded by!vendor/**vendor/futures-util/src/stream/poll_fn.rsis excluded by!vendor/**vendor/futures-util/src/stream/poll_immediate.rsis excluded by!vendor/**vendor/futures-util/src/stream/repeat.rsis excluded by!vendor/**vendor/futures-util/src/stream/repeat_with.rsis excluded by!vendor/**vendor/futures-util/src/stream/select.rsis excluded by!vendor/**vendor/futures-util/src/stream/select_all.rsis excluded by!vendor/**vendor/futures-util/src/stream/select_with_strategy.rsis excluded by!vendor/**vendor/futures-util/src/stream/stream/all.rsis excluded by!vendor/**vendor/futures-util/src/stream/stream/any.rsis excluded by!vendor/**vendor/futures-util/src/stream/stream/buffer_unordered.rsis excluded by!vendor/**vendor/futures-util/src/stream/stream/buffered.rsis excluded by!vendor/**vendor/futures-util/src/stream/stream/catch_unwind.rsis excluded by!vendor/**vendor/futures-util/src/stream/stream/chain.rsis excluded by!vendor/**vendor/futures-util/src/stream/stream/chunks.rsis excluded by!vendor/**vendor/futures-util/src/stream/stream/collect.rsis excluded by!vendor/**vendor/futures-util/src/stream/stream/concat.rsis excluded by!vendor/**vendor/futures-util/src/stream/stream/count.rsis excluded by!vendor/**vendor/futures-util/src/stream/stream/cycle.rsis excluded by!vendor/**vendor/futures-util/src/stream/stream/enumerate.rsis excluded by!vendor/**vendor/futures-util/src/stream/stream/filter.rsis excluded by!vendor/**vendor/futures-util/src/stream/stream/filter_map.rsis excluded by!vendor/**vendor/futures-util/src/stream/stream/flatten.rsis excluded by!vendor/**vendor/futures-util/src/stream/stream/flatten_unordered.rsis excluded by!vendor/**vendor/futures-util/src/stream/stream/fold.rsis excluded by!vendor/**vendor/futures-util/src/stream/stream/for_each.rsis excluded by!vendor/**vendor/futures-util/src/stream/stream/for_each_concurrent.rsis excluded by!vendor/**vendor/futures-util/src/stream/stream/forward.rsis excluded by!vendor/**vendor/futures-util/src/stream/stream/fuse.rsis excluded by!vendor/**vendor/futures-util/src/stream/stream/into_future.rsis excluded by!vendor/**vendor/futures-util/src/stream/stream/map.rsis excluded by!vendor/**vendor/futures-util/src/stream/stream/mod.rsis excluded by!vendor/**vendor/futures-util/src/stream/stream/next.rsis excluded by!vendor/**vendor/futures-util/src/stream/stream/peek.rsis excluded by!vendor/**vendor/futures-util/src/stream/stream/ready_chunks.rsis excluded by!vendor/**vendor/futures-util/src/stream/stream/scan.rsis excluded by!vendor/**vendor/futures-util/src/stream/stream/select_next_some.rsis excluded by!vendor/**vendor/futures-util/src/stream/stream/skip.rsis excluded by!vendor/**vendor/futures-util/src/stream/stream/skip_while.rsis excluded by!vendor/**vendor/futures-util/src/stream/stream/split.rsis excluded by!vendor/**vendor/futures-util/src/stream/stream/take.rsis excluded by!vendor/**vendor/futures-util/src/stream/stream/take_until.rsis excluded by!vendor/**vendor/futures-util/src/stream/stream/take_while.rsis excluded by!vendor/**vendor/futures-util/src/stream/stream/then.rsis excluded by!vendor/**vendor/futures-util/src/stream/stream/unzip.rsis excluded by!vendor/**vendor/futures-util/src/stream/stream/zip.rsis excluded by!vendor/**vendor/futures-util/src/stream/try_stream/and_then.rsis excluded by!vendor/**vendor/futures-util/src/stream/try_stream/into_async_read.rsis excluded by!vendor/**vendor/futures-util/src/stream/try_stream/into_stream.rsis excluded by!vendor/**vendor/futures-util/src/stream/try_stream/mod.rsis excluded by!vendor/**vendor/futures-util/src/stream/try_stream/or_else.rsis excluded by!vendor/**vendor/futures-util/src/stream/try_stream/try_all.rsis excluded by!vendor/**vendor/futures-util/src/stream/try_stream/try_any.rsis excluded by!vendor/**vendor/futures-util/src/stream/try_stream/try_buffer_unordered.rsis excluded by!vendor/**vendor/futures-util/src/stream/try_stream/try_buffered.rsis excluded by!vendor/**vendor/futures-util/src/stream/try_stream/try_chunks.rsis excluded by!vendor/**vendor/futures-util/src/stream/try_stream/try_collect.rsis excluded by!vendor/**vendor/futures-util/src/stream/try_stream/try_concat.rsis excluded by!vendor/**vendor/futures-util/src/stream/try_stream/try_filter.rsis excluded by!vendor/**vendor/futures-util/src/stream/try_stream/try_filter_map.rsis excluded by!vendor/**vendor/futures-util/src/stream/try_stream/try_flatten.rsis excluded by!vendor/**vendor/futures-util/src/stream/try_stream/try_flatten_unordered.rsis excluded by!vendor/**vendor/futures-util/src/stream/try_stream/try_fold.rsis excluded by!vendor/**vendor/futures-util/src/stream/try_stream/try_for_each.rsis excluded by!vendor/**vendor/futures-util/src/stream/try_stream/try_for_each_concurrent.rsis excluded by!vendor/**vendor/futures-util/src/stream/try_stream/try_next.rsis excluded by!vendor/**vendor/futures-util/src/stream/try_stream/try_ready_chunks.rsis excluded by!vendor/**vendor/futures-util/src/stream/try_stream/try_skip_while.rsis excluded by!vendor/**vendor/futures-util/src/stream/try_stream/try_take_while.rsis excluded by!vendor/**vendor/futures-util/src/stream/try_stream/try_unfold.rsis excluded by!vendor/**vendor/futures-util/src/stream/unfold.rsis excluded by!vendor/**vendor/futures-util/src/task/mod.rsis excluded by!vendor/**vendor/futures-util/src/task/spawn.rsis excluded by!vendor/**vendor/futures-util/src/unfold_state.rsis excluded by!vendor/**vendor/handler_table/.cargo-checksum.jsonis excluded by!vendor/**vendor/handler_table/Cargo.toml.origis excluded by!vendor/**
📒 Files selected for processing (138)
AGENTS.mdCargo.tomlarceos/Cargo.tomlarceos/api/axfeat/Cargo.tomlarceos/modules/axdriver/Cargo.tomlarceos/modules/axdriver/src/lib.rsarceos/modules/axdriver/src/prelude.rsarceos/modules/axdriver/src/virtio.rsarceos/modules/axfs/Cargo.tomlarceos/modules/axfs/src/disk.rsarceos/modules/axfs/src/fs/devfs.rsarceos/modules/axfs/src/fs/ext4/fs.rsarceos/modules/axfs/src/fs/ext4/inode.rsarceos/modules/axfs/src/fs/ext4/mod.rsarceos/modules/axfs/src/fs/fat/dir.rsarceos/modules/axfs/src/fs/loop_dev.rsarceos/modules/axfs/src/fs/mod.rsarceos/modules/axfs/src/fs/procfs.rsarceos/modules/axfs/src/fs/tmpfs.rsarceos/modules/axfs/src/highlevel/file.rsarceos/modules/axfs/src/highlevel/fs.rsarceos/modules/axfs/src/lib.rsarceos/modules/axnet/Cargo.tomlarceos/modules/axnet/src/lib.rsarceos/modules/axnet/src/smoltcp_impl/mod.rsarceos/modules/axnet/src/smoltcp_impl/tcp.rsarceos/modules/axnet/src/smoltcp_impl/udp.rsarceos/modules/axruntime/src/lib.rsarceos/modules/axtask/Cargo.tomlarceos/modules/axtask/src/api.rsarceos/modules/axtask/src/future/mod.rsarceos/modules/axtask/src/future/poll.rsarceos/modules/axtask/src/future/time.rsarceos/modules/axtask/src/lib.rsarceos/modules/axtask/src/run_queue.rsarceos/modules/axtask/src/task.rsarceos/modules/axtask/src/tests.rsarceos/modules/axtask/src/wait_queue.rscrates/axcpu/Cargo.toml.origcrates/axdriver_base/.cargo-checksum.jsoncrates/axdriver_base/Cargo.tomlcrates/axdriver_base/src/lib.rscrates/axdriver_block/.cargo-checksum.jsoncrates/axdriver_block/Cargo.tomlcrates/axdriver_block/src/bcm2835sdhci.rscrates/axdriver_block/src/lib.rscrates/axdriver_block/src/ramdisk.rscrates/axdriver_net/.cargo-checksum.jsoncrates/axdriver_net/Cargo.tomlcrates/axdriver_net/src/fxmac.rscrates/axdriver_net/src/ixgbe.rscrates/axdriver_net/src/lib.rscrates/axdriver_net/src/net_buf.rscrates/axdriver_pci/.cargo-checksum.jsoncrates/axdriver_pci/Cargo.tomlcrates/axdriver_pci/src/lib.rscrates/axdriver_virtio/.cargo-checksum.jsoncrates/axdriver_virtio/Cargo.tomlcrates/axdriver_virtio/src/blk.rscrates/axdriver_virtio/src/gpu.rscrates/axdriver_virtio/src/lib.rscrates/axdriver_virtio/src/net.rscrates/axfs-ng-vfs/Cargo.tomlcrates/axfs-ng-vfs/Cargo.toml.origcrates/axfs-ng-vfs/src/fs.rscrates/axfs-ng-vfs/src/mount.rscrates/axfs-ng-vfs/src/node/dir.rscrates/axfs-ng-vfs/src/node/file.rscrates/axfs-ng-vfs/src/node/mod.rscrates/axio/Cargo.toml.origcrates/axplat-loongarch64-qemu-virt/Cargo.toml.origcrates/axplat-loongarch64-qemu-virt/axconfig.tomlcrates/axplat-loongarch64-qemu-virt/src/boot.rscrates/axplat-loongarch64-qemu-virt/src/init.rscrates/axplat-loongarch64-qemu-virt/src/irq.rscrates/axplat-loongarch64-qemu-virt/src/irq/eiointc.rscrates/axplat-loongarch64-qemu-virt/src/irq/pch_pic.rscrates/axplat-loongarch64-qemu-virt/src/mp.rscrates/axplat-riscv64-qemu-virt/Cargo.tomlcrates/axplat-riscv64-qemu-virt/Cargo.toml.origcrates/axplat-riscv64-qemu-virt/src/init.rscrates/axplat-riscv64-qemu-virt/src/irq.rscrates/axplat-riscv64-qemu-virt/src/lib.rscrates/axplat-riscv64-qemu-virt/src/plic.rscrates/axplat/.cargo-okcrates/axplat/.cargo_vcs_info.jsoncrates/axplat/Cargo.tomlcrates/axplat/README.mdcrates/axplat/src/console.rscrates/axplat/src/init.rscrates/axplat/src/irq.rscrates/axplat/src/lib.rscrates/axplat/src/mem.rscrates/axplat/src/power.rscrates/axplat/src/time.rscrates/axpoll/.cargo-checksum.jsoncrates/axpoll/.cargo_vcs_info.jsoncrates/axpoll/.github/workflows/ci.ymlcrates/axpoll/CHANGELOG.mdcrates/axpoll/Cargo.tomlcrates/axpoll/LICENSEcrates/axpoll/README.mdcrates/axpoll/README_CN.mdcrates/axpoll/src/lib.rscrates/axpoll/tests/async.rscrates/axpoll/tests/tests.rscrates/axsched/Cargo.toml.origcrates/ext4plus/src/dir_htree.rscrates/ext4plus/src/journal/block_map.rscrates/handler_table/.cargo-okcrates/handler_table/.cargo_vcs_info.jsoncrates/handler_table/.github/workflows/ci.ymlcrates/handler_table/.gitignorecrates/handler_table/Cargo.tomlcrates/handler_table/README.mdcrates/handler_table/src/lib.rscrates/memory_addr/Cargo.toml.origcrates/memory_set/Cargo.toml.origcrates/page_table_multiarch/Cargo.toml.origcrates/virtio-drivers/Cargo.toml.origcrates/virtio-drivers/src/transport/pci.rscrates/virtio-drivers/src/transport/pci/bus.rspulse_core/src/fd_table.rspulse_core/src/mm/loader.rspulse_core/src/net/mod.rspulse_core/src/task/exec.rspulse_core/src/task/mod.rspulse_syscalls/Cargo.tomlpulse_syscalls/src/impls/fs/common/path_resolve.rspulse_syscalls/src/impls/fs/common/permission.rspulse_syscalls/src/impls/fs/cwd.rspulse_syscalls/src/impls/fs/epoll.rspulse_syscalls/src/impls/fs/meta.rspulse_syscalls/src/impls/fs/path.rspulse_syscalls/src/impls/misc.rspulse_syscalls/src/impls/net/socket.rspulse_syscalls/src/impls/task/exec.rssrc/main.rs
💤 Files with no reviewable changes (11)
- crates/memory_addr/Cargo.toml.orig
- crates/axsched/Cargo.toml.orig
- crates/virtio-drivers/Cargo.toml.orig
- crates/page_table_multiarch/Cargo.toml.orig
- crates/memory_set/Cargo.toml.orig
- crates/axfs-ng-vfs/Cargo.toml.orig
- crates/axplat-loongarch64-qemu-virt/Cargo.toml.orig
- crates/axcpu/Cargo.toml.orig
- crates/ext4plus/src/journal/block_map.rs
- crates/axio/Cargo.toml.orig
- crates/axplat-riscv64-qemu-virt/Cargo.toml.orig
There was a problem hiding this comment.
Caution
Inline review comments failed to post. This is likely due to GitHub's internal server error or limits when posting large numbers of comments. If you are seeing this consistently it is likely a permissions issue. Please check "Moderation" -> "Code review limits" under your organization settings.
🛑 Comments failed to post (16)
arceos/modules/axdriver/src/virtio.rs (3)
34-42: 🔒 Security & Privacy | 🔴 Critical | 🏗️ Heavy lift
让 IRQ 注册表持有设备的强引用。
VirtioInterruptInfo只保存Arc::as_ptr返回的裸指针;wrapper 被释放后,中断仍会解引用悬空指针,造成内核 UAF。对于启动后永久存在的设备,可用Arc::into_raw(inner.clone())保留强引用;若支持设备移除,则必须同时反注册并回收该引用。建议修复
- let dev_ptr = Arc::as_ptr(&inner) as *const (); + // IRQ 注册表持有一个永久强引用。 + let dev_ptr = Arc::into_raw(inner.clone()) as *const ();🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@arceos/modules/axdriver/src/virtio.rs` around lines 34 - 42, 更新 VirtioInterruptInfo 及 IRQ 注册流程,除 dev_ptr 外保留设备 Arc 的强引用,注册时通过 Arc::into_raw(inner.clone()) 持有生命周期并确保中断处理使用有效对象;若存在设备移除路径,必须在反注册时停止 IRQ、移除对应记录并将该裸指针恢复为 Arc 以释放引用。
83-98: 🩺 Stability & Availability | 🔴 Critical | 🏗️ Heavy lift
irq == 0时必须回退到轮询,不能进入 IRQ 等待。此时没有 handler 会调用
PollSet::wake或WaitQueue::notify_all,但网络仍返回Some(poll_set),块设备也可能永久睡眠。网络应在无 IRQ 时返回None;同步块 I/O 仅在self.irq > 0 && irqs_enabled()时等待,异步路径也需要可让出 CPU 的轮询回退。同步路径的最小修复
fn poll_set(&self) -> Option<&axpoll::PollSet> { - Some(&self.inner.poll_set) + (self.irq > 0).then_some(&self.inner.poll_set) } -if axhal::asm::irqs_enabled() { +if self.irq > 0 && axhal::asm::irqs_enabled() {Also applies to: 143-145, 197-222, 252-267, 294-309, 393-400, 431-438
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@arceos/modules/axdriver/src/virtio.rs` around lines 83 - 98, 为 irq == 0 增加轮询回退:网络设备初始化或 poll_set 返回路径在无 IRQ 时返回 None。同步块 I/O 仅在 self.irq > 0 且 irqs_enabled() 时进入等待,否则执行轮询;异步 I/O 路径同样避免无限等待,并通过可让出 CPU 的轮询回退继续推进。同步更新 VirtIoNetDevInner、块设备等待逻辑及相关异步路径,同时保留 irq > 0 时现有中断注册与唤醒行为。
557-558: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win
不要对设备提供的 MSI-X BAR 信息执行
unwrap()。缺失或非法的 BIR 会在设备探测期间直接 panic,导致系统启动失败。应将其视为 MSI-X 配置失败并回退到 legacy IRQ。
建议修复
- let bar_info = root.bar_info(bdf, table_bir).unwrap(); - if let BarInfo::Memory { address, .. } = bar_info { + if let Some(BarInfo::Memory { address, .. }) = + root.bar_info(bdf, table_bir) + {📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.if let Some(BarInfo::Memory { address, .. }) = root.bar_info(bdf, table_bir) {🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@arceos/modules/axdriver/src/virtio.rs` around lines 557 - 558, 在处理 MSI-X BAR 的代码中移除 root.bar_info 的 unwrap 调用,改为显式处理缺失或非法 BIR:将其视为 MSI-X 配置失败,并沿现有路径回退到 legacy IRQ,同时保持有效 BarInfo::Memory 情况的处理不变。arceos/modules/axtask/src/tests.rs (1)
131-151: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
static FINISHED在测试函数内部定义,会在多次调用间共享状态。
static FINISHED: AtomicBool定义在函数体内部,虽然由于SERIAL锁保证了串行执行,不会产生并发问题,但如果该测试被多次调用,FINISHED不会重置为false,第二次调用时while循环会立即跳过,测试实际上不会重新执行异步任务。建议在循环前显式重置:
static FINISHED: AtomicBool = AtomicBool::new(false); + + FINISHED.store(false, Ordering::Relaxed); axtask::spawn_async(async {📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.#[test] fn test_async_task() { use core::sync::atomic::AtomicBool; let _lock = SERIAL.lock(); INIT.call_once(axtask::init_scheduler); static FINISHED: AtomicBool = AtomicBool::new(false); FINISHED.store(false, Ordering::Relaxed); axtask::spawn_async(async { println!("async task: Hello, world!"); crate::future::yield_now().await; println!("async task: Resumed!"); FINISHED.store(true, Ordering::Release); }); while !FINISHED.load(Ordering::Acquire) { axtask::yield_now(); } assert!(FINISHED.load(Ordering::Acquire)); }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@arceos/modules/axtask/src/tests.rs` around lines 131 - 151, Reset the function-local static FINISHED flag to false before spawning the async task in test_async_task. Keep the existing acquire/release synchronization and completion assertion unchanged so repeated test invocations wait for the newly spawned task to finish.arceos/modules/axtask/src/wait_queue.rs (1)
267-297: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
notify_one唤醒所有 waker 而非仅一个——语义不一致且可能引发惊群。当
notify_one在阻塞任务队列中找不到可唤醒任务时,else分支使用core::mem::take取出并唤醒 全部 已注册 waker(L288-296)。这与方法名 "notify_one" 的语义矛盾:阻塞任务路径仅唤醒一个任务(L284-286),waker 路径应保持一致。全部唤醒会导致 N 个异步等待者同时被唤醒(惊群效应),仅一个能获取资源,其余需重新阻塞。🐛 修复:仅弹出一个 waker 唤醒
if let Some(task) = target { unblock_one_task(task, resched); true } else { - let wakers = { + let waker = { let mut wakers = self.wakers.lock(); - core::mem::take(&mut *wakers) + wakers.pop_front() }; - let has_wakers = !wakers.is_empty(); - for (_, waker) in wakers { - waker.wake(); - } - has_wakers + if let Some((_, waker)) = waker { + waker.wake(); + true + } else { + false + } }📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements./// Wake up a task in the wait queue. /// /// If `resched` is true, the current task will yield the CPU. pub fn notify_one(&self, resched: bool) -> bool { let mut wq = self.queue.lock(); let mut target = None; while let Some(task) = wq.pop_front() { if task.state() == crate::task::TaskState::Blocked { target = Some(task); break; } // The task is no longer blocked (e.g., timed out), but still in the wait queue. // We should mark it as not in the wait queue. task.set_in_wait_queue(false); } drop(wq); if let Some(task) = target { unblock_one_task(task, resched); true } else { let waker = { let mut wakers = self.wakers.lock(); wakers.pop_front() }; if let Some((_, waker)) = waker { waker.wake(); true } else { false } }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@arceos/modules/axtask/src/wait_queue.rs` around lines 267 - 297, Update notify_one’s waker fallback to remove and wake only one registered waker, matching the single-task behavior. Preserve the existing return value semantics: report whether a waker was available, and leave all other wakers registered for future notifications.crates/axdriver_block/src/bcm2835sdhci.rs (1)
63-65: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
write_block缓冲区大小校验返回了不一致的错误类型。
read_block(Line 51-52)对缓冲区过小返回DevError::InvalidParam,但write_block(Line 64-65)对相同条件返回DevError::Io。缓冲区大小校验属于参数验证,应统一返回InvalidParam。🔧 修复建议
fn write_block(&mut self, block_id: u64, buf: &[u8]) -> DevResult { if buf.len() < BLOCK_SIZE { - return Err(DevError::Io); + return Err(DevError::InvalidParam); }📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.fn write_block(&mut self, block_id: u64, buf: &[u8]) -> DevResult { if buf.len() < BLOCK_SIZE { return Err(DevError::InvalidParam);🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@crates/axdriver_block/src/bcm2835sdhci.rs` around lines 63 - 65, Update the buffer-length validation in write_block so a buffer smaller than BLOCK_SIZE returns DevError::InvalidParam, matching read_block’s parameter-validation behavior; leave the normal write path unchanged.crates/axdriver_virtio/src/gpu.rs (1)
20-27: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win
try_new用unwrap()而非错误传播,违背函数自身的DevResult契约。函数签名承诺通过
DevResult返回错误,但初始化步骤全部使用unwrap(),一旦设备初始化失败会直接 panic,而不是像flush()一样通过as_dev_err优雅地返回错误。🛡️ 建议修复
pub fn try_new(transport: T) -> DevResult<Self> { - let mut virtio = InnerDev::new(transport).unwrap(); + let mut virtio = InnerDev::new(transport).map_err(as_dev_err)?; // get framebuffer - let fbuffer = virtio.setup_framebuffer().unwrap(); + let fbuffer = virtio.setup_framebuffer().map_err(as_dev_err)?; let fb_base_vaddr = fbuffer.as_mut_ptr() as usize; let fb_size = fbuffer.len(); - let (width, height) = virtio.resolution().unwrap(); + let (width, height) = virtio.resolution().map_err(as_dev_err)?;📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.pub fn try_new(transport: T) -> DevResult<Self> { let mut virtio = InnerDev::new(transport).map_err(as_dev_err)?; // get framebuffer let fbuffer = virtio.setup_framebuffer().map_err(as_dev_err)?; let fb_base_vaddr = fbuffer.as_mut_ptr() as usize; let fb_size = fbuffer.len(); let (width, height) = virtio.resolution().map_err(as_dev_err)?;🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@crates/axdriver_virtio/src/gpu.rs` around lines 20 - 27, Update try_new to propagate failures from InnerDev::new, setup_framebuffer, and resolution through its DevResult return type instead of panicking with unwrap(). Convert each underlying error using the same as_dev_err error-mapping pattern used by flush(), while preserving the existing initialization flow.crates/axdriver_virtio/src/lib.rs (1)
49-50: 🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win
unwrap()应替换为?以保持错误处理一致性。
probe_mmio_device返回Option,函数内其他错误路径均使用?传播None,但此处NonNull::new(...).unwrap()在reg_base为 null 时会 panic。在内核驱动探测场景中,null 指针可能因设备配置错误导致,返回None比 panic 更合理。🔧 建议修复
- let header = NonNull::new(reg_base as *mut VirtIOHeader).unwrap(); + let header = NonNull::new(reg_base as *mut VirtIOHeader)?;📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.let header = NonNull::new(reg_base as *mut VirtIOHeader)?; let transport = unsafe { MmioTransport::new(header) }.ok()?;🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@crates/axdriver_virtio/src/lib.rs` around lines 49 - 50, Update probe_mmio_device so the NonNull::new conversion for reg_base propagates None with ? instead of calling unwrap. Preserve the existing MmioTransport::new error propagation and avoid panicking when reg_base is null.crates/axdriver_virtio/src/net.rs (1)
19-19: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win
避免整体公开
inner字段,改用窄接口转发。
inner持有底层虚拟队列,其收发操作与rx_buffers/tx_buffers/free_tx_bufs/buf_pool的账本严格绑定(参见try_new中的初始化逻辑)。将其整体设为pub后,外部代码可以绕过这些账本直接操作队列(例如直接调用底层的收发/完成接口),从而破坏 token 与缓冲区计数的一致性,可能导致缓冲区重复使用或计数错乱等问题。建议仅新增所需的窄粒度委托方法(如本次已新增的
enable_interrupts/ack_interrupt),而不是公开整个inner。♻️ 建议改动
- pub inner: InnerDev<H, T, QS>, + inner: InnerDev<H, T, QS>,📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.inner: InnerDev<H, T, QS>,🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@crates/axdriver_virtio/src/net.rs` at line 19, Remove public visibility from the `inner` field of the net device, keeping it encapsulated so callers cannot bypass the buffer and queue bookkeeping initialized by `try_new`. Expose only the narrow delegate methods required by external callers, such as `enable_interrupts` and `ack_interrupt`, and preserve their existing behavior.crates/axfs-ng-vfs/src/node/dir.rs (1)
216-223: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win
link未在持锁期间调用ops.link,与create/unlink的加锁方式不一致,存在竞态窗口。
create_locked/unlink均在持有self.cache锁的情况下调用底层ops.create/ops.unlink,保证底层操作与缓存写入的原子性;而link是先await self.ops.link(...),再单独获取锁插入缓存。在这两步之间,另一个任务对同名条目的lookup/create可能与link的底层操作交错,产生两个代表同一文件的不同DirEntry实例被先后写入缓存,导致缓存与底层文件系统状态不一致(如引用计数、元数据缓存等出现分裂)。♻️ 建议修复
pub async fn link(&self, name: &str, node: &DirEntry) -> VfsResult<DirEntry> { verify_entry_name(name)?; - - let entry = self.ops.link(name, node).await?; - self.cache.lock().await.insert(name.to_owned(), entry.clone()); + let mut children = self.cache.lock().await; + let entry = self.ops.link(name, node).await?; + children.insert(name.to_owned(), entry.clone()); Ok(entry) }📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements./// Creates a link to a node. pub async fn link(&self, name: &str, node: &DirEntry) -> VfsResult<DirEntry> { verify_entry_name(name)?; let mut children = self.cache.lock().await; let entry = self.ops.link(name, node).await?; children.insert(name.to_owned(), entry.clone()); Ok(entry) }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@crates/axfs-ng-vfs/src/node/dir.rs` around lines 216 - 223, Update Dir::link to acquire and hold self.cache’s lock before awaiting self.ops.link, then insert the returned entry into the cache while retaining that same lock. Match the locking and atomicity pattern used by create_locked and unlink, while preserving name validation and the existing returned-entry behavior.crates/axplat-loongarch64-qemu-virt/src/irq/eiointc.rs (1)
60-63: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash set -euo pipefail echo '--- file outline ---' ast-grep outline crates/axplat-loongarch64-qemu-virt/src/irq/eiointc.rs --view expanded || true echo '--- relevant file excerpt ---' cat -n crates/axplat-loongarch64-qemu-virt/src/irq/eiointc.rs | sed -n '1,220p' echo '--- search EIOINTC_IPMAP usage in repo ---' rg -n "EIOINTC_IPMAP|IPMAP|eiointc" crates -g '!**/target/**' || trueRepository: muou000/PulseOS
Length of output: 1953
🌐 Web query:
LoongArch EIOINTC IPMAP register one-hot HWI0 Linux driver semantics💡 Result:
In the LoongArch architecture, the Extended I/O Interrupt Controller (EIOINTC) manages interrupt routing, including the mapping of I/O interrupts to CPU cores and specific interrupt pins (IPs) [1]. The IPMAP register is used to define the routing of EIOINTC interrupts to the CPU's interrupt input pins (IPs), typically IP0–IP3 [2]. In the Linux kernel's EIOINTC driver (and its KVM emulation counterpart), the IPMAP register configuration follows a specific one-hot encoding semantic for the destination IP [3][1]. Key aspects of the IPMAP register semantics include: 1. Routing Control: The IPMAP register dictates which IP pin on the destination CPU node is triggered by a specific interrupt [3]. 2. One-Hot Encoding: The configuration uses one-hot bit-mapping to select the target IP [3]. For instance, to route an interrupt to a specific IP, the corresponding bit in the IPMAP field is set. The driver often calculates this by creating a bitmask, such as
BIT(1 + index), whereindexrelates to the target IP, and this value is shifted to occupy the correct byte/word position in the register [3]. 3. Initialization-Time Configuration: The IPMAP register is intended to be set during the initialization phase of the irqchip driver [4][5]. It is generally treated as immutable at runtime, meaning that the driver does not support updating this mapping after the system has initialized the interrupt hierarchy [4][6]. 4. KVM Emulation Context: Within KVM, the IPMAP register is emulated to maintain consistent interrupt delivery to guests [1]. Developers must ensure that register access (specifically byte-offset calculations) correctly targets the underlying structure to avoid out-of-bounds access, as the layout of theipmapfield in the emulated controller's state structure may differ from direct hardware register offsets [1]. In summary, the "one-hot HWI0" reference likely pertains to the routing configuration where HWI0 (or other hardware interrupt pins) is mapped by setting the corresponding bit position in the IPMAP register, effectively assigning the interrupt source to a designated CPU input pin [3].Citations:
- 1: https://lexplain.net/commit-analyses/6bcfb7f46d667b04bd1a1169ccedf5fb699c60df
- 2: https://docs.kernel.org/arch/loongarch/irq-chip-model.html
- 3: https://github.com/lilili-kernel/deepin-kernel/blob/kernel-rolling/drivers/irqchip/irq-loongson-eiointc.c
- 4: https://lists.openwall.net/linux-kernel/2025/07/09/474
- 5: https://lists.openwall.net/linux-kernel/2024/11/08/184
- 6: https://lists.openwall.net/linux-kernel/2025/07/01/137
🌐 Web query:
kernel irq-loongson-eiointc.c IPMAP 0x01 one-hot pin mapping💡 Result:
In the Loongson EIOINTC (Extended I/O Interrupt Controller) driver, the IPMAP (Interrupt Pin Mapping) register is used to configure the routing of interrupt vectors to specific CPU interrupt pins (IP lines) [1][2]. The "one-hot" pin mapping logic refers to how the driver calculates the bitmask for these registers to direct a set of vectors to a particular interrupt pin [3][4]. Key aspects of this implementation include: 1. Register Organization: The EIOINTC_REG_IPMAP (0x14c0) register controls this routing [5][3]. The driver typically configures this by writing a bitmask where a single bit set to 1 corresponds to a specific CPU interrupt pin [5][2]. 2. One-Hot Bit Manipulation: In the kernel driver, this is often implemented as: bit = BIT(target_pin_index); data = bit | (bit << 8) | (bit << 16) | (bit << 24); iocsr_write32(data, EIOINTC_REG_IPMAP + i * 4); This operation effectively writes the same "one-hot" encoded value into four consecutive byte-lanes within a 32-bit register, ensuring that specific groups of 32 interrupts (depending on the implementation context) are consistently mapped to the desired hardware interrupt pin [5][3][2]. 3. Evolution and Flexibility: - Older or simpler implementations often hard-coded this routing, for example, by using index-based offsets (like 1 + index) to target pins starting from IP1 [5][3]. - Newer versions of the driver have introduced support for parsing parent interrupt information from ACPI or Device Tree (DTS) to dynamically determine the target hardware interrupt pin (e.g., using
parent_hwirq - INT_HWI0) [1][2]. - Advanced support has also been added for multi-interrupt pin routing (EIOINTC_ROUTE_MULT_IP), where vectors are distributed across multiple interrupt pins rather than being confined to a single global mapping [2]. Technical note: When working with these registers—particularly in KVM/emulation contexts—developers must ensure correct byte-offset pointer arithmetic. Incorrectly adding integer offsets to 64-bit register pointers can lead to memory access errors, which has been a specific area of recent kernel development for LoongArch KVM [6][7].Citations:
- 1: https://lists.openwall.net/linux-kernel/2025/08/24/206
- 2: https://lists.openwall.net/linux-kernel/2024/12/13/154
- 3: https://github.com/lilili-kernel/deepin-kernel/blob/kernel-rolling/drivers/irqchip/irq-loongson-eiointc.c
- 4: https://github.com/sladewatkins/linux-stable/blob/master/drivers/irqchip/irq-loongson-eiointc.c
- 5: https://github.com/p-/ch-linux/blob/master/drivers/irqchip/irq-loongson-eiointc.c
- 6: https://lexplain.net/commit-analyses/6bcfb7f46d667b04bd1a1169ccedf5fb699c60df
- 7: https://yhbt.net/lore/lkml/20250701031504.1233777-2-maobibo@loongson.cn/
🌐 Web query:
irq-loongson-eiointc.c IPMAP initialization iocsr_write32 BIT(target_pin_index) data bit << 8💡 Result:
In the Linux kernel driver drivers/irqchip/irq-loongson-eiointc.c, the IPMAP (Interrupt Pin Map) initialization involves configuring how EIOINTC (Extended I/O Interrupt Controller) vectors are routed to specific interrupt pins [1][2]. The relevant code sequence used during the EIOINTC router initialization is [1][3]: for (i = 0; i < eiointc_priv->vec_count / 32 / 4; i++) { bit = BIT(1 + index); /* Route to IP[1 + index] */ data = bit | (bit << 8) | (bit << 16) | (bit << 24); iocsr_write32(data, EIOINTC_REG_IPMAP + i * 4); } In this code: - bit represents the target pin index, calculated using BIT(1 + index), where index corresponds to the EIOINTC node index [1][4]. - The variable data is constructed by setting the target pin bit at four different byte positions (0, 8, 16, and 24 bits) to support four vectors per 32-bit register write [1][3]. - iocsr_write32 is then used to write this 32-bit configuration data to the appropriate register offset starting at EIOINTC_REG_IPMAP [1][2]. This initialization ensures that interrupts managed by the EIOINTC are correctly routed to the designated interrupt pins on the LoongArch system [5][6].
Citations:
- 1: https://kernel.googlesource.com/pub/scm/linux/kernel/git/torvalds/linux/+/88afbb21d4b36fee6acaa167641f9f0fc122f01b/drivers/irqchip/irq-loongson-eiointc.c
- 2: https://kernel.googlesource.com/pub/scm/linux/kernel/git/torvalds/linux/+/45e34c8af58f23db4474e2bfe79183efec09a18b/drivers/irqchip/irq-loongson-eiointc.c
- 3: https://github.com/rockos-riscv/rockos-kernel/blob/rockos-v6.6.y/drivers/irqchip/irq-loongson-eiointc.c
- 4: https://github.com/hconion/linux-riscv/blob/sg2042-dev/drivers/irqchip/irq-loongson-eiointc.c
- 5: https://docs.kernel.org/arch/loongarch/irq-chip-model.html
- 6: https://lkml.iu.edu/hypermail/linux/kernel/2206.1/10870.html
🌐 Web query:
EIOINTC_REG_IPMAP one-hot initialization code 0x01010101 Linux driver💡 Result:
The identifier EIOINTC_REG_IPMAP relates to the Loongson Extended I/O interrupt controller (EIOINTC) driver in the Linux kernel [1][2]. In this driver, the EIOINTC_REG_IPMAP register is initialized to route interrupt vectors to specific interrupt pins [1][2]. The specific value 0x01010101 is not a standard hardcoded initialization value in the Loongson EIOINTC Linux driver source code. Instead, the driver dynamically calculates the routing data based on the interrupt controller's flags and configuration [1][2]. The Linux driver for the Loongson EIOINTC calculates the initialization value as follows: 1. It determines the routing target based on the hwirq (hardware interrupt number) [1][2]. 2. If EIOINTC_ROUTE_MULT_IP is set, it computes a bitmask for consecutive interrupt pins [1][2]. 3. If not set, it constructs a value where the same bit is replicated across all four bytes (e.g., bit | (bit << 8) | (bit << 16) | (bit << 24)), which allows all four vectors within the 32-bit register window to target the same interrupt pin [1][2]. The value 0x01010101 is commonly associated with the ARM Generic Interrupt Controller (GIC) Interrupt Processor Targets Registers (ICDIPTR), where it is used to target CPU interface 0 for four interrupts simultaneously [3][4]. It is likely that you have encountered this value in the context of GIC-based systems or are observing a pattern where four identical 8-bit target identifiers are packed into a single 32-bit register to configure multiple interrupts at once [4][5]. The Loongson EIOINTC uses a similar architectural concept of packing routing information for multiple vectors into 32-bit registers, but the specific configuration values depend on the dynamic CPU and node mapping of the Loongson platform [1][2].
Citations:
- 1: https://github.com/ayufan-rock64/linux-mainline-kernel/blob/release-7.0/drivers/irqchip/irq-loongson-eiointc.c
- 2: https://elixir.bootlin.com/linux/v7.0.10/source/drivers/irqchip/irq-loongson-eiointc.c
- 3: https://github.com/NienfengYao/armv8-bare-metal/blob/master/gic_v3.h
- 4: https://docs.amd.com/r/en-US/ug585-zynq-7000-SoC-TRM/Register-mpcore-ICDIPTR1?contentId=USi4uJOsrgizctcTunJE7A
- 5: https://github.com/LineageOS/android_kernel_oneplus_sm8150/blob/lineage-23.2/drivers/irqchip/irq-gic.c
🌐 Web query:
docs.kernel.org LoongArch irq-chip-model EIOINTC IPMAP one-hot zero meaning💡 Result:
In the context of the LoongArch architecture and the Extended I/O Interrupt Controller (EIOINTC), the terms "one-hot," "zero," and "IPMAP" relate to how interrupts are routed and encoded [1][2][3]. IPMAP refers to the EIOINTC_REG_IPMAP register, which is used to configure the routing of interrupt vectors to specific interrupt pins (IPs) on the CPU [2][4]. The concepts of "one-hot" and "zero" in this context typically refer to how bits are set within these configuration registers or mapping structures: 1. One-hot: In many interrupt controller implementations, including aspects of EIOINTC routing, a "one-hot" encoding is used to select a single target from a set of possibilities (e.g., selecting one specific CPU core or one specific interrupt pin) by setting exactly one bit in a field to high (1) while leaving the others low (0) [2][5]. 2. Zero: The term "zero" often refers to a default state or an unconfigured state, or it may appear in documentation regarding the index or value of a field where 0 represents the first element (e.g., IP0, Core0, or Node0) [1][2]. For example, when routing interrupts using bitmasks, a value of 0 might indicate that no routing is enabled for that specific index [2]. In EIOINTC programming, specifically when configuring IPMAP or other routing registers (like NODEMAP or ROUTE), software often writes bit patterns where specific bit positions are set to 1 to enable a path or select a target [2]. If "one-hot" is explicitly referenced in your context, it likely emphasizes that for a particular hardware feature, multiple simultaneous targets must not be selected, and only a single bit (one-hot) must be active [2]. If a value is "zero," it signifies the absence of such an active selection [2][5]. For detailed technical implementation, the Linux kernel source code for
drivers/irqchip/irq-loongson-eiointc.cprovides the authoritative reference for how these registers are populated, demonstrating the use of bit shifts and masks to set these values [2].Citations:
- 1: https://docs.kernel.org/next/arch/loongarch/irq-chip-model.html
- 2: https://kernel.googlesource.com/pub/scm/linux/kernel/git/torvalds/linux/+/45e34c8af58f23db4474e2bfe79183efec09a18b/drivers/irqchip/irq-loongson-eiointc.c
- 3: https://lkml.iu.edu/2411.0/09368.html
- 4: https://lists.openwall.net/linux-kernel/2024/11/08/184
- 5: https://lwn.net/Articles/989621/
🌐 Web query:
LoongArch EIOINTC IPMAP register zero meaning no mapping one-hot💡 Result:
In the LoongArch Extended I/O Interrupt Controller (EIOINTC), the IPMAP register is used to map interrupt vectors to interrupt pins (IPs) of the CPU [1]. Regarding the mapping mechanism: - The IPMAP register does not typically employ a "zero means no mapping" scheme in the sense of disabling the interrupt through a null value. Instead, it uses a bitmask to route specific interrupt groups to designated CPU interrupt pins [1][2]. - The mapping is structured by grouping interrupts (e.g., in blocks of 32) and using a portion of the IPMAP register to specify which CPU IP (from IP0 to IP3) an interrupt group is routed to [1][2]. - Within this register, the configuration typically involves setting a specific bit that corresponds to the desired target IP [1][2]. For example, the Linux kernel implementation often uses a one-hot-like encoding (using BIT(index) where index refers to the IP number) to define the destination IP [1]. - If no mapping is desired for a specific interrupt, the corresponding bits for that interrupt in the IPMAP are effectively left unset or configured to a state that does not route the interrupt to a valid CPU pin [1][2]. In summary, the register acts as a routing table where the value determines the path to the CPU. The use of one-hot encoding ensures that a specific interrupt group is associated with the intended interrupt pin, and the configuration is strictly defined at the initialization of the interrupt driver [1][3][2].
Citations:
- 1: https://kernel.googlesource.com/pub/scm/linux/kernel/git/torvalds/linux/+/45e34c8af58f23db4474e2bfe79183efec09a18b/drivers/irqchip/irq-loongson-eiointc.c
- 2: https://lists.libreplanet.org/archive/html/qemu-devel/2022-05/msg03468.html
- 3: https://lwn.net/Articles/989621/
IPMAP 这里不能写 0
这里应按目标 CPU IP 写入 one-hot 映射;写 0 等于没有有效路由,这组外部中断将无法送达 CPU。🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@crates/axplat-loongarch64-qemu-virt/src/irq/eiointc.rs` around lines 60 - 63, Update the EIOINTC_IPMAP initialization to write the target CPU IP as a one-hot mapping instead of zero, using the correct value for CPU HWI0/IP2 (pin index 0). Apply the same mapping to both register writes covering all interrupt groups, preserving the existing 256-interrupt setup.crates/axplat/README.md (1)
46-48: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
标题层级跳跃,应为 h3。
#### 1. Implement each interface trait直接跟在## How to write a platform package之后,从 h2 跳到 h4,静态分析工具已标出。📝 建议修复
-#### 1. Implement each interface trait +### 1. Implement each interface trait同时第 76 行的
#### 2. Implement platform bootstrapping code...也应改为###。📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.## How to write a platform package ### 1. Implement each interface trait🧰 Tools
🪛 markdownlint-cli2 (0.22.1)
[warning] 48-48: Heading levels should only increment by one level at a time
Expected: h3; Actual: h4(MD001, heading-increment)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@crates/axplat/README.md` around lines 46 - 48, Update the “How to write a platform package” section headings so “1. Implement each interface trait” and the nearby “2. Implement platform bootstrapping code...” use h3 (`###`) rather than h4, preserving the existing heading text.Source: Linters/SAST tools
crates/axpoll/README.md (1)
28-28: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
README 文件中的版本号和路径与本仓库不一致。 两份 README 均从上游复制但未更新为本地仓库的版本和路径。
crates/axpoll/README.md#L28-L28: 将axpoll = "0.3.2"更新为0.3.9以匹配CHANGELOG.md。crates/axpoll/README.md#L35-L35: 将cd components/axpoll改为cd crates/axpoll。crates/axpoll/README_CN.md#L28-L28: 同上,将版本号更新为0.3.9。crates/axpoll/README_CN.md#L35-L35: 同上,将路径改为cd crates/axpoll。📍 Affects 2 files
crates/axpoll/README.md#L28-L28(this comment)crates/axpoll/README.md#L35-L35crates/axpoll/README_CN.md#L28-L28crates/axpoll/README_CN.md#L35-L35🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@crates/axpoll/README.md` at line 28, Update the axpoll README dependency version from 0.3.2 to 0.3.9 and change the directory path from components/axpoll to crates/axpoll in both crates/axpoll/README.md (lines 28 and 35) and crates/axpoll/README_CN.md (lines 28 and 35).crates/axpoll/tests/async.rs (1)
20-31: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win
WaitFuture::poll存在“先检查后注册”导致的丢失唤醒竞态。
poll()先load(ready),只有在为false时才调用self.ps.register(cx.waker())。如果在“检查”和“注册”之间,另一线程恰好完成ready.store(true)并调用ps.wake(),那么本次wake()不会唤醒任何 waker(此时尚未注册),随后本 future 注册的 waker 也再也不会被触发,导致该await永久挂起(CI 中表现为测试 hang/超时)。正确的顺序应先注册 waker,再检查条件,从而保证任何在注册之后发生的
wake()都不会被错过:🐛 修复建议
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { - if self.ready.load(Ordering::SeqCst) { - Poll::Ready(()) - } else { - self.ps.register(cx.waker()); - Poll::Pending - } + self.ps.register(cx.waker()); + if self.ready.load(Ordering::SeqCst) { + Poll::Ready(()) + } else { + Poll::Pending + } }同一代码库中
run_queue.rs新增的blocked_resched_woke采用了“持锁检查 + 状态置位”的方式来规避此类丢失唤醒问题,可作为参考模式。📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.impl Future for WaitFuture { type Output = (); fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { self.ps.register(cx.waker()); if self.ready.load(Ordering::SeqCst) { Poll::Ready(()) } else { Poll::Pending } } }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@crates/axpoll/tests/async.rs` around lines 20 - 31, 调整 WaitFuture::poll 的操作顺序,先通过 self.ps.register(cx.waker()) 注册当前 waker,再检查 ready 状态;ready 为真时返回 Poll::Ready(()),否则返回 Poll::Pending。确保注册后的唤醒不会被遗漏,并保持现有 Future 输出行为不变。pulse_core/src/mm/loader.rs (1)
421-429: 🩺 Stability & Availability | 🟠 Major | 🏗️ Heavy lift
read_elf_range中block_on同样存在死锁风险。与
read_elf_file相同的问题:File::open、file.read_at、fs_ctx.read均通过block_on阻塞执行。如果此函数从异步上下文调用,会阻塞调度器线程。此外,Line 429 在短读时回退读取整个文件 (fs_ctx.read(path)),在block_on中阻塞时间更长,加剧了死锁风险。🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@pulse_core/src/mm/loader.rs` around lines 421 - 429, Remove the synchronous block_on calls from read_elf_range for File::open, file.read_at, and fs_ctx.read, and refactor the function to await these filesystem operations directly within its async flow. Preserve the existing error mappings, short-read fallback, and successful range-read behavior.src/main.rs (1)
121-136: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win
不要把生产启动失败退化为永久
yield。非
testcode模式既不观察init_task的退出,也在new_uspace失败后永久循环;因此 ELF 解析/加载失败或进程创建失败都会表现为无响应的启动挂起。请等待并处理初始化任务退出,或在失败时进入明确的恢复、停机或重启策略。🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/main.rs` around lines 121 - 136, Update the non-testcode startup failure paths around init_task and the “Failed to create user process” error so they do not enter permanent axtask::yield_now loops. Observe and handle init_task termination, and use an explicit recovery, shutdown, or restart strategy when new_uspace or process creation fails; preserve the existing testcode behavior.
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
crates/axplat-loongarch64-qemu-virt/src/irq.rs (1)
26-44: 🩺 Stability & Availability | 🟠 Major | 🏗️ Heavy lift解决 CPU 异常号与 EIOINTC 硬件中断号的命名空间冲突(Namespace collision)。
在当前实现中,CPU 内部中断(如
TIMER_IRQ,在 LoongArch 上通常是 11)与 EIOINTC 中断(0-255)共享同一个irq_num参数与IRQ_HANDLER_TABLE注册表。这会导致严重的问题:
如果 QEMU 分配的外设碰巧使用了与TIMER_IRQ相同编号的 EIOINTC IRQ(如 EIOINTC IRQ 11):
- 在
set_enable中会被最外层的if irq_num == crate::config::devices::TIMER_IRQ错误拦截,导致本该配置到 EIOINTC 的外设中断未被使能,反而重复使能了 CPU 定时器。- 它们在
IRQ_HANDLER_TABLE中共享同一个索引,会导致处理函数被相互覆盖或错误执行。建议将所有 EIOINTC 外部中断在系统中统一增加一个偏移量(例如
irq_num = eiointc_pin + 16),或者将TIMER_IRQ等 CPU 特有中断映射到安全的高位虚拟中断号(例如 256,并相应提升MAX_IRQ_COUNT),以彻底隔离不同中断源的命名空间。🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@crates/axplat-loongarch64-qemu-virt/src/irq.rs` around lines 26 - 44, 统一隔离 CPU 内部中断与 EIOINTC 外部中断的 IRQ 命名空间,避免 EIOINTC pin 与 TIMER_IRQ 使用同一编号。更新 set_enable 及 IRQ_HANDLER_TABLE 的注册、分发和查找逻辑,为外部中断采用统一偏移映射,或将 TIMER_IRQ 映射到不会与外部中断冲突的虚拟编号,并同步调整 MAX_IRQ_COUNT;确保定时器仍配置 CPU 中断寄存器,外部中断仍正确配置 EIOINTC/PCH-PIC。arceos/modules/axfs/src/fs/ext4/fs.rs (1)
191-194: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win
flush仍然是同步阻塞刷盘,不要把它暴露成async。crate::disk::flush_all_disks()及其下游flush_disk()/dev.flush()都没有异步等待点,会在轮询期间直接占住当前执行器线程。要么改成真正的异步刷盘,要么保留同步接口并放到阻塞线程池。🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@arceos/modules/axfs/src/fs/ext4/fs.rs` around lines 191 - 194, 将 Ext4 文件系统的 flush 实现改回同步接口,不要将 flush 标记为 async;直接复用 crate::disk::flush_all_disks 及其现有错误映射,并确保 flush_disk/dev.flush 的同步阻塞操作不暴露为异步任务。
🧹 Nitpick comments (5)
crates/axplat-loongarch64-qemu-virt/src/irq.rs (1)
69-78: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win一次性排空(Drain)所有挂起的 EIOINTC 中断。
在引入异步与网络 I/O 等高并发特性的场景下,EIOINTC 极可能在单次陷入时存在多个中断挂起。将其改为
while let循环,可以有效避免频繁退出再陷入 trap 所带来的 CPU 开销,提升系统的高负载吞吐量。♻️ 建议的代码结构
- } else if irq == EIOINTC_CPU_IRQ { - if let Some(irq_num) = eiointc::claim_irq() { - trace!("EIOINTC IRQ {}", irq_num); - if !IRQ_HANDLER_TABLE.handle(irq_num) { - warn!("Unhandled EIOINTC IRQ {}", irq_num); - } - eiointc::complete_irq(irq_num); - } else { - debug!("Spurious EIOINTC interrupt"); - } + } else if irq == EIOINTC_CPU_IRQ { + let mut handled = false; + while let Some(irq_num) = eiointc::claim_irq() { + handled = true; + trace!("EIOINTC IRQ {}", irq_num); + if !IRQ_HANDLER_TABLE.handle(irq_num) { + warn!("Unhandled EIOINTC IRQ {}", irq_num); + } + eiointc::complete_irq(irq_num); + } + if !handled { + debug!("Spurious EIOINTC interrupt"); + }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@crates/axplat-loongarch64-qemu-virt/src/irq.rs` around lines 69 - 78, Update the EIOINTC handling branch for EIOINTC_CPU_IRQ to drain every pending interrupt in one trap by replacing the single eiointc::claim_irq call with a while-let loop. Keep the existing trace, IRQ_HANDLER_TABLE.handle, warning, and eiointc::complete_irq operations inside the loop, and retain the spurious-interrupt debug message only when no IRQ is claimed.arceos/modules/axfs/src/fs/ext4/fs.rs (1)
156-156: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value清理
Drop中的无效语句。
let _ = &self.inner;不产生任何副作用,只是创建了一个立即丢弃的引用,属于旧的self.lock()保护路径被移除后遗留的占位代码,可直接删除。🧹 建议删除死代码
fn drop(&mut self) { cleanup_dir_cache_registry(self as *const Self as usize); - let _ = &self.inner; }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@arceos/modules/axfs/src/fs/ext4/fs.rs` at line 156, Remove the no-op `let _ = &self.inner;` statement from the `Drop` implementation, leaving the remaining drop logic unchanged.arceos/modules/axdriver/src/virtio.rs (2)
606-611: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueriscv64 MMIO 中断号推导使用了未加注释的魔数。
(mmio_base - 0x1000_1000) / 0x1000 + 1隐含了对 QEMU virt 内存布局的假设,建议补充注释说明该地址范围与中断号的对应关系来源,便于后续维护者理解,无需改动逻辑本身。🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@arceos/modules/axdriver/src/virtio.rs` around lines 606 - 611, 在 virtio 初始化中计算 irq 的 riscv64 分支处补充注释,说明该公式基于 QEMU virt 的 MMIO 地址布局,并解释 0x1000_1000 起始地址、0x1000 步长与中断号映射的来源;保持现有 irq 推导逻辑不变。
256-267: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win建议移除或复用
register_then_check
poll_token已经内联了同样的“先注册 waker,再检查就绪”逻辑,而register_then_check在仓库里没有其他调用点。建议抽回该辅助函数统一实现,或直接删除它。🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@arceos/modules/axdriver/src/virtio.rs` around lines 256 - 267, 移除未被使用的辅助函数 register_then_check,并保留 poll_token 中现有的“先注册 waker、再检查就绪”内联逻辑;不要引入额外重构。arceos/modules/axfs/src/fs/ext4/mod.rs (1)
203-221: 🗄️ Data Integrity & Integration | 🔵 Trivial | ⚡ Quick win补充
Clone语义契约:这里先clone再await,需要保证D::clone()是廉价且共享底层状态;建议在 trait 文档或此处说明这一约定,避免未来实现出现读写不一致。🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@arceos/modules/axfs/src/fs/ext4/mod.rs` around lines 203 - 221, Document the Clone contract used by write_block_to_disk_async: cloning D before await must be cheap and preserve shared underlying device state so reads and writes remain consistent. Add this clarification to the relevant trait documentation or as a concise comment at the clone site, without changing the existing write flow.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@arceos/modules/axlog/Cargo.toml`:
- Around line 27-28: Update the chrono dependency declaration in the axlog Cargo
manifest to inherit the workspace configuration with default features disabled,
and adjust the axlog feature definitions to forward chrono’s std-related feature
only when axlog’s std feature is enabled. Preserve optional chrono usage and
ensure the default no_std build does not enable chrono’s std support.
---
Outside diff comments:
In `@arceos/modules/axfs/src/fs/ext4/fs.rs`:
- Around line 191-194: 将 Ext4 文件系统的 flush 实现改回同步接口,不要将 flush 标记为 async;直接复用
crate::disk::flush_all_disks 及其现有错误映射,并确保 flush_disk/dev.flush 的同步阻塞操作不暴露为异步任务。
In `@crates/axplat-loongarch64-qemu-virt/src/irq.rs`:
- Around line 26-44: 统一隔离 CPU 内部中断与 EIOINTC 外部中断的 IRQ 命名空间,避免 EIOINTC pin 与
TIMER_IRQ 使用同一编号。更新 set_enable 及 IRQ_HANDLER_TABLE 的注册、分发和查找逻辑,为外部中断采用统一偏移映射,或将
TIMER_IRQ 映射到不会与外部中断冲突的虚拟编号,并同步调整 MAX_IRQ_COUNT;确保定时器仍配置 CPU 中断寄存器,外部中断仍正确配置
EIOINTC/PCH-PIC。
---
Nitpick comments:
In `@arceos/modules/axdriver/src/virtio.rs`:
- Around line 606-611: 在 virtio 初始化中计算 irq 的 riscv64 分支处补充注释,说明该公式基于 QEMU virt 的
MMIO 地址布局,并解释 0x1000_1000 起始地址、0x1000 步长与中断号映射的来源;保持现有 irq 推导逻辑不变。
- Around line 256-267: 移除未被使用的辅助函数 register_then_check,并保留 poll_token 中现有的“先注册
waker、再检查就绪”内联逻辑;不要引入额外重构。
In `@arceos/modules/axfs/src/fs/ext4/fs.rs`:
- Line 156: Remove the no-op `let _ = &self.inner;` statement from the `Drop`
implementation, leaving the remaining drop logic unchanged.
In `@arceos/modules/axfs/src/fs/ext4/mod.rs`:
- Around line 203-221: Document the Clone contract used by
write_block_to_disk_async: cloning D before await must be cheap and preserve
shared underlying device state so reads and writes remain consistent. Add this
clarification to the relevant trait documentation or as a concise comment at the
clone site, without changing the existing write flow.
In `@crates/axplat-loongarch64-qemu-virt/src/irq.rs`:
- Around line 69-78: Update the EIOINTC handling branch for EIOINTC_CPU_IRQ to
drain every pending interrupt in one trap by replacing the single
eiointc::claim_irq call with a while-let loop. Keep the existing trace,
IRQ_HANDLER_TABLE.handle, warning, and eiointc::complete_irq operations inside
the loop, and retain the spurious-interrupt debug message only when no IRQ is
claimed.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro Plus
Run ID: b91fcacf-35aa-4bbf-be16-585669d7559f
📒 Files selected for processing (42)
.cargo/config.tomlCargo.tomlarceos/Cargo.tomlarceos/modules/axalloc/Cargo.tomlarceos/modules/axconfig/Cargo.tomlarceos/modules/axdisplay/Cargo.tomlarceos/modules/axdma/Cargo.tomlarceos/modules/axdriver/Cargo.tomlarceos/modules/axdriver/src/virtio.rsarceos/modules/axfs/Cargo.tomlarceos/modules/axfs/src/disk.rsarceos/modules/axfs/src/fs/ext4/fs.rsarceos/modules/axfs/src/fs/ext4/inode.rsarceos/modules/axfs/src/fs/ext4/mod.rsarceos/modules/axfs/src/fs/mod.rsarceos/modules/axfs/src/highlevel/file.rsarceos/modules/axfs/src/highlevel/fs.rsarceos/modules/axhal/Cargo.tomlarceos/modules/axipi/Cargo.tomlarceos/modules/axlog/Cargo.tomlarceos/modules/axmm/Cargo.tomlarceos/modules/axnet/Cargo.tomlarceos/modules/axns/Cargo.tomlarceos/modules/axruntime/Cargo.tomlarceos/modules/axsync/Cargo.tomlarceos/modules/axtask/Cargo.tomlarceos/modules/axtask/src/wait_queue.rscargo/config.tomlcrates/axfs-ng-vfs/src/node/dir.rscrates/axplat-loongarch64-qemu-virt/src/irq.rscrates/axplat-loongarch64-qemu-virt/src/irq/eiointc.rscrates/axplat-loongarch64-qemu-virt/src/irq/irq_common.rscrates/axplat-loongarch64-qemu-virt/src/irq/pch_pic.rscrates/axplat-riscv64-qemu-virt/src/console.rscrates/axplat-riscv64-qemu-virt/src/irq.rscrates/axplat-riscv64-qemu-virt/src/plic.rscrates/ext4plus/src/lib.rscrates/virtio-drivers/src/transport/pci.rspulse_core/Cargo.tomlpulse_core/src/mm/loader.rspulse_syscalls/Cargo.tomlsrc/main.rs
💤 Files with no reviewable changes (3)
- .cargo/config.toml
- cargo/config.toml
- src/main.rs
🚧 Files skipped from review as they are similar to previous changes (11)
- crates/axplat-loongarch64-qemu-virt/src/irq/pch_pic.rs
- pulse_core/src/mm/loader.rs
- arceos/modules/axfs/src/fs/mod.rs
- arceos/Cargo.toml
- arceos/modules/axfs/src/disk.rs
- arceos/modules/axtask/src/wait_queue.rs
- crates/axplat-riscv64-qemu-virt/src/plic.rs
- crates/axplat-riscv64-qemu-virt/src/irq.rs
- crates/axfs-ng-vfs/src/node/dir.rs
- arceos/modules/axfs/src/highlevel/fs.rs
- arceos/modules/axfs/src/fs/ext4/inode.rs
| # The `std` feature needs Chrono's default features, which are disabled workspace-wide. | ||
| chrono = { version = "0.4", optional = true } |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win
避免隐式启用 default-features 导致 no_std 内核编译失败。
直接在此处声明 chrono = { version = "0.4", optional = true } 会脱离 workspace 配置,并隐式启用 chrono 的 default-features(包含 std 依赖)。
由于 Cargo 的特性合并机制,即使在内核态只希望启用 axlog 的 chrono 特性来获取时间戳,也会意外拉取标准库,从而破坏 no_std 环境并导致编译失败。
建议使用 workspace = true 继承无标准库的配置,并在 [features] 中按需传递 std 相关特性:
🛠️ 建议的修复方案
- # The `std` feature needs Chrono's default features, which are disabled workspace-wide.
- chrono = { version = "0.4", optional = true }
+ chrono = { workspace = true, optional = true }
+
+ # 请确保在文件底部的 [features] 块中进行如下配置(如果已有 std 特性请补充):
+ # std = ["chrono?/std", "chrono?/clock"]📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| # The `std` feature needs Chrono's default features, which are disabled workspace-wide. | |
| chrono = { version = "0.4", optional = true } | |
| chrono = { workspace = true, optional = true } | |
| # 请确保在文件底部的 [features] 块中进行如下配置(如果已有 std 特性请补充): | |
| # std = ["chrono?/std", "chrono?/clock"] |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@arceos/modules/axlog/Cargo.toml` around lines 27 - 28, Update the chrono
dependency declaration in the axlog Cargo manifest to inherit the workspace
configuration with default features disabled, and adjust the axlog feature
definitions to forward chrono’s std-related feature only when axlog’s std
feature is enabled. Preserve optional chrono usage and ensure the default no_std
build does not enable chrono’s std support.
Summary by CodeRabbit
新功能
文档与测试