diff options
author | Keir Fraser <keir.fraser@citrix.com> | 2008-06-18 09:40:39 +0100 |
---|---|---|
committer | Keir Fraser <keir.fraser@citrix.com> | 2008-06-18 09:40:39 +0100 |
commit | cc5871d6da53bdf1ba296fcedfc9a956787a900f (patch) | |
tree | f4da4836063d2f9d3ccb66e1a0e4015e8cd25e00 /tools/ioemu | |
parent | 0a8346854e56486156268113c4632e6f2545bc93 (diff) | |
download | xen-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.target | 1 | ||||
-rw-r--r-- | tools/ioemu/hw/pc.c | 7 | ||||
-rw-r--r-- | tools/ioemu/hw/pci_emulation.c | 118 | ||||
-rw-r--r-- | tools/ioemu/hw/pci_emulation.h | 24 | ||||
-rw-r--r-- | tools/ioemu/vl.c | 38 | ||||
-rw-r--r-- | tools/ioemu/vl.h | 4 |
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); |