aboutsummaryrefslogtreecommitdiffstats
path: root/tools/ioemu
diff options
context:
space:
mode:
authorKeir Fraser <keir.fraser@citrix.com>2008-06-18 09:40:39 +0100
committerKeir Fraser <keir.fraser@citrix.com>2008-06-18 09:40:39 +0100
commitcc5871d6da53bdf1ba296fcedfc9a956787a900f (patch)
treef4da4836063d2f9d3ccb66e1a0e4015e8cd25e00 /tools/ioemu
parent0a8346854e56486156268113c4632e6f2545bc93 (diff)
downloadxen-cc5871d6da53bdf1ba296fcedfc9a956787a900f.tar.gz
xen-cc5871d6da53bdf1ba296fcedfc9a956787a900f.tar.bz2
xen-cc5871d6da53bdf1ba296fcedfc9a956787a900f.zip
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@marathontechnologies.com>
Diffstat (limited to 'tools/ioemu')
-rw-r--r--tools/ioemu/Makefile.target1
-rw-r--r--tools/ioemu/hw/pc.c7
-rw-r--r--tools/ioemu/hw/pci_emulation.c118
-rw-r--r--tools/ioemu/hw/pci_emulation.h24
-rw-r--r--tools/ioemu/vl.c38
-rw-r--r--tools/ioemu/vl.h4
6 files changed, 192 insertions, 0 deletions
diff --git a/tools/ioemu/Makefile.target b/tools/ioemu/Makefile.target
index a5f715896f..e307d2d5b8 100644
--- a/tools/ioemu/Makefile.target
+++ b/tools/ioemu/Makefile.target
@@ -441,6 +441,7 @@ ifdef CONFIG_STUBDOM
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 --git a/tools/ioemu/hw/pc.c b/tools/ioemu/hw/pc.c
index 3835191ac1..fdffbbccf0 100644
--- a/tools/ioemu/hw/pc.c
+++ b/tools/ioemu/hw/pc.c
@@ -1090,6 +1090,13 @@ static void pc_init1(uint64_t ram_size, int vga_ram_size, char *boot_device,
}
}
#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 --git a/tools/ioemu/hw/pci_emulation.c b/tools/ioemu/hw/pci_emulation.c
new file mode 100644
index 0000000000..0a4a7b452b
--- /dev/null
+++ b/tools/ioemu/hw/pci_emulation.c
@@ -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 --git a/tools/ioemu/hw/pci_emulation.h b/tools/ioemu/hw/pci_emulation.h
new file mode 100644
index 0000000000..abb7572fce
--- /dev/null
+++ b/tools/ioemu/hw/pci_emulation.h
@@ -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 --git a/tools/ioemu/vl.c b/tools/ioemu/vl.c
index 3b703871d0..c0d4537306 100644
--- a/tools/ioemu/vl.c
+++ b/tools/ioemu/vl.c
@@ -137,6 +137,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];
IOPortReadFunc *ioport_read_table[3][MAX_IOPORTS];
@@ -212,6 +215,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 --git a/tools/ioemu/vl.h b/tools/ioemu/vl.h
index bc06ecbe52..efe1ab2b16 100644
--- a/tools/ioemu/vl.h
+++ b/tools/ioemu/vl.h
@@ -1560,6 +1560,10 @@ void timeoffset_get(void);
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);