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

[Xen-changelog] [xen-unstable] ioemu: generic PCI device config-space emulation



# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1213778439 -3600
# Node ID 97e02365a7818450d2261afda85287c3270d88af
# Parent  9493a853df9ef0c17c6fb12efdcc86c5d67c7e03
ioemu: generic PCI device config-space emulation

This patch is an extension for qemu-dm to enable emulation of generic
PCI devices. The information for the PCI devices can be passed by
command line parameter.

The command line parameter is "-pciemulation" followed by the
information which contains a label and hex value of the configuration
registers separated by ":".

The configuration registers for each PCI device are below.
vendorid
deviceid
command
status
revision
classcode
headertype
subvendorid
subsystemid
interruputline
interruptpin

This is an example of command line parameter.

 -pciemulation hba1:1240:0780:0002:0:0:010000:0:10b5:0777:05:1

Signed-off-by: Shinji Matsumoto <smatsumoto@xxxxxxxxxxxxxxxxxxxxxxxx>
---
 tools/ioemu/Makefile.target    |    1 
 tools/ioemu/hw/pc.c            |    7 ++
 tools/ioemu/hw/pci_emulation.c |  118 +++++++++++++++++++++++++++++++++++++++++
 tools/ioemu/hw/pci_emulation.h |   24 ++++++++
 tools/ioemu/vl.c               |   38 +++++++++++++
 tools/ioemu/vl.h               |    4 +
 6 files changed, 192 insertions(+)

diff -r 9493a853df9e -r 97e02365a781 tools/ioemu/Makefile.target
--- a/tools/ioemu/Makefile.target       Wed Jun 18 09:39:14 2008 +0100
+++ b/tools/ioemu/Makefile.target       Wed Jun 18 09:40:39 2008 +0100
@@ -441,6 +441,7 @@ VL_OBJS+= xenfbfront.o
 VL_OBJS+= xenfbfront.o
 endif
 VL_OBJS+= xen_console.o
+VL_OBJS+= pci_emulation.o
 ifndef CONFIG_STUBDOM
 VL_OBJS+= tpm_tis.o
 VL_OBJS+= $(SOUND_HW) $(AUDIODRV) mixeng.o 
diff -r 9493a853df9e -r 97e02365a781 tools/ioemu/hw/pc.c
--- a/tools/ioemu/hw/pc.c       Wed Jun 18 09:39:14 2008 +0100
+++ b/tools/ioemu/hw/pc.c       Wed Jun 18 09:40:39 2008 +0100
@@ -1090,6 +1090,13 @@ static void pc_init1(uint64_t ram_size, 
         }
     }
 #endif /* !CONFIG_DM */
+
+    if (pci_enabled) {
+        PCI_EMULATION_INFO *p;
+        for (p = PciEmulationInfoHead; p != NULL; p = p->next) {
+            pci_emulation_init(pci_bus, p);
+        }
+    }
 }
 
 static void pc_init_pci(uint64_t ram_size, int vga_ram_size, char *boot_device,
diff -r 9493a853df9e -r 97e02365a781 tools/ioemu/hw/pci_emulation.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/ioemu/hw/pci_emulation.c    Wed Jun 18 09:40:39 2008 +0100
@@ -0,0 +1,118 @@
+/*
+ * Changes to PCI emulation made by Marathon Technologies, June 2008
+ */
+
+#include "vl.h"
+
+typedef struct {
+    PCIDevice dev;
+}   PCI_EMULATION_State;
+
+void parse_pci_emulation_info(char *config_text, PCI_EMULATION_INFO 
*pci_emulation_info)
+{
+    char *p;
+    int i;
+    int ret;
+    for (p = config_text, i = 0; *p != '\0'; p++) {
+        if (*p == ':') {
+            break;
+        }
+        if (i < sizeof(pci_emulation_info->name) - 1) {
+            pci_emulation_info->name[i] = *p;
+            i++;
+        }
+    }
+    pci_emulation_info->name[i] = '\0';
+    if (*p == '\0') return;
+    p++;
+    ret = sscanf(p, "%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x",
+                 &(pci_emulation_info->vendorid),
+                 &(pci_emulation_info->deviceid),
+                 &(pci_emulation_info->command),
+                 &(pci_emulation_info->status),
+                 &(pci_emulation_info->revision),
+                 &(pci_emulation_info->classcode),
+                 &(pci_emulation_info->headertype),
+                 &(pci_emulation_info->subvendorid),
+                 &(pci_emulation_info->subsystemid),
+                 &(pci_emulation_info->interruputline),
+                 &(pci_emulation_info->interruputpin));
+#ifdef DEBUG
+    fprintf(logfile, "qemu: pciemulation 
%s:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x\n",
+            pci_emulation_info->name,
+            pci_emulation_info->vendorid,
+            pci_emulation_info->deviceid,
+            pci_emulation_info->command,
+            pci_emulation_info->status,
+            pci_emulation_info->revision,
+            pci_emulation_info->classcode,
+            pci_emulation_info->headertype,
+            pci_emulation_info->subvendorid,
+            pci_emulation_info->subsystemid,
+            pci_emulation_info->interruputline,
+            pci_emulation_info->interruputpin);
+#endif
+    return;
+}
+
+static void pci_emulation_save(QEMUFile *f, void *opaque)
+{
+    PCIDevice *d = opaque;
+
+    pci_device_save(d, f);
+}
+
+static int pci_emulation_load(QEMUFile *f, void *opaque, int version_id)
+{
+    PCIDevice *d = opaque;
+
+    if (version_id != 1)
+        return -EINVAL;
+
+    return pci_device_load(d, f);
+}
+
+
+void pci_emulation_init(PCIBus *bus, PCI_EMULATION_INFO *pci_emulation_info)
+{
+    int instance_id;
+    PCI_EMULATION_State *d;
+    uint8_t *pci_conf;
+
+#ifdef DEBUG
+    fprintf(logfile, "qemu: pciinit\n");
+#endif
+    
+    d = (PCI_EMULATION_State *)pci_register_device(bus,
+                                                   pci_emulation_info->name, 
+                                                   sizeof(PCI_EMULATION_State),
+                                                   -1, 
+                                                    NULL, NULL);
+    pci_conf = d->dev.config;
+    pci_conf[0x00] = pci_emulation_info->vendorid & 0xff;
+    pci_conf[0x01] = (pci_emulation_info->vendorid & 0xff00) >> 8;
+    pci_conf[0x02] = pci_emulation_info->deviceid & 0xff;
+    pci_conf[0x03] = (pci_emulation_info->deviceid & 0xff00) >> 8;
+    pci_conf[0x04] = pci_emulation_info->command & 0xff;
+    pci_conf[0x05] = (pci_emulation_info->command & 0xff00) >> 8;
+    pci_conf[0x06] = pci_emulation_info->status & 0xff;
+    pci_conf[0x07] = (pci_emulation_info->status & 0xff00) >> 8;
+    pci_conf[0x08] = pci_emulation_info->revision & 0xff;
+    pci_conf[0x09] = pci_emulation_info->classcode & 0xff;
+    pci_conf[0x0a] = (pci_emulation_info->classcode & 0xff00) >> 8;
+    pci_conf[0x0b] = (pci_emulation_info->classcode & 0xff0000) >> 16;
+    pci_conf[0x0e] = pci_emulation_info->headertype & 0xff;
+    pci_conf[0x2c] = pci_emulation_info->subvendorid & 0xff;
+    pci_conf[0x2d] = (pci_emulation_info->subvendorid & 0xff00) >> 8;
+    pci_conf[0x2e] = pci_emulation_info->subsystemid & 0xff;
+    pci_conf[0x2f] = (pci_emulation_info->subsystemid & 0xff00) >> 8;
+    pci_conf[0x3c] = pci_emulation_info->interruputline & 0xff;
+    pci_conf[0x3d] = pci_emulation_info->interruputpin & 0xff;
+
+    instance_id = pci_bus_num(bus) << 8 | d->dev.devfn;
+    register_savevm(pci_emulation_info->name, instance_id,
+                    1, pci_emulation_save, pci_emulation_load, d);
+
+
+    return;    
+}
diff -r 9493a853df9e -r 97e02365a781 tools/ioemu/hw/pci_emulation.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/ioemu/hw/pci_emulation.h    Wed Jun 18 09:40:39 2008 +0100
@@ -0,0 +1,24 @@
+/*
+ * Changes to PCI emulation made by Marathon Technologies, June 2008
+ */
+
+typedef struct PCI_EMULATION_INFO_t {
+    struct PCI_EMULATION_INFO_t *next;
+    char name[32];
+    unsigned int vendorid;
+    unsigned int deviceid;
+    unsigned int command;
+    unsigned int status;
+    unsigned int revision;
+    unsigned int classcode;
+    unsigned int headertype;
+    unsigned int subvendorid;
+    unsigned int subsystemid;
+    unsigned int interruputline;
+    unsigned int interruputpin;
+}   PCI_EMULATION_INFO;
+    
+void parse_pci_emulation_info(char *config_text, PCI_EMULATION_INFO 
*pci_emulation_info);
+void pci_emulation_init(PCIBus *bus, PCI_EMULATION_INFO *pci_emulation_info);
+
+extern PCI_EMULATION_INFO *PciEmulationInfoHead;
diff -r 9493a853df9e -r 97e02365a781 tools/ioemu/vl.c
--- a/tools/ioemu/vl.c  Wed Jun 18 09:39:14 2008 +0100
+++ b/tools/ioemu/vl.c  Wed Jun 18 09:40:39 2008 +0100
@@ -136,6 +136,9 @@
 
 /* XXX: use a two level table to limit memory usage */
 #define MAX_IOPORTS 65536
+
+/* Max number of PCI emulation */
+#define MAX_PCI_EMULATION 32
 
 const char *bios_dir = CONFIG_QEMU_SHAREDIR;
 void *ioport_opaque[MAX_IOPORTS];
@@ -211,6 +214,8 @@ int xc_handle;
 
 char domain_name[64] = "Xen-no-name";
 extern int domid;
+
+PCI_EMULATION_INFO *PciEmulationInfoHead = NULL;
 
 /***********************************************************/
 /* x86 ISA bus support */
@@ -4399,6 +4404,17 @@ void do_pci_add(char *devname)
 #endif
 }
 
+static int pci_emulation_add(char *config_text)
+{
+    PCI_EMULATION_INFO *new;
+    if ((new = qemu_mallocz(sizeof(PCI_EMULATION_INFO))) == NULL) {
+        return -1;
+    }
+    parse_pci_emulation_info(config_text, new);
+    new->next = PciEmulationInfoHead;
+    PciEmulationInfoHead = new;
+    return 0;
+}
 
 /***********************************************************/
 /* pid file */
@@ -6590,6 +6606,7 @@ void help(void)
 #endif
           "-option-rom rom load a file, rom, into the option ROM space\n"
            "-acpi           disable or enable ACPI of HVM domain \n"
+           "-pciemulation       
name:vendorid:deviceid:command:status:revision:classcode:headertype:subvendorid:subsystemid:interruputline:interruputpin\n"
            "\n"
            "During emulation, the following keys are useful:\n"
            "ctrl-alt-f      toggle full screen\n"
@@ -6688,6 +6705,7 @@ enum {
     QEMU_OPTION_vncviewer,
     QEMU_OPTION_vncunused,
     QEMU_OPTION_pci,
+    QEMU_OPTION_pci_emulation,
 };
 
 typedef struct QEMUOption {
@@ -6789,6 +6807,7 @@ const QEMUOption qemu_options[] = {
     { "vcpus", 1, QEMU_OPTION_vcpus },
     { "acpi", 0, QEMU_OPTION_acpi },
     { "pci", HAS_ARG, QEMU_OPTION_pci},
+    { "pciemulation", HAS_ARG, QEMU_OPTION_pci_emulation },
     { NULL },
 };
 
@@ -7073,6 +7092,8 @@ int main(int argc, char **argv)
     sigset_t set;
     char qemu_dm_logfilename[128];
     const char *direct_pci = direct_pci_str;
+    int nb_pci_emulation = 0;
+    char pci_emulation_config_text[MAX_PCI_EMULATION][256];
 
 #if !defined(__sun__) && !defined(CONFIG_STUBDOM)
     /* Maximise rlimits. Needed where default constraints are tight (*BSD). */
@@ -7598,6 +7619,16 @@ int main(int argc, char **argv)
             case QEMU_OPTION_vncunused:
                 vncunused++;
                 break;
+            case QEMU_OPTION_pci_emulation:
+                if (nb_pci_emulation >= MAX_PCI_EMULATION) {
+                    fprintf(stderr, "Too many PCI emulations\n");
+                    exit(1);
+                }
+                pstrcpy(pci_emulation_config_text[nb_pci_emulation],
+                        sizeof(pci_emulation_config_text[0]),
+                        optarg);
+                nb_pci_emulation++;
+                break;
             }
         }
     }
@@ -7897,6 +7928,13 @@ int main(int argc, char **argv)
         }
     }
 
+    for (i = 0; i < nb_pci_emulation; i++) {
+        if(pci_emulation_add(pci_emulation_config_text[i]) < 0) {
+            fprintf(stderr, "Warning: could not add PCI device %s\n",
+                    pci_emulation_config_text[i]);
+        }
+    }
+
     qemu_set_fd_handler(xenstore_fd(), xenstore_process_event, NULL, NULL);
 
     machine->init(ram_size, vga_ram_size, boot_device,
diff -r 9493a853df9e -r 97e02365a781 tools/ioemu/vl.h
--- a/tools/ioemu/vl.h  Wed Jun 18 09:39:14 2008 +0100
+++ b/tools/ioemu/vl.h  Wed Jun 18 09:40:39 2008 +0100
@@ -1560,6 +1560,10 @@ void pci_xen_platform_init(PCIBus *bus);
 void pci_xen_platform_init(PCIBus *bus);
 #endif
 
+/* pci_emulation.c */
+#ifndef QEMU_TOOL
+#include "hw/pci_emulation.h"
+#endif
 
 void kqemu_record_dump(void);
 

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.