From: Arnd Bergmann <arnd@arndb.de>
To: Cornelia Huck <cornelia.huck@de.ibm.com>
Cc: "H. Peter Anvin" <hpa@zytor.com>,
Jeremy Fitzhardinge <jeremy@goop.org>, Andi Kleen <ak@suse.de>,
Jeff Garzik <jeff@garzik.org>,
virtualization@lists.linux-foundation.org,
Virtualization Mailing List <virtualization@lists.osdl.org>,
Linux Kernel Mailing List <linux-kernel@vger.kernel.org>,
mathiasen@gmail.com
Subject: Re: A set of "standard" virtual devices?
Date: Tue, 3 Apr 2007 14:15:37 +0200 [thread overview]
Message-ID: <200704031415.38381.arnd@arndb.de> (raw)
In-Reply-To: <20070403124108.06108665@gondolin.boeblingen.de.ibm.com>
On Tuesday 03 April 2007, Cornelia Huck wrote:
> >
> > I think that's true outside of s390, but a standardized virtual device
> > interface should be able to work there as well. Interestingly, the
> > s390 channel I/O also uses two 16 bit numbers to identify a device
> > (type and model), just like PCI or USB, so in that light, we might
> > be able to use the same number space for something entirely different
> > depending on the virtual bus.
>
> Even if we used those ids for cu_type and dev_type, it would still be
> ugly IMO. It would be much cleaner to just define a very simple, easy
> to implement virtual bus without dragging implementation details for
> other types of devices around.
Right, but an interesting point is the question what to do when running
another operating system as a guest under Linux, e.g. with kvm.
Ideally, you'd want to use the same interface to announce the presence
of the device, which can be done far more easily with PCI than using
a new bus type that you'd need to implement for every OS, instead of
just implementing the virtual PCI driver.
Using a 16 bit number to identify a specific interface sounds like
a good idea to me, if only for the reason that it is a widely used
approach. The alternative would be to use an ascii string, like we
have for open-firmware devices on powerpc or sparc.
I think in either way, we need to abstract the driver for the virtual
device from the underlying bus infrastructure, which is hypervisor
and/or platform dependent. The abstraction could work roughly like this:
==========
virt_dev.h
==========
struct virt_driver { /* platform independent */
struct device_driver drv;
struct pci_device_id *ids; /* not necessarily PCI */
};
struct virt_bus {
/* platform dependent */
long (*transfer)(struct virt_dev *dev, void *buffer,
unsigned long size, int type);
};
struct virt_dev {
struct device dev;
struct virt_driver *driver;
struct virt_bus *bus;
struct pci_device_id id;
int irq;
};
==============
virt_example.c
==============
static ssize_t virt_pipe_read(struct file *filp, char __user *buffer,
size_t len, loff_t *off)
{
struct virt_dev *dev = filp->private_data;
ssize_t ret = dev->bus->transfer(dev, buffer, len, READ);
*off += ret;
return ret;
}
static struct file_operations virt_pipe_fops = {
.open = nonseekable_open,
.read = virt_pipe_read,
};
static int virt_pipe_probe(struct device *dev)
{
struct virt_dev *vdev = to_virt_dev(dev);
struct miscdev *mdev = kmalloc(sizeof(*dev), GFP_KERNEL);
mdev->name = "virt_pipe";
mdev->fops = &virt_pipe_fops;
mdev->parent = dev;
return register_miscdev(mdev);
}
static struct pci_device_id virt_pipe_id = {
.vendor = PCI_VENDOR_LINUX, .device = 0x3456,
};
MODULE_DEVICE_TABLE(pci, virt_pipe_id);
static struct virt_driver virt_pipe_driver = {
.drv = {
.name = "virt_pipe",
.probe = virt_pipe_probe,
},
.ids = &virt_pipe_id,
}
static int virt_pipe_init(void)
{
return virt_driver_register(&virt_pipe_driver);
}
module_init(virt_pipe_init);
==============
virt_devtree.c
==============
static long virt_devtree_transfer(struct virt_dev *dev, void *buffer,
unsigned long size, int type)
{
long reg;
switch type {
case READ:
ret = hcall(HV_READ, dev->dev.platform_data, buffer, size);
break;
case WRITE:
ret = hcall(HV_WRITE, dev->dev.platform_data, buffer, size);
break;
default:
BUG();
}
return ret;
}
static struct virt_bus virt_devtree_bus = {
.transfer = virt_devtree_transfer,
};
static int virt_devtree_probe(struct of_device *ofdev,
struct of_device_id *match)
{
struct virt_dev *vdev = kzalloc(sizeof(*vdev);
vdev->bus = &virt_devtree_bus;
vdev->dev.parent = &ofdev->dev;
vdev.id.vendor = PCI_VENDOR_LINUX;
vdev.id.device = *of_get_property(ofdev, "virt_dev_id"),
vdev.irq = of_irq_parse_and_map(ofdev, 0);
return device_register(&vdev->dev);
}
struct of_device_id virt_devtree_ids = {
.compatible = "virt-dev",
};
static struct of_platform_driver virt_devtree_driver = {
.probe = virt_devtree_probe,
.match_table = &virt_devtree_ids,
};
==============
virt_pci.c
==============
static long virt_pci_transfer(struct virt_dev *dev, void *buffer,
unsigned long size, int type)
{
struct virt_pci_regs __iomem *regs = dev->dev.platform_data;
switch type {
case READ:
mmio_insb(regs->read_port, buffer, size);
break;
case WRITE:
mmio_outsb(regs->write_port, buffer, size);
break;
default:
BUG();
}
return size;
}
static struct virt_bus virt_pci_bus = {
.transfer = virt_pci_transfer,
};
static int virt_pci_probe(struct pci_dev *pdev,
struct pci_device_id *match)
{
struct virt_dev *vdev = kzalloc(sizeof(*vdev);
vdev->bus = &virt_pci_bus;
vdev->dev.parent = &pdev->dev;
vdev.id = *match;
vdev.irq = pdev->irq;
return device_register(&vdev->dev);
}
struct pci_device_id virt_pci_ids = {
.compatible = "virt-dev",
};
static struct of_platform_driver virt_pci_driver = {
.probe = virt_pci_probe,
.match_table = &virt_pci_ids,
};
Arnd <><
next prev parent reply other threads:[~2007-04-03 12:15 UTC|newest]
Thread overview: 36+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <4611652F.700@zytor.com>
2007-04-02 20:56 ` A set of "standard" virtual devices? Jeremy Fitzhardinge
2007-04-02 21:12 ` Andi Kleen
2007-04-02 21:33 ` Jeff Garzik
2007-04-02 21:36 ` Andi Kleen
2007-04-02 21:42 ` Jeremy Fitzhardinge
2007-04-02 21:53 ` Anthony Liguori
2007-04-02 22:04 ` Jeremy Fitzhardinge
2007-04-02 22:10 ` H. Peter Anvin
2007-04-02 22:25 ` Jeff Garzik
2007-04-02 22:30 ` H. Peter Anvin
2007-04-03 9:41 ` Arnd Bergmann
2007-04-03 10:41 ` Cornelia Huck
2007-04-03 12:15 ` Arnd Bergmann [this message]
2007-04-03 13:39 ` Cornelia Huck
2007-04-03 14:03 ` Arnd Bergmann
2007-04-03 16:07 ` Cornelia Huck
2007-04-03 8:29 ` Christian Borntraeger
2007-04-03 8:30 ` Andi Kleen
2007-04-03 9:17 ` Cornelia Huck
2007-04-03 9:26 ` Andi Kleen
2007-04-03 10:51 ` Cornelia Huck
2007-04-03 15:00 ` Adrian Bunk
2007-04-03 17:50 ` Arnd Bergmann
2007-04-03 19:07 ` Jeremy Fitzhardinge
2007-04-03 19:42 ` Arnd Bergmann
2007-04-03 19:55 ` Jeremy Fitzhardinge
2007-04-03 20:03 ` H. Peter Anvin
2007-04-03 21:00 ` Jeremy Fitzhardinge
2007-04-03 21:45 ` H. Peter Anvin
2007-04-03 21:51 ` Arnd Bergmann
2007-04-03 22:10 ` H. Peter Anvin
2007-04-03 22:49 ` Arnd Bergmann
2007-04-04 0:52 ` H. Peter Anvin
2007-04-04 13:11 ` Arnd Bergmann
2007-04-04 15:50 ` H. Peter Anvin
2007-04-03 20:50 ` Arnd Bergmann
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=200704031415.38381.arnd@arndb.de \
--to=arnd@arndb.de \
--cc=ak@suse.de \
--cc=cornelia.huck@de.ibm.com \
--cc=hpa@zytor.com \
--cc=jeff@garzik.org \
--cc=jeremy@goop.org \
--cc=linux-kernel@vger.kernel.org \
--cc=mathiasen@gmail.com \
--cc=virtualization@lists.linux-foundation.org \
--cc=virtualization@lists.osdl.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).