Skip to content

perf(e1000e): agrupa el doorbell RDT y elimina MMIO redundante en RX - #752

Merged
Pryancito merged 1 commit into
masterfrom
claude/e1000e-driver-bugs-im87by
Aug 6, 2026
Merged

perf(e1000e): agrupa el doorbell RDT y elimina MMIO redundante en RX#752
Pryancito merged 1 commit into
masterfrom
claude/e1000e-driver-bugs-im87by

Conversation

@Pryancito

Copy link
Copy Markdown
Owner

El camino RX no agrupaba ningun acceso MMIO por paquete: cada frame recibido pagaba su propio round-trip completo, sin importar cuantos llegaran en la misma rafaga. Bajo QEMU (el objetivo de pruebas habitual de este driver) cada acceso MMIO tipicamente dispara una VM exit completa, asi que esta sobrecarga por-paquete domina el coste real de mover los bytes.

Cambios en drivers/src/net/e1000e.rs, todos en el camino RX:

  • receive() cachea RDH una sola vez por llamada en vez de releerlo por MMIO en cada iteracion del bucle de drenaje (hasta 2 lecturas por iteracion antes). process_rx_slot ya no relee RDH: el invariante lo garantiza quien llama.
  • El doorbell RDT se difiere (rx_doorbell_dirty) y se agrupa con flush_rx_doorbell(), llamado una vez por rafaga en poll_with_irq_hint (tras iface.poll()) y en NetScheme::recv(). Se elimina tambien la lectura de flush sincrona que seguia a cada escritura de RDT.
  • ensure_rx_armed_if_link_up ya no relee STATUS por MMIO cuando el enlace ya se sabe activo (se invoca en cada poll).
  • La invalidacion de cache del buffer RX usa la longitud real del frame en vez de BUF_SIZE completo (2048B) — nada lee mas alla de esa longitud.

Nuevo test rx_doorbell_is_batched_not_rung_per_packet que verifica el agrupamiento explicitamente. Los 13 tests existentes (RX, TX, coherency bench) siguen en verde; cargo build (no_std real) y clippy limpios.

Claude-Session: https://claude.ai/code/session_01GFLBAPffWxDbLjrj9TEoW4

El camino RX no agrupaba ningun acceso MMIO por paquete: cada frame
recibido pagaba su propio round-trip completo, sin importar cuantos
llegaran en la misma rafaga. Bajo QEMU (el objetivo de pruebas habitual
de este driver) cada acceso MMIO tipicamente dispara una VM exit
completa, asi que esta sobrecarga por-paquete domina el coste real de
mover los bytes.

Cambios en drivers/src/net/e1000e.rs, todos en el camino RX:

- receive() cachea RDH una sola vez por llamada en vez de releerlo por
  MMIO en cada iteracion del bucle de drenaje (hasta 2 lecturas por
  iteracion antes). process_rx_slot ya no relee RDH: el invariante lo
  garantiza quien llama.
- El doorbell RDT se difiere (rx_doorbell_dirty) y se agrupa con
  flush_rx_doorbell(), llamado una vez por rafaga en poll_with_irq_hint
  (tras iface.poll()) y en NetScheme::recv(). Se elimina tambien la
  lectura de flush sincrona que seguia a cada escritura de RDT.
- ensure_rx_armed_if_link_up ya no relee STATUS por MMIO cuando el
  enlace ya se sabe activo (se invoca en cada poll).
- La invalidacion de cache del buffer RX usa la longitud real del frame
  en vez de BUF_SIZE completo (2048B) — nada lee mas alla de esa
  longitud.

Nuevo test rx_doorbell_is_batched_not_rung_per_packet que verifica el
agrupamiento explicitamente. Los 13 tests existentes (RX, TX, coherency
bench) siguen en verde; cargo build (no_std real) y clippy limpios.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GFLBAPffWxDbLjrj9TEoW4
Copilot AI lite review requested due to automatic review settings August 6, 2026 01:51
@Pryancito
Pryancito merged commit 719c4f5 into master Aug 6, 2026
2 of 14 checks passed

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR optimizes the e1000e RX fast path by reducing per-packet MMIO round-trips (particularly important under QEMU where MMIO often triggers VM-exits) and by tightening DMA cache invalidation to only the bytes actually read.

Changes:

  • Cache RDH once per receive() call and remove per-slot RDH MMIO reads in process_rx_slot.
  • Defer/batch RX RDT doorbell writes via rx_doorbell_dirty + flush_rx_doorbell(), called once per poll burst and in NetScheme::recv().
  • Reduce RX buffer cache invalidation from BUF_SIZE to the actual frame fragment length; add a test to assert doorbell batching behavior.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.

File Description
drivers/src/net/e1000e.rs Batches RX doorbell writes, reduces redundant MMIO reads, and narrows DMA sync ranges; adds a regression test for batching.
docs/README-e1000e-bugs.md Documents the diagnosed RX MMIO batching issue and the applied performance fixes/verification.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants