pci, pc, acpi fixes, enhancements

This includes some pretty big changes:
 - pci master abort support by Marcel
 - pci IRQ API rework by Marcel
 - acpi generation support by myself
 
 Everything has gone through several revisions, latest versions have been on
 list for a while without any more comments, tested by several
 people.
 
 Please pull for 1.7.
 
 Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1.4.15 (GNU/Linux)
 
 iQEcBAABAgAGBQJSXNO8AAoJECgfDbjSjVRp7VAH/0B73mCOiyVACGx7fazK3SGK
 X8TxZWVtG5A77ISqKyrtjLAhK9DCQjEzQTbMNhXHM3Ar6crwo7nJZnQvH2Gh1X2p
 34BOQSVc4rtXz5pwDIr48dBLrxeslwXub79chUs+IK1/4RSn3h3nuS3k6JVkmLJN
 rcHMj4ljJmi4Hd9vOpmS1jo/a61usi36hhU7CMgcrsXzStZycBBzCozOB3VW8p1X
 /iwyf91YjmNPkn9gA3/aViGjszu8jE91dkA0C+ljwvcGbs2yEl3LCWEJfsMvoh5P
 2M+k0XXbHwq/P9PFMa/2/lWOo4EO4Oxa+G/6QvovJrteYnktr+E9DqjU8pCT7yI=
 =CVfs
 -----END PGP SIGNATURE-----

Merge remote-tracking branch 'mst/tags/for_anthony' into staging

pci, pc, acpi fixes, enhancements

This includes some pretty big changes:
- pci master abort support by Marcel
- pci IRQ API rework by Marcel
- acpi generation support by myself

Everything has gone through several revisions, latest versions have been on
list for a while without any more comments, tested by several
people.

Please pull for 1.7.

Signed-off-by: Michael S. Tsirkin <mst@redhat.com>

# gpg: Signature made Tue 15 Oct 2013 07:33:48 AM CEST using RSA key ID D28D5469
# gpg: Can't check signature: public key not found

* mst/tags/for_anthony: (39 commits)
  ssdt-proc: update generated file
  ssdt: fix PBLK length
  i386: ACPI table generation code from seabios
  pc: use new api to add builtin tables
  acpi: add interface to access user-installed tables
  hpet: add API to find it
  pvpanic: add API to access io port
  ich9: APIs for pc guest info
  piix: APIs for pc guest info
  acpi/piix: add macros for acpi property names
  i386: define pc guest info
  loader: allow adding ROMs in done callbacks
  i386: add bios linker/loader
  loader: use file path size from fw_cfg.h
  acpi: ssdt pcihp: updat generated file
  acpi: pre-compiled ASL files
  acpi: add rules to compile ASL source
  i386: add ACPI table files from seabios
  q35: expose mmcfg size as a property
  q35: use macro for MCFG property name
  ...

Message-id: 1381818560-18367-1-git-send-email-mst@redhat.com
Signed-off-by: Anthony Liguori <anthony@codemonkey.ws>
This commit is contained in:
Anthony Liguori 2013-10-31 16:58:32 +01:00
commit b0eb759fb2
95 changed files with 16666 additions and 172 deletions

View file

@ -83,7 +83,7 @@ static const TypeInfo pcie_bus_info = {
static PCIBus *pci_find_bus_nr(PCIBus *bus, int bus_num);
static void pci_update_mappings(PCIDevice *d);
static void pci_set_irq(void *opaque, int irq_num, int level);
static void pci_irq_handler(void *opaque, int irq_num, int level);
static int pci_add_option_rom(PCIDevice *pdev, bool is_default_rom);
static void pci_del_option_rom(PCIDevice *pdev);
@ -161,7 +161,7 @@ void pci_device_deassert_intx(PCIDevice *dev)
{
int i;
for (i = 0; i < PCI_NUM_PINS; ++i) {
qemu_set_irq(dev->irq[i], 0);
pci_irq_handler(dev, i, 0);
}
}
@ -283,6 +283,24 @@ const char *pci_root_bus_path(PCIDevice *dev)
return rootbus->qbus.name;
}
static uint64_t master_abort_mem_read(void *opaque, hwaddr addr, unsigned size)
{
return -1ULL;
}
static void master_abort_mem_write(void *opaque, hwaddr addr, uint64_t val,
unsigned size)
{
}
static const MemoryRegionOps master_abort_mem_ops = {
.read = master_abort_mem_read,
.write = master_abort_mem_write,
.endianness = DEVICE_LITTLE_ENDIAN,
};
#define MASTER_ABORT_MEM_PRIORITY INT_MIN
static void pci_bus_init(PCIBus *bus, DeviceState *parent,
const char *name,
MemoryRegion *address_space_mem,
@ -294,6 +312,14 @@ static void pci_bus_init(PCIBus *bus, DeviceState *parent,
bus->address_space_mem = address_space_mem;
bus->address_space_io = address_space_io;
memory_region_init_io(&bus->master_abort_mem, OBJECT(bus),
&master_abort_mem_ops, bus, "pci-master-abort",
memory_region_size(bus->address_space_mem));
memory_region_add_subregion_overlap(bus->address_space_mem,
0, &bus->master_abort_mem,
MASTER_ABORT_MEM_PRIORITY);
/* host bridge */
QLIST_INIT(&bus->child);
@ -863,14 +889,12 @@ static PCIDevice *do_pci_register_device(PCIDevice *pci_dev, PCIBus *bus,
pci_dev->config_read = config_read;
pci_dev->config_write = config_write;
bus->devices[devfn] = pci_dev;
pci_dev->irq = qemu_allocate_irqs(pci_set_irq, pci_dev, PCI_NUM_PINS);
pci_dev->version_id = 2; /* Current pci device vmstate version */
return pci_dev;
}
static void do_pci_unregister_device(PCIDevice *pci_dev)
{
qemu_free_irqs(pci_dev->irq);
pci_dev->bus->devices[pci_dev->devfn] = NULL;
pci_config_free(pci_dev);
@ -1175,7 +1199,7 @@ void pci_default_write_config(PCIDevice *d, uint32_t addr, uint32_t val, int l)
/* generic PCI irq support */
/* 0 <= irq_num <= 3. level must be 0 or 1 */
static void pci_set_irq(void *opaque, int irq_num, int level)
static void pci_irq_handler(void *opaque, int irq_num, int level)
{
PCIDevice *pci_dev = opaque;
int change;
@ -1191,6 +1215,24 @@ static void pci_set_irq(void *opaque, int irq_num, int level)
pci_change_irq_level(pci_dev, irq_num, change);
}
static inline int pci_intx(PCIDevice *pci_dev)
{
return pci_get_byte(pci_dev->config + PCI_INTERRUPT_PIN) - 1;
}
qemu_irq pci_allocate_irq(PCIDevice *pci_dev)
{
int intx = pci_intx(pci_dev);
return qemu_allocate_irq(pci_irq_handler, pci_dev, intx);
}
void pci_set_irq(PCIDevice *pci_dev, int level)
{
int intx = pci_intx(pci_dev);
pci_irq_handler(pci_dev, intx, level);
}
/* Special hooks used by device assignment */
void pci_bus_set_route_irq_fn(PCIBus *bus, pci_route_irq_fn route_intx_to_irq)
{
@ -2264,7 +2306,7 @@ static void pci_dev_get_w64(PCIBus *b, PCIDevice *dev, void *opaque)
Range *range = opaque;
PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(dev);
uint16_t cmd = pci_get_word(dev->config + PCI_COMMAND);
int r;
int i;
if (!(cmd & PCI_COMMAND_MEMORY)) {
return;
@ -2283,17 +2325,21 @@ static void pci_dev_get_w64(PCIBus *b, PCIDevice *dev, void *opaque)
range_extend(range, &pref_range);
}
}
for (r = 0; r < PCI_NUM_REGIONS; ++r) {
PCIIORegion *region = &dev->io_regions[r];
for (i = 0; i < PCI_NUM_REGIONS; ++i) {
PCIIORegion *r = &dev->io_regions[i];
Range region_range;
if (!region->size ||
(region->type & PCI_BASE_ADDRESS_SPACE_IO) ||
!(region->type & PCI_BASE_ADDRESS_MEM_TYPE_64)) {
if (!r->size ||
(r->type & PCI_BASE_ADDRESS_SPACE_IO) ||
!(r->type & PCI_BASE_ADDRESS_MEM_TYPE_64)) {
continue;
}
region_range.begin = pci_bar_address(dev, i, r->type, r->size);
region_range.end = region_range.begin + r->size;
if (region_range.begin == PCI_BAR_UNMAPPED) {
continue;
}
region_range.begin = pci_get_quad(dev->config + pci_bar(dev, r));
region_range.end = region_range.begin + region->size;
region_range.begin = MAX(region_range.begin, 0x1ULL << 32);

View file

@ -187,7 +187,7 @@ static void hotplug_event_notify(PCIDevice *dev)
} else if (msi_enabled(dev)) {
msi_notify(dev, pcie_cap_flags_get_vector(dev));
} else {
qemu_set_irq(dev->irq[dev->exp.hpev_intx], dev->exp.hpev_notified);
pci_set_irq(dev, dev->exp.hpev_notified);
}
}
@ -195,7 +195,7 @@ static void hotplug_event_clear(PCIDevice *dev)
{
hotplug_event_update_event_status(dev);
if (!msix_enabled(dev) && !msi_enabled(dev) && !dev->exp.hpev_notified) {
qemu_set_irq(dev->irq[dev->exp.hpev_intx], 0);
pci_irq_deassert(dev);
}
}

View file

@ -285,7 +285,7 @@ static void pcie_aer_root_notify(PCIDevice *dev)
} else if (msi_enabled(dev)) {
msi_notify(dev, pcie_aer_root_get_vector(dev));
} else {
qemu_set_irq(dev->irq[dev->exp.aer_intx], 1);
pci_irq_assert(dev);
}
}
@ -768,7 +768,7 @@ void pcie_aer_root_write_config(PCIDevice *dev,
uint32_t root_cmd = pci_get_long(aer_cap + PCI_ERR_ROOT_COMMAND);
/* 6.2.4.1.2 Interrupt Generation */
if (!msix_enabled(dev) && !msi_enabled(dev)) {
qemu_set_irq(dev->irq[dev->exp.aer_intx], !!(root_cmd & enabled_cmd));
pci_set_irq(dev, !!(root_cmd & enabled_cmd));
return;
}

View file

@ -24,27 +24,6 @@
#include "hw/pci/pcie_host.h"
#include "exec/address-spaces.h"
/*
* PCI express mmcfig address
* bit 20 - 28: bus number
* bit 15 - 19: device number
* bit 12 - 14: function number
* bit 0 - 11: offset in configuration space of a given device
*/
#define PCIE_MMCFG_SIZE_MAX (1ULL << 28)
#define PCIE_MMCFG_SIZE_MIN (1ULL << 20)
#define PCIE_MMCFG_BUS_BIT 20
#define PCIE_MMCFG_BUS_MASK 0x1ff
#define PCIE_MMCFG_DEVFN_BIT 12
#define PCIE_MMCFG_DEVFN_MASK 0xff
#define PCIE_MMCFG_CONFOFFSET_MASK 0xfff
#define PCIE_MMCFG_BUS(addr) (((addr) >> PCIE_MMCFG_BUS_BIT) & \
PCIE_MMCFG_BUS_MASK)
#define PCIE_MMCFG_DEVFN(addr) (((addr) >> PCIE_MMCFG_DEVFN_BIT) & \
PCIE_MMCFG_DEVFN_MASK)
#define PCIE_MMCFG_CONFOFFSET(addr) ((addr) & PCIE_MMCFG_CONFOFFSET_MASK)
/* a helper function to get a PCIDevice for a given mmconfig address */
static inline PCIDevice *pcie_dev_find_by_mmcfg_addr(PCIBus *s,
uint32_t mmcfg_addr)
@ -104,9 +83,6 @@ static const MemoryRegionOps pcie_mmcfg_ops = {
.endianness = DEVICE_NATIVE_ENDIAN,
};
/* pcie_host::base_addr == PCIE_BASE_ADDR_UNMAPPED when it isn't mapped. */
#define PCIE_BASE_ADDR_UNMAPPED ((hwaddr)-1ULL)
int pcie_host_init(PCIExpressHost *e)
{
e->base_addr = PCIE_BASE_ADDR_UNMAPPED;

View file

@ -172,7 +172,7 @@ static void shpc_interrupt_update(PCIDevice *d)
if (msi_enabled(d) && shpc->msi_requested != level)
msi_notify(d, 0);
else
qemu_set_irq(d->irq[0], level);
pci_set_irq(d, level);
shpc->msi_requested = level;
}