[hypervisor] Support synchronous accesses to PIO space.
Fixes a bug reading PCI PIO BARs and also implements the write path for
handling PCI PIO packets synchronously.
Change-Id: I8777a2c0dd6181c536b12f99d5e895725a97a539
diff --git a/kernel/lib/hypervisor/packet_mux.cpp b/kernel/lib/hypervisor/packet_mux.cpp
index ac30478..fa93fc0 100644
--- a/kernel/lib/hypervisor/packet_mux.cpp
+++ b/kernel/lib/hypervisor/packet_mux.cpp
@@ -53,6 +53,8 @@
}
zx_status_t PortRange::Queue(const zx_port_packet_t& packet, StateReloader* reloader) {
+ if (port_ == nullptr)
+ return ZX_ERR_NOT_FOUND;
PortPacket* port_packet = port_allocator_.Alloc(reloader);
if (port_packet == nullptr)
return ZX_ERR_NO_MEMORY;
@@ -106,6 +108,8 @@
zx_status_t status = FindPortRange(kind, addr, &port_range);
if (status != ZX_OK)
return status;
+
+ DEBUG_ASSERT(port_range->HasPort());
return port_range->Queue(packet, reloader);
}
diff --git a/system/ulib/hypervisor/vcpu.cpp b/system/ulib/hypervisor/vcpu.cpp
index c28edc3..eb58ef5 100644
--- a/system/ulib/hypervisor/vcpu.cpp
+++ b/system/ulib/hypervisor/vcpu.cpp
@@ -200,7 +200,7 @@
uint16_t port_off;
PciBus* bus = vcpu_ctx->guest_ctx->pci_bus;
PciDevice* pci_device;
- zx_status_t status = bus->MappedDevice(PCI_BAR_ASPACE_MMIO, io->port, &pci_device, &bar,
+ zx_status_t status = bus->MappedDevice(PCI_BAR_ASPACE_PIO, io->port, &pci_device, &bar,
&port_off);
if (status != ZX_ERR_NOT_FOUND) {
status = pci_device->ReadBar(bar, port_off, io->access_size, &vcpu_io);
@@ -242,6 +242,23 @@
return vcpu_ctx->guest_ctx->pci_bus->WriteIoPort(io);
case UART_INTERRUPT_ENABLE_PORT ... UART_SCR_SCRATCH_PORT:
return uart_write(vcpu_ctx->guest_ctx->uart, io);
+ default: {
+ uint8_t bar;
+ uint16_t port_off;
+ PciBus* bus = vcpu_ctx->guest_ctx->pci_bus;
+ PciDevice* pci_device;
+ zx_status_t status = bus->MappedDevice(PCI_BAR_ASPACE_PIO, io->port, &pci_device, &bar,
+ &port_off);
+ if (status != ZX_ERR_NOT_FOUND) {
+ // Convert the IO packet into a vcpu_io structure.
+ zx_vcpu_io_t vcpu_io;
+ static_assert(sizeof(vcpu_io.data) == sizeof(io->data),
+ "data size mismatch between zx_vcpu_io and zx_packet_get_io.");
+ memcpy(vcpu_io.data, io->data, sizeof(vcpu_io.data));
+ vcpu_io.access_size = io->access_size;
+ return pci_device->WriteBar(bar, port_off, &vcpu_io);
+ }
+ }
}
fprintf(stderr, "Unhandled port out %#x\n", io->port);
return ZX_ERR_NOT_SUPPORTED;