ia64/xen-unstable

changeset 17881:97e02365a781

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>
author Keir Fraser <keir.fraser@citrix.com>
date Wed Jun 18 09:40:39 2008 +0100 (2008-06-18)
parents 9493a853df9e
children 666f5196f0fc
files tools/ioemu/Makefile.target tools/ioemu/hw/pc.c tools/ioemu/hw/pci_emulation.c tools/ioemu/hw/pci_emulation.h tools/ioemu/vl.c tools/ioemu/vl.h
line diff
     1.1 --- a/tools/ioemu/Makefile.target	Wed Jun 18 09:39:14 2008 +0100
     1.2 +++ b/tools/ioemu/Makefile.target	Wed Jun 18 09:40:39 2008 +0100
     1.3 @@ -441,6 +441,7 @@ ifdef CONFIG_STUBDOM
     1.4  VL_OBJS+= xenfbfront.o
     1.5  endif
     1.6  VL_OBJS+= xen_console.o
     1.7 +VL_OBJS+= pci_emulation.o
     1.8  ifndef CONFIG_STUBDOM
     1.9  VL_OBJS+= tpm_tis.o
    1.10  VL_OBJS+= $(SOUND_HW) $(AUDIODRV) mixeng.o 
     2.1 --- a/tools/ioemu/hw/pc.c	Wed Jun 18 09:39:14 2008 +0100
     2.2 +++ b/tools/ioemu/hw/pc.c	Wed Jun 18 09:40:39 2008 +0100
     2.3 @@ -1090,6 +1090,13 @@ static void pc_init1(uint64_t ram_size, 
     2.4          }
     2.5      }
     2.6  #endif /* !CONFIG_DM */
     2.7 +
     2.8 +    if (pci_enabled) {
     2.9 +        PCI_EMULATION_INFO *p;
    2.10 +        for (p = PciEmulationInfoHead; p != NULL; p = p->next) {
    2.11 +            pci_emulation_init(pci_bus, p);
    2.12 +        }
    2.13 +    }
    2.14  }
    2.15  
    2.16  static void pc_init_pci(uint64_t ram_size, int vga_ram_size, char *boot_device,
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/tools/ioemu/hw/pci_emulation.c	Wed Jun 18 09:40:39 2008 +0100
     3.3 @@ -0,0 +1,118 @@
     3.4 +/*
     3.5 + * Changes to PCI emulation made by Marathon Technologies, June 2008
     3.6 + */
     3.7 +
     3.8 +#include "vl.h"
     3.9 +
    3.10 +typedef struct {
    3.11 +    PCIDevice dev;
    3.12 +}   PCI_EMULATION_State;
    3.13 +
    3.14 +void parse_pci_emulation_info(char *config_text, PCI_EMULATION_INFO *pci_emulation_info)
    3.15 +{
    3.16 +    char *p;
    3.17 +    int i;
    3.18 +    int ret;
    3.19 +    for (p = config_text, i = 0; *p != '\0'; p++) {
    3.20 +        if (*p == ':') {
    3.21 +            break;
    3.22 +        }
    3.23 +        if (i < sizeof(pci_emulation_info->name) - 1) {
    3.24 +            pci_emulation_info->name[i] = *p;
    3.25 +            i++;
    3.26 +        }
    3.27 +    }
    3.28 +    pci_emulation_info->name[i] = '\0';
    3.29 +    if (*p == '\0') return;
    3.30 +    p++;
    3.31 +    ret = sscanf(p, "%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x",
    3.32 +                 &(pci_emulation_info->vendorid),
    3.33 +                 &(pci_emulation_info->deviceid),
    3.34 +                 &(pci_emulation_info->command),
    3.35 +                 &(pci_emulation_info->status),
    3.36 +                 &(pci_emulation_info->revision),
    3.37 +                 &(pci_emulation_info->classcode),
    3.38 +                 &(pci_emulation_info->headertype),
    3.39 +                 &(pci_emulation_info->subvendorid),
    3.40 +                 &(pci_emulation_info->subsystemid),
    3.41 +                 &(pci_emulation_info->interruputline),
    3.42 +                 &(pci_emulation_info->interruputpin));
    3.43 +#ifdef DEBUG
    3.44 +    fprintf(logfile, "qemu: pciemulation %s:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x\n",
    3.45 +            pci_emulation_info->name,
    3.46 +            pci_emulation_info->vendorid,
    3.47 +            pci_emulation_info->deviceid,
    3.48 +            pci_emulation_info->command,
    3.49 +            pci_emulation_info->status,
    3.50 +            pci_emulation_info->revision,
    3.51 +            pci_emulation_info->classcode,
    3.52 +            pci_emulation_info->headertype,
    3.53 +            pci_emulation_info->subvendorid,
    3.54 +            pci_emulation_info->subsystemid,
    3.55 +            pci_emulation_info->interruputline,
    3.56 +            pci_emulation_info->interruputpin);
    3.57 +#endif
    3.58 +    return;
    3.59 +}
    3.60 +
    3.61 +static void pci_emulation_save(QEMUFile *f, void *opaque)
    3.62 +{
    3.63 +    PCIDevice *d = opaque;
    3.64 +
    3.65 +    pci_device_save(d, f);
    3.66 +}
    3.67 +
    3.68 +static int pci_emulation_load(QEMUFile *f, void *opaque, int version_id)
    3.69 +{
    3.70 +    PCIDevice *d = opaque;
    3.71 +
    3.72 +    if (version_id != 1)
    3.73 +        return -EINVAL;
    3.74 +
    3.75 +    return pci_device_load(d, f);
    3.76 +}
    3.77 +
    3.78 +
    3.79 +void pci_emulation_init(PCIBus *bus, PCI_EMULATION_INFO *pci_emulation_info)
    3.80 +{
    3.81 +    int instance_id;
    3.82 +    PCI_EMULATION_State *d;
    3.83 +    uint8_t *pci_conf;
    3.84 +
    3.85 +#ifdef DEBUG
    3.86 +    fprintf(logfile, "qemu: pciinit\n");
    3.87 +#endif
    3.88 +    
    3.89 +    d = (PCI_EMULATION_State *)pci_register_device(bus,
    3.90 +                                                   pci_emulation_info->name, 
    3.91 +                                                   sizeof(PCI_EMULATION_State),
    3.92 +                                                   -1, 
    3.93 +                                                    NULL, NULL);
    3.94 +    pci_conf = d->dev.config;
    3.95 +    pci_conf[0x00] = pci_emulation_info->vendorid & 0xff;
    3.96 +    pci_conf[0x01] = (pci_emulation_info->vendorid & 0xff00) >> 8;
    3.97 +    pci_conf[0x02] = pci_emulation_info->deviceid & 0xff;
    3.98 +    pci_conf[0x03] = (pci_emulation_info->deviceid & 0xff00) >> 8;
    3.99 +    pci_conf[0x04] = pci_emulation_info->command & 0xff;
   3.100 +    pci_conf[0x05] = (pci_emulation_info->command & 0xff00) >> 8;
   3.101 +    pci_conf[0x06] = pci_emulation_info->status & 0xff;
   3.102 +    pci_conf[0x07] = (pci_emulation_info->status & 0xff00) >> 8;
   3.103 +    pci_conf[0x08] = pci_emulation_info->revision & 0xff;
   3.104 +    pci_conf[0x09] = pci_emulation_info->classcode & 0xff;
   3.105 +    pci_conf[0x0a] = (pci_emulation_info->classcode & 0xff00) >> 8;
   3.106 +    pci_conf[0x0b] = (pci_emulation_info->classcode & 0xff0000) >> 16;
   3.107 +    pci_conf[0x0e] = pci_emulation_info->headertype & 0xff;
   3.108 +    pci_conf[0x2c] = pci_emulation_info->subvendorid & 0xff;
   3.109 +    pci_conf[0x2d] = (pci_emulation_info->subvendorid & 0xff00) >> 8;
   3.110 +    pci_conf[0x2e] = pci_emulation_info->subsystemid & 0xff;
   3.111 +    pci_conf[0x2f] = (pci_emulation_info->subsystemid & 0xff00) >> 8;
   3.112 +    pci_conf[0x3c] = pci_emulation_info->interruputline & 0xff;
   3.113 +    pci_conf[0x3d] = pci_emulation_info->interruputpin & 0xff;
   3.114 +
   3.115 +    instance_id = pci_bus_num(bus) << 8 | d->dev.devfn;
   3.116 +    register_savevm(pci_emulation_info->name, instance_id,
   3.117 +                    1, pci_emulation_save, pci_emulation_load, d);
   3.118 +
   3.119 +
   3.120 +    return;    
   3.121 +}
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/tools/ioemu/hw/pci_emulation.h	Wed Jun 18 09:40:39 2008 +0100
     4.3 @@ -0,0 +1,24 @@
     4.4 +/*
     4.5 + * Changes to PCI emulation made by Marathon Technologies, June 2008
     4.6 + */
     4.7 +
     4.8 +typedef struct PCI_EMULATION_INFO_t {
     4.9 +    struct PCI_EMULATION_INFO_t *next;
    4.10 +    char name[32];
    4.11 +    unsigned int vendorid;
    4.12 +    unsigned int deviceid;
    4.13 +    unsigned int command;
    4.14 +    unsigned int status;
    4.15 +    unsigned int revision;
    4.16 +    unsigned int classcode;
    4.17 +    unsigned int headertype;
    4.18 +    unsigned int subvendorid;
    4.19 +    unsigned int subsystemid;
    4.20 +    unsigned int interruputline;
    4.21 +    unsigned int interruputpin;
    4.22 +}   PCI_EMULATION_INFO;
    4.23 +    
    4.24 +void parse_pci_emulation_info(char *config_text, PCI_EMULATION_INFO *pci_emulation_info);
    4.25 +void pci_emulation_init(PCIBus *bus, PCI_EMULATION_INFO *pci_emulation_info);
    4.26 +
    4.27 +extern PCI_EMULATION_INFO *PciEmulationInfoHead;
     5.1 --- a/tools/ioemu/vl.c	Wed Jun 18 09:39:14 2008 +0100
     5.2 +++ b/tools/ioemu/vl.c	Wed Jun 18 09:40:39 2008 +0100
     5.3 @@ -137,6 +137,9 @@
     5.4  /* XXX: use a two level table to limit memory usage */
     5.5  #define MAX_IOPORTS 65536
     5.6  
     5.7 +/* Max number of PCI emulation */
     5.8 +#define MAX_PCI_EMULATION 32
     5.9 +
    5.10  const char *bios_dir = CONFIG_QEMU_SHAREDIR;
    5.11  void *ioport_opaque[MAX_IOPORTS];
    5.12  IOPortReadFunc *ioport_read_table[3][MAX_IOPORTS];
    5.13 @@ -212,6 +215,8 @@ int xc_handle;
    5.14  char domain_name[64] = "Xen-no-name";
    5.15  extern int domid;
    5.16  
    5.17 +PCI_EMULATION_INFO *PciEmulationInfoHead = NULL;
    5.18 +
    5.19  /***********************************************************/
    5.20  /* x86 ISA bus support */
    5.21  
    5.22 @@ -4399,6 +4404,17 @@ void do_pci_add(char *devname)
    5.23  #endif
    5.24  }
    5.25  
    5.26 +static int pci_emulation_add(char *config_text)
    5.27 +{
    5.28 +    PCI_EMULATION_INFO *new;
    5.29 +    if ((new = qemu_mallocz(sizeof(PCI_EMULATION_INFO))) == NULL) {
    5.30 +        return -1;
    5.31 +    }
    5.32 +    parse_pci_emulation_info(config_text, new);
    5.33 +    new->next = PciEmulationInfoHead;
    5.34 +    PciEmulationInfoHead = new;
    5.35 +    return 0;
    5.36 +}
    5.37  
    5.38  /***********************************************************/
    5.39  /* pid file */
    5.40 @@ -6590,6 +6606,7 @@ void help(void)
    5.41  #endif
    5.42  	   "-option-rom rom load a file, rom, into the option ROM space\n"
    5.43             "-acpi           disable or enable ACPI of HVM domain \n"
    5.44 +           "-pciemulation       name:vendorid:deviceid:command:status:revision:classcode:headertype:subvendorid:subsystemid:interruputline:interruputpin\n"
    5.45             "\n"
    5.46             "During emulation, the following keys are useful:\n"
    5.47             "ctrl-alt-f      toggle full screen\n"
    5.48 @@ -6688,6 +6705,7 @@ enum {
    5.49      QEMU_OPTION_vncviewer,
    5.50      QEMU_OPTION_vncunused,
    5.51      QEMU_OPTION_pci,
    5.52 +    QEMU_OPTION_pci_emulation,
    5.53  };
    5.54  
    5.55  typedef struct QEMUOption {
    5.56 @@ -6789,6 +6807,7 @@ const QEMUOption qemu_options[] = {
    5.57      { "vcpus", 1, QEMU_OPTION_vcpus },
    5.58      { "acpi", 0, QEMU_OPTION_acpi },
    5.59      { "pci", HAS_ARG, QEMU_OPTION_pci},
    5.60 +    { "pciemulation", HAS_ARG, QEMU_OPTION_pci_emulation },
    5.61      { NULL },
    5.62  };
    5.63  
    5.64 @@ -7073,6 +7092,8 @@ int main(int argc, char **argv)
    5.65      sigset_t set;
    5.66      char qemu_dm_logfilename[128];
    5.67      const char *direct_pci = direct_pci_str;
    5.68 +    int nb_pci_emulation = 0;
    5.69 +    char pci_emulation_config_text[MAX_PCI_EMULATION][256];
    5.70  
    5.71  #if !defined(__sun__) && !defined(CONFIG_STUBDOM)
    5.72      /* Maximise rlimits. Needed where default constraints are tight (*BSD). */
    5.73 @@ -7598,6 +7619,16 @@ int main(int argc, char **argv)
    5.74              case QEMU_OPTION_vncunused:
    5.75                  vncunused++;
    5.76                  break;
    5.77 +            case QEMU_OPTION_pci_emulation:
    5.78 +                if (nb_pci_emulation >= MAX_PCI_EMULATION) {
    5.79 +                    fprintf(stderr, "Too many PCI emulations\n");
    5.80 +                    exit(1);
    5.81 +                }
    5.82 +                pstrcpy(pci_emulation_config_text[nb_pci_emulation],
    5.83 +                        sizeof(pci_emulation_config_text[0]),
    5.84 +                        optarg);
    5.85 +                nb_pci_emulation++;
    5.86 +                break;
    5.87              }
    5.88          }
    5.89      }
    5.90 @@ -7897,6 +7928,13 @@ int main(int argc, char **argv)
    5.91          }
    5.92      }
    5.93  
    5.94 +    for (i = 0; i < nb_pci_emulation; i++) {
    5.95 +        if(pci_emulation_add(pci_emulation_config_text[i]) < 0) {
    5.96 +            fprintf(stderr, "Warning: could not add PCI device %s\n",
    5.97 +                    pci_emulation_config_text[i]);
    5.98 +        }
    5.99 +    }
   5.100 +
   5.101      qemu_set_fd_handler(xenstore_fd(), xenstore_process_event, NULL, NULL);
   5.102  
   5.103      machine->init(ram_size, vga_ram_size, boot_device,
     6.1 --- a/tools/ioemu/vl.h	Wed Jun 18 09:39:14 2008 +0100
     6.2 +++ b/tools/ioemu/vl.h	Wed Jun 18 09:40:39 2008 +0100
     6.3 @@ -1560,6 +1560,10 @@ void timeoffset_get(void);
     6.4  void pci_xen_platform_init(PCIBus *bus);
     6.5  #endif
     6.6  
     6.7 +/* pci_emulation.c */
     6.8 +#ifndef QEMU_TOOL
     6.9 +#include "hw/pci_emulation.h"
    6.10 +#endif
    6.11  
    6.12  void kqemu_record_dump(void);
    6.13