[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Qemu-devel] [PATCH] virtio-net: count VIRTIO_NET_F_MAC when calcula
From: |
Michael S. Tsirkin |
Subject: |
Re: [Qemu-devel] [PATCH] virtio-net: count VIRTIO_NET_F_MAC when calculating config_len |
Date: |
Mon, 29 Apr 2013 23:09:52 +0300 |
On Mon, Apr 29, 2013 at 08:45:50PM +0200, KONRAD Frédéric wrote:
> On 29/04/2013 20:15, Michael S. Tsirkin wrote:
>
> On Mon, Apr 29, 2013 at 08:01:52PM +0200, KONRAD Frédéric wrote:
>
> On 29/04/2013 19:52, Michael S. Tsirkin wrote:
>
> On Mon, Apr 29, 2013 at 07:23:49PM +0200, KONRAD Frédéric wrote:
>
> On 29/04/2013 19:01, Michael S. Tsirkin wrote:
>
> On Mon, Apr 29, 2013 at 06:41:08PM +0200, KONRAD Frédéric
> wrote:
>
> On 29/04/2013 18:30, Michael S. Tsirkin wrote:
>
> On Mon, Apr 29, 2013 at 07:21:06PM +0300, Michael
> S. Tsirkin wrote:
>
> On Mon, Apr 29, 2013 at 06:14:41PM +0200,
> KONRAD Frédéric wrote:
>
> On 29/04/2013 18:02, Michael S. Tsirkin
> wrote:
>
> On Mon, Apr 29, 2013 at 10:55:36AM
> -0500, Jesse Larrew wrote:
>
> On 04/29/2013 10:29 AM, KONRAD
> Frédéric wrote:
>
> On 29/04/2013 17:14, Jesse
> Larrew wrote:
>
> On 04/29/2013 09:55 AM,
> KONRAD Frédéric wrote:
>
> On 29/04/2013 16:42,
> Jesse Larrew wrote:
>
> On 04/25/2013 01:59
> AM, Michael S. Tsirkin wrote:
>
> On Thu, Apr 25, 2013
> at 02:21:29PM +0800, Jason Wang wrote:
>
> Commit 14f9b664
> (hw/virtio-net.c: set config size using host features) tries to
> calculate config size
> based on the host features. But it forgets the
> VIRTIO_NET_F_MAC were
> always set for qemu later. This will lead a zero config
> len for virtio-net
> device when both VIRTIO_NET_F_STATUS and VIRTIO_NET_F_MQ were
> disabled form command
> line. Then qemu will crash when user tries to read the
> config of virtio-net.
>
> Fix this by counting
> VIRTIO_NET_F_MAC and make sure the config at least contains
> the mac address.
>
> Cc: Jesse Larrew
> <address@hidden>
> Signed-off-by: Jason
> Wang <address@hidden>
> ---
>
> hw/net/virtio-net.c | 3 ++-
> 1 files changed, 2
> insertions(+), 1 deletions(-)
>
> diff --git
> a/hw/net/virtio-net.c b/hw/net/virtio-net.c
> index
> 70c8fce..33a70ef 100644
> ---
> a/hw/net/virtio-net.c
> +++
> b/hw/net/virtio-net.c
> @@ -1264,7 +1264,8 @@
> static void virtio_net_guest_notifier_mask(VirtIODevice *vdev, int idx,
> void
> virtio_net_set_config_size(VirtIONet *n, uint32_t host_features)
> {
> - int i,
> config_size = 0;
> + /*
> VIRTIO_NET_F_MAC can't be disabled from qemu side */
> + int i,
> config_size = feature_sizes[0].end;
>
> This would be cleaner:
> host_features |=
> (1 << VIRTIO_NET_F_MAC);
>
> no need for a comment
> then.
>
>
> It seems to me that
> the real problem here is that host_features isn't
> properly populated
> before virtio_net_set_config_size() is called. Looking
> at
> virtio_device_init(), we can see why:
>
> static int
> virtio_device_init(DeviceState *qdev)
> {
> VirtIODevice
> *vdev = VIRTIO_DEVICE(qdev);
>
> VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(qdev);
> assert(k->init
> != NULL);
> if
> (k->init(vdev) < 0) {
> return -1;
> }
>
> virtio_bus_plug_device(vdev);
> return 0;
> }
>
>
> virtio_net_set_config_size() is currently being called as part of the
> k->init call, but the
> host_features aren't properly setup until the device
> is plugged into the
> bus using virtio_bus_plug_device().
>
> After talking with
> mdroth, I think the proper way to fix this would be to
> extend
> VirtioDeviceClass to include a calculate_config_size() method that
> can be called at the
> appropriate time during device initialization like so:
>
> static int
> virtio_device_init(DeviceState *qdev)
> {
> VirtIODevice
> *vdev = VIRTIO_DEVICE(qdev);
>
> VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(qdev);
> assert(k->init
> != NULL);
> if
> (k->init(vdev) < 0) {
> return -1;
> }
>
> virtio_bus_plug_device(vdev);
> + if
> (k->calculate_config_size && k->calculate_config_size(vdev) < 0) {
> + return -1;
> + }
> return 0;
> }
>
> This would ensure
> that host_features contains the proper data before any
> devices try to make
> use of it to calculate the config size.
>
> Good point, I didn't
> saw that.
>
> but this was not the
> case with commit 14f9b664 no?
>
>
> I suspect this bug was
> present in 14f9b664 as well. We just hadn't triggered
> it yet. I'll confirm this
> afternoon.
>
> Ok, I think there is a
> problem with your patch:
>
>
> virtio_init(VIRTIO_DEVICE(n), "virtio-net", VIRTIO_ID_NET,
>
> n->config_size);
>
> is called in
> virtio_net_device_init (k->init).
>
> Is there a way to resize the
> config after that?
>
>
> Nope. That's definitely a bug. I
> can send a patch to fix this today. Any
> objection to the method suggested
> above (extending VirtioDeviceClass)?
>
> This needs more thought. All devices
> expected everything
> is setup during the init call. config
> size is
> likely not the only issue.
>
> So we need almost all of
> virtio_bus_plug_device before init,
> and then after init send the signal:
>
> if (klass->device_plugged !=
> NULL) {
>
> klass->device_plugged(qbus->parent);
> }
>
> Seems the interesting part is in
> virtio_pci_device_plugged at the end:
>
> proxy->host_features |= 0x1 <<
> VIRTIO_F_NOTIFY_ON_EMPTY;
> proxy->host_features |= 0x1 <<
> VIRTIO_F_BAD_FEATURE;
> proxy->host_features =
> virtio_bus_get_vdev_features(bus,
> proxy->host_features);
>
> This is and was called after
> set_config_size, isn't that the issue?
>
> Basically devices expected everything to be
> setup at
> the point where init is called.
> We found one bug but let's fix it properly.
> There's no reason to delay parts of setup
> until after init,
> if we do, we'll trip on more uses of
> uninitialized data.
>
>
> for (i = 0;
> feature_sizes[i].flags != 0; i++) {
> if
> (host_features & feature_sizes[i].flags) {
>
> config_size = MAX(feature_sizes[i].end, config_size);
> --
> 1.7.1
>
> Jesse Larrew
> Software Engineer, KVM
> Team
> IBM Linux Technology
> Center
> Phone: (512) 973-2052
> (T/L: 363-2052)
> address@hidden
>
>
> --
>
> Jesse Larrew
> Software Engineer, KVM Team
> IBM Linux Technology Center
> Phone: (512) 973-2052 (T/L:
> 363-2052)
> address@hidden
>
> Basically this is what I propose. Warning!
> compile-tested
> only. (I also dropped an unused return value).
>
>
> Signed-off-by: Michael S. Tsirkin <address@hidden>
>
> Which tree are you using? Is it up to date?
>
> Heh, more changes came in. So now, it's even simpler:
>
> Signed-off-by: Michael S. Tsirkin <address@hidden>
>
> ---
>
> diff --git a/hw/virtio/virtio-bus.c
> b/hw/virtio/virtio-bus.c
> index aab72ff..447ba16 100644
> --- a/hw/virtio/virtio-bus.c
> +++ b/hw/virtio/virtio-bus.c
> @@ -38,7 +38,7 @@ do { printf("virtio_bus: " fmt , ##
> __VA_ARGS__); } while (0)
> #endif
>
> /* Plug the VirtIODevice */
> -int virtio_bus_plug_device(VirtIODevice *vdev)
> +void virtio_bus_plug_device(VirtIODevice *vdev)
> {
> DeviceState *qdev = DEVICE(vdev);
> BusState *qbus = BUS(qdev_get_parent_bus(qdev));
> @@ -51,8 +51,6 @@ int virtio_bus_plug_device(VirtIODevice
> *vdev)
> if (klass->device_plugged != NULL) {
> klass->device_plugged(qbus->parent);
> }
> -
> - return 0;
> }
>
> /* Reset the virtio_bus */
> diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
> index 0f88c25..c5228e6 100644
> --- a/hw/virtio/virtio.c
> +++ b/hw/virtio/virtio.c
> @@ -1091,11 +1091,11 @@ static int
> virtio_device_init(DeviceState *qdev)
> {
> VirtIODevice *vdev = VIRTIO_DEVICE(qdev);
> VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(qdev);
> + virtio_bus_plug_device(vdev);
> assert(k->init != NULL);
> if (k->init(vdev) < 0) {
> return -1;
> }
> - virtio_bus_plug_device(vdev);
> return 0;
> }
>
>
> Not sure this is what you want to do.
> The device would be plugged before it is inited :/.
>
> I think this is exacly what we want to do.
> In fact, this is what other buses do, because
> devices simply can't init properly if they
> do not know on which bus they reside.
>
> E.g. with pci:
> do_pci_register_device (adds device on bus)
> init
>
> We can add an analog of hotplug bus callback
> if bus wants to get notified after device initialization.
> I don't see a need for this though.
> Do you?
>
>
>
>
> No, as we don't want to allow virtio-device hotplug.
>
> but look at the plugged callback in virtio-pci:
>
> pci_set_word(config + PCI_SUBSYSTEM_ID,
> virtio_bus_get_vdev_id(bus));
>
> proxy->host_features = virtio_bus_get_vdev_features(bus,
> proxy->host_features);
>
> are impossible before the virtio-net init.
>
>
> At this point I have to admit I don't understand what's
> going on any more.
>
> virtio_net_instance_init sets config size to
> some value, then virtio_net_set_config_size overrides it...
> Help!
>
> I am guessing it's this hack that backfires somehow.
>
>
>
> It would be interferring if virtio_net_set_config_size was not called.
>
> The best I think is to set the config size in the virtio_net_init function,
> then remove the instance init.
>
> The issue is that in the init function, the host_feature is not completely
> computed:
>
> it lacks the three line in virtio pci plugged function.
>
> Maybe we can move the two firsts line in the virtio_net_pci_init before the
> init if they are usefull in the
> config_size computing:
>
>
> proxy->host_features |= 0x1 << VIRTIO_F_NOTIFY_ON_EMPTY;
> proxy->host_features |= 0x1 << VIRTIO_F_BAD_FEATURE;
Bus can set VIRTIO_F_NOTIFY_ON_EMPTY and VIRTIO_F_BAD_FEATURE
later, this is not going to affect anything.
Reason is, VIRTIO_F_NOTIFY_ON_EMPTY and VIRTIO_F_BAD_FEATURE
are compatibility hacks which is why we dont
have them for s390. It's probably a bug that
we have them for virtio-ccw.
>
> Then compute the last one directly in the init function which is the harder:
>
> virtio_net_get_features
The real fix is to set features in init.
Can we move host_features to struct VirtIODevice, and
init to the device init function?
The reason we didn't do this initially is exactly
because we need to specify them in -device flag,
and there was no way to do this for VirtIODevice,
since it's the proxy that is instanciated.
Does the new bus infrastructure allow this?
> Note that there is in virtio_net_get_features:
>
> features |= (1 << VIRTIO_NET_F_MAC);
>
> Which is exacty the issue the initial patch is solving.
>
> Fred
Yes. the lifetime of host features is as follows:
- configured in device by user, mostly set to "on" by default
- depending on device specific logic,
override some features - mostly to "off",
but we also force some required features to "on"
- Two exceptions (notify on empty+bad) are transport
specific. they are also not user-controllable.
--
MST
- Re: [Qemu-devel] [PATCH] virtio-net: count VIRTIO_NET_F_MAC when calculating config_len, (continued)
- Re: [Qemu-devel] [PATCH] virtio-net: count VIRTIO_NET_F_MAC when calculating config_len, KONRAD Frédéric, 2013/04/29
- Re: [Qemu-devel] [PATCH] virtio-net: count VIRTIO_NET_F_MAC when calculating config_len, Michael S. Tsirkin, 2013/04/29
- Re: [Qemu-devel] [PATCH] virtio-net: count VIRTIO_NET_F_MAC when calculating config_len, Michael S. Tsirkin, 2013/04/29
- Re: [Qemu-devel] [PATCH] virtio-net: count VIRTIO_NET_F_MAC when calculating config_len, KONRAD Frédéric, 2013/04/29
- Re: [Qemu-devel] [PATCH] virtio-net: count VIRTIO_NET_F_MAC when calculating config_len, Michael S. Tsirkin, 2013/04/29
- Re: [Qemu-devel] [PATCH] virtio-net: count VIRTIO_NET_F_MAC when calculating config_len, KONRAD Frédéric, 2013/04/29
- Re: [Qemu-devel] [PATCH] virtio-net: count VIRTIO_NET_F_MAC when calculating config_len, Michael S. Tsirkin, 2013/04/29
- Re: [Qemu-devel] [PATCH] virtio-net: count VIRTIO_NET_F_MAC when calculating config_len, KONRAD Frédéric, 2013/04/29
- Re: [Qemu-devel] [PATCH] virtio-net: count VIRTIO_NET_F_MAC when calculating config_len, Michael S. Tsirkin, 2013/04/29
- Re: [Qemu-devel] [PATCH] virtio-net: count VIRTIO_NET_F_MAC when calculating config_len, KONRAD Frédéric, 2013/04/29
- Re: [Qemu-devel] [PATCH] virtio-net: count VIRTIO_NET_F_MAC when calculating config_len,
Michael S. Tsirkin <=
- Re: [Qemu-devel] [PATCH] virtio-net: count VIRTIO_NET_F_MAC when calculating config_len, KONRAD Frédéric, 2013/04/30
- Re: [Qemu-devel] [PATCH] virtio-net: count VIRTIO_NET_F_MAC when calculating config_len, Michael S. Tsirkin, 2013/04/30