openvmm: wide RTC port reads leave stale bytes in the upper portion of the result

Open Beginner friendly
#1,151 1 comment 0 reactions 0 assignees View on GitHub

Maintainers usually reply within 1 day

Nobody has claimed this yet.

Assessment

Difficulty
2/5
Estimated time
1-3 hours
Newbie friendliness
82/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Active
Tech stack
rust

Research direction

Start in Rtc::io_read in vm/devices/chipset/src/cmos_rtc.rs, where only data[0] is written and the match arms set the register value. Clear the whole destination slice before that write so wider accesses are zero-extended. Done means a 16- or 32-bit read of port 0x71 after selecting index 0x0d returns 0x0080 or 0x00000080, and one-byte reads and invalid-register handling are unchanged.

Written by the indexing model from the issue text.

Description

RTC PIO reads wider than one byte return the register byte together with stale upper bytes from the destination buffer, despite the intercept's documented zero-extension behavior.

In vm/devices/chipset/src/cmos_rtc.rs, Rtc::io_read writes only data[0]:

        // We assume all accesses are one byte in size. Attempts to
        // access larger sizes will return a single byte of information
        // (zero-extended to the size of the access).
        data[0] = match RtcIoPort(io_port) {
            RtcIoPort::ADDR => self.state.addr,
            RtcIoPort::DATA => self.get_cmos_byte(self.state.addr),
            _ => return IoResult::Err(IoError::InvalidRegister),
        };

        IoResult::Ok

For a two- or four-byte destination, the remaining bytes are never overwritten. On a reused PIO exit buffer, those bytes can come from an earlier operation rather than the current RTC read.

Reproduction

Write 0x0d to address port 0x70 to select RTC status D, then read data port 0x71 with a 16- or 32-bit PIO access. The low byte is status D's 0x80, but the upper bytes retain the read buffer's previous contents instead of producing 0x0080 or 0x00000080.

A wide read of address port 0x70 has the same problem: only the selected CMOS index replaces the previous buffer contents.

Fix

fix.patch determines the register value, clears the entire destination, then writes the value to its first byte. Invalid-register handling and one-byte reads remain unchanged.

Dominant language
Rust
Stars
758
Forks
48
Avg merge
17h 50m
Merged PRs (30d)
450

Getting set up

This project ships no dev container, Dockerfile or contributing guide, so setting up is up to you: start from its README, and see our first-contribution guide for the general steps.

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from microsoft/nvx

All issues in microsoft/nvx

Similar issues

More Rust issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.