/* * x86-only, but define pio_port for all architectures to minimize the * amount of #ifdeffery and complexity, without having to sacrifice * verbose error messages.
*/
uint8_t pio_port;
};
/* * Annoyingly, reading PIO data is safe only for PIO exits, otherwise * data_offset is garbage, e.g. an MMIO gpa.
*/ if (run->exit_reason == KVM_EXIT_IO)
pio_value = *(uint32_t *)((void *)run + run->io.data_offset); else
pio_value = 0;
TEST_ASSERT((ring->last + 1) % io->ring_size == ring->first, "Expected ring to be full (minus 1), first = %u, last = %u, max = %u, start = %u",
ring->first, ring->last, io->ring_size, ring_start);
for (i = 0; i < io->ring_size - 1; i++) {
uint32_t idx = (ring->first + i) % io->ring_size; struct kvm_coalesced_mmio *entry = &ring->coalesced_mmio[idx];
#ifdef __x86_64__ if (i & 1)
TEST_ASSERT(entry->phys_addr == io->pio_port &&
entry->len == 4 && entry->pio &&
*(uint32_t *)entry->data == io->pio_port + i, "Wanted 4-byte port I/O 0x%x = 0x%x in entry %u, got %u-byte %s 0x%llx = 0x%x",
io->pio_port, io->pio_port + i, i,
entry->len, entry->pio ? "PIO" : "MMIO",
entry->phys_addr, *(uint32_t *)entry->data); else #endif
TEST_ASSERT(entry->phys_addr == io->mmio_gpa &&
entry->len == 8 && !entry->pio, "Wanted 8-byte MMIO to 0x%lx = %lx in entry %u, got %u-byte %s 0x%llx = 0x%lx",
io->mmio_gpa, io->mmio_gpa + i, i,
entry->len, entry->pio ? "PIO" : "MMIO",
entry->phys_addr, *(uint64_t *)entry->data);
}
}
kvm_builtin_io_ring = (struct kvm_coalesced_io) { /* * The I/O ring is a kernel-allocated page whose address is * relative to each vCPU's run page, with the page offset * provided by KVM in the return of KVM_CAP_COALESCED_MMIO.
*/
.ring = (void *)vcpu->run +
(kvm_check_cap(KVM_CAP_COALESCED_MMIO) * getpagesize()),
/* * The size of the I/O ring is fixed, but KVM defines the sized * based on the kernel's PAGE_SIZE. Thus, userspace must query * the host's page size at runtime to compute the ring size.
*/
.ring_size = (getpagesize() - sizeof(struct kvm_coalesced_mmio_ring)) / sizeof(struct kvm_coalesced_mmio),
/* * Arbitrary address+port (MMIO mustn't overlap memslots), with * the MMIO GPA identity mapped in the guest.
*/
.mmio_gpa = 4ull * SZ_1G,
.mmio = (uint64_t *)(4ull * SZ_1G),
.pio_port = 0x80,
};
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.