virtio implementation (draft VI)
Subsystems (3)
cover virtio implementation (draft VI)
I'm not reposting the drivers this time since they haven't changed significantly. See http://lguest.ozlabs.org/patches for the whole thing, from new-io.patch onwards).
Changes since last version:
- Switch to our own bus implementation, rather than relying on an implementation-specific bus to back this up.
- Make virtio_config_ops much higher-level, don't assume layout of config space.
- Expose "struct virtqueue" again and move ops inside that.
- virtio_ring uses 64 bit address, 32 bit length, not addr64 + offset16 + len16.
- flags in virtio_ring to allow suppression of interrupts (by guest) or notifications (by host).
I'm not too unhappy with this as it stands. Feedback welcome!
Cheers,
Rusty.
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
A message that is not in the archive (sent off-list or not yet received): 1190625194.27805.199.camel-bi+AKbBUZKY6gyzm1THtWbp2dZbC/[email protected]
PATCH 1/3 virtio interface
This attempts to implement a "virtual I/O" layer which should allow common drivers to be efficiently used across most virtual I/O mechanisms. It will no-doubt need further enhancement.
The virtio drivers add buffers to virtio queues; as the buffers are consumed the driver "interrupt" callbacks are invoked.
There is also a generic implementation of config space which drivers can query to get setup information from the host.
--- drivers/Kconfig | 2 drivers/Makefile | 1 drivers/virtio/Kconfig | 3 drivers/virtio/Makefile | 1 drivers/virtio/config.c | 13 ++ drivers/virtio/virtio.c | 187 +++++++++++++++++++++++++++++++++++++++ include/linux/mod_devicetable.h | 6 + include/linux/virtio.h | 110 ++++++++++++++++++++++ include/linux/virtio_config.h | 111 +++++++++++++++++++++++ 9 files changed, 434 insertions(+)
===================================================================
drivers/Kconfig +2 -0
@@ -87,4 +87,6 @@ source "drivers/kvm/Kconfig" source "drivers/kvm/Kconfig" source "drivers/uio/Kconfig" + +source "drivers/virtio/Kconfig" endmenu
===================================================================
drivers/Makefile +1 -0
@@ -88,3 +88,4 @@ obj-$(CONFIG_HID) += hid/ obj-$(CONFIG_HID) += hid/ obj-$(CONFIG_PPC_PS3) += ps3/ obj-$(CONFIG_OF) += of/ +obj-$(CONFIG_VIRTIO) += virtio/
===================================================================
drivers/virtio/Kconfig new file +3 -0
@@ -0,0 +1,3 @@ +# Virtio always gets selected by whoever wants it. +config VIRTIO + bool
===================================================================
drivers/virtio/Makefile new file +1 -0
@@ -0,0 +1,1 @@ +obj-$(CONFIG_VIRTIO) += virtio.o
===================================================================
drivers/virtio/config.c new file +13 -0
@@ -0,0 +1,13 @@ +/* Configuration space parsing helpers for virtio. +* +* The configuration is [type][len][... len bytes ...] fields. +* +* Copyright 2007 Rusty Russell, IBM Corporation. +* GPL v2 or later. +*/ +#include <linux/err.h> +#include <linux/virtio.h> +#include <linux/virtio_config.h> +#include <linux/bug.h> +#include <asm/system.h> +
===================================================================
drivers/virtio/virtio.c new file +187 -0
187 lines not on this page · raw message
===================================================================
include/linux/mod_devicetable.h +6 -0
@@ -340,4 +340,10 @@ struct parisc_device_id {#define PA_HVERSION_ANY_ID 0xffff#define PA_SVERSION_ANY_ID 0xffffffff +struct virtio_device_id { +__u32 device; +__u32 vendor; +}; +#define VIRTIO_DEV_ANY_ID 0xffffffff +#endif /* LINUX_MOD_DEVICETABLE_H */
===================================================================
include/linux/virtio.h new file +110 -0
110 lines not on this page · raw message
===================================================================
include/linux/virtio_config.h new file +111 -0
111 lines not on this page · raw message
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
A message that is not in the archive (sent off-list or not yet received): 1190625256.27805.201.camel-bi+AKbBUZKY6gyzm1THtWbp2dZbC/[email protected]
PATCH 2/3 virtio ring implementation
These helper routines supply most of the virtqueue_ops for hypervisors which want to use a ring for virtio. Unlike the previous lguest implementation:
1) The rings are variable sized (2^n-1 elements).
2) They have an unfortunate limit of 65535 bytes per sg element.
3) The page numbers are always 64 bit (PAE anyone?)
4) They no longer place used[] on a separate page, just a separate cacheline.
5) We do a modulo on a variable. We could be tricky if we cared.
6) Interrupts and notifies are suppressed using flags within the rings.
Users need only implement the new_vq and free_vq hooks (KVM wants the guest to allocate the rings, lguest does it sanely).
--- arch/i386/lguest/Kconfig | 1 drivers/virtio/Kconfig | 5 drivers/virtio/Makefile | 1 drivers/virtio/virtio_ring.c | 316 ++++++++++++++++++++++++++++++++++++++++++ include/linux/virtio_ring.h | 119 +++++++++++++++ 5 files changed, 442 insertions(+)
===================================================================
arch/i386/lguest/Kconfig +1 -0
@@ -2,6 +2,7 @@ config LGUEST_GUEST bool "Lguest guest support" select PARAVIRT depends on !X86_PAE + select VIRTIO_RING help Lguest is a tiny in-kernel hypervisor. Selecting this will allow your kernel to boot under lguest. This option will increase
===================================================================
drivers/virtio/Kconfig +5 -0
@@ -1,3 +1,8 @@ # Virtio always gets selected by whoever wants it. config VIRTIO bool + +# Similarly the virtio ring implementation. +config VIRTIO_RING + bool + depends on VIRTIO
===================================================================
drivers/virtio/Makefile +1 -0
@@ -1,1 +1,2 @@ obj-$(CONFIG_VIRTIO) += virtio.o obj-$(CONFIG_VIRTIO) += virtio.o +obj-$(CONFIG_VIRTIO_RING) += virtio_ring.o
===================================================================
drivers/virtio/virtio_ring.c new file +316 -0
316 lines not on this page · raw message
===================================================================
include/linux/virtio_ring.h new file +119 -0
119 lines not on this page · raw message
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
A message that is not in the archive (sent off-list or not yet received): 1190625307.27805.203.camel-bi+AKbBUZKY6gyzm1THtWbp2dZbC/[email protected]
PATCH 3/3 virtio module alias support
This adds the logic to convert the virtio ids into module aliases, and includes a modalias entry in sysfs.
Unfortunately this does not seem sufficient to have the module autoprobed at startup on my Ubuntu system. Greg? Am I missing some udev magic?
--- drivers/virtio/virtio.c | 9 +++++++++ scripts/mod/file2alias.c | 18 ++++++++++++++++++ 2 files changed, 27 insertions(+)
===================================================================
drivers/virtio/virtio.c +9 -0
@@ -20,10 +20,19 @@ static ssize_t status_show(struct device struct virtio_device *dev = container_of(_d,struct virtio_device,dev);return sprintf (buf,"0x%08x" , dev->config->get_status (dev)); } +static ssize_t modalias_show (struct device *_d, +struct device_attribute *attr,char *buf) +{ + struct virtio_device *dev = container_of(_d,struct virtio_device,dev); + +return sprintf (buf,"virtio:d%08Xv%08X\n" , + dev->id.device, dev->id.vendor); +}static struct device_attribute virtio_dev_attrs[] = {__ATTR_RO (device),__ATTR_RO (vendor),__ATTR_RO (status), +__ATTR_RO (modalias), __ATTR_NULL };
===================================================================
scripts/mod/file2alias.c +18 -0
@@ -484,6 +484,20 @@ static int do_parisc_entry(const char *freturn 1 ; } +/* Looks like: virtio:dNvN */ +static int do_virtio_entry (const char *filename,struct virtio_device_id *id, +char *alias) +{ + id->device =TO_NATIVE (id->device); + id->vendor =TO_NATIVE (id->vendor); + +strcpy (alias,"virtio:" ); +ADD (alias,"d" ,1 , id->device); +ADD (alias,"v" , id->vendor !=VIRTIO_DEV_ANY_ID , id->vendor); + +return 1 ; +} +/* Ignore any prefix, eg. v850 prepends _ */ static inline int sym_is (const char *symbol,const char *name) {
@@ -599,6 +613,10 @@ void handle_moddevtable(struct module *mdo_table (symval, sym->st_size,sizeof (struct parisc_device_id ),"parisc" , do_parisc_entry, mod); + else if (sym_is(symname, "__mod_virtio_device_table")) + do_table(symval, sym->st_size, + sizeof(struct virtio_device_id), "virtio", + do_virtio_entry, mod); }/* Now add out buffered information to the generated C source */
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
A message that is not in the archive (sent off-list or not yet received): 1190625394.27805.206.camel-bi+AKbBUZKY6gyzm1THtWbp2dZbC/[email protected]
Re: [PATCH 3/3] virtio module alias support
Quoted 6 lines · Rusty Russell
This adds the logic to convert the virtio ids into module aliases, and includes a modalias entry in sysfs.
Unfortunately this does not seem sufficient to have the module autoprobed at startup on my Ubuntu system. Greg? Am I missing some udev magic?
You also need to pass the MODINFO environment variable to the hotplug call so that udev can pick it up.
hope this helps,
greg k-h
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
A message that is not in the archive (sent off-list or not yet received): [email protected]
Re: [PATCH 3/3] virtio module alias support
Quoted 4 lines · Greg KH
Quoted 3 lines · Rusty Russell
This adds the logic to convert the virtio ids into module aliases, and includes a modalias entry in sysfs.
Quoted 8 lines
Quoted 3 lines
Unfortunately this does not seem sufficient to have the module autoprobed at startup on my Ubuntu system. Greg? Am I missing some udev magic?
You also need to pass the MODINFO environment variable to the hotplug call so that udev can pick it up.
hope this helps,
Well, I finally decoded this as follows:
You need to implement the bus_type.uevent hook, and use add_uevent_var() to add a "MODALIAS=virtio:..." var. See drivers/pci/hotplug.c.
Not sure why I need the modalias here when it's in sysfs. But, it works.
Thanks!
Rusty.
---
Module autoprobing support for virtio drivers.
This adds the logic to convert the virtio ids into module aliases, and includes a modalias entry in sysfs and the env var to make probing work.
--- drivers/virtio/virtio.c | 9 +++++++++ scripts/mod/file2alias.c | 18 ++++++++++++++++++ 2 files changed, 27 insertions(+)
drivers/virtio/virtio.c +26 -0
@@ -19,11 +19,20 @@ static ssize_t status_show(struct device { struct virtio_device *dev = container_of(_d,struct virtio_device,dev);return sprintf (buf,"0x%08x" , dev->config->get_status (dev)); +} +static ssize_t modalias_show (struct device *_d, +struct device_attribute *attr,char *buf) +{ + struct virtio_device *dev = container_of(_d,struct virtio_device,dev); + +return sprintf (buf,"virtio:d%08Xv%08X\n" , + dev->id.device, dev->id.vendor); }static struct device_attribute virtio_dev_attrs[] = {__ATTR_RO (device),__ATTR_RO (vendor),__ATTR_RO (status), +__ATTR_RO (modalias), __ATTR_NULL };
@@ -48,6 +57,22 @@ static int virtio_dev_match(struct devicfor (i =0 ; ids[i].device; i++)if (virtio_id_match (dev, &ids[i]))return 1 ; +return 0 ; +} + +static int virtio_uevent (struct device *_dv,char **envp, +int num_envp,char *buffer,int buffer_size) +{ + struct virtio_device *dev = container_of(_dv,struct virtio_device,dev); +int i =0 , err; +int length =0 ; + + err =add_uevent_var (envp, num_envp, &i, buffer, buffer_size, &length, +"MODALIAS=virtio:d%08Xv%08X" , + dev->id.device, dev->id.vendor); +if (err) +return err; + envp[i] =NULL ;return 0 ; }
@@ -61,6 +86,7 @@ static struct virtio_bus virtio_bus = { .name = "virtio", .match = virtio_dev_match, .dev_attrs = virtio_dev_attrs, + .uevent = virtio_uevent, }, .dev = {/* Can override this if you have a real bus behind it. */
scripts/mod/file2alias.c +18 -0
@@ -484,6 +484,20 @@ static int do_parisc_entry(const char *freturn 1 ; } +/* Looks like: virtio:dNvN */ +static int do_virtio_entry (const char *filename,struct virtio_device_id *id, +char *alias) +{ + id->device =TO_NATIVE (id->device); + id->vendor =TO_NATIVE (id->vendor); + +strcpy (alias,"virtio:" ); +ADD (alias,"d" ,1 , id->device); +ADD (alias,"v" , id->vendor !=VIRTIO_DEV_ANY_ID , id->vendor); + +return 1 ; +} +/* Ignore any prefix, eg. v850 prepends _ */ static inline int sym_is (const char *symbol,const char *name) {
@@ -599,6 +613,10 @@ void handle_moddevtable(struct module *mdo_table (symval, sym->st_size,sizeof (struct parisc_device_id ),"parisc" , do_parisc_entry, mod); + else if (sym_is(symname, "__mod_virtio_device_table")) + do_table(symval, sym->st_size, + sizeof(struct virtio_device_id), "virtio", + do_virtio_entry, mod); }/* Now add out buffered information to the generated C source */
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
A message that is not in the archive (sent off-list or not yet received): 1190681405.27805.243.camel-bi+AKbBUZKY6gyzm1THtWbp2dZbC/[email protected]
Re: [PATCH 3/3] virtio module alias support
Quoted 12 lines · Rusty Russell
Quoted 11 lines · Greg KH
Quoted 6 lines · Rusty Russell
This adds the logic to convert the virtio ids into module aliases, and includes a modalias entry in sysfs.
Unfortunately this does not seem sufficient to have the module autoprobed at startup on my Ubuntu system. Greg? Am I missing some udev magic?
You also need to pass the MODINFO environment variable to the hotplug call so that udev can pick it up.
Quoted 7 lines
Quoted 1 line
hope this helps,
Well, I finally decoded this as follows:
You need to implement the bus_type.uevent hook, and use
add_uevent_var()to add a "MODALIAS=virtio:..." var. Seedrivers/pci/hotplug.c.
Ah, sorry, thanks for intrepreting it properly :)
Quoted 2 lines
Not sure why I need the modalias here when it's in sysfs. But, it works.
udev does not read from sysfs anymore, it just uses the environment variables. It's faster and race-free that way.
thanks,
greg k-h
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
A message that is not in the archive (sent off-list or not yet received): [email protected]
Re: [PATCH 3/3] virtio module alias support
Quoted 6 lines · Greg KH
Quoted 2 lines · Rusty Russell
Not sure why I need the modalias here when it's in sysfs. But, it works.
udev does not read from sysfs anymore, it just uses the environment variables. It's faster and race-free that way.
Should I leave the modalias entry in sysfs for back compat, or not? This will be for >= 2.6.24 only...
Thanks,
Rusty.
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
A message that is not in the archive (sent off-list or not yet received): 1190686275.27805.255.camel-bi+AKbBUZKY6gyzm1THtWbp2dZbC/[email protected]
Re: [PATCH 3/3] virtio module alias support
Quoted 10 lines · Rusty Russell
Quoted 6 lines · Greg KH
Quoted 2 lines · Rusty Russell
Not sure why I need the modalias here when it's in sysfs. But, it works.
udev does not read from sysfs anymore, it just uses the environment variables. It's faster and race-free that way.
Should I leave the modalias entry in sysfs for back compat, or not? This will be for >= 2.6.24 only...
No, leave it in sysfs, other tools use it (like older versions of udev).
thanks,
greg k-h
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
Re: [PATCH 3/3] virtio module alias support
In reply to Rusty RussellQuoted 10 lines · Rusty Russell
Quoted 6 lines · Greg KH
Quoted 2 lines · Rusty Russell
Not sure why I need the modalias here when it's in sysfs. But, it works.
udev does not read from sysfs anymore, it just uses the environment variables. It's faster and race-free that way.
Should I leave the modalias entry in sysfs for back compat, or not? This will be for >= 2.6.24 only...
No, leave it in sysfs, other tools use it (like older versions of udev).
thanks,
greg k-h
Re: [PATCH 3/3] virtio module alias support
In reply to Greg KHQuoted 6 lines · Greg KH
Quoted 2 lines · Rusty Russell
Not sure why I need the modalias here when it's in sysfs. But, it works.
udev does not read from sysfs anymore, it just uses the environment variables. It's faster and race-free that way.
Should I leave the modalias entry in sysfs for back compat, or not? This will be for >= 2.6.24 only...
Thanks,
Rusty.
Re: [PATCH 3/3] virtio module alias support
In reply to Rusty RussellQuoted 12 lines · Rusty Russell
Quoted 11 lines · Greg KH
Quoted 6 lines · Rusty Russell
This adds the logic to convert the virtio ids into module aliases, and includes a modalias entry in sysfs.
Unfortunately this does not seem sufficient to have the module autoprobed at startup on my Ubuntu system. Greg? Am I missing some udev magic?
You also need to pass the MODINFO environment variable to the hotplug call so that udev can pick it up.
Quoted 7 lines
Quoted 1 line
hope this helps,
Well, I finally decoded this as follows:
You need to implement the bus_type.uevent hook, and use
add_uevent_var()to add a "MODALIAS=virtio:..." var. Seedrivers/pci/hotplug.c.
Ah, sorry, thanks for intrepreting it properly :)
Quoted 2 lines
Not sure why I need the modalias here when it's in sysfs. But, it works.
udev does not read from sysfs anymore, it just uses the environment variables. It's faster and race-free that way.
thanks,
greg k-h
Re: [PATCH 3/3] virtio module alias support
In reply to Greg KHQuoted 4 lines · Greg KH
Quoted 3 lines · Rusty Russell
This adds the logic to convert the virtio ids into module aliases, and includes a modalias entry in sysfs.
Quoted 8 lines
Quoted 3 lines
Unfortunately this does not seem sufficient to have the module autoprobed at startup on my Ubuntu system. Greg? Am I missing some udev magic?
You also need to pass the MODINFO environment variable to the hotplug call so that udev can pick it up.
hope this helps,
Well, I finally decoded this as follows:
You need to implement the bus_type.uevent hook, and use add_uevent_var() to add a "MODALIAS=virtio:..." var. See drivers/pci/hotplug.c.
Not sure why I need the modalias here when it's in sysfs. But, it works.
Thanks!
Rusty.
---
Module autoprobing support for virtio drivers.
This adds the logic to convert the virtio ids into module aliases, and includes a modalias entry in sysfs and the env var to make probing work.
--- drivers/virtio/virtio.c | 9 +++++++++ scripts/mod/file2alias.c | 18 ++++++++++++++++++ 2 files changed, 27 insertions(+)
drivers/virtio/virtio.c +26 -0
@@ -19,11 +19,20 @@ static ssize_t status_show(struct device { struct virtio_device *dev = container_of(_d,struct virtio_device,dev);return sprintf (buf,"0x%08x" , dev->config->get_status (dev)); +} +static ssize_t modalias_show (struct device *_d, +struct device_attribute *attr,char *buf) +{ + struct virtio_device *dev = container_of(_d,struct virtio_device,dev); + +return sprintf (buf,"virtio:d%08Xv%08X\n" , + dev->id.device, dev->id.vendor); }static struct device_attribute virtio_dev_attrs[] = {__ATTR_RO (device),__ATTR_RO (vendor),__ATTR_RO (status), +__ATTR_RO (modalias), __ATTR_NULL };
@@ -48,6 +57,22 @@ static int virtio_dev_match(struct devicfor (i =0 ; ids[i].device; i++)if (virtio_id_match (dev, &ids[i]))return 1 ; +return 0 ; +} + +static int virtio_uevent (struct device *_dv,char **envp, +int num_envp,char *buffer,int buffer_size) +{ + struct virtio_device *dev = container_of(_dv,struct virtio_device,dev); +int i =0 , err; +int length =0 ; + + err =add_uevent_var (envp, num_envp, &i, buffer, buffer_size, &length, +"MODALIAS=virtio:d%08Xv%08X" , + dev->id.device, dev->id.vendor); +if (err) +return err; + envp[i] =NULL ;return 0 ; }
@@ -61,6 +86,7 @@ static struct virtio_bus virtio_bus = { .name = "virtio", .match = virtio_dev_match, .dev_attrs = virtio_dev_attrs, + .uevent = virtio_uevent, }, .dev = {/* Can override this if you have a real bus behind it. */
scripts/mod/file2alias.c +18 -0
@@ -484,6 +484,20 @@ static int do_parisc_entry(const char *freturn 1 ; } +/* Looks like: virtio:dNvN */ +static int do_virtio_entry (const char *filename,struct virtio_device_id *id, +char *alias) +{ + id->device =TO_NATIVE (id->device); + id->vendor =TO_NATIVE (id->vendor); + +strcpy (alias,"virtio:" ); +ADD (alias,"d" ,1 , id->device); +ADD (alias,"v" , id->vendor !=VIRTIO_DEV_ANY_ID , id->vendor); + +return 1 ; +} +/* Ignore any prefix, eg. v850 prepends _ */ static inline int sym_is (const char *symbol,const char *name) {
@@ -599,6 +613,10 @@ void handle_moddevtable(struct module *mdo_table (symval, sym->st_size,sizeof (struct parisc_device_id ),"parisc" , do_parisc_entry, mod); + else if (sym_is(symname, "__mod_virtio_device_table")) + do_table(symval, sym->st_size, + sizeof(struct virtio_device_id), "virtio", + do_virtio_entry, mod); }/* Now add out buffered information to the generated C source */
Re: [PATCH 3/3] virtio module alias support
In reply to Rusty RussellQuoted 6 lines · Rusty Russell
This adds the logic to convert the virtio ids into module aliases, and includes a modalias entry in sysfs.
Unfortunately this does not seem sufficient to have the module autoprobed at startup on my Ubuntu system. Greg? Am I missing some udev magic?
You also need to pass the MODINFO environment variable to the hotplug call so that udev can pick it up.
hope this helps,
greg k-h
Re: [PATCH 2/3] virtio ring implementation
In reply to a message not in the archiveQuoted 18 lines · Rusty Russell
These helper routines supply most of the
virtqueue_opsfor hypervisors which want to use a ring for virtio. Unlike the previous lguest implementation:1) The rings are variable sized (2^n-1 elements).
2) They have an unfortunate limit of 65535 bytes per sg element.
3) The page numbers are always 64 bit (PAE anyone?)
4) They no longer place used[] on a separate page, just a separate cacheline.
5) We do a modulo on a variable. We could be tricky if we cared.
6) Interrupts and notifies are suppressed using flags within the rings.Users need only implement the
new_vqandfree_vqhooks (KVM wants the guest to allocate the rings, lguest does it sanely).Signed-off-by Rusty Russell <rusty-8n+1lVoiYb80n/[email protected]>
[snip]
Quoted 19 lines
drivers/virtio/virtio_ring.c new file +16
-0+irqreturn_t vring_interrupt (int irq,void *_vq) +{ +struct vring_virtqueue *vq =to_vvq (_vq); + +pr_debug ("virtqueue interrupt for %p\n" , vq); + +if (unlikely (vq->broken)) +return IRQ_HANDLED ; + +if (more_used (vq)) { +pr_debug ("virtqueue callback for %p (%p)\n" , + vq, vq->vq.callback); +if (!vq->vq.callback) +return IRQ_NONE ; +if (!vq->vq.callback (&vq->vq)) + vq->vring.avail->flags |=
VRING_AVAIL_F_NO_INTERRUPT;
drivers/virtio/virtio_ring.c line 265
Quoted 6 lines
drivers/virtio/virtio_ring.c new file +6
-0+ }else +pr_debug ("virtqueue %p no more used\n" , vq); + +return IRQ_HANDLED ; +} +
Seems like there is a problem with shared irq line, the interrupt handler always returns IRQ_HANDLED (except for the trivial case were the callback is null).
It can be solved by having a host irq counter (in the shared ring) and a guest irq counter and return mb(); return (host_counter!=guest_counter)? IRQ_HANDLED:IRQ_NONE;
Dor.
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
kvm-devel mailing list [email protected]
https://lists.sourceforge.net/lists/listinfo/kvm-devel
A message that is not in the archive (sent off-list or not yet received): 46F7BF41.9060705-atKUWr5tajBWk0Htik3J/[email protected]
Re: [PATCH 2/3] virtio ring implementation
Quoted 7 lines · Dor Laor
Seems like there is a problem with shared irq line, the interrupt handler always returns
IRQ_HANDLED(except for the trivial case were the callback is null).It can be solved by having a host irq counter (in the shared ring) and a guest irq counter and return
mb(); return (host_counter!=guest_counter)? IRQ_HANDLED:IRQ_NONE;
Or we could make the callback return irqreturn_t and have an explicit "disable" hook to disable interrupts.
Using the return value of the callback to disable the queue has always made be a little uncomfortable, but it's slightly more efficient than a separate hook.
Thanks,
Rusty.
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
Re: [PATCH 2/3] virtio ring implementation
In reply to a message not in the archiveQuoted 20 lines · Dor Laor
Quoted 19 lines · Rusty Russell
drivers/virtio/virtio_ring.c new file +16
-0+irqreturn_t vring_interrupt (int irq,void *_vq) +{ +struct vring_virtqueue *vq =to_vvq (_vq); + +pr_debug ("virtqueue interrupt for %p\n" , vq); + +if (unlikely (vq->broken)) +return IRQ_HANDLED ; + +if (more_used (vq)) { +pr_debug ("virtqueue callback for %p (%p)\n" , + vq, vq->vq.callback); +if (!vq->vq.callback) +return IRQ_NONE ; +if (!vq->vq.callback (&vq->vq)) + vq->vring.avail->flags |=
VRING_AVAIL_F_NO_INTERRUPT;drivers/virtio/virtio_ring.c new file +2
-0+ }else +pr_debug ("virtqueue %p no more used\n" , vq);
Quoted 8 lines
drivers/virtio/virtio_ring.c line 265
Quoted 5 lines
drivers/virtio/virtio_ring.c new file +4
-0+ +return IRQ_HANDLED ; +} +Seems like there is a problem with shared irq line, the interrupt handler always returns
IRQ_HANDLED(except for the trivial case were the callback is null).
To reply for a second time, this time with thought. Sorry.
Yes, this code is wrong. It should be:
irqreturn_t vring_interrupt(int irq, void *_vq)
{
struct vring_virtqueue *vq = to_vvq(_vq);
if (!more_used(vq)) {
pr_debug("virtqueue interrupt with no work for %p\n", vq);
return IRQ_NONE;
}
if (unlikely(vq->broken))
return IRQ_HANDLED;
pr_debug("virtqueue callback for %p (%p)\n", vq, vq->vq.callback);
if (vq->vq.callback && !vq->vq.callback(&vq->vq))
vq->vring.avail->flags |= VRING_AVAIL_F_NO_INTERRUPT;
return IRQ_HANDLED;
}Cheers,
Rusty.
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
A message that is not in the archive (sent off-list or not yet received): 1190727156.27805.332.camel-bi+AKbBUZKY6gyzm1THtWbp2dZbC/[email protected]
Re: [PATCH 2/3] virtio ring implementation
Quoted 54 lines · Rusty Russell
Quoted 20 lines · Dor Laor
Quoted 19 lines · Rusty Russell
drivers/virtio/virtio_ring.c new file +16
-0+irqreturn_t vring_interrupt (int irq,void *_vq) +{ +struct vring_virtqueue *vq =to_vvq (_vq); + +pr_debug ("virtqueue interrupt for %p\n" , vq); + +if (unlikely (vq->broken)) +return IRQ_HANDLED ; + +if (more_used (vq)) { +pr_debug ("virtqueue callback for %p (%p)\n" , + vq, vq->vq.callback); +if (!vq->vq.callback) +return IRQ_NONE ; +if (!vq->vq.callback (&vq->vq)) + vq->vring.avail->flags |=
VRING_AVAIL_F_NO_INTERRUPT;drivers/virtio/virtio_ring.c new file +2
-0+ }else +pr_debug ("virtqueue %p no more used\n" , vq);Quoted 8 lines
drivers/virtio/virtio_ring.c line 265
Quoted 5 lines
drivers/virtio/virtio_ring.c new file +4
-0+ +return IRQ_HANDLED ; +} +Seems like there is a problem with shared irq line, the interrupt handler always returns
IRQ_HANDLED(except for the trivial case were the callback is null).To reply for a second time, this time with thought. Sorry.
Yes, this code is wrong. It should be:
irqreturn_tvring_interrupt(int irq, void *_vq){ struct vring_virtqueue *vq = to_vvq(_vq); if (!more_used(vq)) { pr_debug("virtqueue interrupt with no work for %p\n", vq); return IRQ_NONE; } if (unlikely(vq->broken)) return IRQ_HANDLED; pr_debug("virtqueue callback for %p (%p)\n", vq, vq->vq.callback); if (vq->vq.callback && !vq->vq.callback(&vq->vq)) vq->vring.avail->flags |= VRING_AVAIL_F_NO_INTERRUPT; return IRQ_HANDLED; }
Quoted 3 lines
Cheers,
Rusty.
At the moment it's not good enough, there is a potential race were the guest optimistically turn off the VRING_AVAIL_F_NO_INTERRUPT in the vring_restart and afterwards finds there are more_used so it consume them in the poll function.
If in the middle, packets arrive the host will see the flag is off and send irq.
In that case the above irq handler will report IRQ_NONE.
It's also not trivial to cancel the optimistic approach in the restart function since then there might be another race that will result in missing irq reaching the guest.
I'll try to think of something better than a hypercall for switching irq on/off.
Cheers mate,
Dor.
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
kvm-devel mailing list [email protected]
https://lists.sourceforge.net/lists/listinfo/kvm-devel
A message that is not in the archive (sent off-list or not yet received): 46F94243.2000602-atKUWr5tajBWk0Htik3J/[email protected]
Re: [PATCH 2/3] virtio ring implementation
Quoted 8 lines · Dor Laor
At the moment it's not good enough, there is a potential race were the guest optimistically turn off
theVRING_AVAIL_F_NO_INTERRUPTin thevring_restartand afterwards finds there aremore_usedso
it consume them in the poll function.
If in the middle, packets arrive the host will see the flag is off and send irq.
In that case the above irq handler will reportIRQ_NONE.
Good point. On the one hand, reporting IRQ_NONE occasionally is not fatal. On the other, it'd be nice to get this right.
Quoted 3 lines
It's also not trivial to cancel the optimistic approach in the restart function since then there might be another race
that will result in missing irq reaching the guest.
I did it optimistically because otherwise we need two barriers (and still have a window).
Quoted 2 lines
I'll try to think of something better than a hypercall for switching irq on/off.
Erk. That would be v. bad...
Thanks,
Rusty.
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
A message that is not in the archive (sent off-list or not yet received): 1190763475.2227.20.camel-bi+AKbBUZKY6gyzm1THtWbp2dZbC/[email protected]
Re: [PATCH 2/3] virtio ring implementation
Quoted 25 lines · Rusty Russell
Quoted 9 lines · Dor Laor
At the moment it's not good enough, there is a potential race were the guest optimistically turn off
theVRING_AVAIL_F_NO_INTERRUPTin thevring_restartand afterwards finds there aremore_usedso
it consume them in the poll function.
If in the middle, packets arrive the host will see the flag is off and send irq.
In that case the above irq handler will reportIRQ_NONE.Good point. On the one hand, reporting
IRQ_NONEoccasionally is not fatal. On the other, it'd be nice to get this right.Quoted 4 lines
It's also not trivial to cancel the optimistic approach in the restart function since then there might be another race
that will result in missing irq reaching the guest.I did it optimistically because otherwise we need two barriers (and still have a window).
Quoted 6 lines
Quoted 3 lines
I'll try to think of something better than a hypercall for switching irq on/off.
Erk. That would be v. bad...
Actually double barrier will satisfy non-shared irq lines and will report irq handling right.
The more complex scenario is shared irqs (pci...), since several devices are raising the irq line (level triggered)
in the same time, while the tap add receive packets it always leaves a potential race for irq handled return
value. So seems like we better not have shared irq and if only if shared irq is a must we should do the
naughty naughty things.
If returning IRQ_NONE once in a while is not too bad (including the matching windows implementation)
then there is no issue.
Dor.
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
Re: [kvm-devel] [PATCH 2/3] virtio ring implementation
In reply to Rusty RussellQuoted 24 lines · Rusty Russell
Quoted 8 lines · Dor Laor
At the moment it's not good enough, there is a potential race were the
guest optimistically turn off
theVRING_AVAIL_F_NO_INTERRUPTin thevring_restartand afterwards
finds there aremore_usedso
it consume them in the poll function. If in the middle, packets arrive the host will see the flag is off and send irq.
In that case the above irq handler will reportIRQ_NONE.Good point. On the one hand, reporting
IRQ_NONEoccasionally is not fatal. On the other, it'd be nice to get this right.Quoted 4 lines
It's also not trivial to cancel the optimistic approach in the restart function since then there might be another race
that will result in missing irq reaching the guest.I did it optimistically because otherwise we need two barriers (and still have a window).
Quoted 6 lines
Quoted 3 lines
I'll try to think of something better than a hypercall for switching irq on/off.
Erk. That would be v. bad...
Actually double barrier will satisfy non-shared irq lines and will report irq handling right. The more complex scenario is shared irqs (pci...), since several devices are raising the irq line (level triggered) in the same time, while the tap add receive packets it always leaves a potential race for irq handled return value. So seems like we better not have shared irq and if only if shared irq is a must we should do the naughty naughty things.
If returning IRQ_NONE once in a while is not too bad (including the matching windows implementation) then there is no issue.
Dor.
Re: [kvm-devel] [PATCH 2/3] virtio ring implementation
In reply to Dor LaorQuoted 8 lines · Dor Laor
At the moment it's not good enough, there is a potential race were the guest optimistically turn off
theVRING_AVAIL_F_NO_INTERRUPTin thevring_restartand afterwards finds there aremore_usedso
it consume them in the poll function.
If in the middle, packets arrive the host will see the flag is off and send irq.
In that case the above irq handler will reportIRQ_NONE.
Good point. On the one hand, reporting IRQ_NONE occasionally is not fatal. On the other, it'd be nice to get this right.
Quoted 3 lines
It's also not trivial to cancel the optimistic approach in the restart function since then there might be another race
that will result in missing irq reaching the guest.
I did it optimistically because otherwise we need two barriers (and still have a window).
Quoted 2 lines
I'll try to think of something better than a hypercall for switching irq on/off.
Erk. That would be v. bad...
Thanks,
Rusty.
Re: [kvm-devel] [PATCH 2/3] virtio ring implementation
In reply to Rusty RussellQuoted 54 lines · Rusty Russell
Quoted 20 lines · Dor Laor
Quoted 19 lines · Rusty Russell
drivers/virtio/virtio_ring.c new file +16
-0+irqreturn_t vring_interrupt (int irq,void *_vq) +{ +struct vring_virtqueue *vq =to_vvq (_vq); + +pr_debug ("virtqueue interrupt for %p\n" , vq); + +if (unlikely (vq->broken)) +return IRQ_HANDLED ; + +if (more_used (vq)) { +pr_debug ("virtqueue callback for %p (%p)\n" , + vq, vq->vq.callback); +if (!vq->vq.callback) +return IRQ_NONE ; +if (!vq->vq.callback (&vq->vq)) + vq->vring.avail->flags |=
VRING_AVAIL_F_NO_INTERRUPT;drivers/virtio/virtio_ring.c new file +2
-0+ }else +pr_debug ("virtqueue %p no more used\n" , vq);Quoted 8 lines
drivers/virtio/virtio_ring.c line 265
Quoted 5 lines
drivers/virtio/virtio_ring.c new file +4
-0+ +return IRQ_HANDLED ; +} +Seems like there is a problem with shared irq line, the interrupt handler always returns
IRQ_HANDLED(except for the trivial case were the callback is null).To reply for a second time, this time with thought. Sorry.
Yes, this code is wrong. It should be:
irqreturn_tvring_interrupt(int irq, void *_vq){ struct vring_virtqueue *vq = to_vvq(_vq); if (!more_used(vq)) { pr_debug("virtqueue interrupt with no work for %p\n", vq); return IRQ_NONE; } if (unlikely(vq->broken)) return IRQ_HANDLED; pr_debug("virtqueue callback for %p (%p)\n", vq, vq->vq.callback); if (vq->vq.callback && !vq->vq.callback(&vq->vq)) vq->vring.avail->flags |= VRING_AVAIL_F_NO_INTERRUPT; return IRQ_HANDLED; }
Quoted 3 lines
Cheers,
Rusty.
At the moment it's not good enough, there is a potential race were the guest optimistically turn off the VRING_AVAIL_F_NO_INTERRUPT in the vring_restart and afterwards finds there are more_used so it consume them in the poll function.
If in the middle, packets arrive the host will see the flag is off and send irq.
In that case the above irq handler will report IRQ_NONE.
It's also not trivial to cancel the optimistic approach in the restart function since then there might be another race that will result in missing irq reaching the guest.
I'll try to think of something better than a hypercall for switching irq on/off.
Cheers mate,
Dor.
_______________________________________________
Virtualization mailing list
[email protected]
https://lists.linux-foundation.org/mailman/listinfo/virtualization
Re: [kvm-devel] [PATCH 2/3] virtio ring implementation
In reply to Dor LaorQuoted 7 lines · Dor Laor
Seems like there is a problem with shared irq line, the interrupt handler always returns
IRQ_HANDLED(except for the trivial case were the callback is null).It can be solved by having a host irq counter (in the shared ring) and a guest irq counter and return
mb(); return (host_counter!=guest_counter)? IRQ_HANDLED:IRQ_NONE;
Or we could make the callback return irqreturn_t and have an explicit "disable" hook to disable interrupts.
Using the return value of the callback to disable the queue has always made be a little uncomfortable, but it's slightly more efficient than a separate hook.
Thanks,
Rusty.
Re: [kvm-devel] [PATCH 2/3] virtio ring implementation
In reply to Dor LaorQuoted 20 lines · Dor Laor
Quoted 19 lines · Rusty Russell
drivers/virtio/virtio_ring.c new file +16
-0+irqreturn_t vring_interrupt (int irq,void *_vq) +{ +struct vring_virtqueue *vq =to_vvq (_vq); + +pr_debug ("virtqueue interrupt for %p\n" , vq); + +if (unlikely (vq->broken)) +return IRQ_HANDLED ; + +if (more_used (vq)) { +pr_debug ("virtqueue callback for %p (%p)\n" , + vq, vq->vq.callback); +if (!vq->vq.callback) +return IRQ_NONE ; +if (!vq->vq.callback (&vq->vq)) + vq->vring.avail->flags |=
VRING_AVAIL_F_NO_INTERRUPT;drivers/virtio/virtio_ring.c new file +2
-0+ }else +pr_debug ("virtqueue %p no more used\n" , vq);
Quoted 8 lines
drivers/virtio/virtio_ring.c line 265
Quoted 5 lines
drivers/virtio/virtio_ring.c new file +4
-0+ +return IRQ_HANDLED ; +} +Seems like there is a problem with shared irq line, the interrupt handler always returns
IRQ_HANDLED(except for the trivial case were the callback is null).
To reply for a second time, this time with thought. Sorry.
Yes, this code is wrong. It should be:
irqreturn_t vring_interrupt(int irq, void *_vq)
{
struct vring_virtqueue *vq = to_vvq(_vq);
if (!more_used(vq)) {
pr_debug("virtqueue interrupt with no work for %p\n", vq);
return IRQ_NONE;
}
if (unlikely(vq->broken))
return IRQ_HANDLED;
pr_debug("virtqueue callback for %p (%p)\n", vq, vq->vq.callback);
if (vq->vq.callback && !vq->vq.callback(&vq->vq))
vq->vring.avail->flags |= VRING_AVAIL_F_NO_INTERRUPT;
return IRQ_HANDLED;
}Cheers,
Rusty.
PATCH 3/3 virtio module alias support
In reply to Rusty RussellThis adds the logic to convert the virtio ids into module aliases, and includes a modalias entry in sysfs.
Unfortunately this does not seem sufficient to have the module autoprobed at startup on my Ubuntu system. Greg? Am I missing some udev magic?
--- drivers/virtio/virtio.c | 9 +++++++++ scripts/mod/file2alias.c | 18 ++++++++++++++++++ 2 files changed, 27 insertions(+)
===================================================================
drivers/virtio/virtio.c +9 -0
@@ -20,10 +20,19 @@ static ssize_t status_show(struct device struct virtio_device *dev = container_of(_d,struct virtio_device,dev);return sprintf (buf,"0x%08x" , dev->config->get_status (dev)); } +static ssize_t modalias_show (struct device *_d, +struct device_attribute *attr,char *buf) +{ + struct virtio_device *dev = container_of(_d,struct virtio_device,dev); + +return sprintf (buf,"virtio:d%08Xv%08X\n" , + dev->id.device, dev->id.vendor); +}static struct device_attribute virtio_dev_attrs[] = {__ATTR_RO (device),__ATTR_RO (vendor),__ATTR_RO (status), +__ATTR_RO (modalias), __ATTR_NULL };
===================================================================
scripts/mod/file2alias.c +18 -0
@@ -484,6 +484,20 @@ static int do_parisc_entry(const char *freturn 1 ; } +/* Looks like: virtio:dNvN */ +static int do_virtio_entry (const char *filename,struct virtio_device_id *id, +char *alias) +{ + id->device =TO_NATIVE (id->device); + id->vendor =TO_NATIVE (id->vendor); + +strcpy (alias,"virtio:" ); +ADD (alias,"d" ,1 , id->device); +ADD (alias,"v" , id->vendor !=VIRTIO_DEV_ANY_ID , id->vendor); + +return 1 ; +} +/* Ignore any prefix, eg. v850 prepends _ */ static inline int sym_is (const char *symbol,const char *name) {
@@ -599,6 +613,10 @@ void handle_moddevtable(struct module *mdo_table (symval, sym->st_size,sizeof (struct parisc_device_id ),"parisc" , do_parisc_entry, mod); + else if (sym_is(symname, "__mod_virtio_device_table")) + do_table(symval, sym->st_size, + sizeof(struct virtio_device_id), "virtio", + do_virtio_entry, mod); }/* Now add out buffered information to the generated C source */
Re: [kvm-devel] [PATCH 2/3] virtio ring implementation
In reply to Rusty RussellQuoted 18 lines · Rusty Russell
These helper routines supply most of the
virtqueue_opsfor hypervisors which want to use a ring for virtio. Unlike the previous lguest implementation:1) The rings are variable sized (2^n-1 elements).
2) They have an unfortunate limit of 65535 bytes per sg element.
3) The page numbers are always 64 bit (PAE anyone?)
4) They no longer place used[] on a separate page, just a separate cacheline.
5) We do a modulo on a variable. We could be tricky if we cared.
6) Interrupts and notifies are suppressed using flags within the rings.Users need only implement the
new_vqandfree_vqhooks (KVM wants the guest to allocate the rings, lguest does it sanely).Signed-off-by Rusty Russell <[email protected]>
[snip]
Quoted 19 lines
drivers/virtio/virtio_ring.c new file +16
-0+irqreturn_t vring_interrupt (int irq,void *_vq) +{ +struct vring_virtqueue *vq =to_vvq (_vq); + +pr_debug ("virtqueue interrupt for %p\n" , vq); + +if (unlikely (vq->broken)) +return IRQ_HANDLED ; + +if (more_used (vq)) { +pr_debug ("virtqueue callback for %p (%p)\n" , + vq, vq->vq.callback); +if (!vq->vq.callback) +return IRQ_NONE ; +if (!vq->vq.callback (&vq->vq)) + vq->vring.avail->flags |=
VRING_AVAIL_F_NO_INTERRUPT;
drivers/virtio/virtio_ring.c line 265
Quoted 6 lines
drivers/virtio/virtio_ring.c new file +6
-0+ }else +pr_debug ("virtqueue %p no more used\n" , vq); + +return IRQ_HANDLED ; +} +
Seems like there is a problem with shared irq line, the interrupt handler always returns IRQ_HANDLED (except for the trivial case were the callback is null).
It can be solved by having a host irq counter (in the shared ring) and a guest irq counter and return mb(); return (host_counter!=guest_counter)? IRQ_HANDLED:IRQ_NONE;
Dor.
_______________________________________________
Virtualization mailing list
[email protected]
https://lists.linux-foundation.org/mailman/listinfo/virtualization
Re: [PATCH 1/3] virtio interface
In reply to a message not in the archiveQuoted 3 lines · Rusty Russell
This attempts to implement a "virtual I/O" layer which should allow common drivers to be efficiently used across most virtual I/O mechanisms. It will no-doubt need further enhancement.
Hi Rusty,
Thanks for your update, as you can imagine, I'm much happier with this version ;-)
Quoted 8 lines
drivers/virtio/virtio.c new file +8
-0+ +struct virtio_bus { +struct bus_type bus; +struct device dev; +}; + +static struct virtio_bus virtio_bus = { + .bus = {
drivers/virtio/virtio.c line 70
Quoted 10 lines
drivers/virtio/virtio.c new file +10
-0+ .name = "virtio", + .match = virtio_dev_match, + .dev_attrs = virtio_dev_attrs, + }, + .dev = { +/* Can override this if you have a real bus behind it. */ + .parent = NULL, + .bus_id = "virtio", + } +};
This is a pattern I've seen a few times before, but could never understand what it's good for. What is your reason for defining a new data structure that is used only once, instead of just
static struct bus_type virtio_bus_type;
static struct device virtio_root_dev;
Also, I would not mix the two in a single source file. Instead, I think every driver that can provide virtio devices (pci, lguest, ...) should be responsible for setting the parent appropriately.
Quoted 61 lines
include/linux/virtio_config.h new file +61
-0+#ifndef _LINUX_VIRTIO_CONFIG_H +#define _LINUX_VIRTIO_CONFIG_H +/* Virtio devices use a standardized configuration space to define their + * features and pass configuration information, but each implementation can + * store and access that space differently. */ +#include <linux/types.h> + +/* Status byte for guest to report progress, and synchronize config. */ +/* We have seen device and processed generic fields (VIRTIO_CONFIG_F_VIRTIO) */ +#define VIRTIO_CONFIG_S_ACKNOWLEDGE 1 +/* We have found a driver for the device. */ +#define VIRTIO_CONFIG_S_DRIVER 2 +/* Driver has used its parts of the config, and is happy */ +#define VIRTIO_CONFIG_S_DRIVER_OK 4 +/* We've given up on this device. */ +#define VIRTIO_CONFIG_S_FAILED 0x80 + +/* Feature byte (actually 7 bits availabe): */ +/* Requirements/features of the virtio implementation. */ +#define VIRTIO_CONFIG_F_VIRTIO 1 +/* Requirements/features of the virtqueue (may have more than one). */ +#define VIRTIO_CONFIG_F_VIRTQUEUE 2 + +#ifdef __KERNEL__ +struct virtio_device; + +/** + * virtio_config_ops - operations for configuring a virtio device + * @find: search for the next configuration field of the given type. + * vdev: the virtio_device + * type: the feature type + * len: the (returned) length of the field if found. + * Returns a token if found, or NULL. Never returnes the same field twice + * (ie. it's used up). + * @get: read the value of a configuration field after find(). + * vdev: the virtio_device + * token: the token returned from find(). + * buf: the buffer to write the field value into. + * len: the length of the buffer (given by find()). + * Note that contents are conventionally little-endian. + * @set: write the value of a configuration field after find(). + * vdev: the virtio_device + * token: the token returned from find(). + * buf: the buffer to read the field value from. + * len: the length of the buffer (given by find()). + * Note that contents are conventionally little-endian. + * @get_status: read the status byte + * vdev: the virtio_device + * Returns the status byte + * @set_status: write the status byte + * vdev: the virtio_device + * status: the new status byte + * @find_vq: find the first VIRTIO_CONFIG_F_VIRTQUEUE and create a virtqueue. + * vdev: the virtio_device + * callback: the virqtueue callback + * Returns the new virtqueue or ERR_PTR(). + * @del_vq: free a virtqueue found by find_vq(). + */ +struct virtio_config_ops +{ + void *(*find)(struct virtio_device *vdev, u8 type, unsigned *len);
include/linux/virtio_config.h line 71
Quoted 10 lines
include/linux/virtio_config.h new file +10
-0+void (*get)(struct virtio_device *vdev,void *token, +void *buf,unsigned len); +void (*set)(struct virtio_device *vdev,void *token, +const void *buf,unsigned len); +u8 (*get_status)(struct virtio_device *vdev); +void (*set_status)(struct virtio_device *vdev,u8 status); +struct virtqueue *(*find_vq)(struct virtio_device *vdev, +bool (*callback)(struct virtqueue *)); +void (*del_vq)(struct virtqueue *vq); +};
The configuration logic looks more complicated than it should be. Maybe more of this can be done using data structure definitions instead of dynamic callback. E.g. the virtqueues of a given device can be listed as members of the struct virtio_device.
Quoted 12 lines
include/linux/virtio_config.h new file +12
-0+/** +* virtio_config_val - get a single virtio config and mark it used. +* @config: the virtio config space +* @type: the type to search for. +* @val: a pointer to the value to fill in. +* +* Once used, the config type is marked with VIRTIO_CONFIG_F_USED so it can't +* be found again. This version does endian conversion. */ +#define virtio_config_val (vdev, type, v) ({ \ + int _err = __virtio_config_val((vdev),(type),(v),sizeof(*(v))); \ + \ + BUILD_BUG_ON(sizeof(*(v)) != 1 && sizeof(*(v)) != 2 \
include/linux/virtio_config.h line 94
Quoted 10 lines
include/linux/virtio_config.h new file +10
-0+ && sizeof(*(v)) != 4 && sizeof(*(v)) != 8); \ +if (!_err) { \ +switch (sizeof (*(v))) { \ +case 2 :le16_to_cpus (v);break ; \ +case 4 :le32_to_cpus (v);break ; \ +case 8 :le64_to_cpus (v);break ; \ + } \ + } \ + _err; \ +})
Especially the macro looks like something better avoided...
Arnd <><
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
A message that is not in the archive (sent off-list or not yet received): [email protected]
Re: [PATCH 1/3] virtio interface
Quoted 9 lines · Arnd Bergmann
Quoted 3 lines · Rusty Russell
This attempts to implement a "virtual I/O" layer which should allow common drivers to be efficiently used across most virtual I/O mechanisms. It will no-doubt need further enhancement.
Hi Rusty,
Thanks for your update, as you can imagine, I'm much happier with this version ;-)
Hi Arnd,
Yes, I thought you might be...
Quoted 23 lines
Quoted 8 lines
drivers/virtio/virtio.c new file +8
-0+ +struct virtio_bus { +struct bus_type bus; +struct device dev; +}; + +static struct virtio_bus virtio_bus = { + .bus = {drivers/virtio/virtio.c line 70
Quoted 10 lines
drivers/virtio/virtio.c new file +10
-0+ .name = "virtio", + .match = virtio_dev_match, + .dev_attrs = virtio_dev_attrs, + }, + .dev = { +/* Can override this if you have a real bus behind it. */ + .parent = NULL, + .bus_id = "virtio", + } +};This is a pattern I've seen a few times before, but could never understand what it's good for. What is your reason for defining a new data structure that is used only once, instead of just
Quoted 2 lines
static struct
bus_typevirtio_bus_type;
static struct devicevirtio_root_dev;
It's copied from the lguest bus which was copied from somewhere else. Creating a struct like this is a quiet complaint about the requirements to do so: it's not clear to me why I need to create a fake device, rather than making the bus the parent of the device if it needs one.
Quoted 3 lines
Also, I would not mix the two in a single source file. Instead, I think every driver that can provide virtio devices (pci, lguest, ...) should be responsible for setting the parent appropriately.
I don't mind: we could expose it.
Quoted 10 lines
Quoted 10 lines
include/linux/virtio_config.h new file +10
-0+struct virtio_config_ops +{ +void *(*find)(struct virtio_device *vdev,u8 type,unsigned *len); +void (*get)(struct virtio_device *vdev,void *token, +void *buf,unsigned len); +void (*set)(struct virtio_device *vdev,void *token, +const void *buf,unsigned len); +u8 (*get_status)(struct virtio_device *vdev); +void (*set_status)(struct virtio_device *vdev,u8 status); + struct virtqueue *(*find_vq)(struct virtio_device *vdev,
Quoted 8 lines
include/linux/virtio_config.h line 71
Quoted 3 lines
include/linux/virtio_config.h new file +3
-0+ bool (*callback)(struct virtqueue *)); +void (*del_vq)(struct virtqueue *vq); +};The configuration logic looks more complicated than it should be. Maybe more of this can be done using data structure definitions instead of dynamic callback. E.g. the virtqueues of a given device can be listed as members of the struct
virtio_device.
I agree about the complexity, but the reason I didn't do that is the way the config system works. Drivers look for fields they want, and those fields are marked so the host can see what was used. This makes it fairly easy to add new fields and then tell if the guest understood them or not.
This includes new virtqueues, so the core must not simply grab them all. My previous solution was to put a "new_vq" and "del_vq" insidevirtqueue_ops: the driver found the config field and handed it through. That was a little messier for the driver.
Quoted 16 lines
Quoted 16 lines
include/linux/virtio_config.h new file +16
-0+/** +* virtio_config_val - get a single virtio config and mark it used. +* @config: the virtio config space +* @type: the type to search for. +* @val: a pointer to the value to fill in. +* +* Once used, the config type is marked with VIRTIO_CONFIG_F_USED so it can't +* be found again. This version does endian conversion. */ +#define virtio_config_val (vdev, type, v) ({ \ + int _err = __virtio_config_val((vdev),(type),(v),sizeof(*(v))); \ + \ + BUILD_BUG_ON(sizeof(*(v)) != 1 && sizeof(*(v)) != 2 \ + && sizeof(*(v)) != 4 && sizeof(*(v)) != 8); \ + if (!_err) { \ + switch (sizeof(*(v))) { \ + case 2: le16_to_cpus(v); break; \
Quoted 8 lines
include/linux/virtio_config.h line 94
Quoted 6 lines
include/linux/virtio_config.h new file +6
-0+case 4 :le32_to_cpus (v);break ; \ +case 8 :le64_to_cpus (v);break ; \ + } \ + } \ + _err; \ +})Especially the macro looks like something better avoided...
C'mon, everyone loves optimization!
(Which reminds me, I said little endian here but didn't actually do that in the lguest launcher, bad Rusty).
Thanks,
Rusty.
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
A message that is not in the archive (sent off-list or not yet received): 1190677058.27805.225.camel-bi+AKbBUZKY6gyzm1THtWbp2dZbC/[email protected]
Re: [PATCH 1/3] virtio interface
Quoted 13 lines · Rusty Russell
Quoted 6 lines · Arnd Bergmann
This is a pattern I've seen a few times before, but could never understand what it's good for. What is your reason for defining a new data structure that is used only once, instead of just
static struct
bus_typevirtio_bus_type;
static struct devicevirtio_root_dev;It's copied from the lguest bus which was copied from somewhere else. Creating a struct like this is a quiet complaint about the requirements to do so: it's not clear to me why I need to create a fake device, rather than making the bus the parent of the device if it needs one.
Quoted 5 lines
Quoted 3 lines
Also, I would not mix the two in a single source file. Instead, I think every driver that can provide virtio devices (pci, lguest, ...) should be responsible for setting the parent appropriately.
I don't mind: we could expose it.
What I mean with setting the parent appropriately is not to have a global device that is used by the hv-specific probing code, but to make sure that each of them provides their own one. The bus_type should either be global or provide the wrappers for device_register and driver_register that you have, but the host bridge device belongs with the code that probes it. E.g. when all virtio devices are behind PCI bridges, there does not need to be an empty /virtio or /lguest device node at all.
Arnd <><
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
A message that is not in the archive (sent off-list or not yet received): [email protected]
Re: [PATCH 1/3] virtio interface
Quoted 10 lines · Arnd Bergmann
Quoted 1 line · Rusty Russell
I don't mind: we could expose it.
What I mean with setting the parent appropriately is not to have a global device that is used by the hv-specific probing code, but to make sure that each of them provides their own one. The
bus_typeshould either be global or provide the wrappers fordevice_registeranddriver_registerthat you have, but the host bridge device belongs with the code that probes it. E.g. when all virtio devices are behind PCI bridges, there does not need to be an empty /virtio or /lguest device node at all.
Right, that makes sense. I'll shift this "virtio" device node out to the lguest code.
Thanks!
Rusty.
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
Re: [kvm-devel] [PATCH 1/3] virtio interface
In reply to Arnd BergmannQuoted 10 lines · Arnd Bergmann
Quoted 1 line · Rusty Russell
I don't mind: we could expose it.
What I mean with setting the parent appropriately is not to have a global device that is used by the hv-specific probing code, but to make sure that each of them provides their own one. The
bus_typeshould either be global or provide the wrappers fordevice_registeranddriver_registerthat you have, but the host bridge device belongs with the code that probes it. E.g. when all virtio devices are behind PCI bridges, there does not need to be an empty /virtio or /lguest device node at all.
Right, that makes sense. I'll shift this "virtio" device node out to the lguest code.
Thanks!
Rusty.
Re: [PATCH 1/3] virtio interface
In reply to a message not in the archiveQuoted 25 lines · Rusty Russell
Quoted 24 lines · Arnd Bergmann
Quoted 8 lines · Rusty Russell
drivers/virtio/virtio.c new file +8
-0+ +struct virtio_bus { +struct bus_type bus; +struct device dev; +}; + +static struct virtio_bus virtio_bus = { + .bus = {drivers/virtio/virtio.c line 70
Quoted 10 lines
drivers/virtio/virtio.c new file +10
-0+ .name = "virtio", + .match = virtio_dev_match, + .dev_attrs = virtio_dev_attrs, + }, + .dev = { +/* Can override this if you have a real bus behind it. */ + .parent = NULL, + .bus_id = "virtio", + } +};This is a pattern I've seen a few times before, but could never understand what it's good for. What is your reason for defining a new data structure that is used only once, instead of just
Quoted 7 lines
Quoted 2 lines
static struct
bus_typevirtio_bus_type;
static struct devicevirtio_root_dev;It's copied from the lguest bus which was copied from somewhere else. Creating a struct like this is a quiet complaint about the requirements to do so: it's not clear to me why I need to create a fake device, rather than making the bus the parent of the device if it needs one.
You may want to have different busses, all having their own root device, which share the same bus type.
Or you may want to embed the root device into a more complex structure.
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
Re: [kvm-devel] [PATCH 1/3] virtio interface
In reply to Rusty RussellQuoted 13 lines · Rusty Russell
Quoted 6 lines · Arnd Bergmann
This is a pattern I've seen a few times before, but could never understand what it's good for. What is your reason for defining a new data structure that is used only once, instead of just
static struct
bus_typevirtio_bus_type;
static struct devicevirtio_root_dev;It's copied from the lguest bus which was copied from somewhere else. Creating a struct like this is a quiet complaint about the requirements to do so: it's not clear to me why I need to create a fake device, rather than making the bus the parent of the device if it needs one.
Quoted 5 lines
Quoted 3 lines
Also, I would not mix the two in a single source file. Instead, I think every driver that can provide virtio devices (pci, lguest, ...) should be responsible for setting the parent appropriately.
I don't mind: we could expose it.
What I mean with setting the parent appropriately is not to have a global device that is used by the hv-specific probing code, but to make sure that each of them provides their own one. The bus_type should either be global or provide the wrappers for device_register and driver_register that you have, but the host bridge device belongs with the code that probes it. E.g. when all virtio devices are behind PCI bridges, there does not need to be an empty /virtio or /lguest device node at all.
Arnd <><
Re: [kvm-devel] [PATCH 1/3] virtio interface
In reply to Rusty RussellQuoted 25 lines · Rusty Russell
Quoted 24 lines · Arnd Bergmann
Quoted 8 lines · Rusty Russell
drivers/virtio/virtio.c new file +8
-0+ +struct virtio_bus { +struct bus_type bus; +struct device dev; +}; + +static struct virtio_bus virtio_bus = { + .bus = {drivers/virtio/virtio.c line 70
Quoted 10 lines
drivers/virtio/virtio.c new file +10
-0+ .name = "virtio", + .match = virtio_dev_match, + .dev_attrs = virtio_dev_attrs, + }, + .dev = { +/* Can override this if you have a real bus behind it. */ + .parent = NULL, + .bus_id = "virtio", + } +};This is a pattern I've seen a few times before, but could never understand what it's good for. What is your reason for defining a new data structure that is used only once, instead of just
Quoted 7 lines
Quoted 2 lines
static struct
bus_typevirtio_bus_type;
static struct devicevirtio_root_dev;It's copied from the lguest bus which was copied from somewhere else. Creating a struct like this is a quiet complaint about the requirements to do so: it's not clear to me why I need to create a fake device, rather than making the bus the parent of the device if it needs one.
You may want to have different busses, all having their own root device, which share the same bus type.
Or you may want to embed the root device into a more complex structure.
Re: [kvm-devel] [PATCH 1/3] virtio interface
In reply to Arnd BergmannQuoted 9 lines · Arnd Bergmann
Quoted 3 lines · Rusty Russell
This attempts to implement a "virtual I/O" layer which should allow common drivers to be efficiently used across most virtual I/O mechanisms. It will no-doubt need further enhancement.
Hi Rusty,
Thanks for your update, as you can imagine, I'm much happier with this version ;-)
Hi Arnd,
Yes, I thought you might be...
Quoted 23 lines
Quoted 8 lines
drivers/virtio/virtio.c new file +8
-0+ +struct virtio_bus { +struct bus_type bus; +struct device dev; +}; + +static struct virtio_bus virtio_bus = { + .bus = {drivers/virtio/virtio.c line 70
Quoted 10 lines
drivers/virtio/virtio.c new file +10
-0+ .name = "virtio", + .match = virtio_dev_match, + .dev_attrs = virtio_dev_attrs, + }, + .dev = { +/* Can override this if you have a real bus behind it. */ + .parent = NULL, + .bus_id = "virtio", + } +};This is a pattern I've seen a few times before, but could never understand what it's good for. What is your reason for defining a new data structure that is used only once, instead of just
Quoted 2 lines
static struct
bus_typevirtio_bus_type;
static struct devicevirtio_root_dev;
It's copied from the lguest bus which was copied from somewhere else. Creating a struct like this is a quiet complaint about the requirements to do so: it's not clear to me why I need to create a fake device, rather than making the bus the parent of the device if it needs one.
Quoted 3 lines
Also, I would not mix the two in a single source file. Instead, I think every driver that can provide virtio devices (pci, lguest, ...) should be responsible for setting the parent appropriately.
I don't mind: we could expose it.
Quoted 10 lines
Quoted 10 lines
include/linux/virtio_config.h new file +10
-0+struct virtio_config_ops +{ +void *(*find)(struct virtio_device *vdev,u8 type,unsigned *len); +void (*get)(struct virtio_device *vdev,void *token, +void *buf,unsigned len); +void (*set)(struct virtio_device *vdev,void *token, +const void *buf,unsigned len); +u8 (*get_status)(struct virtio_device *vdev); +void (*set_status)(struct virtio_device *vdev,u8 status); + struct virtqueue *(*find_vq)(struct virtio_device *vdev,
Quoted 8 lines
include/linux/virtio_config.h line 71
Quoted 3 lines
include/linux/virtio_config.h new file +3
-0+ bool (*callback)(struct virtqueue *)); +void (*del_vq)(struct virtqueue *vq); +};The configuration logic looks more complicated than it should be. Maybe more of this can be done using data structure definitions instead of dynamic callback. E.g. the virtqueues of a given device can be listed as members of the struct
virtio_device.
I agree about the complexity, but the reason I didn't do that is the way the config system works. Drivers look for fields they want, and those fields are marked so the host can see what was used. This makes it fairly easy to add new fields and then tell if the guest understood them or not.
This includes new virtqueues, so the core must not simply grab them all. My previous solution was to put a "new_vq" and "del_vq" insidevirtqueue_ops: the driver found the config field and handed it through. That was a little messier for the driver.
Quoted 16 lines
Quoted 16 lines
include/linux/virtio_config.h new file +16
-0+/** +* virtio_config_val - get a single virtio config and mark it used. +* @config: the virtio config space +* @type: the type to search for. +* @val: a pointer to the value to fill in. +* +* Once used, the config type is marked with VIRTIO_CONFIG_F_USED so it can't +* be found again. This version does endian conversion. */ +#define virtio_config_val (vdev, type, v) ({ \ + int _err = __virtio_config_val((vdev),(type),(v),sizeof(*(v))); \ + \ + BUILD_BUG_ON(sizeof(*(v)) != 1 && sizeof(*(v)) != 2 \ + && sizeof(*(v)) != 4 && sizeof(*(v)) != 8); \ + if (!_err) { \ + switch (sizeof(*(v))) { \ + case 2: le16_to_cpus(v); break; \
Quoted 8 lines
include/linux/virtio_config.h line 94
Quoted 6 lines
include/linux/virtio_config.h new file +6
-0+case 4 :le32_to_cpus (v);break ; \ +case 8 :le64_to_cpus (v);break ; \ + } \ + } \ + _err; \ +})Especially the macro looks like something better avoided...
C'mon, everyone loves optimization!
(Which reminds me, I said little endian here but didn't actually do that in the lguest launcher, bad Rusty).
Thanks,
Rusty.
PATCH 2/3 virtio ring implementation
In reply to Rusty RussellThese helper routines supply most of the virtqueue_ops for hypervisors which want to use a ring for virtio. Unlike the previous lguest implementation:
1) The rings are variable sized (2^n-1 elements).
2) They have an unfortunate limit of 65535 bytes per sg element.
3) The page numbers are always 64 bit (PAE anyone?)
4) They no longer place used[] on a separate page, just a separate cacheline.
5) We do a modulo on a variable. We could be tricky if we cared.
6) Interrupts and notifies are suppressed using flags within the rings.
Users need only implement the new_vq and free_vq hooks (KVM wants the guest to allocate the rings, lguest does it sanely).
--- arch/i386/lguest/Kconfig | 1 drivers/virtio/Kconfig | 5 drivers/virtio/Makefile | 1 drivers/virtio/virtio_ring.c | 316 ++++++++++++++++++++++++++++++++++++++++++ include/linux/virtio_ring.h | 119 +++++++++++++++ 5 files changed, 442 insertions(+)
===================================================================
arch/i386/lguest/Kconfig +1 -0
@@ -2,6 +2,7 @@ config LGUEST_GUEST bool "Lguest guest support" select PARAVIRT depends on !X86_PAE + select VIRTIO_RING help Lguest is a tiny in-kernel hypervisor. Selecting this will allow your kernel to boot under lguest. This option will increase
===================================================================
drivers/virtio/Kconfig +5 -0
@@ -1,3 +1,8 @@ # Virtio always gets selected by whoever wants it. config VIRTIO bool + +# Similarly the virtio ring implementation. +config VIRTIO_RING + bool + depends on VIRTIO
===================================================================
drivers/virtio/Makefile +1 -0
@@ -1,1 +1,2 @@ obj-$(CONFIG_VIRTIO) += virtio.o obj-$(CONFIG_VIRTIO) += virtio.o +obj-$(CONFIG_VIRTIO_RING) += virtio_ring.o
===================================================================
drivers/virtio/virtio_ring.c new file +316 -0
316 lines not on this page · raw message
===================================================================
include/linux/virtio_ring.h new file +119 -0
119 lines not on this page · raw message
Re: [kvm-devel] [PATCH 1/3] virtio interface
In reply to Rusty RussellQuoted 3 lines · Rusty Russell
This attempts to implement a "virtual I/O" layer which should allow common drivers to be efficiently used across most virtual I/O mechanisms. It will no-doubt need further enhancement.
Hi Rusty,
Thanks for your update, as you can imagine, I'm much happier with this version ;-)
Quoted 8 lines
drivers/virtio/virtio.c new file +8
-0+ +struct virtio_bus { +struct bus_type bus; +struct device dev; +}; + +static struct virtio_bus virtio_bus = { + .bus = {
drivers/virtio/virtio.c line 70
Quoted 10 lines
drivers/virtio/virtio.c new file +10
-0+ .name = "virtio", + .match = virtio_dev_match, + .dev_attrs = virtio_dev_attrs, + }, + .dev = { +/* Can override this if you have a real bus behind it. */ + .parent = NULL, + .bus_id = "virtio", + } +};
This is a pattern I've seen a few times before, but could never understand what it's good for. What is your reason for defining a new data structure that is used only once, instead of just
static struct bus_type virtio_bus_type;
static struct device virtio_root_dev;
Also, I would not mix the two in a single source file. Instead, I think every driver that can provide virtio devices (pci, lguest, ...) should be responsible for setting the parent appropriately.
Quoted 61 lines
include/linux/virtio_config.h new file +61
-0+#ifndef _LINUX_VIRTIO_CONFIG_H +#define _LINUX_VIRTIO_CONFIG_H +/* Virtio devices use a standardized configuration space to define their + * features and pass configuration information, but each implementation can + * store and access that space differently. */ +#include <linux/types.h> + +/* Status byte for guest to report progress, and synchronize config. */ +/* We have seen device and processed generic fields (VIRTIO_CONFIG_F_VIRTIO) */ +#define VIRTIO_CONFIG_S_ACKNOWLEDGE 1 +/* We have found a driver for the device. */ +#define VIRTIO_CONFIG_S_DRIVER 2 +/* Driver has used its parts of the config, and is happy */ +#define VIRTIO_CONFIG_S_DRIVER_OK 4 +/* We've given up on this device. */ +#define VIRTIO_CONFIG_S_FAILED 0x80 + +/* Feature byte (actually 7 bits availabe): */ +/* Requirements/features of the virtio implementation. */ +#define VIRTIO_CONFIG_F_VIRTIO 1 +/* Requirements/features of the virtqueue (may have more than one). */ +#define VIRTIO_CONFIG_F_VIRTQUEUE 2 + +#ifdef __KERNEL__ +struct virtio_device; + +/** + * virtio_config_ops - operations for configuring a virtio device + * @find: search for the next configuration field of the given type. + * vdev: the virtio_device + * type: the feature type + * len: the (returned) length of the field if found. + * Returns a token if found, or NULL. Never returnes the same field twice + * (ie. it's used up). + * @get: read the value of a configuration field after find(). + * vdev: the virtio_device + * token: the token returned from find(). + * buf: the buffer to write the field value into. + * len: the length of the buffer (given by find()). + * Note that contents are conventionally little-endian. + * @set: write the value of a configuration field after find(). + * vdev: the virtio_device + * token: the token returned from find(). + * buf: the buffer to read the field value from. + * len: the length of the buffer (given by find()). + * Note that contents are conventionally little-endian. + * @get_status: read the status byte + * vdev: the virtio_device + * Returns the status byte + * @set_status: write the status byte + * vdev: the virtio_device + * status: the new status byte + * @find_vq: find the first VIRTIO_CONFIG_F_VIRTQUEUE and create a virtqueue. + * vdev: the virtio_device + * callback: the virqtueue callback + * Returns the new virtqueue or ERR_PTR(). + * @del_vq: free a virtqueue found by find_vq(). + */ +struct virtio_config_ops +{ + void *(*find)(struct virtio_device *vdev, u8 type, unsigned *len);
include/linux/virtio_config.h line 71
Quoted 10 lines
include/linux/virtio_config.h new file +10
-0+void (*get)(struct virtio_device *vdev,void *token, +void *buf,unsigned len); +void (*set)(struct virtio_device *vdev,void *token, +const void *buf,unsigned len); +u8 (*get_status)(struct virtio_device *vdev); +void (*set_status)(struct virtio_device *vdev,u8 status); +struct virtqueue *(*find_vq)(struct virtio_device *vdev, +bool (*callback)(struct virtqueue *)); +void (*del_vq)(struct virtqueue *vq); +};
The configuration logic looks more complicated than it should be. Maybe more of this can be done using data structure definitions instead of dynamic callback. E.g. the virtqueues of a given device can be listed as members of the struct virtio_device.
Quoted 12 lines
include/linux/virtio_config.h new file +12
-0+/** +* virtio_config_val - get a single virtio config and mark it used. +* @config: the virtio config space +* @type: the type to search for. +* @val: a pointer to the value to fill in. +* +* Once used, the config type is marked with VIRTIO_CONFIG_F_USED so it can't +* be found again. This version does endian conversion. */ +#define virtio_config_val (vdev, type, v) ({ \ + int _err = __virtio_config_val((vdev),(type),(v),sizeof(*(v))); \ + \ + BUILD_BUG_ON(sizeof(*(v)) != 1 && sizeof(*(v)) != 2 \
include/linux/virtio_config.h line 94
Quoted 10 lines
include/linux/virtio_config.h new file +10
-0+ && sizeof(*(v)) != 4 && sizeof(*(v)) != 8); \ +if (!_err) { \ +switch (sizeof (*(v))) { \ +case 2 :le16_to_cpus (v);break ; \ +case 4 :le32_to_cpus (v);break ; \ +case 8 :le64_to_cpus (v);break ; \ + } \ + } \ + _err; \ +})
Especially the macro looks like something better avoided...
Arnd <><
PATCH 1/3 virtio interface
In reply to Rusty RussellThis attempts to implement a "virtual I/O" layer which should allow common drivers to be efficiently used across most virtual I/O mechanisms. It will no-doubt need further enhancement.
The virtio drivers add buffers to virtio queues; as the buffers are consumed the driver "interrupt" callbacks are invoked.
There is also a generic implementation of config space which drivers can query to get setup information from the host.
--- drivers/Kconfig | 2 drivers/Makefile | 1 drivers/virtio/Kconfig | 3 drivers/virtio/Makefile | 1 drivers/virtio/config.c | 13 ++ drivers/virtio/virtio.c | 187 +++++++++++++++++++++++++++++++++++++++ include/linux/mod_devicetable.h | 6 + include/linux/virtio.h | 110 ++++++++++++++++++++++ include/linux/virtio_config.h | 111 +++++++++++++++++++++++ 9 files changed, 434 insertions(+)
===================================================================
drivers/Kconfig +2 -0
@@ -87,4 +87,6 @@ source "drivers/kvm/Kconfig" source "drivers/kvm/Kconfig" source "drivers/uio/Kconfig" + +source "drivers/virtio/Kconfig" endmenu
===================================================================
drivers/Makefile +1 -0
@@ -88,3 +88,4 @@ obj-$(CONFIG_HID) += hid/ obj-$(CONFIG_HID) += hid/ obj-$(CONFIG_PPC_PS3) += ps3/ obj-$(CONFIG_OF) += of/ +obj-$(CONFIG_VIRTIO) += virtio/
===================================================================
drivers/virtio/Kconfig new file +3 -0
@@ -0,0 +1,3 @@ +# Virtio always gets selected by whoever wants it. +config VIRTIO + bool
===================================================================
drivers/virtio/Makefile new file +1 -0
@@ -0,0 +1,1 @@ +obj-$(CONFIG_VIRTIO) += virtio.o
===================================================================
drivers/virtio/config.c new file +13 -0
@@ -0,0 +1,13 @@ +/* Configuration space parsing helpers for virtio. +* +* The configuration is [type][len][... len bytes ...] fields. +* +* Copyright 2007 Rusty Russell, IBM Corporation. +* GPL v2 or later. +*/ +#include <linux/err.h> +#include <linux/virtio.h> +#include <linux/virtio_config.h> +#include <linux/bug.h> +#include <asm/system.h> +
===================================================================
drivers/virtio/virtio.c new file +187 -0
187 lines not on this page · raw message
===================================================================
include/linux/mod_devicetable.h +6 -0
@@ -340,4 +340,10 @@ struct parisc_device_id {#define PA_HVERSION_ANY_ID 0xffff#define PA_SVERSION_ANY_ID 0xffffffff +struct virtio_device_id { +__u32 device; +__u32 vendor; +}; +#define VIRTIO_DEV_ANY_ID 0xffffffff +#endif /* LINUX_MOD_DEVICETABLE_H */
===================================================================
include/linux/virtio.h new file +110 -0
110 lines not on this page · raw message
===================================================================
include/linux/virtio_config.h new file +111 -0
111 lines not on this page · raw message