Skip to content

Commit 5b84cdb

Browse files
ppennaCopilot
andcommitted
microVM: remove portb's host input
portb, the microVM's byte channel at ports 0xe9 to 0xeb, delivered host input to the guest's hvc0 console. microsoft/nvx#549 removes that input, so that host input reaches a microVM guest only through its boot and control consoles, by design rather than by how a frontend wires portb. The device no longer reads its host endpoint: its input-pending status bit stays clear, a data read without a selected record returns zeros, and it no longer takes part in the snapshot input gate. A snapshot saves an empty input buffer, and a restore refuses the state of an earlier VMM that holds input the guest had not read, rather than drop it. The output buffer keeps its 1 MiB bound, and the machine ABI its version: a host that never sends input was always valid. When the boot console does not own the terminal, portb still writes to stdout and keeps the terminal, but OpenVMM now discards keystrokes until Ctrl-Q opens the REPL, instead of handing them to a device that no longer reads them. The CLI and RPC guides say so. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 16975e6 commit 5b84cdb

5 files changed

Lines changed: 110 additions & 164 deletions

File tree

‎Guide/src/reference/openvmm/management/cli.md‎

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,11 @@ describes the source definitions.
3939

4040
The kernel must be an uncompressed ELF64 image. The profile owns the base command line
4141
(`earlycon=xe9 console=hvc0 reboot=t panic=-1`) and switches the primary
42-
console to `hvc1` when `--virtio-console` is present. It appends
42+
console to `hvc1` when `--virtio-console` is present. The portb console,
43+
`hvc0`, takes no host input, so an interactive guest console needs
44+
`--virtio-console console`; without a boot console on the terminal, portb
45+
writes to stdout, and OpenVMM discards keystrokes until Ctrl-Q opens the
46+
REPL. It appends
4347
`nr_cpus=<capacity>` from the validated processor topology. It reserves a 1-GiB
4448
MMIO gap from 3 to 4 GiB and exposes only PIC/IOAPIC, PIT, a CMOS RTC
4549
anchored to UTC,
@@ -1006,7 +1010,8 @@ Serial devices can be configured to appear as different devices inside the guest
10061010
* `--virtio-console <BACKEND>`: Expose a virtio console device. It normally
10071011
appears as `/dev/hvc0`. Under `--machine microvm`, it occupies fixed MMIO
10081012
`0xd0002000`, IRQ 18, and is selected as `/dev/hvc1`; the raw portb path
1009-
remains available as `hvc0` for early output and recovery.
1013+
remains available as `hvc0` for early output and failure reports, and takes
1014+
no host input.
10101015

10111016
A microVM accepts these explicit attachment policies:
10121017

‎Guide/src/reference/openvmm/management/grpc.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,7 @@ restore flow over both transports:
190190
absent, or may contain only the matching microVM profile, an optional exact
191191
processor-count assertion, a `cpu_profile` that the restore accepts (see
192192
below), serial port 0 host
193-
attachment, matching `DevicesConfig.virtio_consoles` and
193+
attachment, which receives portb's output and is never read, matching `DevicesConfig.virtio_consoles` and
194194
`DevicesConfig.virtiofs_config` attachments, and guest power actions.
195195
Guest-visible boot, memory, processor topology, other device, NUMA, and PCIe
196196
fields are rejected. A saved listener is reconstructed from the manifest; a saved

‎openvmm/openvmm_entry/src/microvm/config.rs‎

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -242,10 +242,13 @@ impl<'a> MicrovmConfigBuilder<'a> {
242242
}
243243
}
244244

245-
/// Connects the host side of the portb console (`hvc0`).
245+
/// Connects the host side of the portb console (`hvc0`), which takes no
246+
/// host input.
246247
///
247-
/// This must run before the other serial devices so that portb owns the
248-
/// interactive console when the boot virtio-console does not.
248+
/// When the boot virtio-console does not own the terminal, portb does: it
249+
/// writes to stdout, and OpenVMM discards keystrokes until Ctrl-Q opens
250+
/// the REPL. This must run before the other serial devices, which would
251+
/// otherwise take the terminal.
249252
pub(crate) fn setup_portb(
250253
&mut self,
251254
console_state: &RefCell<Option<ConsoleState<'static>>>,
@@ -268,6 +271,7 @@ impl<'a> MicrovmConfigBuilder<'a> {
268271
"microvm-portb",
269272
backend,
270273
"hvc0",
274+
false,
271275
console_state,
272276
serial_driver,
273277
)?);
@@ -324,6 +328,7 @@ impl<'a> MicrovmConfigBuilder<'a> {
324328
"virtio-console",
325329
SerialConfigCli::Console,
326330
"hvc1",
331+
true,
327332
console_state,
328333
serial_driver,
329334
)?;
@@ -856,11 +861,14 @@ fn aggregate_child_kind(
856861
}
857862

858863
/// Connects a portb or boot virtio-console endpoint to the host console or
859-
/// stderr, returning its backend and output-relay completion.
864+
/// stderr, returning its backend and output-relay completion. The device
865+
/// receives the console's input when `input` is set; otherwise, OpenVMM
866+
/// discards it.
860867
fn setup_host_console(
861868
name: &str,
862869
backend: SerialConfigCli,
863870
device: &'static str,
871+
input: bool,
864872
console_state: &RefCell<Option<ConsoleState<'static>>>,
865873
serial_driver: &DefaultDriver,
866874
) -> anyhow::Result<(Resource<SerialBackendHandle>, OutputCompletion)> {
@@ -871,10 +879,12 @@ fn setup_host_console(
871879
}
872880
let (config, serial) = serial_io::anonymous_serial_pair(serial_driver)?;
873881
let (serial_read, serial_write) = AsyncReadExt::split(serial);
874-
*console_state.borrow_mut() = Some(ConsoleState {
875-
device,
876-
input: Box::new(serial_write),
877-
});
882+
let input: Box<dyn futures::AsyncWrite + Unpin + Send> = if input {
883+
Box::new(serial_write)
884+
} else {
885+
Box::new(futures::io::sink())
886+
};
887+
*console_state.borrow_mut() = Some(ConsoleState { device, input });
878888
let completed = spawn_output(name, serial_read, term::raw_stdout())?;
879889
(config, completed)
880890
}

0 commit comments

Comments
 (0)