From patchwork Mon Dec 21 15:26:56 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Michael S. Tsirkin" X-Patchwork-Id: 41557 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [199.232.76.165]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id C8DA9B6EF0 for ; Tue, 22 Dec 2009 02:33:23 +1100 (EST) Received: from localhost ([127.0.0.1]:37332 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1NMkG4-0008OH-B8 for incoming@patchwork.ozlabs.org; Mon, 21 Dec 2009 10:33:16 -0500 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1NMkCh-0007BC-Qm for qemu-devel@nongnu.org; Mon, 21 Dec 2009 10:29:47 -0500 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1NMkCd-00079R-T8 for qemu-devel@nongnu.org; Mon, 21 Dec 2009 10:29:47 -0500 Received: from [199.232.76.173] (port=34608 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1NMkCd-00079N-Pk for qemu-devel@nongnu.org; Mon, 21 Dec 2009 10:29:43 -0500 Received: from mx1.redhat.com ([209.132.183.28]:20722) by monty-python.gnu.org with esmtp (Exim 4.60) (envelope-from ) id 1NMkCd-0007fk-4a for qemu-devel@nongnu.org; Mon, 21 Dec 2009 10:29:43 -0500 Received: from int-mx02.intmail.prod.int.phx2.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) by mx1.redhat.com (8.13.8/8.13.8) with ESMTP id nBLFTfKu003361 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Mon, 21 Dec 2009 10:29:41 -0500 Received: from redhat.com (vpn-6-201.tlv.redhat.com [10.35.6.201]) by int-mx02.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id nBLFTdxh007982; Mon, 21 Dec 2009 10:29:39 -0500 Date: Mon, 21 Dec 2009 17:26:56 +0200 From: "Michael S. Tsirkin" To: qemu-devel@nongnu.org, Anthony Liguori , kraxel@redhat.com Message-ID: <20091221152655.GC10095@redhat.com> References: MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.5.19 (2009-01-05) X-Scanned-By: MIMEDefang 2.67 on 10.5.11.12 X-detected-operating-system: by monty-python.gnu.org: Genre and OS details not recognized. Cc: Subject: [Qemu-devel] [PATCHv2-RFC 2/2] virtio: add features as qdev properties X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Add feature bits as properties to virtio. This makes it possible to e.g. define machine without indirect buffer support, which is required for 0.10 compatibility, or without hardware checksum support, which is required for 0.11 compatibility. Since default values for optional features are now set by qdev, get_features callback has been modified: it sets non-optional bits, and clears bits not supported by host. Signed-off-by: Michael S. Tsirkin --- hw/syborg_virtio.c | 12 +++++++----- hw/virtio-balloon.c | 4 ++-- hw/virtio-blk.c | 10 +++------- hw/virtio-blk.h | 10 ++++++++++ hw/virtio-console.c | 4 ++-- hw/virtio-net.c | 39 ++++++++++++++++----------------------- hw/virtio-net.h | 20 ++++++++++++++++++++ hw/virtio-pci.c | 25 +++++++++++++++++-------- hw/virtio.c | 2 +- hw/virtio.h | 7 ++++++- 10 files changed, 84 insertions(+), 49 deletions(-) diff --git a/hw/syborg_virtio.c b/hw/syborg_virtio.c index fe6fc23..b3c2734 100644 --- a/hw/syborg_virtio.c +++ b/hw/syborg_virtio.c @@ -66,6 +66,7 @@ typedef struct { uint32_t int_enable; uint32_t id; NICConf nic; + uint32_t host_features; } SyborgVirtIOProxy; static uint32_t syborg_virtio_readl(void *opaque, target_phys_addr_t offset) @@ -86,8 +87,7 @@ static uint32_t syborg_virtio_readl(void *opaque, target_phys_addr_t offset) ret = s->id; break; case SYBORG_VIRTIO_HOST_FEATURES: - ret = vdev->get_features(vdev); - ret |= vdev->binding->get_features(s); + ret = s->host_features; break; case SYBORG_VIRTIO_GUEST_FEATURES: ret = vdev->guest_features; @@ -244,9 +244,8 @@ static void syborg_virtio_update_irq(void *opaque, uint16_t vector) static unsigned syborg_virtio_get_features(void *opaque) { - unsigned ret = 0; - ret |= (1 << VIRTIO_F_NOTIFY_ON_EMPTY); - return ret; + SyborgVirtIOProxy *proxy = opaque; + return proxy->host_features; } static VirtIOBindings syborg_virtio_bindings = { @@ -272,6 +271,8 @@ static int syborg_virtio_init(SyborgVirtIOProxy *proxy, VirtIODevice *vdev) qemu_register_reset(virtio_reset, vdev); virtio_bind_device(vdev, &syborg_virtio_bindings, proxy); + proxy->host_features |= (0x1 << VIRTIO_F_NOTIFY_ON_EMPTY); + proxy->host_features = vdev->get_features(vdev, proxy->host_features); return 0; } @@ -292,6 +293,7 @@ static SysBusDeviceInfo syborg_virtio_net_info = { .qdev.size = sizeof(SyborgVirtIOProxy), .qdev.props = (Property[]) { DEFINE_NIC_PROPERTIES(SyborgVirtIOProxy, nic), + DEFINE_VIRTIO_NET_FEATURES(SyborgVirtIOProxy, host_features), DEFINE_PROP_END_OF_LIST(), } }; diff --git a/hw/virtio-balloon.c b/hw/virtio-balloon.c index cfd3b41..e17880f 100644 --- a/hw/virtio-balloon.c +++ b/hw/virtio-balloon.c @@ -124,9 +124,9 @@ static void virtio_balloon_set_config(VirtIODevice *vdev, dev->actual = config.actual; } -static uint32_t virtio_balloon_get_features(VirtIODevice *vdev) +static uint32_t virtio_balloon_get_features(VirtIODevice *vdev, uint32_t f) { - return 0; + return f; } static ram_addr_t virtio_balloon_to_target(void *opaque, ram_addr_t target) diff --git a/hw/virtio-blk.c b/hw/virtio-blk.c index a2f0639..72970ef 100644 --- a/hw/virtio-blk.c +++ b/hw/virtio-blk.c @@ -432,19 +432,15 @@ static void virtio_blk_update_config(VirtIODevice *vdev, uint8_t *config) memcpy(config, &blkcfg, s->config_size); } -static uint32_t virtio_blk_get_features(VirtIODevice *vdev) +static uint32_t virtio_blk_get_features(VirtIODevice *vdev, uint32_t features) { VirtIOBlock *s = to_virtio_blk(vdev); - uint32_t features = 0; features |= (1 << VIRTIO_BLK_F_SEG_MAX); features |= (1 << VIRTIO_BLK_F_GEOMETRY); - if (bdrv_enable_write_cache(s->bs)) - features |= (1 << VIRTIO_BLK_F_WCACHE); -#ifdef __linux__ - features |= (1 << VIRTIO_BLK_F_SCSI); -#endif + if (!bdrv_enable_write_cache(s->bs)) + features &= ~(1 << VIRTIO_BLK_F_WCACHE); if (strcmp(s->serial_str, "0")) features |= 1 << VIRTIO_BLK_F_IDENTIFY; diff --git a/hw/virtio-blk.h b/hw/virtio-blk.h index 23ad74c..3dee5c2 100644 --- a/hw/virtio-blk.h +++ b/hw/virtio-blk.h @@ -92,4 +92,14 @@ struct virtio_scsi_inhdr uint32_t residual; }; +#ifdef __linux__ +#define DEFINE_VIRTIO_BLK_FEATURES(_state, _field) \ + DEFINE_VIRTIO_COMMON_FEATURES(_state, _field), \ + DEFINE_PROP_BIT("scsi", _state, _field, VIRTIO_BLK_F_SCSI, true), \ + DEFINE_PROP_BIT("wcache", _state, _field, VIRTIO_BLK_F_WCACHE, true) +#else +#define DEFINE_VIRTIO_BLK_FEATURES(_state, _field) \ + DEFINE_VIRTIO_COMMON_FEATURES(_state, _field), \ + DEFINE_PROP_BIT("wcache", _state, _field, VIRTIO_BLK_F_WCACHE, true) +#endif #endif diff --git a/hw/virtio-console.c b/hw/virtio-console.c index 57f8f89..4f18ef2 100644 --- a/hw/virtio-console.c +++ b/hw/virtio-console.c @@ -51,9 +51,9 @@ static void virtio_console_handle_input(VirtIODevice *vdev, VirtQueue *vq) { } -static uint32_t virtio_console_get_features(VirtIODevice *vdev) +static uint32_t virtio_console_get_features(VirtIODevice *vdev, uint32_t f) { - return 0; + return f; } static int vcon_can_read(void *opaque) diff --git a/hw/virtio-net.c b/hw/virtio-net.c index ab20a33..c2a389f 100644 --- a/hw/virtio-net.c +++ b/hw/virtio-net.c @@ -147,34 +147,27 @@ static int peer_has_ufo(VirtIONet *n) return n->has_ufo; } -static uint32_t virtio_net_get_features(VirtIODevice *vdev) +static uint32_t virtio_net_get_features(VirtIODevice *vdev, uint32_t features) { VirtIONet *n = to_virtio_net(vdev); - uint32_t features = (1 << VIRTIO_NET_F_MAC) | - (1 << VIRTIO_NET_F_MRG_RXBUF) | - (1 << VIRTIO_NET_F_STATUS) | - (1 << VIRTIO_NET_F_CTRL_VQ) | - (1 << VIRTIO_NET_F_CTRL_RX) | - (1 << VIRTIO_NET_F_CTRL_VLAN) | - (1 << VIRTIO_NET_F_CTRL_RX_EXTRA); if (peer_has_vnet_hdr(n)) { tap_using_vnet_hdr(n->nic->nc.peer, 1); + } else { + features &= ~(0x1 << VIRTIO_NET_F_CSUM); + features &= ~(0x1 << VIRTIO_NET_F_HOST_TSO4); + features &= ~(0x1 << VIRTIO_NET_F_HOST_TSO6); + features &= ~(0x1 << VIRTIO_NET_F_HOST_ECN); + + features &= ~(0x1 << VIRTIO_NET_F_GUEST_CSUM); + features &= ~(0x1 << VIRTIO_NET_F_GUEST_TSO4); + features &= ~(0x1 << VIRTIO_NET_F_GUEST_TSO6); + features &= ~(0x1 << VIRTIO_NET_F_GUEST_ECN); + } - features |= (1 << VIRTIO_NET_F_CSUM); - features |= (1 << VIRTIO_NET_F_HOST_TSO4); - features |= (1 << VIRTIO_NET_F_HOST_TSO6); - features |= (1 << VIRTIO_NET_F_HOST_ECN); - - features |= (1 << VIRTIO_NET_F_GUEST_CSUM); - features |= (1 << VIRTIO_NET_F_GUEST_TSO4); - features |= (1 << VIRTIO_NET_F_GUEST_TSO6); - features |= (1 << VIRTIO_NET_F_GUEST_ECN); - - if (peer_has_ufo(n)) { - features |= (1 << VIRTIO_NET_F_GUEST_UFO); - features |= (1 << VIRTIO_NET_F_HOST_UFO); - } + if (!peer_has_vnet_hdr(n) || !peer_has_ufo(n)) { + features &= ~(0x1 << VIRTIO_NET_F_GUEST_UFO); + features &= ~(0x1 << VIRTIO_NET_F_HOST_UFO); } return features; @@ -192,7 +185,7 @@ static uint32_t virtio_net_bad_features(VirtIODevice *vdev) features |= (1 << VIRTIO_NET_F_HOST_TSO6); features |= (1 << VIRTIO_NET_F_HOST_ECN); - return features & virtio_net_get_features(vdev); + return features; } static void virtio_net_set_features(VirtIODevice *vdev, uint32_t features) diff --git a/hw/virtio-net.h b/hw/virtio-net.h index 2085181..9130d75 100644 --- a/hw/virtio-net.h +++ b/hw/virtio-net.h @@ -153,4 +153,24 @@ struct virtio_net_ctrl_mac { #define VIRTIO_NET_CTRL_VLAN_ADD 0 #define VIRTIO_NET_CTRL_VLAN_DEL 1 +#define DEFINE_VIRTIO_NET_FEATURES(_state, _field) \ + DEFINE_VIRTIO_COMMON_FEATURES(_state, _field), \ + DEFINE_PROP_BIT("csum", _state, _field, VIRTIO_NET_F_CSUM, true), \ + DEFINE_PROP_BIT("guest_csum", _state, _field, VIRTIO_NET_F_GUEST_CSUM, true), \ + DEFINE_PROP_BIT("mac", _state, _field, VIRTIO_NET_F_MAC, true), \ + DEFINE_PROP_BIT("gso", _state, _field, VIRTIO_NET_F_GSO, true), \ + DEFINE_PROP_BIT("guest_tso4", _state, _field, VIRTIO_NET_F_GUEST_TSO4, true), \ + DEFINE_PROP_BIT("guest_tso6", _state, _field, VIRTIO_NET_F_GUEST_TSO6, true), \ + DEFINE_PROP_BIT("guest_ecn", _state, _field, VIRTIO_NET_F_GUEST_ECN, true), \ + DEFINE_PROP_BIT("guest_ufo", _state, _field, VIRTIO_NET_F_GUEST_UFO, true), \ + DEFINE_PROP_BIT("host_tso4", _state, _field, VIRTIO_NET_F_HOST_TSO4, true), \ + DEFINE_PROP_BIT("host_tso6", _state, _field, VIRTIO_NET_F_HOST_TSO6, true), \ + DEFINE_PROP_BIT("host_ecn", _state, _field, VIRTIO_NET_F_HOST_ECN, true), \ + DEFINE_PROP_BIT("host_ufo", _state, _field, VIRTIO_NET_F_HOST_UFO, true), \ + DEFINE_PROP_BIT("mrg_rxbuf", _state, _field, VIRTIO_NET_F_MRG_RXBUF, true), \ + DEFINE_PROP_BIT("status", _state, _field, VIRTIO_NET_F_STATUS, true), \ + DEFINE_PROP_BIT("ctrl_vq", _state, _field, VIRTIO_NET_F_CTRL_VQ, true), \ + DEFINE_PROP_BIT("ctrl_rx", _state, _field, VIRTIO_NET_F_CTRL_RX, true), \ + DEFINE_PROP_BIT("ctrl_vlan", _state, _field, VIRTIO_NET_F_CTRL_VLAN, true), \ + DEFINE_PROP_BIT("ctrl_rx_extra", _state, _field, VIRTIO_NET_F_CTRL_RX_EXTRA, true) #endif diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c index 80bc645..891f5cc 100644 --- a/hw/virtio-pci.c +++ b/hw/virtio-pci.c @@ -16,6 +16,8 @@ #include #include "virtio.h" +#include "virtio-blk.h" +#include "virtio-net.h" #include "pci.h" #include "sysemu.h" #include "msix.h" @@ -92,6 +94,7 @@ typedef struct { uint32_t nvectors; DriveInfo *dinfo; NICConf nic; + uint32_t host_features; } VirtIOPCIProxy; /* virtio device */ @@ -175,7 +178,7 @@ static void virtio_ioport_write(void *opaque, uint32_t addr, uint32_t val) /* Guest does not negotiate properly? We have to assume nothing. */ if (val & (1 << VIRTIO_F_BAD_FEATURE)) { if (vdev->bad_features) - val = vdev->bad_features(vdev); + val = proxy->host_features & vdev->bad_features(vdev); else val = 0; } @@ -235,8 +238,7 @@ static uint32_t virtio_ioport_read(VirtIOPCIProxy *proxy, uint32_t addr) switch (addr) { case VIRTIO_PCI_HOST_FEATURES: - ret = vdev->get_features(vdev); - ret |= vdev->binding->get_features(proxy); + ret = proxy->host_features; break; case VIRTIO_PCI_GUEST_FEATURES: ret = vdev->guest_features; @@ -382,11 +384,8 @@ static void virtio_write_config(PCIDevice *pci_dev, uint32_t address, static unsigned virtio_pci_get_features(void *opaque) { - unsigned ret = 0; - ret |= (1 << VIRTIO_F_NOTIFY_ON_EMPTY); - ret |= (1 << VIRTIO_RING_F_INDIRECT_DESC); - ret |= (1 << VIRTIO_F_BAD_FEATURE); - return ret; + VirtIOPCIProxy *proxy = opaque; + return proxy->host_features; } static const VirtIOBindings virtio_pci_bindings = { @@ -442,6 +441,9 @@ static void virtio_init_pci(VirtIOPCIProxy *proxy, VirtIODevice *vdev, virtio_map); virtio_bind_device(vdev, &virtio_pci_bindings, proxy); + proxy->host_features |= 0x1 << VIRTIO_F_NOTIFY_ON_EMPTY; + proxy->host_features |= 0x1 << VIRTIO_F_BAD_FEATURE; + proxy->host_features = vdev->get_features(vdev, proxy->host_features); } static int virtio_blk_init_pci(PCIDevice *pci_dev) @@ -561,6 +563,7 @@ static PCIDeviceInfo virtio_info[] = { DEFINE_PROP_HEX32("class", VirtIOPCIProxy, class_code, 0), DEFINE_PROP_DRIVE("drive", VirtIOPCIProxy, dinfo), DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 2), + DEFINE_VIRTIO_BLK_FEATURES(VirtIOPCIProxy, host_features), DEFINE_PROP_END_OF_LIST(), }, .qdev.reset = virtio_pci_reset, @@ -571,6 +574,7 @@ static PCIDeviceInfo virtio_info[] = { .exit = virtio_net_exit_pci, .qdev.props = (Property[]) { DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 3), + DEFINE_VIRTIO_NET_FEATURES(VirtIOPCIProxy, host_features), DEFINE_NIC_PROPERTIES(VirtIOPCIProxy, nic), DEFINE_PROP_END_OF_LIST(), }, @@ -582,6 +586,7 @@ static PCIDeviceInfo virtio_info[] = { .exit = virtio_exit_pci, .qdev.props = (Property[]) { DEFINE_PROP_HEX32("class", VirtIOPCIProxy, class_code, 0), + DEFINE_VIRTIO_COMMON_FEATURES(VirtIOPCIProxy, host_features), DEFINE_PROP_END_OF_LIST(), }, .qdev.reset = virtio_pci_reset, @@ -590,6 +595,10 @@ static PCIDeviceInfo virtio_info[] = { .qdev.size = sizeof(VirtIOPCIProxy), .init = virtio_balloon_init_pci, .exit = virtio_exit_pci, + .qdev.props = (Property[]) { + DEFINE_VIRTIO_COMMON_FEATURES(VirtIOPCIProxy, host_features), + DEFINE_PROP_END_OF_LIST(), + }, .qdev.reset = virtio_pci_reset, },{ /* end of list */ diff --git a/hw/virtio.c b/hw/virtio.c index f01548e..3c609ce 100644 --- a/hw/virtio.c +++ b/hw/virtio.c @@ -650,7 +650,7 @@ int virtio_load(VirtIODevice *vdev, QEMUFile *f) { int num, i, ret; uint32_t features; - uint32_t supported_features = vdev->get_features(vdev) | + uint32_t supported_features = vdev->binding->get_features(vdev->binding_opaque); if (vdev->binding->load_config) { diff --git a/hw/virtio.h b/hw/virtio.h index 85ef171..3994cc9 100644 --- a/hw/virtio.h +++ b/hw/virtio.h @@ -105,7 +105,7 @@ struct VirtIODevice void *config; uint16_t config_vector; int nvectors; - uint32_t (*get_features)(VirtIODevice *vdev); + uint32_t (*get_features)(VirtIODevice *vdev, uint32_t requested_features); uint32_t (*bad_features)(VirtIODevice *vdev); void (*set_features)(VirtIODevice *vdev, uint32_t val); void (*get_config)(VirtIODevice *vdev, uint8_t *config); @@ -176,4 +176,9 @@ VirtIODevice *virtio_balloon_init(DeviceState *dev); void virtio_net_exit(VirtIODevice *vdev); +#define DEFINE_VIRTIO_COMMON_FEATURES(_state, _field) \ + DEFINE_PROP_BIT("indirect_desc", _state, _field, \ + VIRTIO_RING_F_INDIRECT_DESC, true) + + #endif