Repository navigation
NVNet Networking
xemu models the Xbox MCPX Ethernet controller as a PCI NIC with guest-visible registers, descriptor rings, DMA, PHY/MDIO state, link negotiation, packet filtering and interrupts. The physical Ethernet PHY and wire are not simulated electrically; packet payloads cross into QEMU's host networking backend after the guest NIC semantics have been processed.
flowchart LR
A[Guest network driver] --> B[NVNet MMIO]
A --> C[TX/RX descriptor rings in guest RAM]
B --> D[NvNetState]
C --> E[pci_dma_read/write]
D --> E
E --> F[TX/RX packet assembly]
F --> G[QEMU NetClient backend]
G --> H[Host network backend]
F --> I[Descriptor/status update]
I --> J[PCI IRQ]
J --> A
The guest still sees a DMA-driven NIC. The abstraction boundary is below the emulated MAC/descriptor engine and above physical Ethernet signaling.
hw/xbox/mcpx/nvnet/nvnet.c exposes an MMIO register area of 0x400 bytes plus an I/O region. NvNetState stores the register bytes directly and provides helpers for 8-, 16- and 32-bit accesses.
The model includes state for:
- interrupt status/mask;
- transmitter and receiver control/status;
- MAC and multicast addresses/masks;
- TX and RX ring physical addresses and sizes;
- current/next descriptor addresses;
- PHY/MDIO state;
- link speed/control;
- power/wakeup-related registers;
- TX/RX temporary packet buffers;
- virtual auto-negotiation timer.
Some register meanings remain named UNKNOWN_*, reflecting incomplete hardware knowledge rather than hidden complete behavior.
Current ring descriptors are modeled as packed guest-memory structures:
uint32 buffer_addr
uint16 length
uint16 flags
The device reads and writes descriptors with pci_dma_read() and pci_dma_write(), converting little-endian guest fields to host values explicitly.
This is important for fidelity: descriptor ownership is not replaced by a host socket API. xemu first reproduces the NIC's guest-memory protocol, then hands a completed packet to QEMU networking.
sequenceDiagram
participant G as Guest driver
participant R as Guest TX ring
participant N as NVNet model
participant Q as QEMU network backend
G->>R: Fill descriptors + packet buffers
G->>N: Write TX/RX CONTROL KICK
N->>R: DMA-read current descriptor
loop valid descriptors
N->>R: DMA-read packet fragment
N->>N: Append to tx_dma_buf
N->>R: Clear/update descriptor flags
end
N->>Q: qemu_send_packet() on LASTPACKET
N->>G: Set TX IRQ status and assert PCI IRQ
dma_packet_from_guest() stops when it finds an invalid descriptor or after the current packet's LASTPACKET. The implementation currently contains a FIXME at the post-last-packet break, so unusual multi-packet/ring scheduling deserves explicit testing.
The temporary TX assembly buffer is bounded. The source currently asserts that accumulated fragment length fits the buffer instead of modeling a hardware overflow/error path.
sequenceDiagram
participant Q as QEMU network backend
participant N as NVNet model
participant R as Guest RX ring/RAM
participant G as Guest driver
Q->>N: Packet arrives
N->>N: Size/filter check
N->>R: Find available RX descriptor
N->>R: DMA-write packet bytes
N->>R: Write actual length + completion flags
N->>G: Set RX IRQ status and assert PCI IRQ
N->>N: Advance ring pointer
A packet can be accepted only when receive is enabled, DMA is enabled, link is up and an RX descriptor is available.
The current receive path asserts that the selected descriptor's buffer is large enough for the packet (FIXME in source). Physical hardware would normally have defined truncation/error/drop behavior; an assertion-enabled emulator build can therefore fail more strongly on malformed or unusual guest ring state.
Current and next descriptor addresses are kept as guest-visible registers. If a computed next/current pointer falls outside the configured ring, xemu wraps it back to the base ring address.
base <= descriptor < base + ring_size * 8
→ use descriptor
otherwise
→ wrap to base
Ring size register fields are interpreted as encoded value + 1 descriptors.
The receive filter implements broadcast, multicast and unicast checks using guest-programmed registers.
Current known approximations include source FIXMEs around:
- broadcast filtering behavior;
- exact meaning of
PFF_MYADDRfor multicast; - MII status mask handling.
This is a good example of a model that is substantially functional but still has protocol corners where hardware behavior is not fully established.
The PHY is represented by a small logical register array rather than an analog Ethernet transceiver. PHY_ADDR is fixed to 1, and implemented PHY registers include common MII identity/control/status/autonegotiation fields.
Guest MDIO access is handled synchronously:
flowchart LR
A[Guest writes MDIO address/control] --> B[nvnet_mmio_write]
B --> C{read or write?}
C -->|Read| D[phy_reg_read]
C -->|Write| E[phy_reg_write]
D --> F[MDIO data register]
E --> F
F --> G[Clear INUSE]
There is no serial MDIO bit-clock model in this path.
Link negotiation is one place where xemu deliberately retains visible latency. When autonegotiation is enabled and the host link comes up, xemu schedules a QEMU_CLOCK_VIRTUAL timer for 250 ms.
stateDiagram-v2
[*] --> LinkDown
LinkDown --> Negotiating: host link up + AUTOEN
Negotiating --> LinkUp: 250 ms virtual timer expires
LinkUp --> LinkDown: host link down
LinkUp --> Negotiating: renegotiation
At completion the model marks partner ACK/autoneg complete, marks link up and raises the appropriate MII/link-change interrupt state.
This is virtual device timing, not a real PHY waveform simulation.
update_irq() compares NVNET_IRQ_STATUS with NVNET_IRQ_MASK and asserts the PCI interrupt whenever any enabled status bit is pending.
device event
↓
set status bit
↓
status & mask != 0 ?
├─ yes → pci_irq_assert
└─ no → pci_irq_deassert
Guest writes to IRQ/MII status registers clear selected bits and recompute the line.
NVNet deliberately uses QEMU PCI DMA APIs rather than caching a permanent raw pointer for descriptor-ring traffic. That preserves the device's PCI/DMA address-space abstraction and makes reads/writes visible through QEMU's memory system.
register contains guest physical/DMA address
↓
pci_dma_read/write
↓
QEMU DMA/address-space translation
↓
guest RAM
This is different from the APU's direct RAM-pointer fast path and is useful when comparing memory overhead between devices.
Once a complete guest TX packet is assembled, qemu_send_packet() transfers it into QEMU's network backend. For RX, the configured backend invokes the NVNet receive callback with a host-side packet.
What xemu does not model at that boundary includes:
- analog PHY signaling;
- magnetics;
- cable propagation;
- physical collision waveforms;
- electrical link partner behavior.
Any latency or loss introduced by TAP/socket/bridge/NAT/host networking belongs below the emulated NIC and should be profiled separately.
| Mechanism | Effect | Risk/limitation |
|---|---|---|
| Direct register byte array | Cheap ordinary MMIO storage | Unknown registers may lack side effects |
| Synchronous MDIO reads/writes | No serial-bus timing overhead | PHY transaction latency omitted |
| 250 ms virtual autoneg timer | Preserves coarse link delay | Real negotiation details are simplified |
| Whole packet assembled in bounded host buffer | Simple descriptor-fragment handling | Buffer limits currently protected by assertions |
pci_dma_read/write |
Preserves DMA abstraction | More host overhead than a raw RAM pointer, but safer for device semantics |
| QEMU network backend | Reuses mature host I/O plumbing | Host backend behavior can dominate end-to-end latency |
Current source contains explicit uncertainty or strong assertions around several areas:
- RX descriptor buffer-too-small condition uses an assertion with
FIXME. - TX temporary-buffer overflow uses an assertion.
- TX loop stops after
LASTPACKETwithFIXME. - broadcast filtering is not fully implemented;
- multicast filter semantics contain a confirmation
FIXME; - MII status masking is incomplete/uncertain;
- unaligned/unsupported MMIO access can assert rather than emulate undefined hardware behavior.
These should be treated as architecture constraints when fuzzing drivers or evaluating homebrew that programs NVNet differently from the retail kernel.
flowchart TD
A[Slow networking] --> B{Where is time?}
B -->|Guest CPU| C[driver / IRQ / descriptor handling]
B -->|NVNet model| D[MMIO + ring walks + DMA copies]
B -->|QEMU backend| E[host network queue/backend]
B -->|Host network| F[OS/TAP/socket/bridge]
D --> G{Packet copy or DMA lookup dominant?}
E --> H{Backend wait/backpressure?}
C --> I[Profile vCPU/device exits]
Do not optimize pci_dma_read() away without proving the target address is always ordinary RAM and preserving dirty/mapping semantics.
| Source | Responsibility |
|---|---|
hw/xbox/mcpx/nvnet/nvnet.c |
Device, MMIO, descriptor/DMA, filtering, PHY, IRQ, network backend integration |
hw/xbox/mcpx/nvnet/nvnet_regs.h |
Register and descriptor flag definitions |
hw/xbox/mcpx/nvnet/trace-events |
Existing tracepoints useful for diagnosis |
hw/xbox/xbox.c |
PCI device creation and NIC configuration |
- NVNet receive-status combinations — framing-only versus combined hard-error driver policy.
- Platform & I/O
- Memory & DMA
- Clocks & Timers
- Hardware Fidelity & Emulation Boundaries
- Performance Methodology
DSP tooling guide and navigation updated November 2, 2026 for experimental PR #384, source 8f51d237. Capture/replay usage and limits.
The earlier wiki-wide review was published November 1, 2026. Emulator source: b7140848. Reviewed wiki content: 1d2b671. Current status · Release availability · Publication process.
- Home
- Current status
- Stable versus main
- Implemented mechanisms
- Controls and defaults
- Measured results and limits
- Complete change register
- System
- CPU and vCPU
- Memory and DMA
- Graphics / NV2A
- APU and audio
- Timing and timers
- Platform and I/O
- Hardware observations
- Fidelity boundaries
- Methodology
- PGR2 routes
- Debugging lag / hot paths
- Tools and commands
- DSP capture, replay and fuzzing
- HLE readiness and public XISO proof
- Concurrent DSP shadow and OpenAL proof
- DSP HLE operation inventory
- DSP HLE fix examples and testing
- Development
- Upstream shortlist
- Wiki maintenance
- Research / retired work
- Optimization catalog
- Hot-path shortcuts
- Researched experiments
- Unproven proposal directory
- PR lessons
- September26 snapshot
Repository · PRs · Issues