#include "kvm/virtio_pci.h"
#include "kvm/ioport.h"
+#include "kvm/kvm.h"
#include "kvm/pci.h"
-#define VIRTIO_PCI_IOPORT_SIZE 24
+#define VIRTIO_BLK_IRQ 14
struct device {
uint32_t guest_features;
offset = port - IOPORT_VIRTIO;
+ /* XXX: Let virtio block device handle this */
+ if (offset >= VIRTIO_PCI_CONFIG_NOMSI)
+ return true;
+
switch (offset) {
case VIRTIO_PCI_HOST_FEATURES:
ioport__write32(data, 0x00);
break;
case VIRTIO_PCI_GUEST_FEATURES:
+ return false;
case VIRTIO_PCI_QUEUE_PFN:
+ ioport__write32(data, 0x00);
+ break;
case VIRTIO_PCI_QUEUE_NUM:
+ ioport__write16(data, 0x10);
+ break;
case VIRTIO_PCI_QUEUE_SEL:
case VIRTIO_PCI_QUEUE_NOTIFY:
return false;
ioport__write8(data, device.status);
break;
case VIRTIO_PCI_ISR:
+ ioport__write8(data, 0x1);
+ kvm__irq_line(self, VIRTIO_BLK_IRQ, 0);
+ return true;
case VIRTIO_MSI_CONFIG_VECTOR:
default:
return false;
return true;
}
-#include <stdio.h>
-
static bool blk_virtio_out(struct kvm *self, uint16_t port, void *data, int size, uint32_t count)
{
unsigned long offset;
offset = port - IOPORT_VIRTIO;
+ /* XXX: Let virtio block device handle this */
+ if (offset >= VIRTIO_PCI_CONFIG_NOMSI)
+ return true;
+
switch (offset) {
case VIRTIO_PCI_GUEST_FEATURES:
device.guest_features = ioport__read32(data);
break;
case VIRTIO_PCI_QUEUE_PFN:
+ return true;
case VIRTIO_PCI_QUEUE_SEL:
- case VIRTIO_PCI_QUEUE_NOTIFY:
- return false;
+ return true;
+ case VIRTIO_PCI_QUEUE_NOTIFY: {
+ kvm__irq_line(self, VIRTIO_BLK_IRQ, 1);
+ return true;
+ }
case VIRTIO_PCI_STATUS:
device.status = ioport__read8(data);
break;
.subsys_vendor_id = PCI_SUBSYSTEM_VENDOR_ID_REDHAT_QUMRANET,
.subsys_id = PCI_SUBSYSTEM_ID_VIRTIO_BLK,
.bar[0] = IOPORT_VIRTIO | PCI_BASE_ADDRESS_SPACE_IO,
+ /* XXX: Is this IRQ setup OK? */
+ .irq_pin = 1,
+ .irq_line = VIRTIO_BLK_IRQ,
};
void blk_virtio__init(void)
{
pci__register(&blk_virtio_pci_device, 1);
- ioport__register(IOPORT_VIRTIO, &blk_virtio_io_ops, VIRTIO_PCI_IOPORT_SIZE);
+ ioport__register(IOPORT_VIRTIO, &blk_virtio_io_ops, 256);
}
void kvm__reset_vcpu(struct kvm *self);
void kvm__setup_mem(struct kvm *self);
void kvm__run(struct kvm *self);
+void kvm__irq_line(struct kvm *self, int irq, int level);
bool kvm__emulate_io(struct kvm *self, uint16_t port, void *data, int direction, int size, uint32_t count);
bool kvm__emulate_mmio(struct kvm *self, uint64_t phys_addr, uint8_t *data, uint32_t len, uint8_t is_write);
die_perror("KVM_RUN failed");
}
+void kvm__irq_line(struct kvm *self, int irq, int level)
+{
+ struct kvm_irq_level irq_level;
+
+ irq_level = (struct kvm_irq_level) {
+ {
+ .irq = irq,
+ },
+ .level = level,
+ };
+
+ if (ioctl(self->vm_fd, KVM_IRQ_LINE, &irq_level) < 0)
+ die_perror("KVM_IRQ_LINE failed");
+}
+
static void print_dtable(const char *name, struct kvm_dtable *dtable)
{
printf(" %s %016" PRIx64 " %08" PRIx16 "\n",
const char *kernel_cmdline = NULL;
const char *kvm_dev = "/dev/kvm";
unsigned long ram_size = 64UL << 20;
+ bool enable_virtio = false;
bool single_step = false;
int i;
} else if (option_matches(argv[i], "--single-step")) {
single_step = true;
continue;
+ } else if (option_matches(argv[i], "--enable-virtio")) {
+ enable_virtio = true;
+ continue;
} else if (option_matches(argv[i], "--mem=")) {
unsigned long val = atol(&argv[i][6]) << 20;
if (val < ram_size)
early_printk__init();
pci__init();
- blk_virtio__init();
+
+ if (enable_virtio)
+ blk_virtio__init();
for (;;) {
kvm__run(kvm);