Skip to content

Commit

Permalink
Merge remote-tracking branch 'remotes/mst/tags/for_upstream' into sta…
Browse files Browse the repository at this point in the history
…ging

pc, acpi, virtio, tpm

This includes pxb support by Marcel, as well as multiple enhancements all over
the place.

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

# gpg: Signature made Thu Jun  4 11:51:02 2015 BST using RSA key ID D28D5469
# gpg: Good signature from "Michael S. Tsirkin <mst@kernel.org>"
# gpg:                 aka "Michael S. Tsirkin <mst@redhat.com>"

* remotes/mst/tags/for_upstream: (28 commits)
  vhost: logs sharing
  hw/acpi: piix4_pm_init(): take fw_cfg object no more
  hw/acpi: move "etc/system-states" fw_cfg file from PIIX4 to core
  hw/acpi: acpi_pm1_cnt_init(): take "disable_s3" and "disable_s4"
  pc-dimm: don't assert if pc-dimm alignment != hotpluggable mem range size
  docs: Add PXB documentation
  apci: fix PXB behaviour if used with unsupported BIOS
  hw/pxb: add numa_node parameter
  hw/pci: add support for NUMA nodes
  hw/pxb: add map_irq func
  hw/pci: inform bios if the system has extra pci root buses
  hw/pci: introduce PCI Expander Bridge (PXB)
  hw/pci: removed 'rootbus nr is 0' assumption from qmp_pci_query
  hw/acpi: remove from root bus 0 the crs resources used by other buses.
  hw/acpi: add _CRS method for extra root busses
  hw/apci: add _PRT method for extra PCI root busses
  hw/acpi: add support for i440fx 'snooping' root busses
  hw/pci: extend PCI config access to support devices behind PXB
  hw/i386: query only for q35/pc when looking for pci host bridge
  hw/pci: made pci_bus_num a PCIBusClass method
  ...

Conflicts:
	hw/i386/pc_piix.c

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
  • Loading branch information
pm215 committed Jun 4, 2015
2 parents 3b730f5 + 309750f commit d6688ba
Show file tree
Hide file tree
Showing 32 changed files with 920 additions and 108 deletions.
58 changes: 58 additions & 0 deletions docs/pci_expander_bridge.txt
@@ -0,0 +1,58 @@
PCI EXPANDER BRIDGE (PXB)
=========================

Description
===========
PXB is a "light-weight" host bridge in the same PCI domain
as the main host bridge whose purpose is to enable
the main host bridge to support multiple PCI root buses.
It is implemented only for i440fx and can be placed only
on bus 0 (pci.0).

As opposed to PCI-2-PCI bridge's secondary bus, PXB's bus
is a primary bus and can be associated with a NUMA node
(different from the main host bridge) allowing the guest OS
to recognize the proximity of a pass-through device to
other resources as RAM and CPUs.

Usage
=====
A detailed command line would be:

[qemu-bin + storage options]
-m 2G
-object memory-backend-ram,size=1024M,policy=bind,host-nodes=0,id=ram-node0 -numa node,nodeid=0,cpus=0,memdev=ram-node0
-object memory-backend-ram,size=1024M,policy=bind,host-nodes=1,id=ram-node1 -numa node,nodeid=1,cpus=1,memdev=ram-node1
-device pxb,id=bridge1,bus=pci.0,numa_node=1,bus_nr=4 -netdev user,id=nd-device e1000,bus=bridge1,addr=0x4,netdev=nd
-device pxb,id=bridge2,bus=pci.0,numa_node=0,bus_nr=8,bus=pci.0 -device e1000,bus=bridge2,addr=0x3
-device pxb,id=bridge3,bus=pci.0,bus_nr=40,bus=pci.0 -drive if=none,id=drive0,file=[img] -device virtio-blk-pci,drive=drive0,scsi=off,bus=bridge3,addr=1

Here you have:
- 2 NUMA nodes for the guest, 0 and 1. (both mapped to the same NUMA node in host, but you can and should put it in different host NUMA nodes)
- a pxb host bridge attached to NUMA 1 with an e1000 behind it
- a pxb host bridge attached to NUMA 0 with an e1000 behind it
- a pxb host bridge not attached to any NUMA with a hard drive behind it.

Limitations
===========
Please observe that we specified the bus "pci.0" for the second and third pxb.
This is because when no bus is given, another pxb can be selected by QEMU as default bus,
however, PXBs can be placed only under the root bus.

Implementation
==============
The PXB is composed by:
- HostBridge (TYPE_PXB_HOST)
The host bridge allows to register and query the PXB's rPCI root bus in QEMU.
- PXBDev(TYPE_PXB_DEVICE)
It is a regular PCI Device that resides on the piix host-bridge bus and its bus uses the same PCI domain.
However, the bus behind is exposed through ACPI as a primary PCI bus and starts a new PCI hierarchy.
The interrupts from devices behind the PXB are routed through this device the same as if it were a
PCI-2-PCI bridge. The _PRT follows the i440fx model.
- PCIBridgeDev(TYPE_PCI_BRIDGE_DEV)
Created automatically as part of init sequence.
When adding a device to PXB it is attached to the bridge for two reasons:
- Using the bridge will enable hotplug support
- All the devices behind the bridge will use bridge's IO/MEM windows compacting
the PCI address space.

8 changes: 8 additions & 0 deletions hw/acpi/aml-build.c
Expand Up @@ -687,6 +687,14 @@ Aml *aml_else(void)
return var;
}

/* ACPI 1.0b: 16.2.5.3 Type 1 Opcodes Encoding: DefWhile */
Aml *aml_while(Aml *predicate)
{
Aml *var = aml_bundle(0xA2 /* WhileOp */, AML_PACKAGE);
aml_append(var, predicate);
return var;
}

/* ACPI 1.0b: 16.2.5.2 Named Objects Encoding: DefMethod */
Aml *aml_method(const char *name, int arg_count)
{
Expand Down
22 changes: 21 additions & 1 deletion hw/acpi/core.c
Expand Up @@ -22,6 +22,7 @@
#include "hw/hw.h"
#include "hw/i386/pc.h"
#include "hw/acpi/acpi.h"
#include "hw/nvram/fw_cfg.h"
#include "qemu/config-file.h"
#include "qapi/opts-visitor.h"
#include "qapi/dealloc-visitor.h"
Expand Down Expand Up @@ -592,14 +593,26 @@ static const MemoryRegionOps acpi_pm_cnt_ops = {
.endianness = DEVICE_LITTLE_ENDIAN,
};

void acpi_pm1_cnt_init(ACPIREGS *ar, MemoryRegion *parent, uint8_t s4_val)
void acpi_pm1_cnt_init(ACPIREGS *ar, MemoryRegion *parent,
bool disable_s3, bool disable_s4, uint8_t s4_val)
{
FWCfgState *fw_cfg;

ar->pm1.cnt.s4_val = s4_val;
ar->wakeup.notify = acpi_notify_wakeup;
qemu_register_wakeup_notifier(&ar->wakeup);
memory_region_init_io(&ar->pm1.cnt.io, memory_region_owner(parent),
&acpi_pm_cnt_ops, ar, "acpi-cnt", 2);
memory_region_add_subregion(parent, 4, &ar->pm1.cnt.io);

fw_cfg = fw_cfg_find();
if (fw_cfg) {
uint8_t suspend[6] = {128, 0, 0, 129, 128, 128};
suspend[3] = 1 | ((!disable_s3) << 7);
suspend[4] = s4_val | ((!disable_s4) << 7);

fw_cfg_add_file(fw_cfg, "etc/system-states", g_memdup(suspend, 6), 6);
}
}

void acpi_pm1_cnt_reset(ACPIREGS *ar)
Expand Down Expand Up @@ -666,6 +679,13 @@ uint32_t acpi_gpe_ioport_readb(ACPIREGS *ar, uint32_t addr)
return val;
}

void acpi_send_gpe_event(ACPIREGS *ar, qemu_irq irq,
AcpiGPEStatusBits status)
{
ar->gpe.sts[0] |= status;
acpi_update_sci(ar, irq);
}

void acpi_update_sci(ACPIREGS *regs, qemu_irq irq)
{
int sci_level, pm1a_sts;
Expand Down
3 changes: 1 addition & 2 deletions hw/acpi/cpu_hotplug.c
Expand Up @@ -59,8 +59,7 @@ void acpi_cpu_plug_cb(ACPIREGS *ar, qemu_irq irq,
return;
}

ar->gpe.sts[0] |= ACPI_CPU_HOTPLUG_STATUS;
acpi_update_sci(ar, irq);
acpi_send_gpe_event(ar, irq, ACPI_CPU_HOTPLUG_STATUS);
}

void acpi_cpu_hotplug_init(MemoryRegion *parent, Object *owner,
Expand Down
3 changes: 2 additions & 1 deletion hw/acpi/ich9.c
Expand Up @@ -219,7 +219,8 @@ void ich9_pm_init(PCIDevice *lpc_pci, ICH9LPCPMRegs *pm,

acpi_pm_tmr_init(&pm->acpi_regs, ich9_pm_update_sci_fn, &pm->io);
acpi_pm1_evt_init(&pm->acpi_regs, ich9_pm_update_sci_fn, &pm->io);
acpi_pm1_cnt_init(&pm->acpi_regs, &pm->io, pm->s4_val);
acpi_pm1_cnt_init(&pm->acpi_regs, &pm->io, pm->disable_s3, pm->disable_s4,
pm->s4_val);

acpi_gpe_init(&pm->acpi_regs, ICH9_PMIO_GPE0_LEN);
memory_region_init_io(&pm->io_gpe, OBJECT(lpc_pci), &ich9_gpe_ops, pm,
Expand Down
6 changes: 2 additions & 4 deletions hw/acpi/memory_hotplug.c
Expand Up @@ -241,8 +241,7 @@ void acpi_memory_plug_cb(ACPIREGS *ar, qemu_irq irq, MemHotplugState *mem_st,
mdev->is_inserting = true;

/* do ACPI magic */
ar->gpe.sts[0] |= ACPI_MEMORY_HOTPLUG_STATUS;
acpi_update_sci(ar, irq);
acpi_send_gpe_event(ar, irq, ACPI_MEMORY_HOTPLUG_STATUS);
return;
}

Expand All @@ -260,8 +259,7 @@ void acpi_memory_unplug_request_cb(ACPIREGS *ar, qemu_irq irq,
mdev->is_removing = true;

/* Do ACPI magic */
ar->gpe.sts[0] |= ACPI_MEMORY_HOTPLUG_STATUS;
acpi_update_sci(ar, irq);
acpi_send_gpe_event(ar, irq, ACPI_MEMORY_HOTPLUG_STATUS);
}

void acpi_memory_unplug_cb(MemHotplugState *mem_st,
Expand Down
7 changes: 2 additions & 5 deletions hw/acpi/pcihp.c
Expand Up @@ -45,7 +45,6 @@
# define ACPI_PCIHP_DPRINTF(format, ...) do { } while (0)
#endif

#define ACPI_PCI_HOTPLUG_STATUS 2
#define ACPI_PCIHP_ADDR 0xae00
#define ACPI_PCIHP_SIZE 0x0014
#define ACPI_PCIHP_LEGACY_SIZE 0x000f
Expand Down Expand Up @@ -202,8 +201,7 @@ void acpi_pcihp_device_plug_cb(ACPIREGS *ar, qemu_irq irq, AcpiPciHpState *s,

s->acpi_pcihp_pci_status[bsel].up |= (1U << slot);

ar->gpe.sts[0] |= ACPI_PCI_HOTPLUG_STATUS;
acpi_update_sci(ar, irq);
acpi_send_gpe_event(ar, irq, ACPI_PCI_HOTPLUG_STATUS);
}

void acpi_pcihp_device_unplug_cb(ACPIREGS *ar, qemu_irq irq, AcpiPciHpState *s,
Expand All @@ -220,8 +218,7 @@ void acpi_pcihp_device_unplug_cb(ACPIREGS *ar, qemu_irq irq, AcpiPciHpState *s,

s->acpi_pcihp_pci_status[bsel].down |= (1U << slot);

ar->gpe.sts[0] |= ACPI_PCI_HOTPLUG_STATUS;
acpi_update_sci(ar, irq);
acpi_send_gpe_event(ar, irq, ACPI_PCI_HOTPLUG_STATUS);
}

static uint64_t pci_read(void *opaque, hwaddr addr, unsigned int size)
Expand Down
13 changes: 2 additions & 11 deletions hw/acpi/piix4.c
Expand Up @@ -475,7 +475,7 @@ static void piix4_pm_realize(PCIDevice *dev, Error **errp)

acpi_pm_tmr_init(&s->ar, pm_tmr_timer, &s->io);
acpi_pm1_evt_init(&s->ar, pm_tmr_timer, &s->io);
acpi_pm1_cnt_init(&s->ar, &s->io, s->s4_val);
acpi_pm1_cnt_init(&s->ar, &s->io, s->disable_s3, s->disable_s4, s->s4_val);
acpi_gpe_init(&s->ar, GPE_LEN);

s->powerdown_notifier.notify = piix4_pm_powerdown_req;
Expand Down Expand Up @@ -503,8 +503,7 @@ Object *piix4_pm_find(void)

I2CBus *piix4_pm_init(PCIBus *bus, int devfn, uint32_t smb_io_base,
qemu_irq sci_irq, qemu_irq smi_irq,
int kvm_enabled, FWCfgState *fw_cfg,
DeviceState **piix4_pm)
int kvm_enabled, DeviceState **piix4_pm)
{
DeviceState *dev;
PIIX4PMState *s;
Expand All @@ -525,14 +524,6 @@ I2CBus *piix4_pm_init(PCIBus *bus, int devfn, uint32_t smb_io_base,

qdev_init_nofail(dev);

if (fw_cfg) {
uint8_t suspend[6] = {128, 0, 0, 129, 128, 128};
suspend[3] = 1 | ((!s->disable_s3) << 7);
suspend[4] = s->s4_val | ((!s->disable_s4) << 7);

fw_cfg_add_file(fw_cfg, "etc/system-states", g_memdup(suspend, 6), 6);
}

return s->smb.smbus;
}

Expand Down

0 comments on commit d6688ba

Please sign in to comment.