diff mbox series

[RFC,33/34] vmbus: add support for rom files

Message ID 20180206203048.11096-34-rkagan@virtuozzo.com
State New
Headers show
Series Hyper-V / VMBus | expand

Commit Message

Roman Kagan Feb. 6, 2018, 8:30 p.m. UTC
In order to leverage third-party drivers for VMBus devices in firmware
(in particular, there's a case with iPXE driver for hv-net in SeaBIOS
and OVMF), introduce an infrastructure to supply such drivers as option
ROMs.

To make it easy for the firmware to locate such ROMs, they are stored in
fw_cfg with names "vmbus/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx.rom" for
default class ROMs (where xxx... is the class GUID) and
"vmbus/dev/yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy.rom" for per-device
(i.e. specified via .romfile property) ROMs (where yyy... is the device
instance GUID).

The format and the calling convention for the ROMs is out of scope for
this patch: QEMU doesn't try to interpret them.

Signed-off-by: Roman Kagan <rkagan@virtuozzo.com>
---
 include/hw/vmbus/vmbus.h |  3 +++
 hw/vmbus/vmbus.c         | 39 +++++++++++++++++++++++++++++++++++++++
 2 files changed, 42 insertions(+)

Comments

Paolo Bonzini Feb. 7, 2018, 11:18 a.m. UTC | #1
On 06/02/2018 21:30, Roman Kagan wrote:
> In order to leverage third-party drivers for VMBus devices in firmware
> (in particular, there's a case with iPXE driver for hv-net in SeaBIOS
> and OVMF), introduce an infrastructure to supply such drivers as option
> ROMs.
> 
> To make it easy for the firmware to locate such ROMs, they are stored in
> fw_cfg with names "vmbus/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx.rom" for
> default class ROMs (where xxx... is the class GUID) and
> "vmbus/dev/yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy.rom" for per-device
> (i.e. specified via .romfile property) ROMs (where yyy... is the device
> instance GUID).
> 
> The format and the calling convention for the ROMs is out of scope for
> this patch: QEMU doesn't try to interpret them.

Out of curiosity, do you have a SCSI driver for SeaBIOS and/or OVMF?

Thanks,

Paolo
Roman Kagan Feb. 7, 2018, 7:46 p.m. UTC | #2
On Wed, Feb 07, 2018 at 12:18:38PM +0100, Paolo Bonzini wrote:
> On 06/02/2018 21:30, Roman Kagan wrote:
> > In order to leverage third-party drivers for VMBus devices in firmware
> > (in particular, there's a case with iPXE driver for hv-net in SeaBIOS
> > and OVMF), introduce an infrastructure to supply such drivers as option
> > ROMs.
> > 
> > To make it easy for the firmware to locate such ROMs, they are stored in
> > fw_cfg with names "vmbus/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx.rom" for
> > default class ROMs (where xxx... is the class GUID) and
> > "vmbus/dev/yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy.rom" for per-device
> > (i.e. specified via .romfile property) ROMs (where yyy... is the device
> > instance GUID).
> > 
> > The format and the calling convention for the ROMs is out of scope for
> > this patch: QEMU doesn't try to interpret them.
> 
> Out of curiosity, do you have a SCSI driver for SeaBIOS and/or OVMF?

Yes, both, can be found at https://src.openvz.org/scm/up/seabios.git and
https://src.openvz.org/scm/up/edk2.git respectively (I mentioned that in
the cover letter).

Roman.
diff mbox series

Patch

diff --git a/include/hw/vmbus/vmbus.h b/include/hw/vmbus/vmbus.h
index cdb5180796..847edc08d7 100644
--- a/include/hw/vmbus/vmbus.h
+++ b/include/hw/vmbus/vmbus.h
@@ -49,6 +49,8 @@  typedef struct VMBusDeviceClass {
     int (*open_channel) (VMBusDevice *vdev);
     void (*close_channel) (VMBusDevice *vdev);
     VMBusChannelNotifyCb chan_notify_cb;
+
+    const char *romfile;
 } VMBusDeviceClass;
 
 typedef struct VMBusDevice {
@@ -57,6 +59,7 @@  typedef struct VMBusDevice {
     uint16_t num_channels;
     VMBusChannel *channels;
     AddressSpace *dma_as;
+    char *romfile;
 } VMBusDevice;
 
 extern const VMStateDescription vmstate_vmbus_dev;
diff --git a/hw/vmbus/vmbus.c b/hw/vmbus/vmbus.c
index 42d12dfdf6..c2aec004e7 100644
--- a/hw/vmbus/vmbus.c
+++ b/hw/vmbus/vmbus.c
@@ -12,6 +12,7 @@ 
 #include "qapi/error.h"
 #include "hw/vmbus/vmbus.h"
 #include "hw/sysbus.h"
+#include "hw/loader.h"
 #include "trace.h"
 
 #define TYPE_VMBUS "vmbus"
@@ -2061,6 +2062,36 @@  unmap:
     cpu_physical_memory_unmap(int_map, len, 1, is_dirty);
 }
 
+static void vmbus_install_rom(VMBusDevice *vdev)
+{
+    VMBusDeviceClass *vdc = VMBUS_DEVICE_GET_CLASS(vdev);
+    VMBus *vmbus = VMBUS(qdev_get_parent_bus(DEVICE(vdev)));
+    BusChild *child;
+    char uuid[UUID_FMT_LEN + 1];
+    char romname[10 + UUID_FMT_LEN + 4 + 1];
+
+    if (vdev->romfile) {
+        /* device-specific rom */
+        qemu_uuid_unparse(&vdc->instanceid, uuid);
+        snprintf(romname, sizeof(romname), "vmbus/dev/%s.rom", uuid);
+        rom_add_file(vdev->romfile, romname, 0, -1, true, NULL, NULL);
+    } else if (vdc->romfile) {
+        /* class-wide rom */
+        QTAILQ_FOREACH(child, &BUS(vmbus)->children, sibling) {
+            VMBusDevice *chlddev = VMBUS_DEVICE(child->child);
+
+            /* another device of the same class has already installed it */
+            if (chlddev != vdev && !chlddev->romfile &&
+                VMBUS_DEVICE_GET_CLASS(chlddev) == vdc) {
+                return;
+            }
+        }
+        qemu_uuid_unparse(&vdc->classid, uuid);
+        snprintf(romname, sizeof(romname), "vmbus/%s.rom", uuid);
+        rom_add_file(vdc->romfile, romname, 0, -1, true, NULL, NULL);
+    }
+}
+
 static void vmbus_dev_realize(DeviceState *dev, Error **errp)
 {
     VMBusDevice *vdev = VMBUS_DEVICE(dev);
@@ -2098,6 +2129,8 @@  static void vmbus_dev_realize(DeviceState *dev, Error **errp)
         goto error_out;
     }
 
+    vmbus_install_rom(vdev);
+
     if (vdc->vmdev_realize) {
         vdc->vmdev_realize(vdev, &err);
         if (err) {
@@ -2145,6 +2178,11 @@  static void vmbus_dev_unrealize(DeviceState *dev, Error **errp)
     free_channels(vmbus, vdev);
 }
 
+static Property vmbus_dev_props[] = {
+    DEFINE_PROP_STRING("romfile", VMBusDevice, romfile),
+    DEFINE_PROP_END_OF_LIST()
+};
+
 static void vmbus_dev_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *kdev = DEVICE_CLASS(klass);
@@ -2152,6 +2190,7 @@  static void vmbus_dev_class_init(ObjectClass *klass, void *data)
     kdev->realize = vmbus_dev_realize;
     kdev->unrealize = vmbus_dev_unrealize;
     kdev->reset = vmbus_dev_reset;
+    kdev->props = vmbus_dev_props;
 }
 
 static int vmbus_dev_post_load(void *opaque, int version_id)