Skip to content

Commit 2b803de

Browse files
authored
fix(whp): respect IO port access size in IoPortAccess exit handler (#1387)
The WHP IoPortAccess exit handler was returning the full 8 bytes of RAX regardless of the guest's operand width. For outb (1-byte writes like serial port console output), this produced 8 bytes per character, resulting in garbled multi-byte sequences in the host's eprint! output. Extract AccessSize from IoPortAccess.AccessInfo (bits 1..3) and truncate the returned data vec to the actual operand width (1 for outb, 2 for outw, 4 for outl). Signed-off-by: danbugs <danilochiarlone@gmail.com>
1 parent e41799c commit 2b803de

File tree

1 file changed

+13
-5
lines changed
  • src/hyperlight_host/src/hypervisor/virtual_machine

1 file changed

+13
-5
lines changed

src/hyperlight_host/src/hypervisor/virtual_machine/whp.rs

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -311,14 +311,17 @@ impl VirtualMachine for WhpVm {
311311
let rip = exit_context.VpContext.Rip + instruction_length as u64;
312312
let port = exit_context.Anonymous.IoPortAccess.PortNumber;
313313
let rax = exit_context.Anonymous.IoPortAccess.Rax;
314-
let is_write = exit_context
314+
let access_info_bits = exit_context
315315
.Anonymous
316316
.IoPortAccess
317317
.AccessInfo
318318
.Anonymous
319-
._bitfield
320-
& 1
321-
!= 0;
319+
._bitfield;
320+
let is_write = access_info_bits & 1 != 0;
321+
// Bits 1..3 of AccessInfo encode the operand width in
322+
// bytes (1 for outb, 2 for outw, 4 for outl). Clamp to
323+
// 1..=8 to avoid a zero-length slice.
324+
let access_size = (((access_info_bits >> 1) & 0x7) as usize).clamp(1, 8);
322325

323326
self.set_registers(&[(
324327
WHvX64RegisterRip,
@@ -357,7 +360,12 @@ impl VirtualMachine for WhpVm {
357360
// Suppress unused variable warnings when hw-interrupts is disabled
358361
let _ = is_write;
359362

360-
return Ok(VmExit::IoOut(port, rax.to_le_bytes().to_vec()));
363+
// Only return the bytes that the guest actually wrote
364+
// (1 for outb, 2 for outw, 4 for outl). Previously all
365+
// 8 RAX bytes were returned, producing garbled output
366+
// for single-byte console writes.
367+
let data = rax.to_le_bytes();
368+
return Ok(VmExit::IoOut(port, data[..access_size].to_vec()));
361369
},
362370
WHvRunVpExitReasonX64Halt => {
363371
// With software timer active, re-enter the guest.

0 commit comments

Comments
 (0)