qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH] [virtio] Add virtio block device sanboot support


From: Stefan Hajnoczi
Subject: [Qemu-devel] [PATCH] [virtio] Add virtio block device sanboot support
Date: Tue, 5 Jan 2010 20:46:45 +0000

This patch adds virtio block device support alongside the existing iSCSI,
ATA-over-Ethernet, and ramdisk block devices.  The virtio block device provides
storage in virtualized environments.

Using this patch, a gPXE option ROM can boot a QEMU/KVM virtual machine
directly from a virtio block device.

Here is an example QEMU invocation:
qemu -drive if=virtio,file=debian.qcow2 -option-rom gpxe/src/bin/1af41001.rom

SANBOOT_PROTO_VIRTIO_BLK must be defined in config/general.h to enable this
feature.  The gPXE option ROM must be built for PCI ID 1af4:1001.

The sanboot gPXE command is used with the virtio_blk: root path scheme.  The
virtio block device instance is identified by its PCI bus, device, and function
(there could be multiple virtio block devices).

gPXE> sanboot virtio_blk:PCI00:04.0

Perhaps the first available device should be chosen if virtio_blk: is given
without PCI bus, device, and function.  I am open to suggestions on how virtio
block device option ROMs should work.

I have successfully booted Debian testing i386 and FreeDOS 0.84-pre2 under QEMU
0.11.0.

Note that QEMU/KVM can boot from a virtio block device using a separate
non-virtio interface (-drive if=virtio,boot=on,[...]).  This gPXE patch
provides a native virtio block implementation.

While developing this feature, I noticed that the AoE sanboot code leaves a
pointer to a stack value around after it returns.  A commit to fix this is
included.

Stefan Hajnoczi (2):
  [sanboot] Prevent leaking a stack reference for "keep-san" AoE
  [virtio] Add virtio block device sanboot support

 src/arch/i386/interface/pcbios/aoeboot.c        |   54 +++--
 src/arch/i386/interface/pcbios/virtio_blkboot.c |   70 ++++++
 src/config/config.c                             |    3 +
 src/config/general.h                            |    1 +
 src/drivers/block/virtio-blk.c                  |  271 +++++++++++++++++++++++
 src/drivers/block/virtio-blk.h                  |   30 +++
 src/include/gpxe/errfile.h                      |    2 +
 src/include/gpxe/virtblk.h                      |   37 +++
 8 files changed, 447 insertions(+), 21 deletions(-)
 create mode 100644 src/arch/i386/interface/pcbios/virtio_blkboot.c
 create mode 100644 src/drivers/block/virtio-blk.c
 create mode 100644 src/drivers/block/virtio-blk.h
 create mode 100644 src/include/gpxe/virtblk.h

>From 0926649bece8e06dfdb19e4f819795da6ee364dd Mon Sep 17 00:00:00 2001
From: Stefan Hajnoczi <address@hidden>
Date: Tue, 5 Jan 2010 08:05:32 +0000
Subject: [PATCH 1/2] [sanboot] Prevent leaking a stack reference for
"keep-san" AoE

When the "keep-san" option is used, the function is exited without
unregistering the stack allocated int13h drive.  To prevent a dangling
pointer to the stack, these structs should be heap allocated.
---
 src/arch/i386/interface/pcbios/aoeboot.c |   54 ++++++++++++++++++-----------
 1 files changed, 33 insertions(+), 21 deletions(-)

diff --git a/src/arch/i386/interface/pcbios/aoeboot.c
b/src/arch/i386/interface/pcbios/aoeboot.c
index 8446c15..2670b15 100644
--- a/src/arch/i386/interface/pcbios/aoeboot.c
+++ b/src/arch/i386/interface/pcbios/aoeboot.c
@@ -1,11 +1,11 @@
 #include <stdint.h>
 #include <string.h>
+#include <stdlib.h>
 #include <stdio.h>
-#include <byteswap.h>
+#include <errno.h>
 #include <gpxe/aoe.h>
 #include <gpxe/ata.h>
 #include <gpxe/netdevice.h>
-#include <gpxe/settings.h>
 #include <gpxe/sanboot.h>
 #include <gpxe/abft.h>
 #include <int13.h>
@@ -13,50 +13,62 @@
 FILE_LICENCE ( GPL2_OR_LATER );

 static int aoeboot ( const char *root_path ) {
-       struct ata_device ata;
-       struct int13_drive drive;
+       struct ata_device *ata;
+       struct int13_drive *drive;
        int rc;

-       memset ( &ata, 0, sizeof ( ata ) );
-       memset ( &drive, 0, sizeof ( drive ) );
+       ata = zalloc ( sizeof ( *ata ) );
+       if ( ! ata ) {
+               rc = -ENOMEM;
+               goto err_alloc_ata;
+       }
+       drive = zalloc ( sizeof ( *drive ) );
+       if ( ! drive ) {
+               rc = -ENOMEM;
+               goto err_alloc_drive;
+       }

        /* FIXME: ugly, ugly hack */
        struct net_device *netdev = last_opened_netdev();

-       if ( ( rc = aoe_attach ( &ata, netdev, root_path ) ) != 0 ) {
+       if ( ( rc = aoe_attach ( ata, netdev, root_path ) ) != 0 ) {
                printf ( "Could not attach AoE device: %s\n",
                         strerror ( rc ) );
-               goto error_attach;
+               goto err_attach;
        }
-       if ( ( rc = init_atadev ( &ata ) ) != 0 ) {
+       if ( ( rc = init_atadev ( ata ) ) != 0 ) {
                printf ( "Could not initialise AoE device: %s\n",
                         strerror ( rc ) );
-               goto error_init;
+               goto err_init;
        }

        /* FIXME: ugly, ugly hack */
        struct aoe_session *aoe =
-               container_of ( ata.backend, struct aoe_session, refcnt );
+               container_of ( ata->backend, struct aoe_session, refcnt );
        abft_fill_data ( aoe );

-       drive.blockdev = &ata.blockdev;
+       drive->blockdev = &ata->blockdev;

-       register_int13_drive ( &drive );
-       printf ( "Registered as BIOS drive %#02x\n", drive.drive );
-       printf ( "Booting from BIOS drive %#02x\n", drive.drive );
-       rc = int13_boot ( drive.drive );
+       register_int13_drive ( drive );
+       printf ( "Registered as BIOS drive %#02x\n", drive->drive );
+       printf ( "Booting from BIOS drive %#02x\n", drive->drive );
+       rc = int13_boot ( drive->drive );
        printf ( "Boot failed\n" );

        /* Leave drive registered, if instructed to do so */
        if ( keep_san() )
                return rc;

-       printf ( "Unregistering BIOS drive %#02x\n", drive.drive );
-       unregister_int13_drive ( &drive );
+       printf ( "Unregistering BIOS drive %#02x\n", drive->drive );
+       unregister_int13_drive ( drive );

- error_init:
-       aoe_detach ( &ata );
- error_attach:
+ err_init:
+       aoe_detach ( ata );
+ err_attach:
+       free ( drive );
+ err_alloc_drive:
+       free ( ata );
+ err_alloc_ata:
        return rc;
 }

-- 
1.6.5


>From 3dbc385d29cbdff520ed0694934c01a6808ff1dc Mon Sep 17 00:00:00 2001
From: Stefan Hajnoczi <address@hidden>
Date: Tue, 5 Jan 2010 17:39:18 +0000
Subject: [PATCH 2/2] [virtio] Add virtio block device sanboot support

This patch adds virtio block device support alongside the existing
iSCSI, ATA-over-Ethernet, and ramdisk block devices.  A gPXE option ROM
can boot a QEMU/KVM virtual machine directly from a virtio block device:

    # Ensure SANBOOT_PROTO_VIRTIO_BLK is defined in config/defaults.h
    make bin/1af41001.rom

The sanboot gPXE command is used with the virtio_blk: root path scheme.
The virtio block device instance is identified by its PCI bus, device,
and function (there could be multiple virtio block devices).

    sanboot virtio_blk:PCI00:04.0

Successfully boots Debian testing i386 and FreeDOS 0.84-pre2 under QEMU.
---
 src/arch/i386/interface/pcbios/virtio_blkboot.c |   70 ++++++
 src/config/config.c                             |    3 +
 src/config/general.h                            |    1 +
 src/drivers/block/virtio-blk.c                  |  271 +++++++++++++++++++++++
 src/drivers/block/virtio-blk.h                  |   30 +++
 src/include/gpxe/errfile.h                      |    2 +
 src/include/gpxe/virtblk.h                      |   37 +++
 7 files changed, 414 insertions(+), 0 deletions(-)
 create mode 100644 src/arch/i386/interface/pcbios/virtio_blkboot.c
 create mode 100644 src/drivers/block/virtio-blk.c
 create mode 100644 src/drivers/block/virtio-blk.h
 create mode 100644 src/include/gpxe/virtblk.h

diff --git a/src/arch/i386/interface/pcbios/virtio_blkboot.c
b/src/arch/i386/interface/pcbios/virtio_blkboot.c
new file mode 100644
index 0000000..3c2dd47
--- /dev/null
+++ b/src/arch/i386/interface/pcbios/virtio_blkboot.c
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2010 Stefan Hajnoczi <address@hidden>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include <gpxe/sanboot.h>
+#include <gpxe/virtblk.h>
+#include <int13.h>
+
+/**
+ * @file
+ *
+ * Virtio block device boot
+ *
+ */
+
+static int virtio_blkboot ( const char *root_path ) {
+       struct int13_drive *drive;
+       struct virtblk *virtblk;
+       int rc;
+
+       virtblk = find_virtblk ( root_path + sizeof ( "virtio_blk:" ) - 1 );
+       if ( ! virtblk )
+               return -ENOENT;
+
+       drive = zalloc ( sizeof ( *drive ) );
+       if ( ! drive )
+               return -ENOMEM;
+
+       drive->blockdev = &virtblk->blockdev;
+
+       register_int13_drive ( drive );
+       printf ( "Registered as BIOS drive %#02x\n", drive->drive );
+       printf ( "Booting from BIOS drive %#02x\n", drive->drive );
+       rc = int13_boot ( drive->drive );
+       printf ( "Boot failed\n" );
+
+       /* Leave drive registered, if instructed to do so */
+       if ( keep_san() )
+               return rc;
+
+       printf ( "Unregistering BIOS drive %#02x\n", drive->drive );
+       unregister_int13_drive ( drive );
+       free ( drive );
+       return rc;
+}
+
+struct sanboot_protocol virtblk_sanboot_protocol __sanboot_protocol = {
+       .prefix = "virtio_blk:",
+       .boot = virtio_blkboot,
+};
diff --git a/src/config/config.c b/src/config/config.c
index 3c43dfb..bb0ff67 100644
--- a/src/config/config.c
+++ b/src/config/config.c
@@ -130,6 +130,9 @@ REQUIRE_OBJECT ( aoeboot );
 #ifdef SANBOOT_PROTO_IB_SRP
 REQUIRE_OBJECT ( ib_srpboot );
 #endif
+#ifdef SANBOOT_PROTO_VIRTIO_BLK
+REQUIRE_OBJECT ( virtio_blkboot );
+#endif

 /*
  * Drag in all requested resolvers
diff --git a/src/config/general.h b/src/config/general.h
index ee07dfc..a1dec39 100644
--- a/src/config/general.h
+++ b/src/config/general.h
@@ -63,6 +63,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
 //#undef       SANBOOT_PROTO_ISCSI     /* iSCSI protocol */
 //#undef       SANBOOT_PROTO_AOE       /* AoE protocol */
 //#undef       SANBOOT_PROTO_IB_SRP    /* Infiniband SCSI RDMA protocol */
+//#undef       SANBOOT_PROTO_VIRTIO_BLK /* Virtio block device */

 /*
  * Name resolution modules
diff --git a/src/drivers/block/virtio-blk.c b/src/drivers/block/virtio-blk.c
new file mode 100644
index 0000000..fab5930
--- /dev/null
+++ b/src/drivers/block/virtio-blk.c
@@ -0,0 +1,271 @@
+/*
+ * Copyright (C) 2010 Stefan Hajnoczi <address@hidden>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <errno.h>
+#include <stdlib.h>
+#include <gpxe/process.h>
+#include <gpxe/virtblk.h>
+#include "virtio-blk.h"
+
+/**
+ * @file
+ *
+ * Virtio block devices
+ *
+ */
+
+/** List of virtio block devices */
+static LIST_HEAD ( virtblk_devices );
+
+/**
+ * Register virtio block device
+ *
+ * @v virtblk          Virtio block device
+ *
+ * Adds the virtio block device to the list of virtio block devices.
+ */
+static void register_virtblk ( struct virtblk *virtblk ) {
+       list_add_tail ( &virtblk->virtblk_devices, &virtblk_devices );
+}
+
+/**
+ * Unregister virtio block device
+ *
+ * @v virtblk          Virtio block device
+ *
+ * Removes the virtio block device from the list of virtio block devices.
+ */
+static void unregister_virtblk ( struct virtblk *virtblk ) {
+       list_del ( &virtblk->virtblk_devices );
+}
+
+/**
+ * Find virtio block device by name
+ *
+ * @v device_name      Device name
+ * @ret virtblk                Virtio block device or NULL
+ *
+ * Searches the list of virtio block devices by name.
+ */
+struct virtblk *find_virtblk ( const char *device_name ) {
+       struct virtblk *virtblk;
+       DBG ( "find_virtblk \"%s\"\n", device_name );
+       list_for_each_entry ( virtblk, &virtblk_devices, virtblk_devices ) {
+               if ( ! strcmp ( device_name, virtblk->pdev->dev.name ) )
+                       return virtblk;
+       }
+       return NULL;
+}
+
+/**
+ * Issue an I/O request and wait for completion
+ *
+ * @v virtblk          Virtio block device
+ * @v type             VIRTIO_BLK_T_IN or VIRTIO_BLK_T_OUT
+ * @v block            Block number
+ * @v count            Block count
+ * @v buffer           Data buffer
+ * @ret rc             Return status code
+ */
+static int virtblk_command ( struct virtblk *virtblk, u32 type,
+                            uint64_t block, unsigned long count,
+                            userptr_t buffer ) {
+       /*
+        * Virtio block requests have the following format:
+        *
+        *   +--------------------------------+
+        *   | struct virtio_blk_outhdr  [IN] |
+        *   +--------------------------------+
+        *   | In/out buffer         [IN/OUT] |
+        *   +--------------------------------+
+        *   | Status byte              [OUT] |
+        *   +--------------------------------+
+        *
+        * The device fills in the status byte to indicate the outcome the
+        * operation.
+        */
+       struct vring_virtqueue *vq = &virtblk->virtqueue;
+       struct virtio_blk_outhdr hdr = {
+               .type = type,
+               .ioprio = 0,
+               .sector = block,
+       };
+       uint8_t status = VIRTIO_BLK_S_UNSUPP;
+       struct vring_list list[] = {
+               {
+                       .addr   = ( char * ) &hdr,
+                       .length = sizeof ( hdr ),
+               },
+               {
+                       .addr   = ( char * ) user_to_virt ( buffer, 0 ),
+                       .length = virtblk->blockdev.blksize * count,
+               },
+               {
+                       .addr   = ( char * ) &status,
+                       .length = sizeof ( status ),
+               },
+       };
+       unsigned int in, out;
+
+       DBG ( "VIRTBLK req 0x%02x LBA 0x%llx count 0x%lx\n",
+             type, block, count );
+
+       /* Number of elements readable and writable */
+       if ( type == VIRTIO_BLK_T_IN ) {
+               out = 1;
+               in = 2;
+       } else {
+               out = 2;
+               in = 1;
+       }
+
+       /* Add to virtqueue and kick host */
+       vring_add_buf ( vq, list, out, in, 0, 0 );
+       vring_kick ( virtblk->pdev->ioaddr, vq, 1 );
+
+       /* Wait for reply */
+       while ( ! vring_more_used ( vq ) ) {
+               mb();
+               step();
+       }
+
+       /* Reclaim virtqueue element */
+       vring_get_buf ( vq, NULL );
+       return status == VIRTIO_BLK_S_OK ? 0 : -EIO;
+}
+
+/**
+ * Read block
+ *
+ * @v blockdev         Block device
+ * @v block            Block number
+ * @v count            Block count
+ * @v buffer           Data buffer
+ * @ret rc             Return status code
+ */
+static int virtblk_read ( struct block_device *blockdev, uint64_t block,
+                         unsigned long count, userptr_t buffer ) {
+       struct virtblk *virtblk =
+               container_of ( blockdev, struct virtblk, blockdev );
+       return virtblk_command ( virtblk, VIRTIO_BLK_T_IN, block,
+                                count, buffer );
+}
+
+/**
+ * Write block
+ *
+ * @v blockdev         Block device
+ * @v block            Block number
+ * @v count            Block count
+ * @v buffer           Data buffer
+ * @ret rc             Return status code
+ */
+static int virtblk_write ( struct block_device *blockdev __unused,
uint64_t block __unused,
+                          unsigned long count __unused, userptr_t buffer 
__unused ) {
+       struct virtblk *virtblk =
+               container_of ( blockdev, struct virtblk, blockdev );
+       return virtblk_command ( virtblk, VIRTIO_BLK_T_OUT, block,
+                                count, buffer );
+}
+
+static struct block_device_operations virtblk_operations = {
+       .read   = virtblk_read,
+       .write  = virtblk_write,
+};
+
+/**
+ * Probe PCI device
+ *
+ * @v pci      PCI device
+ * @v id       PCI ID
+ * @ret rc     Return status code
+ */
+static int virtblk_probe ( struct pci_device *pci,
+                          const struct pci_device_id *id __unused ) {
+       unsigned long ioaddr = pci->ioaddr;
+
+       /* Initialize driver state */
+       struct virtblk *virtblk = zalloc ( sizeof *virtblk );
+       if ( ! virtblk )
+               return -ENOMEM;
+       INIT_LIST_HEAD ( &virtblk->virtblk_devices );
+       virtblk->blockdev.op = &virtblk_operations;
+       virtblk->pdev = pci;
+       pci->priv = virtblk;
+
+       /* Prepare the device */
+       adjust_pci_device ( pci );
+       vp_reset ( ioaddr );
+
+       /* Indicate that the driver is starting */
+       vp_set_status ( ioaddr, VIRTIO_CONFIG_S_ACKNOWLEDGE |
+                               VIRTIO_CONFIG_S_DRIVER );
+
+       /* Grab the I/O requests virtqueue */
+       if ( vp_find_vq ( ioaddr, 0, &virtblk->virtqueue ) < 0 ) {
+               free ( virtblk );
+               return -ENOENT;
+       }
+
+       /* Feature negotiation */
+       u32 features = vp_get_features ( ioaddr );
+       vp_set_features ( ioaddr, 0 ); /* no features required */
+
+       /* Find out the drive capacity */
+       virtblk->blockdev.blksize = 512; /* the default */
+       vp_get ( ioaddr, 0, &virtblk->blockdev.blocks,
+                sizeof virtblk->blockdev.blocks );
+
+       /* Indicate that the driver is ready */
+       vp_set_status ( ioaddr, VIRTIO_CONFIG_S_ACKNOWLEDGE |
+                               VIRTIO_CONFIG_S_DRIVER |
+                               VIRTIO_CONFIG_S_DRIVER_OK );
+
+       DBGC ( virtblk, "VIRTBLK %p virtio_blk:%s ioaddr=0x%lx irq=%d
features=0x%x capacity=%lld\n",
+              virtblk, pci->dev.name, ioaddr, pci->irq,
+              features, virtblk->blockdev.blocks );
+
+       register_virtblk ( virtblk );
+       return 0;
+}
+
+/**
+ * Remove PCI device
+ *
+ * @v pci      PCI device
+ */
+static void virtblk_remove ( struct pci_device *pci ) {
+       struct virtblk *virtblk = pci->priv;
+
+       unregister_virtblk ( virtblk );
+       vp_reset ( pci->ioaddr );
+       free ( virtblk );
+}
+
+static struct pci_device_id virtblk_ids[] = {
+       PCI_ROM(0x1af4, 0x1001, "virtio-blk", "Virtio Block Device", 0),
+};
+
+struct pci_driver virtblk_driver __pci_driver = {
+  .ids = virtblk_ids,
+  .id_count = ( sizeof ( virtblk_ids ) / sizeof ( virtblk_ids[0] ) ),
+  .probe = virtblk_probe,
+  .remove = virtblk_remove,
+};
diff --git a/src/drivers/block/virtio-blk.h b/src/drivers/block/virtio-blk.h
new file mode 100644
index 0000000..3a34868
--- /dev/null
+++ b/src/drivers/block/virtio-blk.h
@@ -0,0 +1,30 @@
+#ifndef _VIRTIO_BLK_H
+#define _VIRTIO_BLK_H
+/* This header is BSD licensed so anyone can use the definitions to implement
+ * compatible drivers/servers. */
+
+FILE_LICENCE ( BSD2 );
+
+/*
+ * Command types
+ */
+
+/* These two define direction. */
+#define VIRTIO_BLK_T_IN                0
+#define VIRTIO_BLK_T_OUT       1
+
+/* This is the first element of the read scatter-gather list. */
+struct virtio_blk_outhdr {
+       /* VIRTIO_BLK_T* */
+       u32 type;
+       /* io priority. */
+       u32 ioprio;
+       /* Sector (ie. 512 byte offset) */
+       u64 sector;
+};
+
+/* And this is the final byte of the write scatter-gather list. */
+#define VIRTIO_BLK_S_OK                0
+#define VIRTIO_BLK_S_IOERR     1
+#define VIRTIO_BLK_S_UNSUPP    2
+#endif /* _VIRTIO_BLK_H */
diff --git a/src/include/gpxe/errfile.h b/src/include/gpxe/errfile.h
index 5231c14..092d7eb 100644
--- a/src/include/gpxe/errfile.h
+++ b/src/include/gpxe/errfile.h
@@ -122,6 +122,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
 #define ERRFILE_linda               ( ERRFILE_DRIVER | 0x00730000 )
 #define ERRFILE_ata                 ( ERRFILE_DRIVER | 0x00740000 )
 #define ERRFILE_srp                 ( ERRFILE_DRIVER | 0x00750000 )
+#define ERRFILE_virtio_blk          ( ERRFILE_DRIVER | 0x00760000 )

 #define ERRFILE_aoe                    ( ERRFILE_NET | 0x00000000 )
 #define ERRFILE_arp                    ( ERRFILE_NET | 0x00010000 )
@@ -191,6 +192,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
 #define ERRFILE_x509                 ( ERRFILE_OTHER | 0x00160000 )
 #define ERRFILE_login_ui             ( ERRFILE_OTHER | 0x00170000 )
 #define ERRFILE_ib_srpboot           ( ERRFILE_OTHER | 0x00180000 )
+#define ERRFILE_virtio_blkboot       ( ERRFILE_OTHER | 0x00190000 )

 /** @} */

diff --git a/src/include/gpxe/virtblk.h b/src/include/gpxe/virtblk.h
new file mode 100644
index 0000000..781d433
--- /dev/null
+++ b/src/include/gpxe/virtblk.h
@@ -0,0 +1,37 @@
+#ifndef _GPXE_VIRTBLK_H
+#define _GPXE_VIRTBLK_H
+
+/** @file
+ *
+ * Virtio block device
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <gpxe/list.h>
+#include <gpxe/pci.h>
+#include <gpxe/virtio-ring.h>
+#include <gpxe/virtio-pci.h>
+#include <gpxe/blockdev.h>
+
+/**
+ * Virtio block device
+ */
+struct virtblk {
+       /** List of virtio-blk devices */
+       struct list_head virtblk_devices;
+
+       /** Underlying PCI device */
+       struct pci_device *pdev;
+
+       /** Outgoing requests virtqueue */
+       struct vring_virtqueue virtqueue;
+
+       /** Block device */
+       struct block_device blockdev;
+};
+
+extern struct virtblk *find_virtblk ( const char *device_name );
+
+#endif /* _GPXE_VIRTBLK_H */
-- 
1.6.5

Attachment: virtio_blk.diff
Description: Text Data


reply via email to

[Prev in Thread] Current Thread [Next in Thread]