Add virtio_mmio_setup() to probe virtio mmio devices. Add vp_init_mmio() to initialize device struct. Because virtio-pci and virtio-mmio are quite simliar we reuse the infrastructure we already have for virtio-pci and just setup struct vp_cap for virtio-mmio.
Signed-off-by: Gerd Hoffmann kraxel@redhat.com --- src/hw/virtio-mmio.h | 71 ++++++++++++++++++++++++++++++++++++++++++++ src/hw/virtio-pci.h | 1 + src/block.c | 2 ++ src/hw/virtio-mmio.c | 49 ++++++++++++++++++++++++++++++ 4 files changed, 123 insertions(+)
diff --git a/src/hw/virtio-mmio.h b/src/hw/virtio-mmio.h index 751984241f49..5e24f692c1ae 100644 --- a/src/hw/virtio-mmio.h +++ b/src/hw/virtio-mmio.h @@ -1,6 +1,77 @@ #ifndef _VIRTIO_MMIO_H #define _VIRTIO_MMIO_H
+struct vp_device; + +typedef struct virtio_mmio_cfg { + u32 magic; + u32 version; + u32 device_id; + u32 vendor_id; + + u32 device_feature; + u32 device_feature_select; + u32 res_18; + u32 res_1c; + + u32 guest_feature; + u32 guest_feature_select; + u32 legacy_guest_page_size; + u32 res_2c; + + u32 queue_select; + u32 queue_num_max; + u32 queue_num; + u32 legacy_queue_align; + + u32 legacy_queue_pfn; + u32 queue_ready; + u32 res_48; + u32 res_4c; + + u32 queue_notify; + u32 res_54; + u32 res_58; + u32 res_5c; + + u32 irq_status; + u32 irq_ack; + u32 res_68; + u32 res_6c; + + u32 device_status; + u32 res_74; + u32 res_78; + u32 res_7c; + + u32 queue_desc_lo; + u32 queue_desc_hi; + u32 res_88; + u32 res_8c; + + u32 queue_driver_lo; + u32 queue_driver_hi; + u32 res_98; + u32 res_9c; + + u32 queue_device_lo; + u32 queue_device_hi; + u32 res_a8; + u32 shm_sel; + + u32 shmem_len_lo; + u32 shmem_len_hi; + u32 shmem_base_lo; + u32 shmem_base_hi; + + u32 res_c0_f7[14]; + + u32 res_f8; + u32 config_generation; +} virtio_mmio_cfg; + void virtio_mmio_register(u64 mmio); +void virtio_mmio_setup(void); +void vp_init_mmio(struct vp_device *vp, void *mmio);
#endif /* _VIRTIO_MMIO_H */ diff --git a/src/hw/virtio-pci.h b/src/hw/virtio-pci.h index 492e5c7c9166..269626448558 100644 --- a/src/hw/virtio-pci.h +++ b/src/hw/virtio-pci.h @@ -111,6 +111,7 @@ struct vp_device { struct vp_cap common, notify, isr, device, legacy; u32 notify_off_multiplier; u8 use_modern; + u8 use_mmio; };
u64 _vp_read(struct vp_cap *cap, u32 offset, u8 size); diff --git a/src/block.c b/src/block.c index 1f600b85391b..9ef607610c40 100644 --- a/src/block.c +++ b/src/block.c @@ -20,6 +20,7 @@ #include "hw/usb-uas.h" // uas_process_op #include "hw/virtio-blk.h" // process_virtio_blk_op #include "hw/virtio-scsi.h" // virtio_scsi_process_op +#include "hw/virtio-mmio.h" // virtio_mmio_setup #include "hw/nvme.h" // nvme_process_op #include "malloc.h" // malloc_low #include "output.h" // dprintf @@ -514,6 +515,7 @@ block_setup(void) ramdisk_setup(); virtio_blk_setup(); virtio_scsi_setup(); + virtio_mmio_setup(); lsi_scsi_setup(); esp_scsi_setup(); megasas_setup(); diff --git a/src/hw/virtio-mmio.c b/src/hw/virtio-mmio.c index 6c969d787ec7..9f4f5b780f59 100644 --- a/src/hw/virtio-mmio.c +++ b/src/hw/virtio-mmio.c @@ -1,8 +1,11 @@ #include "config.h" // CONFIG_DEBUG_LEVEL #include "malloc.h" // free #include "output.h" // dprintf +#include "stacks.h" // run_thread +#include "string.h" // memset #include "virtio-pci.h" #include "virtio-ring.h" +#include "virtio-mmio.h"
/* qemu microvm supports 8 virtio-mmio devices */ static u64 devs[8]; @@ -28,3 +31,49 @@ void virtio_mmio_register(u64 mmio) } dprintf(1, "virtio-mmio: device list full\n"); } + +void virtio_mmio_setup(void) +{ + u32 magic, version, devid; + void *mmio; + int i; + + for (i = 0; i < ARRAY_SIZE(devs); i++) { + if (devs[i] == 0) + return; + mmio = (void*)(u32)(devs[i]); + magic = readl(mmio); + if (magic != 0x74726976) + continue; + version = readl(mmio+4); + if (version != 1 /* legacy */ && + version != 2 /* 1.0 */) + continue; + devid = readl(mmio+8); + dprintf(1, "virtio-mmio: %llx: device id %x%s\n", + devs[i], devid, version == 1 ? " (legacy)" : ""); + switch (devid) { + case 2: /* blk */ + /* TODO */ + break; + case 8: /* scsi */ + /* TODO */ + break; + default: + break; + } + } +} + +void vp_init_mmio(struct vp_device *vp, void *mmio) +{ + memset(vp, 0, sizeof(*vp)); + vp->use_mmio = 1; + vp->common.mode = VP_ACCESS_MMIO; + vp->common.memaddr = mmio; + vp->device.mode = VP_ACCESS_MMIO; + vp->device.memaddr = mmio + 0x100; + vp_reset(vp); + vp_set_status(vp, VIRTIO_CONFIG_S_ACKNOWLEDGE | + VIRTIO_CONFIG_S_DRIVER); +}