rpms/seabios/F-13 seabios-Set-CONFIG_S3_RESUME_VGA_INIT-to-1.patch, NONE, 1.1 seabios-Support-for-booting-from-virtio-disks.patch, NONE, 1.1 seabios-do-not-advertise-hpet-to-a-guest-OS.patch, NONE, 1.1 seabios-fix-resume-from-S3-with-QXL-device.patch, NONE, 1.1 seabios-smbios-avoid-counting-io-hole-as-ram.patch, NONE, 1.1 seabios-zero-memory-before-use.patch, NONE, 1.1 seabios.spec, 1.3, 1.4

Justin M. Forbes jforbes at fedoraproject.org
Wed Jun 30 15:43:24 UTC 2010


Author: jforbes

Update of /cvs/pkgs/rpms/seabios/F-13
In directory cvs01.phx2.fedoraproject.org:/tmp/cvs-serv11654

Modified Files:
	seabios.spec 
Added Files:
	seabios-Set-CONFIG_S3_RESUME_VGA_INIT-to-1.patch 
	seabios-Support-for-booting-from-virtio-disks.patch 
	seabios-do-not-advertise-hpet-to-a-guest-OS.patch 
	seabios-fix-resume-from-S3-with-QXL-device.patch 
	seabios-smbios-avoid-counting-io-hole-as-ram.patch 
	seabios-zero-memory-before-use.patch 
Log Message:
Several fixes from upstream

seabios-Set-CONFIG_S3_RESUME_VGA_INIT-to-1.patch:
 config.h |    3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

--- NEW FILE seabios-Set-CONFIG_S3_RESUME_VGA_INIT-to-1.patch ---
From: Eduardo Habkost <ehabkost at redhat.com>
Date: Tue, 6 Apr 2010 17:37:33 -0300
Subject: [PATCH] Set CONFIG_S3_RESUME_VGA_INIT to 1

> According to conversation in bug 545808, seabios configuration parameter
> CONFIG_S3_RESUME_VGA_INIT should default to 1 for RHEL 6. This way we can make
> KVM bios to run vga rom on S3 resume without running the vbetool (which won't
> be present) inside a virt guest.

Signed-off-by: Eduardo Habkost <ehabkost at redhat.com>
---
 src/config.h |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

Signed-off-by: Eduardo Habkost <ehabkost at redhat.com>
---
 src/config.h |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/src/config.h b/src/config.h
index 6297a48..afa0612 100644
--- a/src/config.h
+++ b/src/config.h
@@ -110,7 +110,7 @@
 // Support S3 resume handler.
 #define CONFIG_S3_RESUME 1
 // Run the vga rom during S3 resume.
-#define CONFIG_S3_RESUME_VGA_INIT 0
+#define CONFIG_S3_RESUME_VGA_INIT 1
 // define it if the (emulated) hardware supports SMM mode
 #define CONFIG_USE_SMM 1
 // Maximum number of map entries in the e820 map
-- 
1.7.0.3


seabios-Support-for-booting-from-virtio-disks.patch:
 Makefile          |    3 
 src/block.c       |    6 +
 src/config.h      |    3 
 src/disk.h        |    1 
 src/pci_ids.h     |    3 
 src/post.c        |    2 
 src/virtio-blk.c  |  170 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/virtio-blk.h  |   44 +++++++++++++
 src/virtio-pci.c  |   69 +++++++++++++++++++++
 src/virtio-pci.h  |  100 +++++++++++++++++++++++++++++++
 src/virtio-ring.c |  154 ++++++++++++++++++++++++++++++++++++++++++++++++
 src/virtio-ring.h |  130 ++++++++++++++++++++++++++++++++++++++++-
 12 files changed, 683 insertions(+), 2 deletions(-)

--- NEW FILE seabios-Support-for-booting-from-virtio-disks.patch ---
From: Gleb Natapov <gleb at redhat.com>
Date: Tue, 11 May 2010 12:46:28 -0300
Subject: [PATCH] Support for booting from virtio disks


This patch adds native support for booting from virtio disks to Seabios.

Upstream status: 89acfa3fb404bd81eac23bd5a3fb92d4eec50648

Signed-off-by: Gleb Natapov <gleb at redhat.com>
--
			Gleb.

Signed-off-by: Eduardo Habkost <ehabkost at redhat.com>
---
 Makefile          |    3 +-
 src/block.c       |    6 ++
 src/config.h      |    3 +
 src/disk.h        |    1 +
 src/pci_ids.h     |    3 +
 src/post.c        |    2 +
 src/virtio-blk.c  |  170 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/virtio-blk.h  |   44 ++++++++++++++
 src/virtio-pci.c  |   69 +++++++++++++++++++++
 src/virtio-pci.h  |  100 +++++++++++++++++++++++++++++++
 src/virtio-ring.c |  154 ++++++++++++++++++++++++++++++++++++++++++++++++
 src/virtio-ring.h |  129 ++++++++++++++++++++++++++++++++++++++++
 12 files changed, 683 insertions(+), 1 deletions(-)
 create mode 100644 src/virtio-blk.c
 create mode 100644 src/virtio-blk.h
 create mode 100644 src/virtio-pci.c
 create mode 100644 src/virtio-pci.h
 create mode 100644 src/virtio-ring.c
 create mode 100644 src/virtio-ring.h

diff --git a/Makefile b/Makefile
index c33647e..ccf41af 100644
--- a/Makefile
+++ b/Makefile
@@ -14,7 +14,8 @@ OUT=out/
 SRCBOTH=misc.c pmm.c stacks.c output.c util.c block.c floppy.c ata.c mouse.c \
         kbd.c pci.c serial.c clock.c pic.c cdrom.c ps2port.c smp.c resume.c \
         pnpbios.c pirtable.c vgahooks.c ramdisk.c pcibios.c \
-        usb.c usb-uhci.c usb-ohci.c usb-hid.c paravirt.c
+        usb.c usb-uhci.c usb-ohci.c usb-hid.c paravirt.c \
+        virtio-ring.c virtio-pci.c virtio-blk.c
 SRC16=$(SRCBOTH) system.c disk.c apm.c font.c
 SRC32FLAT=$(SRCBOTH) post.c shadow.c memmap.c coreboot.c boot.c \
       acpi.c smm.c mptable.c smbios.c pciinit.c optionroms.c mtrr.c \
diff --git a/src/block.c b/src/block.c
index 01aa84a..0ef1c9a 100644
--- a/src/block.c
+++ b/src/block.c
@@ -10,6 +10,7 @@
 #include "cmos.h" // inb_cmos
 #include "util.h" // dprintf
 #include "ata.h" // process_ata_op
+#include "virtio-blk.h" // process_virtio_op
 
 struct drives_s Drives VAR16VISIBLE;
 
@@ -297,6 +298,9 @@ describe_drive(struct drive_s *drive_g)
     case DTYPE_RAMDISK:
         describe_ramdisk(drive_g);
         break;
+    case DTYPE_VIRTIO:
+        describe_virtio(drive_g);
+        break;
     default:
         printf("Unknown");
         break;
@@ -324,6 +328,8 @@ process_op(struct disk_op_s *op)
         return process_ramdisk_op(op);
     case DTYPE_CDEMU:
         return process_cdemu_op(op);
+    case DTYPE_VIRTIO:
+        return  process_virtio_op(op);
     default:
         op->count = 0;
         return DISK_RET_EPARAM;
diff --git a/src/config.h b/src/config.h
index afa0612..1f6a563 100644
--- a/src/config.h
+++ b/src/config.h
@@ -131,6 +131,9 @@
 #define CONFIG_SUBMODEL_ID   0x00
 #define CONFIG_BIOS_REVISION 0x01
 
+// Support boot from virtio storage
+#define CONFIG_VIRTIO_BLK 1
+
 // Various memory addresses used by the code.
 #define BUILD_STACK_ADDR          0x7000
 #define BUILD_S3RESUME_STACK_ADDR 0x1000
diff --git a/src/disk.h b/src/disk.h
index ac5748e..749fedb 100644
--- a/src/disk.h
+++ b/src/disk.h
@@ -198,6 +198,7 @@ struct drive_s {
 #define DTYPE_ATAPI    0x03
 #define DTYPE_RAMDISK  0x04
 #define DTYPE_CDEMU    0x05
+#define DTYPE_VIRTIO   0x07
 
 #define TRANSLATION_NONE  0
 #define TRANSLATION_LBA   1
diff --git a/src/pci_ids.h b/src/pci_ids.h
index 1800f1d..e1cded2 100644
--- a/src/pci_ids.h
+++ b/src/pci_ids.h
@@ -2605,3 +2605,6 @@
 #define PCI_DEVICE_ID_RME_DIGI32	0x9896
 #define PCI_DEVICE_ID_RME_DIGI32_PRO	0x9897
 #define PCI_DEVICE_ID_RME_DIGI32_8	0x9898
+
+#define PCI_VENDOR_ID_REDHAT_QUMRANET	0x1af4
+#define PCI_DEVICE_ID_VIRTIO_BLK	0x1001
diff --git a/src/post.c b/src/post.c
index fb3b37f..ec9d21f 100644
--- a/src/post.c
+++ b/src/post.c
@@ -23,6 +23,7 @@
 #include "smbios.h" // smbios_init
 #include "paravirt.h" // qemu_cfg_port_probe
 #include "ps2port.h" // ps2port_setup
+#include "virtio-blk.h" // virtio_blk_setup
 
 void
 __set_irq(int vector, void *loc)
@@ -212,6 +213,7 @@ post(void)
     floppy_setup();
     ata_setup();
     ramdisk_setup();
+    virtio_blk_setup();
 
     // Run option roms
     if (CONFIG_THREADS && CONFIG_THREAD_OPTIONROMS) {
diff --git a/src/virtio-blk.c b/src/virtio-blk.c
new file mode 100644
index 0000000..14719c9
--- /dev/null
+++ b/src/virtio-blk.c
@@ -0,0 +1,170 @@
+// Virtio block boot support.
+//
+// Copyright (C) 2010 Red Hat Inc.
+//
+// Authors:
+//  Gleb Natapov <gnatapov at redhat.com>
+//
+// This file may be distributed under the terms of the GNU LGPLv3 license.
+
+#include "util.h" // dprintf
+#include "pci.h" // foreachpci
+#include "config.h" // CONFIG_*
+#include "biosvar.h" // GET_GLOBAL
+#include "pci_ids.h" // PCI_DEVICE_ID_VIRTIO_BLK
+#include "pci_regs.h" // PCI_VENDOR_ID
+#include "boot.h" // add_bcv_internal
+#include "virtio-pci.h"
+#include "virtio-ring.h"
+#include "virtio-blk.h"
+#include "disk.h"
+
+struct virtiodrive_s {
+    struct vring_virtqueue *vq;
+    u16 ioaddr;
+};
+
+static int
+virtio_blk_read(struct disk_op_s *op)
+{
+    struct drive_s *drive_g = op->drive_g;
+    struct virtiodrive_s *vdrive_g = (void*)GET_GLOBAL(drive_g->cntl_info);
+    struct vring_virtqueue *vq = GET_FLATPTR(vdrive_g->vq);
+    struct virtio_blk_outhdr hdr = {
+        .type = VIRTIO_BLK_T_IN,
+        .ioprio = 0,
+        .sector = op->lba,
+    };
+    u8 status = VIRTIO_BLK_S_UNSUPP;
+    struct vring_list sg[] = {
+        {
+            .addr	= MAKE_FLATPTR(GET_SEG(SS), &hdr),
+            .length	= sizeof(hdr),
+        },
+        {
+            .addr	= op->buf_fl,
+            .length	= GET_GLOBAL(drive_g->blksize) * op->count,
+        },
+        {
+            .addr	= MAKE_FLATPTR(GET_SEG(SS), &status),
+            .length	= sizeof(status),
+        },
+    };
+
+    /* Add to virtqueue and kick host */
+    vring_add_buf(vq, sg, 1, 2, 0, 0);
+    vring_kick(GET_FLATPTR(vdrive_g->ioaddr), vq, 1);
+
+    /* Wait for reply */
+    while (!vring_more_used(vq))
+        udelay(5);
+
+    /* Reclaim virtqueue element */
+    vring_get_buf(vq, NULL);
+    return status == VIRTIO_BLK_S_OK ? DISK_RET_SUCCESS : DISK_RET_EBADTRACK;
+}
+
+int
+process_virtio_op(struct disk_op_s *op)
+{
+    switch (op->command) {
+    case CMD_READ:
+        return virtio_blk_read(op);
+    case CMD_FORMAT:
+    case CMD_WRITE:
+        return DISK_RET_EWRITEPROTECT;
+    case CMD_RESET:
+    case CMD_ISREADY:
+    case CMD_VERIFY:
+    case CMD_SEEK:
+        return DISK_RET_SUCCESS;
+    default:
+        op->count = 0;
+        return DISK_RET_EPARAM;
+    }
+}
+
+void
+virtio_blk_setup(void)
+{
+    ASSERT32FLAT();
+    if (! CONFIG_VIRTIO_BLK)
+        return;
+
+    dprintf(3, "init virtio-blk\n");
+
+    int bdf, max;
+    u32 id = PCI_VENDOR_ID_REDHAT_QUMRANET | (PCI_DEVICE_ID_VIRTIO_BLK << 16);
+    foreachpci(bdf, max) {
+        u32 v = pci_config_readl(bdf, PCI_VENDOR_ID);
+        if (v != id)
+            continue;
+        dprintf(3, "found virtio-blk at %x:%x\n", pci_bdf_to_bus(bdf),
+                pci_bdf_to_dev(bdf));
+        struct virtiodrive_s *vdrive_g = malloc_fseg(sizeof(*vdrive_g));
+        struct vring_virtqueue *vq = malloc_low(sizeof(*vq));
+        if (!vdrive_g || !vq) {
+        fail:
+            free(vdrive_g);
+            free(vq);
+            dprintf(1, "Can't alloca memory for virtio-blk  %x:%x\n",
+                            pci_bdf_to_bus(bdf), pci_bdf_to_dev(bdf));
+            return;
+        }
+
+        u16 ioaddr = pci_config_readl(bdf, PCI_BASE_ADDRESS_0) &
+            PCI_BASE_ADDRESS_IO_MASK;
+
+        memset(vdrive_g, 0, sizeof(*vdrive_g));
+        vdrive_g->ioaddr = ioaddr;
+        vdrive_g->vq = vq;
+
+        vp_reset(ioaddr);
+        vp_set_status(ioaddr, VIRTIO_CONFIG_S_ACKNOWLEDGE |
+                      VIRTIO_CONFIG_S_DRIVER );
+
+        if (vp_find_vq(ioaddr, 0, vdrive_g->vq) < 0 ) {
+            free(vdrive_g);
+            free(vq);
+            dprintf(1, "fail to find vq for virtio-blk %x:%x\n",
+                    pci_bdf_to_bus (bdf), pci_bdf_to_dev(bdf));
+            continue;
+        }
+
+        struct drive_s *drive_g = allocDrive();
+        if (!drive_g)
+            goto fail;
+
+        drive_g->type = DTYPE_VIRTIO;
+        drive_g->cntl_id = bdf;
+        drive_g->cntl_info = (u32)vdrive_g;
+
+        struct virtio_blk_config cfg;
+        vp_get(ioaddr, 0, &cfg, sizeof(cfg));
+
+        u32 f = vp_get_features(ioaddr);
+        drive_g->blksize = (f & (1 << VIRTIO_BLK_F_BLK_SIZE)) ?
+            cfg.blk_size : DISK_SECTOR_SIZE;
+        drive_g->sectors = cfg.capacity;
+        dprintf(3, "virtio-blk %x:%x blksize=%d sectors=%u\n",
+                pci_bdf_to_bus (bdf), pci_bdf_to_dev(bdf),
+                drive_g->blksize, (u32)drive_g->sectors);
+
+        drive_g->pchs.cylinders = cfg.cylinders;
+        drive_g->pchs.heads = cfg.heads;
+        drive_g->pchs.spt = cfg.sectors;
+
+        setup_translation(drive_g);
+        add_bcv_internal(drive_g);
+
+        vp_set_status(ioaddr, VIRTIO_CONFIG_S_ACKNOWLEDGE |
+                      VIRTIO_CONFIG_S_DRIVER | VIRTIO_CONFIG_S_DRIVER_OK);
+    }
+}
+
+void
+describe_virtio(struct drive_s *drive_g)
+{
+    printf("Virtio disk PCI:%x:%x", pci_bdf_to_bus(drive_g->cntl_id),
+                                    pci_bdf_to_dev(drive_g->cntl_id));
+}
diff --git a/src/virtio-blk.h b/src/virtio-blk.h
new file mode 100644
index 0000000..43a37d6
--- /dev/null
+++ b/src/virtio-blk.h
@@ -0,0 +1,44 @@
+#ifndef _VIRTIO_BLK_H
+#define _VIRTIO_BLK_H
+
+struct virtio_blk_config
+{
+    u64 capacity;
+    u32 size_max;
+    u32 seg_max;
+    u16 cylinders;
+    u8 heads;
+    u8 sectors;
+    u32 blk_size;
+    u8 physical_block_exp;
+    u8 alignment_offset;
+    u16 min_io_size;
+    u32 opt_io_size;
+} __attribute__((packed));
+
+#define VIRTIO_BLK_F_BLK_SIZE 6
+
+/* 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;
+};
+
+#define VIRTIO_BLK_S_OK		0
+#define VIRTIO_BLK_S_IOERR	1
+#define VIRTIO_BLK_S_UNSUPP	2
+
+struct disk_op_s;
+int process_virtio_op(struct disk_op_s *op);
+void virtio_blk_setup(void);
+void describe_virtio(struct drive_s *drive_g);
+
+#endif /* _VIRTIO_BLK_H */
diff --git a/src/virtio-pci.c b/src/virtio-pci.c
new file mode 100644
index 0000000..db19e97
--- /dev/null
+++ b/src/virtio-pci.c
@@ -0,0 +1,69 @@
+/* virtio-pci.c - pci interface for virtio interface
+ *
+ * (c) Copyright 2008 Bull S.A.S.
+ *
+ *  Author: Laurent Vivier <Laurent.Vivier at bull.net>
+ *
+ * some parts from Linux Virtio PCI driver
+ *
+ *  Copyright IBM Corp. 2007
+ *  Authors: Anthony Liguori  <aliguori at us.ibm.com>
+ *
+ *  Adopted for Seabios: Gleb Natapov <gleb at redhat.com>
+ *
+ * This work is licensed under the terms of the GNU LGPLv3
+ * See the COPYING file in the top-level directory.
+ */
+
+#include "virtio-ring.h"
+#include "virtio-pci.h"
+#include "config.h" // CONFIG_DEBUG_LEVEL
+#include "util.h" // dprintf
+
+int vp_find_vq(unsigned int ioaddr, int queue_index,
+               struct vring_virtqueue *vq)
+{
+   struct vring * vr = &vq->vring;
+   u16 num;
+
+   ASSERT32FLAT();
+   /* select the queue */
+
+   outw(queue_index, ioaddr + VIRTIO_PCI_QUEUE_SEL);
+
+   /* check if the queue is available */
+
+   num = inw(ioaddr + VIRTIO_PCI_QUEUE_NUM);
+   if (!num) {
+       dprintf(1, "ERROR: queue size is 0\n");
+       return -1;
+   }
+
+   if (num > MAX_QUEUE_NUM) {
+       dprintf(1, "ERROR: queue size %d > %d\n", num, MAX_QUEUE_NUM);
+       return -1;
+   }
+
+   /* check if the queue is already active */
+
+   if (inl(ioaddr + VIRTIO_PCI_QUEUE_PFN)) {
+       dprintf(1, "ERROR: queue already active\n");
+       return -1;
+   }
+
+   vq->queue_index = queue_index;
+
+   /* initialize the queue */
+
+   vring_init(vr, num, (unsigned char*)&vq->queue);
+
+   /* activate the queue
+    *
+    * NOTE: vr->desc is initialized by vring_init()
+    */
+
+   outl((unsigned long)virt_to_phys(vr->desc) >> PAGE_SHIFT,
+        ioaddr + VIRTIO_PCI_QUEUE_PFN);
+
+   return num;
+}
diff --git a/src/virtio-pci.h b/src/virtio-pci.h
new file mode 100644
index 0000000..9da761d
--- /dev/null
+++ b/src/virtio-pci.h
@@ -0,0 +1,100 @@
+#ifndef _VIRTIO_PCI_H
+#define _VIRTIO_PCI_H
+
+#include "ioport.h" // inl
+
+/* A 32-bit r/o bitmask of the features supported by the host */
+#define VIRTIO_PCI_HOST_FEATURES        0
+
+/* A 32-bit r/w bitmask of features activated by the guest */
+#define VIRTIO_PCI_GUEST_FEATURES       4
+
+/* A 32-bit r/w PFN for the currently selected queue */
+#define VIRTIO_PCI_QUEUE_PFN            8
+
+/* A 16-bit r/o queue size for the currently selected queue */
+#define VIRTIO_PCI_QUEUE_NUM            12
+
+/* A 16-bit r/w queue selector */
+#define VIRTIO_PCI_QUEUE_SEL            14
+
+/* A 16-bit r/w queue notifier */
+#define VIRTIO_PCI_QUEUE_NOTIFY         16
+
+/* An 8-bit device status register.  */
+#define VIRTIO_PCI_STATUS               18
+
+/* An 8-bit r/o interrupt status register.  Reading the value will return the
+ * current contents of the ISR and will also clear it.  This is effectively
+ * a read-and-acknowledge. */
+#define VIRTIO_PCI_ISR                  19
+
+/* The bit of the ISR which indicates a device configuration change. */
+#define VIRTIO_PCI_ISR_CONFIG           0x2
+
+/* The remaining space is defined by each driver as the per-driver
+ * configuration space */
+#define VIRTIO_PCI_CONFIG               20
+
+/* Virtio ABI version, this must match exactly */
+#define VIRTIO_PCI_ABI_VERSION          0
+
+static inline u32 vp_get_features(unsigned int ioaddr)
+{
+   return inl(ioaddr + VIRTIO_PCI_HOST_FEATURES);
+}
+
+static inline void vp_set_features(unsigned int ioaddr, u32 features)
+{
+        outl(features, ioaddr + VIRTIO_PCI_GUEST_FEATURES);
+}
+
+static inline void vp_get(unsigned int ioaddr, unsigned offset,
+                     void *buf, unsigned len)
+{
+   u8 *ptr = buf;
+   unsigned i;
+
+   for (i = 0; i < len; i++)
+           ptr[i] = inb(ioaddr + VIRTIO_PCI_CONFIG + offset + i);
+}
+
+static inline u8 vp_get_status(unsigned int ioaddr)
+{
+   return inb(ioaddr + VIRTIO_PCI_STATUS);
+}
+
+static inline void vp_set_status(unsigned int ioaddr, u8 status)
+{
+   if (status == 0)        /* reset */
+           return;
+   outb(status, ioaddr + VIRTIO_PCI_STATUS);
+}
+
+
+static inline void vp_reset(unsigned int ioaddr)
+{
+   outb(0, ioaddr + VIRTIO_PCI_STATUS);
+   (void)inb(ioaddr + VIRTIO_PCI_ISR);
+}
+
+static inline void vp_notify(unsigned int ioaddr, int queue_index)
+{
+   outw(queue_index, ioaddr + VIRTIO_PCI_QUEUE_NOTIFY);
+}
+
+static inline void vp_del_vq(unsigned int ioaddr, int queue_index)
+{
+   /* select the queue */
+
+   outw(queue_index, ioaddr + VIRTIO_PCI_QUEUE_SEL);
+
+   /* deactivate the queue */
+
+   outl(0, ioaddr + VIRTIO_PCI_QUEUE_PFN);
+}
+
+struct vring_virtqueue;
+int vp_find_vq(unsigned int ioaddr, int queue_index,
+               struct vring_virtqueue *vq);
+#endif /* _VIRTIO_PCI_H_ */
diff --git a/src/virtio-ring.c b/src/virtio-ring.c
new file mode 100644
index 0000000..7565688
--- /dev/null
+++ b/src/virtio-ring.c
@@ -0,0 +1,154 @@
+/* virtio-pci.c - virtio ring management
+ *
+ * (c) Copyright 2008 Bull S.A.S.
+ *
+ *  Author: Laurent Vivier <Laurent.Vivier at bull.net>
+ *
+ *  some parts from Linux Virtio Ring
+ *
+ *  Copyright Rusty Russell IBM Corporation 2007
+ *
+ *  Adopted for Seabios: Gleb Natapov <gleb at redhat.com>
+ *
+ * This work is licensed under the terms of the GNU LGPLv3
+ * See the COPYING file in the top-level directory.
+ *
+ *
+ */
+
+#include "virtio-ring.h"
+#include "virtio-pci.h"
+#include "biosvar.h" // GET_GLOBAL
+#include "util.h" // dprintf
+
+#define BUG() do {                                      \
+        dprintf(1, "BUG: failure at %s:%d/%s()!\n",     \
+                __FILE__, __LINE__, __func__);          \
+                while(1);                               \
+        } while (0)
+#define BUG_ON(condition) do { if (condition) BUG(); } while (0)
+
+/*
+ * vring_more_used
+ *
+ * is there some used buffers ?
+ *
+ */
+
+int vring_more_used(struct vring_virtqueue *vq)
+{
+    struct vring_used *used = GET_FLATPTR(vq->vring.used);
+    wmb();
+    return GET_FLATPTR(vq->last_used_idx) != GET_FLATPTR(used->idx);
+}
+
+/*
+ * vring_free
+ *
+ * put at the begin of the free list the current desc[head]
+ */
+
+void vring_detach(struct vring_virtqueue *vq, unsigned int head)
+{
+    struct vring *vr = &vq->vring;
+    struct vring_desc *desc = GET_FLATPTR(vr->desc);
+    unsigned int i;
+
+    /* find end of given descriptor */
+
+    i = head;
+    while (GET_FLATPTR(desc[i].flags) & VRING_DESC_F_NEXT)
+        i = GET_FLATPTR(desc[i].next);
+
+    /* link it with free list and point to it */
+
+    SET_FLATPTR(desc[i].next, GET_FLATPTR(vq->free_head));
+    wmb();
+    SET_FLATPTR(vq->free_head, head);
+}
+
+/*
+ * vring_get_buf
+ *
+ * get a buffer from the used list
+ *
+ */
+
+int vring_get_buf(struct vring_virtqueue *vq, unsigned int *len)
+{
+    struct vring *vr = &vq->vring;
+    struct vring_used_elem *elem;
+    struct vring_used *used = GET_FLATPTR(vq->vring.used);
+    u32 id;
+    int ret;
+
+//    BUG_ON(!vring_more_used(vq));
+
+    elem = &used->ring[GET_FLATPTR(vq->last_used_idx) % GET_FLATPTR(vr->num)];
+    wmb();
+    id = GET_FLATPTR(elem->id);
+    if (len != NULL)
+        *len = GET_FLATPTR(elem->len);
+
+    ret = GET_FLATPTR(vq->vdata[id]);
+
+    vring_detach(vq, id);
+
+    SET_FLATPTR(vq->last_used_idx, GET_FLATPTR(vq->last_used_idx) + 1);
+
+    return ret;
+}
+
+void vring_add_buf(struct vring_virtqueue *vq,
+                   struct vring_list list[],
+                   unsigned int out, unsigned int in,
+                   int index, int num_added)
+{
+    struct vring *vr = &vq->vring;
+    int i, av, head, prev;
+    struct vring_desc *desc = GET_FLATPTR(vr->desc);
+    struct vring_avail *avail = GET_FLATPTR(vr->avail);
+
+    BUG_ON(out + in == 0);
+
+    prev = 0;
+    head = GET_FLATPTR(vq->free_head);
+    for (i = head; out; i = GET_FLATPTR(desc[i].next), out--) {
+        SET_FLATPTR(desc[i].flags, VRING_DESC_F_NEXT);
+        SET_FLATPTR(desc[i].addr, (u64)virt_to_phys(list->addr));
+        SET_FLATPTR(desc[i].len, list->length);
+        prev = i;
+        list++;
+    }
+    for ( ; in; i = GET_FLATPTR(desc[i].next), in--) {
+        SET_FLATPTR(desc[i].flags, VRING_DESC_F_NEXT|VRING_DESC_F_WRITE);
+        SET_FLATPTR(desc[i].addr, (u64)virt_to_phys(list->addr));
+        SET_FLATPTR(desc[i].len, list->length);
+        prev = i;
+        list++;
+    }
+    SET_FLATPTR(desc[prev].flags,
+                GET_FLATPTR(desc[prev].flags) & ~VRING_DESC_F_NEXT);
+
+    SET_FLATPTR(vq->free_head, i);
+
+    SET_FLATPTR(vq->vdata[head], index);
+
+    av = (GET_FLATPTR(avail->idx) + num_added) % GET_FLATPTR(vr->num);
+    SET_FLATPTR(avail->ring[av], head);
+    wmb();
+}
+
+void vring_kick(unsigned int ioaddr, struct vring_virtqueue *vq, int num_added)
+{
+    struct vring *vr = &vq->vring;
+    struct vring_avail *avail = GET_FLATPTR(vr->avail);
+    struct vring_used *used = GET_FLATPTR(vq->vring.used);
+
+    wmb();
+    SET_FLATPTR(avail->idx, GET_FLATPTR(avail->idx) + num_added);
+
+    mb();
+    if (!(GET_FLATPTR(used->flags) & VRING_USED_F_NO_NOTIFY))
+        vp_notify(ioaddr, GET_FLATPTR(vq->queue_index));
+}
diff --git a/src/virtio-ring.h b/src/virtio-ring.h
new file mode 100644
index 0000000..939c946
--- /dev/null
+++ b/src/virtio-ring.h
@@ -0,0 +1,129 @@
+#ifndef _VIRTIO_RING_H
+#define _VIRTIO_RING_H
+
+#include "types.h" // u64
+#include "memmap.h" // PAGE_SIZE
+
+#define PAGE_SHIFT 12
+#define PAGE_MASK  (PAGE_SIZE-1)
+
+#define virt_to_phys(v) (unsigned long)(v)
+#define phys_to_virt(p) (void*)(p)
+#define wmb() barrier()
+#define mb() barrier()
+
+/* Status byte for guest to report progress, and synchronize features. */
+/* 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
+
+#define MAX_QUEUE_NUM      (128)
+
+#define VRING_DESC_F_NEXT  1
+#define VRING_DESC_F_WRITE 2
+
+#define VRING_AVAIL_F_NO_INTERRUPT 1
+
+#define VRING_USED_F_NO_NOTIFY     1
+
+struct vring_desc
+{
+   u64 addr;
+   u32 len;
+   u16 flags;
+   u16 next;
+};
+
+struct vring_avail
+{
+   u16 flags;
+   u16 idx;
+   u16 ring[0];
+};
+
+struct vring_used_elem
+{
+   u32 id;
+   u32 len;
+};
+
+struct vring_used
+{
+   u16 flags;
+   u16 idx;
+   struct vring_used_elem ring[];
+};
+
+struct vring {
+   unsigned int num;
+   struct vring_desc *desc;
+   struct vring_avail *avail;
+   struct vring_used *used;
+};
+
+#define vring_size(num) \
+   (((((sizeof(struct vring_desc) * num) + \
+      (sizeof(struct vring_avail) + sizeof(u16) * num)) \
+         + PAGE_MASK) & ~PAGE_MASK) + \
+         (sizeof(struct vring_used) + sizeof(struct vring_used_elem) * num))
+
+typedef unsigned char virtio_queue_t[PAGE_MASK + vring_size(MAX_QUEUE_NUM)];
+
+struct vring_virtqueue {
+   virtio_queue_t queue;
+   struct vring vring;
+   u16 free_head;
+   u16 last_used_idx;
+   u16 vdata[MAX_QUEUE_NUM];
+   /* PCI */
+   int queue_index;
+};
+
+struct vring_list {
+  char *addr;
+  unsigned int length;
+};
+
+static inline void vring_init(struct vring *vr,
+                         unsigned int num, unsigned char *queue)
+{
+   unsigned int i;
+   unsigned long pa;
+
+   ASSERT32FLAT();
+   vr->num = num;
+
+   /* physical address of desc must be page aligned */
+
+   pa = virt_to_phys(queue);
+   pa = (pa + PAGE_MASK) & ~PAGE_MASK;
+   vr->desc = phys_to_virt(pa);
+
+   vr->avail = (struct vring_avail *)&vr->desc[num];
+   vr->avail->flags |= VRING_AVAIL_F_NO_INTERRUPT;
+
+   /* physical address of used must be page aligned */
+
+   pa = virt_to_phys(&vr->avail->ring[num]);
+   pa = (pa + PAGE_MASK) & ~PAGE_MASK;
+   vr->used = phys_to_virt(pa);
+
+   for (i = 0; i < num - 1; i++)
+           vr->desc[i].next = i + 1;
+   vr->desc[i].next = 0;
+}
+
+int vring_more_used(struct vring_virtqueue *vq);
+void vring_detach(struct vring_virtqueue *vq, unsigned int head);
+int vring_get_buf(struct vring_virtqueue *vq, unsigned int *len);
+void vring_add_buf(struct vring_virtqueue *vq, struct vring_list list[],
+                   unsigned int out, unsigned int in,
+                   int index, int num_added);
+void vring_kick(unsigned int ioaddr, struct vring_virtqueue *vq, int num_added);
+
+#endif /* _VIRTIO_RING_H_ */
-- 
1.7.0.3


seabios-do-not-advertise-hpet-to-a-guest-OS.patch:
 acpi.c |    2 --
 1 file changed, 2 deletions(-)

--- NEW FILE seabios-do-not-advertise-hpet-to-a-guest-OS.patch ---
From: Gleb Natapov <gleb at redhat.com>
Date: Tue, 15 Jun 2010 08:11:28 -0300
Subject: [PATCH] do not advertise hpet to a guest OS.


Signed-off-by: Gleb Natapov <gleb at redhat.com>
---
 v1->v2:
  - do not remove code to generate HPET tables, only call to the
    function.

--
			Gleb.

Signed-off-by: Eduardo Habkost <ehabkost at redhat.com>
---
 src/acpi.c |    1 -
 1 files changed, 0 insertions(+), 1 deletions(-)

diff --git a/src/acpi.c b/src/acpi.c
index 244536a..1962632 100644
--- a/src/acpi.c
+++ b/src/acpi.c
@@ -635,7 +635,6 @@ acpi_bios_init(void)
     ACPI_INIT_TABLE(build_fadt(bdf));
     ACPI_INIT_TABLE(build_ssdt());
     ACPI_INIT_TABLE(build_madt());
-    ACPI_INIT_TABLE(build_hpet());
     ACPI_INIT_TABLE(build_srat());
 
     u16 i, external_tables = qemu_cfg_acpi_additional_tables();
-- 
1.7.0.3


seabios-fix-resume-from-S3-with-QXL-device.patch:
 acpi-dsdt.dsl |   11 +++++++++--
 1 file changed, 9 insertions(+), 2 deletions(-)

--- NEW FILE seabios-fix-resume-from-S3-with-QXL-device.patch ---
From: Gleb Natapov <gleb at redhat.com>
Date: Mon, 14 Jun 2010 10:02:19 -0300
Subject: [PATCH] fix resume from S3 with QXL device

QXL device is powered down during S3, so tell this to a guest OS
in AML code.

Signed-off-by: Gleb Natapov <gleb at redhat.com>
--
			Gleb.

Signed-off-by: Eduardo Habkost <ehabkost at redhat.com>
---
 src/acpi-dsdt.dsl |   10 +++++++++-
 1 files changed, 9 insertions(+), 1 deletions(-)

diff --git a/src/acpi-dsdt.dsl b/src/acpi-dsdt.dsl
index cc31112..6e4502b 100644
--- a/src/acpi-dsdt.dsl
+++ b/src/acpi-dsdt.dsl
@@ -219,6 +219,10 @@ DefinitionBlock (
     Scope(\_SB.PCI0) {
         Device (VGA) {
                  Name (_ADR, 0x00020000)
+                 OperationRegion(PCIC, PCI_Config, Zero, 0x4)
+                 Field(PCIC, DWordAcc, NoLock, Preserve) {
+                         VEND, 32
+                 } 
                  Method (_S1D, 0, NotSerialized)
                  {
                          Return (0x00)
@@ -229,7 +233,11 @@ DefinitionBlock (
                  }
                  Method (_S3D, 0, NotSerialized)
                  {
-                         Return (0x00)
+                         If (LEqual(VEND, 0x1001b36)) {
+                                 Return (0x03)           // QXL
+                         } Else {
+                                 Return (0x00)
+                         }
                  }
         }
 
-- 
1.7.0.3


seabios-smbios-avoid-counting-io-hole-as-ram.patch:
 smbios.c |   69 +++++++++++++++++++++++++++++++++++++++------------------------
 1 file changed, 43 insertions(+), 26 deletions(-)

--- NEW FILE seabios-smbios-avoid-counting-io-hole-as-ram.patch ---
From: Alex Williamson <alex.williamson at redhat.com>
Date: Tue, 11 May 2010 02:53:23 -0300
Subject: [PATCH] smbios: avoid counting io hole as ram

Upstream commit: 6d66316acc8f1629b65ccee86ee50b0dd9ff467e

Avoid counting the io hole as part of ram, a vm started with 4G
should report 4G in smbios, not 4.5G.

Signed-off-by: Alex Williamson <alex.williamson at redhat.com>
---

 src/smbios.c |   68 +++++++++++++++++++++++++++++++++++++---------------------
 1 files changed, 43 insertions(+), 25 deletions(-)

Signed-off-by: Eduardo Habkost <ehabkost at redhat.com>
---
 src/smbios.c |   68 ++++++++++++++++++++++++++++++++++++---------------------
 1 files changed, 43 insertions(+), 25 deletions(-)

diff --git a/src/smbios.c b/src/smbios.c
index 870afbe..ef2b330 100644
--- a/src/smbios.c
+++ b/src/smbios.c
@@ -246,7 +246,9 @@ smbios_init_type_16(void *start, u32 memory_size_mb, int nr_mem_devs)
     p->location = 0x01; /* other */
     p->use = 0x03; /* system memory */
     p->error_correction = 0x06; /* Multi-bit ECC to make Microsoft happy */
-    p->maximum_capacity = memory_size_mb * 1024;
+    /* 0x80000000 = unknown, accept sizes < 2TB - TODO multiple arrays */
+    p->maximum_capacity = memory_size_mb < 2 << 20 ?
+                          memory_size_mb << 10 : 0x80000000;
     p->memory_error_information_handle = 0xfffe; /* none provided */
     p->number_of_memory_devices = nr_mem_devs;
 
@@ -258,7 +260,7 @@ smbios_init_type_16(void *start, u32 memory_size_mb, int nr_mem_devs)
 
 /* Type 17 -- Memory Device */
 static void *
-smbios_init_type_17(void *start, u32 memory_size_mb, int instance)
+smbios_init_type_17(void *start, u32 size_mb, int instance)
 {
     struct smbios_type_17 *p = (struct smbios_type_17 *)start;
 
@@ -270,7 +272,7 @@ smbios_init_type_17(void *start, u32 memory_size_mb, int instance)
     p->total_width = 64;
     p->data_width = 64;
 /* TODO: should assert in case something is wrong   ASSERT((memory_size_mb & ~0x7fff) == 0); */
-    p->size = memory_size_mb;
+    p->size = size_mb;
     p->form_factor = 0x09; /* DIMM */
     p->device_set = 0;
     p->device_locator_str = 1;
@@ -289,7 +291,7 @@ smbios_init_type_17(void *start, u32 memory_size_mb, int instance)
 
 /* Type 19 -- Memory Array Mapped Address */
 static void *
-smbios_init_type_19(void *start, u32 memory_size_mb, int instance)
+smbios_init_type_19(void *start, u32 start_mb, u32 size_mb, int instance)
 {
     struct smbios_type_19 *p = (struct smbios_type_19 *)start;
 
@@ -297,8 +299,8 @@ smbios_init_type_19(void *start, u32 memory_size_mb, int instance)
     p->header.length = sizeof(struct smbios_type_19);
     p->header.handle = 0x1300 + instance;
 
-    p->starting_address = instance << 24;
-    p->ending_address = p->starting_address + (memory_size_mb << 10) - 1;
+    p->starting_address = start_mb << 10;
+    p->ending_address = p->starting_address + (size_mb << 10) - 1;
     p->memory_array_handle = 0x1000;
     p->partition_width = 1;
 
@@ -310,7 +312,8 @@ smbios_init_type_19(void *start, u32 memory_size_mb, int instance)
 
 /* Type 20 -- Memory Device Mapped Address */
 static void *
-smbios_init_type_20(void *start, u32 memory_size_mb, int instance)
+smbios_init_type_20(void *start, u32 start_mb, u32 size_mb, int instance,
+                    int dev_handle, int array_handle)
 {
     struct smbios_type_20 *p = (struct smbios_type_20 *)start;
 
@@ -318,10 +321,10 @@ smbios_init_type_20(void *start, u32 memory_size_mb, int instance)
     p->header.length = sizeof(struct smbios_type_20);
     p->header.handle = 0x1400 + instance;
 
-    p->starting_address = instance << 24;
-    p->ending_address = p->starting_address + (memory_size_mb << 10) - 1;
-    p->memory_device_handle = 0x1100 + instance;
-    p->memory_array_mapped_address_handle = 0x1300 + instance;
+    p->starting_address = start_mb << 10;
+    p->ending_address = p->starting_address + (size_mb << 10) - 1;
+    p->memory_device_handle = 0x1100 + dev_handle;
+    p->memory_array_mapped_address_handle = 0x1300 + array_handle;
     p->partition_row_position = 1;
     p->interleave_position = 0;
     p->interleaved_data_depth = 0;
@@ -405,21 +408,36 @@ smbios_init(void)
     int cpu_num;
     for (cpu_num = 1; cpu_num <= MaxCountCPUs; cpu_num++)
         add_struct(4, p, cpu_num);
-    u64 memsize = RamSizeOver4G;
-    if (memsize)
-        memsize += 0x100000000ull;
-    else
-        memsize = RamSize;
-    memsize = memsize / (1024 * 1024);
-    int nr_mem_devs = (memsize + 0x3fff) >> 14;
-    add_struct(16, p, memsize, nr_mem_devs);
-    int i;
+
+    int ram_mb = (RamSize + RamSizeOver4G) >> 20;
+    int nr_mem_devs = (ram_mb + 0x3fff) >> 14;
+    add_struct(16, p, ram_mb, nr_mem_devs);
+
+    int i, j;
     for (i = 0; i < nr_mem_devs; i++) {
-        u32 dev_memsize = ((i == (nr_mem_devs - 1))
-                           ? (((memsize-1) & 0x3fff)+1) : 0x4000);
-        add_struct(17, p, dev_memsize, i);
-        add_struct(19, p, dev_memsize, i);
-        add_struct(20, p, dev_memsize, i);
+        u32 dev_mb = ((i == (nr_mem_devs - 1))
+                      ? (((ram_mb - 1) & 0x3fff) + 1)
+                      : 16384);
+        add_struct(17, p, dev_mb, i);
+    }
+        
+    add_struct(19, p, 0, RamSize >> 20, 0);
+    if (RamSizeOver4G)
+        add_struct(19, p, 4096, RamSizeOver4G >> 20, 1);
+
+    add_struct(20, p, 0, RamSize >> 20, 0, 0, 0);
+    if (RamSizeOver4G) {
+        u32 start_mb = 4096;
+        for (j = 1, i = 0; i < nr_mem_devs; i++, j++) {
+            u32 dev_mb = ((i == (nr_mem_devs - 1))
+                               ? (((ram_mb - 1) & 0x3fff) + 1)
+                               : 16384);
+            if (i == 0)
+                dev_mb -= RamSize >> 20;
+
+            add_struct(20, p, start_mb, dev_mb, j, i, 1);
+            start_mb += dev_mb;
+        }
     }
 
     add_struct(32, p);
-- 
1.7.0.3


seabios-zero-memory-before-use.patch:
 virtio-blk.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

--- NEW FILE seabios-zero-memory-before-use.patch ---
From: Gleb Natapov <gleb at redhat.com>
Date: Mon, 31 May 2010 13:04:20 -0300
Subject: [PATCH 2/2] zero memory before use

Zero virtio queue memory before use.

Signed-off-by: Gleb Natapov <gleb at redhat.com>
--
			Gleb.

Signed-off-by: Eduardo Habkost <ehabkost at redhat.com>
---
 src/virtio-blk.c |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/src/virtio-blk.c b/src/virtio-blk.c
index 14719c9..c7144b5 100644
--- a/src/virtio-blk.c
+++ b/src/virtio-blk.c
@@ -115,6 +115,7 @@ virtio_blk_setup(void)
         u16 ioaddr = pci_config_readl(bdf, PCI_BASE_ADDRESS_0) &
             PCI_BASE_ADDRESS_IO_MASK;
 
+        memset(vq, 0, sizeof(*vq));
         memset(vdrive_g, 0, sizeof(*vdrive_g));
         vdrive_g->ioaddr = ioaddr;
         vdrive_g->vq = vq;
-- 
1.7.0.3



Index: seabios.spec
===================================================================
RCS file: /cvs/pkgs/rpms/seabios/F-13/seabios.spec,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -p -r1.3 -r1.4
--- seabios.spec	20 Apr 2010 16:49:03 -0000	1.3
+++ seabios.spec	30 Jun 2010 15:43:24 -0000	1.4
@@ -1,6 +1,6 @@
 Name:           seabios
 Version:        0.5.1
-Release:        2%{?dist}
+Release:        3%{?dist}
 Summary:        Open-source legacy BIOS implementation
 
 Group:          Applications/Emulators
@@ -12,6 +12,14 @@ Source0:        http://linuxtogo.org/~ke
 Patch01: 0001-Go-back-to-using-0xf0000000-for-PCI-memory-start.patch
 Patch02: 0002-Fix-PkgLength-calculation-for-the-SSDT.patch
 
+# Patches from upstream git
+Patch03: seabios-Set-CONFIG_S3_RESUME_VGA_INIT-to-1.patch
+Patch04: seabios-smbios-avoid-counting-io-hole-as-ram.patch
+Patch05: seabios-Support-for-booting-from-virtio-disks.patch
+Patch06: seabios-zero-memory-before-use.patch
+Patch07: seabios-do-not-advertise-hpet-to-a-guest-OS.patch
+Patch08: seabios-fix-resume-from-S3-with-QXL-device.patch
+
 BuildRoot:      %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
 
 BuildRequires: python
@@ -44,6 +52,12 @@ that a typical x86 proprietary BIOS impl
 
 %patch01 -p1
 %patch02 -p1
+%patch03 -p1
+%patch04 -p1
+%patch05 -p1
+%patch06 -p1
+%patch07 -p1
+%patch08 -p1
 
 # Makefile changes version to include date and buildhost
 sed -i 's,VERSION=%{version}.*,VERSION=%{version},g' Makefile
@@ -81,6 +95,13 @@ rm -rf $RPM_BUILD_ROOT
 
 
 %changelog
+* Tue Jun 29 2010 Justin M. Forbes <jforbes at redhat.com> 0.5.1-3
+- Support booting from virtio disks
+- zero memory before use
+- Fix resume from S3 when using QXL device
+- Avoid counting io-hole are RAM
+- Do not advertise hpet to guests
+
 * Tue Apr 20 2010 Justin M. Forbes <jforbes at redhat.com> 0.5.1-2
 - Ugly hacks to make package noarch and available for arch that cannot build it.
 - Disable useless debuginfo



More information about the scm-commits mailing list