mirror of
https://github.com/qemu/qemu.git
synced 2024-11-24 11:23:43 +08:00
virtio, pci fixes, enhancements
Almost exclusively bugfixes, though in this case, we are adding functionality to the pxb in order to make OVMF work on it. Signed-off-by: Michael S. Tsirkin <mst@redhat.com> -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQEcBAABAgAGBQJVjVb/AAoJECgfDbjSjVRpeaEH/2bwK7BGgczEQ7fhzIEaQSQq SV7aychNZvUFASXLV6aVmQCdYixZxlI9KDn0pMRYntUcjxRRB48U3N5Sy4km46Pw LLN3vxGzHazlE7AJ5c+WVDf0e2k7v3CpZ/TKXzPHmvZXIuBfjKXtKzBgyQYxGkmL JgRrRSHDrsbvfmhI4uHMpCTYs/WeY1cuA1IzvimBjmvVP5kkko4NoX+HEWmGJ6WK 13fQuV+Cvz7Yk40HRpPAM0QPV2etGCj+dU7xgF9BWnn9mzbGC5iy8EUClyGil/af k3i/bCxs6IgpQ76LaezJtGPtn1jbohrO4qRqlatUAJCwgCYMCkxkIk+Pr4A3x4c= =6WvB -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/mst/tags/for_upstream' into staging virtio, pci fixes, enhancements Almost exclusively bugfixes, though in this case, we are adding functionality to the pxb in order to make OVMF work on it. Signed-off-by: Michael S. Tsirkin <mst@redhat.com> # gpg: Signature made Fri Jun 26 14:43:27 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: Fix glib_subprocess test hw/pci-bridge: format special OFW unit address for PXB host hw/core: explicit OFW unit address callback for SysBusDeviceClass hw/pci-bridge: disable SHPC in PXB hw/pci-bridge: introduce "shpc" property hw/pci: introduce shpc_present() helper function hw/pci-bridge: add macro for "msi" property hw/pci-bridge: add macro for "chassis_nr" property hw/pci-bridge: expose _test parameter in SHPC_VMSTATE() migration: introduce VMSTATE_BUFFER_UNSAFE_INFO_TEST() add pci-bridge-seat pc: cleanup and convert TMP ACPI device description to AML API MAINTAINERS: add ACPI entry vhost: correctly pass error to caller in vhost_dev_enable_notifiers() balloon: add a feature bit to let Guest OS deflate balloon on oom qdev: fix OVERFLOW_BEFORE_WIDEN virito-pci: fix OVERRUN problem Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
dc1e1350f8
12
MAINTAINERS
12
MAINTAINERS
@ -644,7 +644,19 @@ M: Michael S. Tsirkin <mst@redhat.com>
|
||||
S: Supported
|
||||
F: include/hw/pci/*
|
||||
F: hw/pci/*
|
||||
|
||||
ACPI
|
||||
M: Michael S. Tsirkin <mst@redhat.com>
|
||||
M: Igor Mammedov <imammedo@redhat.com>
|
||||
S: Supported
|
||||
F: include/hw/acpi/*
|
||||
F: hw/mem/*
|
||||
F: hw/acpi/*
|
||||
F: hw/i386/acpi-build.[hc]
|
||||
F: hw/i386/*dsl
|
||||
F: hw/arm/virt-acpi-build.c
|
||||
F: include/hw/arm/virt-acpi-build.h
|
||||
F: scripts/acpi*py
|
||||
|
||||
ppc4xx
|
||||
M: Alexander Graf <agraf@suse.de>
|
||||
|
2
configure
vendored
2
configure
vendored
@ -4773,7 +4773,7 @@ if test "$bluez" = "yes" ; then
|
||||
echo "CONFIG_BLUEZ=y" >> $config_host_mak
|
||||
echo "BLUEZ_CFLAGS=$bluez_cflags" >> $config_host_mak
|
||||
fi
|
||||
if test "glib_subprocess" = "yes" ; then
|
||||
if test "$glib_subprocess" = "yes" ; then
|
||||
echo "CONFIG_HAS_GLIB_SUBPROCESS_TESTS=y" >> $config_host_mak
|
||||
fi
|
||||
echo "GLIB_CFLAGS=$glib_cflags" >> $config_host_mak
|
||||
|
@ -106,6 +106,25 @@ the devices attached to the seat.
|
||||
Background info is here:
|
||||
http://www.freedesktop.org/wiki/Software/systemd/multiseat/
|
||||
|
||||
|
||||
guest side with pci-bridge-seat
|
||||
-------------------------------
|
||||
|
||||
Qemu version FIXME and newer has a new pci-bridge-seat device which
|
||||
can be used instead of pci-bridge. Just swap the device name in the
|
||||
qemu command line above. The only difference between the two devices
|
||||
is the pci id. We can match the pci id instead of the device path
|
||||
with a nice generic rule now, which simplifies the guest
|
||||
configuration:
|
||||
|
||||
[root@fedora ~]# cat /etc/udev/rules.d/70-qemu-pci-bridge-seat.rules
|
||||
SUBSYSTEM=="pci", ATTR{vendor}=="0x1b36", ATTR{device}=="0x000a", \
|
||||
TAG+="seat", ENV{ID_AUTOSEAT}="1"
|
||||
|
||||
Patch with this rule will be submitted to upstream udev/systemd, so
|
||||
long-term, when systemd with this lands in distros, things will work
|
||||
just fine without any manual guest configuration.
|
||||
|
||||
Enjoy!
|
||||
|
||||
--
|
||||
|
@ -47,6 +47,7 @@ PCI devices (other than virtio):
|
||||
1b36:0005 PCI test device (docs/specs/pci-testdev.txt)
|
||||
1b36:0006 PCI Rocker Ethernet switch device
|
||||
1b36:0007 PCI SD Card Host Controller Interface (SDHCI)
|
||||
1b36:000a PCI-PCI bridge (multiseat)
|
||||
|
||||
All these devices are documented in docs/specs.
|
||||
|
||||
|
@ -131,7 +131,7 @@ PropertyInfo qdev_prop_bit = {
|
||||
static uint64_t qdev_get_prop_mask64(Property *prop)
|
||||
{
|
||||
assert(prop->info == &qdev_prop_bit);
|
||||
return 0x1 << prop->bitnr;
|
||||
return 0x1ull << prop->bitnr;
|
||||
}
|
||||
|
||||
static void bit64_prop_set(DeviceState *dev, Property *props, bool val)
|
||||
|
@ -281,6 +281,9 @@ static void sysbus_dev_print(Monitor *mon, DeviceState *dev, int indent)
|
||||
static char *sysbus_get_fw_dev_path(DeviceState *dev)
|
||||
{
|
||||
SysBusDevice *s = SYS_BUS_DEVICE(dev);
|
||||
SysBusDeviceClass *sbc = SYS_BUS_DEVICE_GET_CLASS(s);
|
||||
/* for the explicit unit address fallback case: */
|
||||
char *addr, *fw_dev_path;
|
||||
|
||||
if (s->num_mmio) {
|
||||
return g_strdup_printf("%s@" TARGET_FMT_plx, qdev_fw_name(dev),
|
||||
@ -289,6 +292,14 @@ static char *sysbus_get_fw_dev_path(DeviceState *dev)
|
||||
if (s->num_pio) {
|
||||
return g_strdup_printf("%s@i%04x", qdev_fw_name(dev), s->pio[0]);
|
||||
}
|
||||
if (sbc->explicit_ofw_unit_address) {
|
||||
addr = sbc->explicit_ofw_unit_address(s);
|
||||
if (addr) {
|
||||
fw_dev_path = g_strdup_printf("%s@%s", qdev_fw_name(dev), addr);
|
||||
g_free(addr);
|
||||
return fw_dev_path;
|
||||
}
|
||||
}
|
||||
return g_strdup(qdev_fw_name(dev));
|
||||
}
|
||||
|
||||
|
@ -8,8 +8,7 @@ obj-$(CONFIG_XEN) += ../xenpv/ xen/
|
||||
obj-y += kvmvapic.o
|
||||
obj-y += acpi-build.o
|
||||
hw/i386/acpi-build.o: hw/i386/acpi-build.c \
|
||||
hw/i386/acpi-dsdt.hex hw/i386/q35-acpi-dsdt.hex \
|
||||
hw/i386/ssdt-tpm.hex hw/i386/ssdt-tpm2.hex
|
||||
hw/i386/acpi-dsdt.hex hw/i386/q35-acpi-dsdt.hex
|
||||
|
||||
iasl-option=$(shell if test -z "`$(1) $(2) 2>&1 > /dev/null`" \
|
||||
; then echo "$(2)"; else echo "$(3)"; fi ;)
|
||||
|
@ -433,9 +433,6 @@ build_madt(GArray *table_data, GArray *linker, AcpiCpuInfo *cpu,
|
||||
table_data->len - madt_start, 1);
|
||||
}
|
||||
|
||||
#include "hw/i386/ssdt-tpm.hex"
|
||||
#include "hw/i386/ssdt-tpm2.hex"
|
||||
|
||||
/* Assign BSEL property to all buses. In the future, this can be changed
|
||||
* to only assign to buses that support hotplug.
|
||||
*/
|
||||
@ -1328,6 +1325,19 @@ build_ssdt(GArray *table_data, GArray *linker,
|
||||
Aml *scope = aml_scope("PCI0");
|
||||
/* Scan all PCI buses. Generate tables to support hotplug. */
|
||||
build_append_pci_bus_devices(scope, bus, pm->pcihp_bridge_en);
|
||||
|
||||
if (misc->tpm_version != TPM_VERSION_UNSPEC) {
|
||||
dev = aml_device("ISA.TPM");
|
||||
aml_append(dev, aml_name_decl("_HID", aml_eisaid("PNP0C31")));
|
||||
aml_append(dev, aml_name_decl("_STA", aml_int(0xF)));
|
||||
crs = aml_resource_template();
|
||||
aml_append(crs, aml_memory32_fixed(TPM_TIS_ADDR_BASE,
|
||||
TPM_TIS_ADDR_SIZE, AML_READ_WRITE));
|
||||
aml_append(crs, aml_irq_no_flags(TPM_TIS_IRQ));
|
||||
aml_append(dev, aml_name_decl("_CRS", crs));
|
||||
aml_append(scope, dev);
|
||||
}
|
||||
|
||||
aml_append(sb_scope, scope);
|
||||
}
|
||||
}
|
||||
@ -1382,23 +1392,10 @@ build_tpm_tcpa(GArray *table_data, GArray *linker, GArray *tcpalog)
|
||||
acpi_data_push(tcpalog, TPM_LOG_AREA_MINIMUM_SIZE);
|
||||
}
|
||||
|
||||
static void
|
||||
build_tpm_ssdt(GArray *table_data, GArray *linker)
|
||||
{
|
||||
void *tpm_ptr;
|
||||
|
||||
tpm_ptr = acpi_data_push(table_data, sizeof(ssdt_tpm_aml));
|
||||
memcpy(tpm_ptr, ssdt_tpm_aml, sizeof(ssdt_tpm_aml));
|
||||
}
|
||||
|
||||
static void
|
||||
build_tpm2(GArray *table_data, GArray *linker)
|
||||
{
|
||||
Acpi20TPM2 *tpm2_ptr;
|
||||
void *tpm_ptr;
|
||||
|
||||
tpm_ptr = acpi_data_push(table_data, sizeof(ssdt_tpm2_aml));
|
||||
memcpy(tpm_ptr, ssdt_tpm2_aml, sizeof(ssdt_tpm2_aml));
|
||||
|
||||
tpm2_ptr = acpi_data_push(table_data, sizeof *tpm2_ptr);
|
||||
|
||||
@ -1726,16 +1723,9 @@ void acpi_build(PcGuestInfo *guest_info, AcpiBuildTables *tables)
|
||||
acpi_add_table(table_offsets, tables_blob);
|
||||
build_tpm_tcpa(tables_blob, tables->linker, tables->tcpalog);
|
||||
|
||||
acpi_add_table(table_offsets, tables_blob);
|
||||
switch (misc.tpm_version) {
|
||||
case TPM_VERSION_1_2:
|
||||
build_tpm_ssdt(tables_blob, tables->linker);
|
||||
break;
|
||||
case TPM_VERSION_2_0:
|
||||
if (misc.tpm_version == TPM_VERSION_2_0) {
|
||||
acpi_add_table(table_offsets, tables_blob);
|
||||
build_tpm2(tables_blob, tables->linker);
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
if (guest_info->numa_nodes) {
|
||||
|
@ -1,36 +0,0 @@
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Common parts for TPM 1.2 and TPM 2 (with slight differences for PPI)
|
||||
* to be #included
|
||||
*/
|
||||
|
||||
|
||||
External(\_SB.PCI0.ISA, DeviceObj)
|
||||
Scope(\_SB.PCI0.ISA) {
|
||||
/* TPM with emulated TPM TIS interface */
|
||||
Device (TPM) {
|
||||
Name (_HID, EisaID ("PNP0C31"))
|
||||
Name (_CRS, ResourceTemplate ()
|
||||
{
|
||||
Memory32Fixed (ReadWrite, TPM_TIS_ADDR_BASE, TPM_TIS_ADDR_SIZE)
|
||||
IRQNoFlags () {TPM_TIS_IRQ}
|
||||
})
|
||||
Method (_STA, 0, NotSerialized) {
|
||||
Return (0x0F)
|
||||
}
|
||||
}
|
||||
}
|
@ -1,29 +0,0 @@
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include "hw/acpi/tpm.h"
|
||||
|
||||
ACPI_EXTRACT_ALL_CODE ssdt_tpm_aml
|
||||
|
||||
DefinitionBlock (
|
||||
"ssdt-tpm.aml", // Output Filename
|
||||
"SSDT", // Signature
|
||||
0x01, // SSDT Compliance Revision
|
||||
"BXPC", // OEMID
|
||||
"BXSSDT", // TABLE ID
|
||||
0x1 // OEM Revision
|
||||
)
|
||||
{
|
||||
#include "ssdt-tpm-common.dsl"
|
||||
}
|
@ -1,109 +0,0 @@
|
||||
static unsigned char ssdt_tpm_aml[] = {
|
||||
0x53,
|
||||
0x53,
|
||||
0x44,
|
||||
0x54,
|
||||
0x6b,
|
||||
0x0,
|
||||
0x0,
|
||||
0x0,
|
||||
0x1,
|
||||
0x37,
|
||||
0x42,
|
||||
0x58,
|
||||
0x50,
|
||||
0x43,
|
||||
0x0,
|
||||
0x0,
|
||||
0x42,
|
||||
0x58,
|
||||
0x53,
|
||||
0x53,
|
||||
0x44,
|
||||
0x54,
|
||||
0x0,
|
||||
0x0,
|
||||
0x1,
|
||||
0x0,
|
||||
0x0,
|
||||
0x0,
|
||||
0x49,
|
||||
0x4e,
|
||||
0x54,
|
||||
0x4c,
|
||||
0x7,
|
||||
0x11,
|
||||
0x14,
|
||||
0x20,
|
||||
0x10,
|
||||
0x46,
|
||||
0x4,
|
||||
0x5c,
|
||||
0x2f,
|
||||
0x3,
|
||||
0x5f,
|
||||
0x53,
|
||||
0x42,
|
||||
0x5f,
|
||||
0x50,
|
||||
0x43,
|
||||
0x49,
|
||||
0x30,
|
||||
0x49,
|
||||
0x53,
|
||||
0x41,
|
||||
0x5f,
|
||||
0x5b,
|
||||
0x82,
|
||||
0x33,
|
||||
0x54,
|
||||
0x50,
|
||||
0x4d,
|
||||
0x5f,
|
||||
0x8,
|
||||
0x5f,
|
||||
0x48,
|
||||
0x49,
|
||||
0x44,
|
||||
0xc,
|
||||
0x41,
|
||||
0xd0,
|
||||
0xc,
|
||||
0x31,
|
||||
0x8,
|
||||
0x5f,
|
||||
0x43,
|
||||
0x52,
|
||||
0x53,
|
||||
0x11,
|
||||
0x14,
|
||||
0xa,
|
||||
0x11,
|
||||
0x86,
|
||||
0x9,
|
||||
0x0,
|
||||
0x1,
|
||||
0x0,
|
||||
0x0,
|
||||
0xd4,
|
||||
0xfe,
|
||||
0x0,
|
||||
0x50,
|
||||
0x0,
|
||||
0x0,
|
||||
0x22,
|
||||
0x20,
|
||||
0x0,
|
||||
0x79,
|
||||
0x0,
|
||||
0x14,
|
||||
0x9,
|
||||
0x5f,
|
||||
0x53,
|
||||
0x54,
|
||||
0x41,
|
||||
0x0,
|
||||
0xa4,
|
||||
0xa,
|
||||
0xf
|
||||
};
|
@ -1,29 +0,0 @@
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include "hw/acpi/tpm.h"
|
||||
|
||||
ACPI_EXTRACT_ALL_CODE ssdt_tpm2_aml
|
||||
|
||||
DefinitionBlock (
|
||||
"ssdt-tpm2.aml", // Output Filename
|
||||
"SSDT", // Signature
|
||||
0x01, // SSDT Compliance Revision
|
||||
"BXPC", // OEMID
|
||||
"BXSSDT", // TABLE ID
|
||||
0x1 // OEM Revision
|
||||
)
|
||||
{
|
||||
#include "ssdt-tpm-common.dsl"
|
||||
}
|
@ -1,109 +0,0 @@
|
||||
static unsigned char ssdt_tpm2_aml[] = {
|
||||
0x53,
|
||||
0x53,
|
||||
0x44,
|
||||
0x54,
|
||||
0x6b,
|
||||
0x0,
|
||||
0x0,
|
||||
0x0,
|
||||
0x1,
|
||||
0x37,
|
||||
0x42,
|
||||
0x58,
|
||||
0x50,
|
||||
0x43,
|
||||
0x0,
|
||||
0x0,
|
||||
0x42,
|
||||
0x58,
|
||||
0x53,
|
||||
0x53,
|
||||
0x44,
|
||||
0x54,
|
||||
0x0,
|
||||
0x0,
|
||||
0x1,
|
||||
0x0,
|
||||
0x0,
|
||||
0x0,
|
||||
0x49,
|
||||
0x4e,
|
||||
0x54,
|
||||
0x4c,
|
||||
0x7,
|
||||
0x11,
|
||||
0x14,
|
||||
0x20,
|
||||
0x10,
|
||||
0x46,
|
||||
0x4,
|
||||
0x5c,
|
||||
0x2f,
|
||||
0x3,
|
||||
0x5f,
|
||||
0x53,
|
||||
0x42,
|
||||
0x5f,
|
||||
0x50,
|
||||
0x43,
|
||||
0x49,
|
||||
0x30,
|
||||
0x49,
|
||||
0x53,
|
||||
0x41,
|
||||
0x5f,
|
||||
0x5b,
|
||||
0x82,
|
||||
0x33,
|
||||
0x54,
|
||||
0x50,
|
||||
0x4d,
|
||||
0x5f,
|
||||
0x8,
|
||||
0x5f,
|
||||
0x48,
|
||||
0x49,
|
||||
0x44,
|
||||
0xc,
|
||||
0x41,
|
||||
0xd0,
|
||||
0xc,
|
||||
0x31,
|
||||
0x8,
|
||||
0x5f,
|
||||
0x43,
|
||||
0x52,
|
||||
0x53,
|
||||
0x11,
|
||||
0x14,
|
||||
0xa,
|
||||
0x11,
|
||||
0x86,
|
||||
0x9,
|
||||
0x0,
|
||||
0x1,
|
||||
0x0,
|
||||
0x0,
|
||||
0xd4,
|
||||
0xfe,
|
||||
0x0,
|
||||
0x50,
|
||||
0x0,
|
||||
0x0,
|
||||
0x22,
|
||||
0x20,
|
||||
0x0,
|
||||
0x79,
|
||||
0x0,
|
||||
0x14,
|
||||
0x9,
|
||||
0x5f,
|
||||
0x53,
|
||||
0x54,
|
||||
0x41,
|
||||
0x0,
|
||||
0xa4,
|
||||
0xa,
|
||||
0xf
|
||||
};
|
@ -28,7 +28,8 @@
|
||||
#include "hw/pci/pci_bus.h"
|
||||
#include "hw/hotplug.h"
|
||||
|
||||
#define TYPE_PCI_BRIDGE_DEV "pci-bridge"
|
||||
#define TYPE_PCI_BRIDGE_DEV "pci-bridge"
|
||||
#define TYPE_PCI_BRIDGE_SEAT_DEV "pci-bridge-seat"
|
||||
#define PCI_BRIDGE_DEV(obj) \
|
||||
OBJECT_CHECK(PCIBridgeDev, (obj), TYPE_PCI_BRIDGE_DEV)
|
||||
|
||||
@ -40,6 +41,7 @@ struct PCIBridgeDev {
|
||||
MemoryRegion bar;
|
||||
uint8_t chassis_nr;
|
||||
#define PCI_BRIDGE_DEV_F_MSI_REQ 0
|
||||
#define PCI_BRIDGE_DEV_F_SHPC_REQ 1
|
||||
uint32_t flags;
|
||||
};
|
||||
typedef struct PCIBridgeDev PCIBridgeDev;
|
||||
@ -54,11 +56,17 @@ static int pci_bridge_dev_initfn(PCIDevice *dev)
|
||||
if (err) {
|
||||
goto bridge_error;
|
||||
}
|
||||
dev->config[PCI_INTERRUPT_PIN] = 0x1;
|
||||
memory_region_init(&bridge_dev->bar, OBJECT(dev), "shpc-bar", shpc_bar_size(dev));
|
||||
err = shpc_init(dev, &br->sec_bus, &bridge_dev->bar, 0);
|
||||
if (err) {
|
||||
goto shpc_error;
|
||||
if (bridge_dev->flags & (1 << PCI_BRIDGE_DEV_F_SHPC_REQ)) {
|
||||
dev->config[PCI_INTERRUPT_PIN] = 0x1;
|
||||
memory_region_init(&bridge_dev->bar, OBJECT(dev), "shpc-bar",
|
||||
shpc_bar_size(dev));
|
||||
err = shpc_init(dev, &br->sec_bus, &bridge_dev->bar, 0);
|
||||
if (err) {
|
||||
goto shpc_error;
|
||||
}
|
||||
} else {
|
||||
/* MSI is not applicable without SHPC */
|
||||
bridge_dev->flags &= ~(1 << PCI_BRIDGE_DEV_F_MSI_REQ);
|
||||
}
|
||||
err = slotid_cap_init(dev, 0, bridge_dev->chassis_nr, 0);
|
||||
if (err) {
|
||||
@ -71,15 +79,19 @@ static int pci_bridge_dev_initfn(PCIDevice *dev)
|
||||
goto msi_error;
|
||||
}
|
||||
}
|
||||
/* TODO: spec recommends using 64 bit prefetcheable BAR.
|
||||
* Check whether that works well. */
|
||||
pci_register_bar(dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY |
|
||||
PCI_BASE_ADDRESS_MEM_TYPE_64, &bridge_dev->bar);
|
||||
if (shpc_present(dev)) {
|
||||
/* TODO: spec recommends using 64 bit prefetcheable BAR.
|
||||
* Check whether that works well. */
|
||||
pci_register_bar(dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY |
|
||||
PCI_BASE_ADDRESS_MEM_TYPE_64, &bridge_dev->bar);
|
||||
}
|
||||
return 0;
|
||||
msi_error:
|
||||
slotid_cap_cleanup(dev);
|
||||
slotid_error:
|
||||
shpc_cleanup(dev, &bridge_dev->bar);
|
||||
if (shpc_present(dev)) {
|
||||
shpc_cleanup(dev, &bridge_dev->bar);
|
||||
}
|
||||
shpc_error:
|
||||
pci_bridge_exitfn(dev);
|
||||
bridge_error:
|
||||
@ -93,12 +105,15 @@ static void pci_bridge_dev_exitfn(PCIDevice *dev)
|
||||
msi_uninit(dev);
|
||||
}
|
||||
slotid_cap_cleanup(dev);
|
||||
shpc_cleanup(dev, &bridge_dev->bar);
|
||||
if (shpc_present(dev)) {
|
||||
shpc_cleanup(dev, &bridge_dev->bar);
|
||||
}
|
||||
pci_bridge_exitfn(dev);
|
||||
}
|
||||
|
||||
static void pci_bridge_dev_instance_finalize(Object *obj)
|
||||
{
|
||||
/* this function is idempotent and handles (PCIDevice.shpc == NULL) */
|
||||
shpc_free(PCI_DEVICE(obj));
|
||||
}
|
||||
|
||||
@ -109,7 +124,9 @@ static void pci_bridge_dev_write_config(PCIDevice *d,
|
||||
if (msi_present(d)) {
|
||||
msi_write_config(d, address, val, len);
|
||||
}
|
||||
shpc_cap_write_config(d, address, val, len);
|
||||
if (shpc_present(d)) {
|
||||
shpc_cap_write_config(d, address, val, len);
|
||||
}
|
||||
}
|
||||
|
||||
static void qdev_pci_bridge_dev_reset(DeviceState *qdev)
|
||||
@ -117,25 +134,65 @@ static void qdev_pci_bridge_dev_reset(DeviceState *qdev)
|
||||
PCIDevice *dev = PCI_DEVICE(qdev);
|
||||
|
||||
pci_bridge_reset(qdev);
|
||||
shpc_reset(dev);
|
||||
if (shpc_present(dev)) {
|
||||
shpc_reset(dev);
|
||||
}
|
||||
}
|
||||
|
||||
static Property pci_bridge_dev_properties[] = {
|
||||
/* Note: 0 is not a legal chassis number. */
|
||||
DEFINE_PROP_UINT8("chassis_nr", PCIBridgeDev, chassis_nr, 0),
|
||||
DEFINE_PROP_BIT("msi", PCIBridgeDev, flags, PCI_BRIDGE_DEV_F_MSI_REQ, true),
|
||||
DEFINE_PROP_UINT8(PCI_BRIDGE_DEV_PROP_CHASSIS_NR, PCIBridgeDev, chassis_nr,
|
||||
0),
|
||||
DEFINE_PROP_BIT(PCI_BRIDGE_DEV_PROP_MSI, PCIBridgeDev, flags,
|
||||
PCI_BRIDGE_DEV_F_MSI_REQ, true),
|
||||
DEFINE_PROP_BIT(PCI_BRIDGE_DEV_PROP_SHPC, PCIBridgeDev, flags,
|
||||
PCI_BRIDGE_DEV_F_SHPC_REQ, true),
|
||||
DEFINE_PROP_END_OF_LIST(),
|
||||
};
|
||||
|
||||
static bool pci_device_shpc_present(void *opaque, int version_id)
|
||||
{
|
||||
PCIDevice *dev = opaque;
|
||||
|
||||
return shpc_present(dev);
|
||||
}
|
||||
|
||||
static const VMStateDescription pci_bridge_dev_vmstate = {
|
||||
.name = "pci_bridge",
|
||||
.fields = (VMStateField[]) {
|
||||
VMSTATE_PCI_DEVICE(parent_obj, PCIBridge),
|
||||
SHPC_VMSTATE(shpc, PCIDevice),
|
||||
SHPC_VMSTATE(shpc, PCIDevice, pci_device_shpc_present),
|
||||
VMSTATE_END_OF_LIST()
|
||||
}
|
||||
};
|
||||
|
||||
static void pci_bridge_dev_hotplug_cb(HotplugHandler *hotplug_dev,
|
||||
DeviceState *dev, Error **errp)
|
||||
{
|
||||
PCIDevice *pci_hotplug_dev = PCI_DEVICE(hotplug_dev);
|
||||
|
||||
if (!shpc_present(pci_hotplug_dev)) {
|
||||
error_setg(errp, "standard hotplug controller has been disabled for "
|
||||
"this %s", TYPE_PCI_BRIDGE_DEV);
|
||||
return;
|
||||
}
|
||||
shpc_device_hotplug_cb(hotplug_dev, dev, errp);
|
||||
}
|
||||
|
||||
static void pci_bridge_dev_hot_unplug_request_cb(HotplugHandler *hotplug_dev,
|
||||
DeviceState *dev,
|
||||
Error **errp)
|
||||
{
|
||||
PCIDevice *pci_hotplug_dev = PCI_DEVICE(hotplug_dev);
|
||||
|
||||
if (!shpc_present(pci_hotplug_dev)) {
|
||||
error_setg(errp, "standard hotplug controller has been disabled for "
|
||||
"this %s", TYPE_PCI_BRIDGE_DEV);
|
||||
return;
|
||||
}
|
||||
shpc_device_hot_unplug_request_cb(hotplug_dev, dev, errp);
|
||||
}
|
||||
|
||||
static void pci_bridge_dev_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
@ -154,8 +211,8 @@ static void pci_bridge_dev_class_init(ObjectClass *klass, void *data)
|
||||
dc->props = pci_bridge_dev_properties;
|
||||
dc->vmsd = &pci_bridge_dev_vmstate;
|
||||
set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
|
||||
hc->plug = shpc_device_hotplug_cb;
|
||||
hc->unplug_request = shpc_device_hot_unplug_request_cb;
|
||||
hc->plug = pci_bridge_dev_hotplug_cb;
|
||||
hc->unplug_request = pci_bridge_dev_hot_unplug_request_cb;
|
||||
}
|
||||
|
||||
static const TypeInfo pci_bridge_dev_info = {
|
||||
@ -170,9 +227,31 @@ static const TypeInfo pci_bridge_dev_info = {
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* Multiseat bridge. Same as the standard pci bridge, only with a
|
||||
* different pci id, so we can match it easily in the guest for
|
||||
* automagic multiseat configuration. See docs/multiseat.txt for more.
|
||||
*/
|
||||
static void pci_bridge_dev_seat_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
|
||||
|
||||
k->device_id = PCI_DEVICE_ID_REDHAT_BRIDGE_SEAT;
|
||||
dc->desc = "Standard PCI Bridge (multiseat)";
|
||||
}
|
||||
|
||||
static const TypeInfo pci_bridge_dev_seat_info = {
|
||||
.name = TYPE_PCI_BRIDGE_SEAT_DEV,
|
||||
.parent = TYPE_PCI_BRIDGE_DEV,
|
||||
.instance_size = sizeof(PCIBridgeDev),
|
||||
.class_init = pci_bridge_dev_seat_class_init,
|
||||
};
|
||||
|
||||
static void pci_bridge_dev_register(void)
|
||||
{
|
||||
type_register_static(&pci_bridge_dev_info);
|
||||
type_register_static(&pci_bridge_dev_seat_info);
|
||||
}
|
||||
|
||||
type_init(pci_bridge_dev_register);
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include "hw/pci/pci_bus.h"
|
||||
#include "hw/pci/pci_host.h"
|
||||
#include "hw/pci/pci_bus.h"
|
||||
#include "hw/pci/pci_bridge.h"
|
||||
#include "hw/i386/pc.h"
|
||||
#include "qemu/range.h"
|
||||
#include "qemu/error-report.h"
|
||||
@ -42,6 +43,8 @@ typedef struct PXBDev {
|
||||
uint16_t numa_node;
|
||||
} PXBDev;
|
||||
|
||||
static GList *pxb_dev_list;
|
||||
|
||||
#define TYPE_PXB_HOST "pxb-host"
|
||||
|
||||
static int pxb_bus_num(PCIBus *bus)
|
||||
@ -88,12 +91,45 @@ static const char *pxb_host_root_bus_path(PCIHostState *host_bridge,
|
||||
return bus->bus_path;
|
||||
}
|
||||
|
||||
static char *pxb_host_ofw_unit_address(const SysBusDevice *dev)
|
||||
{
|
||||
const PCIHostState *pxb_host;
|
||||
const PCIBus *pxb_bus;
|
||||
const PXBDev *pxb_dev;
|
||||
int position;
|
||||
const DeviceState *pxb_dev_base;
|
||||
const PCIHostState *main_host;
|
||||
const SysBusDevice *main_host_sbd;
|
||||
|
||||
pxb_host = PCI_HOST_BRIDGE(dev);
|
||||
pxb_bus = pxb_host->bus;
|
||||
pxb_dev = PXB_DEV(pxb_bus->parent_dev);
|
||||
position = g_list_index(pxb_dev_list, pxb_dev);
|
||||
assert(position >= 0);
|
||||
|
||||
pxb_dev_base = DEVICE(pxb_dev);
|
||||
main_host = PCI_HOST_BRIDGE(pxb_dev_base->parent_bus->parent);
|
||||
main_host_sbd = SYS_BUS_DEVICE(main_host);
|
||||
|
||||
if (main_host_sbd->num_mmio > 0) {
|
||||
return g_strdup_printf(TARGET_FMT_plx ",%x",
|
||||
main_host_sbd->mmio[0].addr, position + 1);
|
||||
}
|
||||
if (main_host_sbd->num_pio > 0) {
|
||||
return g_strdup_printf("i%04x,%x",
|
||||
main_host_sbd->pio[0], position + 1);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void pxb_host_class_init(ObjectClass *class, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(class);
|
||||
SysBusDeviceClass *sbc = SYS_BUS_DEVICE_CLASS(class);
|
||||
PCIHostBridgeClass *hc = PCI_HOST_BRIDGE_CLASS(class);
|
||||
|
||||
dc->fw_name = "pci";
|
||||
sbc->explicit_ofw_unit_address = pxb_host_ofw_unit_address;
|
||||
hc->root_bus_path = pxb_host_root_bus_path;
|
||||
}
|
||||
|
||||
@ -148,6 +184,15 @@ static int pxb_map_irq_fn(PCIDevice *pci_dev, int pin)
|
||||
return pin - PCI_SLOT(pxb->devfn);
|
||||
}
|
||||
|
||||
static gint pxb_compare(gconstpointer a, gconstpointer b)
|
||||
{
|
||||
const PXBDev *pxb_a = a, *pxb_b = b;
|
||||
|
||||
return pxb_a->bus_nr < pxb_b->bus_nr ? -1 :
|
||||
pxb_a->bus_nr > pxb_b->bus_nr ? 1 :
|
||||
0;
|
||||
}
|
||||
|
||||
static int pxb_dev_initfn(PCIDevice *dev)
|
||||
{
|
||||
PXBDev *pxb = PXB_DEV(dev);
|
||||
@ -175,7 +220,8 @@ static int pxb_dev_initfn(PCIDevice *dev)
|
||||
|
||||
bds = qdev_create(BUS(bus), "pci-bridge");
|
||||
bds->id = dev_name;
|
||||
qdev_prop_set_uint8(bds, "chassis_nr", pxb->bus_nr);
|
||||
qdev_prop_set_uint8(bds, PCI_BRIDGE_DEV_PROP_CHASSIS_NR, pxb->bus_nr);
|
||||
qdev_prop_set_bit(bds, PCI_BRIDGE_DEV_PROP_SHPC, false);
|
||||
|
||||
PCI_HOST_BRIDGE(ds)->bus = bus;
|
||||
|
||||
@ -190,9 +236,17 @@ static int pxb_dev_initfn(PCIDevice *dev)
|
||||
PCI_STATUS_66MHZ | PCI_STATUS_FAST_BACK);
|
||||
pci_config_set_class(dev->config, PCI_CLASS_BRIDGE_HOST);
|
||||
|
||||
pxb_dev_list = g_list_insert_sorted(pxb_dev_list, pxb, pxb_compare);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void pxb_dev_exitfn(PCIDevice *pci_dev)
|
||||
{
|
||||
PXBDev *pxb = PXB_DEV(pci_dev);
|
||||
|
||||
pxb_dev_list = g_list_remove(pxb_dev_list, pxb);
|
||||
}
|
||||
|
||||
static Property pxb_dev_properties[] = {
|
||||
/* Note: 0 is not a legal a PXB bus number. */
|
||||
DEFINE_PROP_UINT8("bus_nr", PXBDev, bus_nr, 0),
|
||||
@ -206,6 +260,7 @@ static void pxb_dev_class_init(ObjectClass *klass, void *data)
|
||||
PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
|
||||
|
||||
k->init = pxb_dev_initfn;
|
||||
k->exit = pxb_dev_exitfn;
|
||||
k->vendor_id = PCI_VENDOR_ID_REDHAT;
|
||||
k->device_id = PCI_DEVICE_ID_REDHAT_PXB;
|
||||
k->class_id = PCI_CLASS_BRIDGE_HOST;
|
||||
|
@ -999,7 +999,7 @@ int vhost_dev_enable_notifiers(struct vhost_dev *hdev, VirtIODevice *vdev)
|
||||
BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(vdev)));
|
||||
VirtioBusState *vbus = VIRTIO_BUS(qbus);
|
||||
VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(vbus);
|
||||
int i, r;
|
||||
int i, r, e;
|
||||
if (!k->set_host_notifier) {
|
||||
fprintf(stderr, "binding does not support host notifiers\n");
|
||||
r = -ENOSYS;
|
||||
@ -1017,12 +1017,12 @@ int vhost_dev_enable_notifiers(struct vhost_dev *hdev, VirtIODevice *vdev)
|
||||
return 0;
|
||||
fail_vq:
|
||||
while (--i >= 0) {
|
||||
r = k->set_host_notifier(qbus->parent, hdev->vq_index + i, false);
|
||||
if (r < 0) {
|
||||
e = k->set_host_notifier(qbus->parent, hdev->vq_index + i, false);
|
||||
if (e < 0) {
|
||||
fprintf(stderr, "vhost VQ %d notifier cleanup error: %d\n", i, -r);
|
||||
fflush(stderr);
|
||||
}
|
||||
assert (r >= 0);
|
||||
assert (e >= 0);
|
||||
}
|
||||
fail:
|
||||
return r;
|
||||
|
@ -312,6 +312,8 @@ static void virtio_balloon_set_config(VirtIODevice *vdev,
|
||||
|
||||
static uint64_t virtio_balloon_get_features(VirtIODevice *vdev, uint64_t f)
|
||||
{
|
||||
VirtIOBalloon *dev = VIRTIO_BALLOON(vdev);
|
||||
f |= dev->host_features;
|
||||
virtio_add_feature(&f, VIRTIO_BALLOON_F_STATS_VQ);
|
||||
return f;
|
||||
}
|
||||
@ -423,6 +425,8 @@ static void virtio_balloon_instance_init(Object *obj)
|
||||
}
|
||||
|
||||
static Property virtio_balloon_properties[] = {
|
||||
DEFINE_PROP_BIT("deflate-on-oom", VirtIOBalloon, host_features,
|
||||
VIRTIO_BALLOON_F_DEFLATE_ON_OOM, false),
|
||||
DEFINE_PROP_END_OF_LIST(),
|
||||
};
|
||||
|
||||
|
@ -977,7 +977,7 @@ static uint64_t virtio_pci_common_read(void *opaque, hwaddr addr,
|
||||
val = proxy->gfselect;
|
||||
break;
|
||||
case VIRTIO_PCI_COMMON_GF:
|
||||
if (proxy->gfselect <= ARRAY_SIZE(proxy->guest_features)) {
|
||||
if (proxy->gfselect < ARRAY_SIZE(proxy->guest_features)) {
|
||||
val = proxy->guest_features[proxy->gfselect];
|
||||
}
|
||||
break;
|
||||
@ -1052,7 +1052,7 @@ static void virtio_pci_common_write(void *opaque, hwaddr addr,
|
||||
proxy->gfselect = val;
|
||||
break;
|
||||
case VIRTIO_PCI_COMMON_GF:
|
||||
if (proxy->gfselect <= ARRAY_SIZE(proxy->guest_features)) {
|
||||
if (proxy->gfselect < ARRAY_SIZE(proxy->guest_features)) {
|
||||
proxy->guest_features[proxy->gfselect] = val;
|
||||
virtio_set_features(vdev,
|
||||
(((uint64_t)proxy->guest_features[1]) << 32) |
|
||||
|
@ -92,6 +92,7 @@
|
||||
#define PCI_DEVICE_ID_REDHAT_SDHCI 0x0007
|
||||
#define PCI_DEVICE_ID_REDHAT_PCIE_HOST 0x0008
|
||||
#define PCI_DEVICE_ID_REDHAT_PXB 0x0009
|
||||
#define PCI_DEVICE_ID_REDHAT_BRIDGE_SEAT 0x000a
|
||||
#define PCI_DEVICE_ID_REDHAT_QXL 0x0100
|
||||
|
||||
#define FMT_PCIBUS PRIx64
|
||||
|
@ -28,6 +28,10 @@
|
||||
|
||||
#include "hw/pci/pci.h"
|
||||
|
||||
#define PCI_BRIDGE_DEV_PROP_CHASSIS_NR "chassis_nr"
|
||||
#define PCI_BRIDGE_DEV_PROP_MSI "msi"
|
||||
#define PCI_BRIDGE_DEV_PROP_SHPC "shpc"
|
||||
|
||||
int pci_bridge_ssvid_init(PCIDevice *dev, uint8_t offset,
|
||||
uint16_t svid, uint16_t ssid);
|
||||
|
||||
|
@ -6,6 +6,7 @@
|
||||
#include "migration/vmstate.h"
|
||||
#include "qapi/error.h"
|
||||
#include "hw/hotplug.h"
|
||||
#include "hw/pci/pci.h"
|
||||
|
||||
struct SHPCDevice {
|
||||
/* Capability offset in device's config space */
|
||||
@ -51,7 +52,13 @@ void shpc_device_hot_unplug_request_cb(HotplugHandler *hotplug_dev,
|
||||
DeviceState *dev, Error **errp);
|
||||
|
||||
extern VMStateInfo shpc_vmstate_info;
|
||||
#define SHPC_VMSTATE(_field, _type) \
|
||||
VMSTATE_BUFFER_UNSAFE_INFO(_field, _type, 0, shpc_vmstate_info, 0)
|
||||
#define SHPC_VMSTATE(_field, _type, _test) \
|
||||
VMSTATE_BUFFER_UNSAFE_INFO_TEST(_field, _type, _test, 0, \
|
||||
shpc_vmstate_info, 0)
|
||||
|
||||
static inline bool shpc_present(const PCIDevice *dev)
|
||||
{
|
||||
return dev->cap_present & QEMU_PCI_CAP_SHPC;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -41,6 +41,23 @@ typedef struct SysBusDeviceClass {
|
||||
/*< public >*/
|
||||
|
||||
int (*init)(SysBusDevice *dev);
|
||||
|
||||
/*
|
||||
* Let the sysbus device format its own non-PIO, non-MMIO unit address.
|
||||
*
|
||||
* Sometimes a class of SysBusDevices has neither MMIO nor PIO resources,
|
||||
* yet instances of it would like to distinguish themselves, in
|
||||
* OpenFirmware device paths, from other instances of the same class on the
|
||||
* sysbus. For that end we expose this callback.
|
||||
*
|
||||
* The implementation is not supposed to change *@dev, or incur other
|
||||
* observable change.
|
||||
*
|
||||
* The function returns a dynamically allocated string. On error, NULL
|
||||
* should be returned; the unit address portion of the OFW node will be
|
||||
* omitted then. (This is not considered a fatal error.)
|
||||
*/
|
||||
char *(*explicit_ofw_unit_address)(const SysBusDevice *dev);
|
||||
} SysBusDeviceClass;
|
||||
|
||||
struct SysBusDevice {
|
||||
|
@ -42,6 +42,7 @@ typedef struct VirtIOBalloon {
|
||||
QEMUTimer *stats_timer;
|
||||
int64_t stats_last_update;
|
||||
int64_t stats_poll_interval;
|
||||
uint32_t host_features;
|
||||
} VirtIOBalloon;
|
||||
|
||||
#endif
|
||||
|
@ -500,9 +500,10 @@ extern const VMStateInfo vmstate_info_bitmap;
|
||||
.start = (_start), \
|
||||
}
|
||||
|
||||
#define VMSTATE_BUFFER_UNSAFE_INFO(_field, _state, _version, _info, _size) { \
|
||||
#define VMSTATE_BUFFER_UNSAFE_INFO_TEST(_field, _state, _test, _version, _info, _size) { \
|
||||
.name = (stringify(_field)), \
|
||||
.version_id = (_version), \
|
||||
.field_exists = (_test), \
|
||||
.size = (_size), \
|
||||
.info = &(_info), \
|
||||
.flags = VMS_BUFFER, \
|
||||
@ -562,6 +563,10 @@ extern const VMStateInfo vmstate_info_bitmap;
|
||||
VMSTATE_STRUCT_ARRAY_TEST(_field, _state, _num, NULL, _version, \
|
||||
_vmsd, _type)
|
||||
|
||||
#define VMSTATE_BUFFER_UNSAFE_INFO(_field, _state, _version, _info, _size) \
|
||||
VMSTATE_BUFFER_UNSAFE_INFO_TEST(_field, _state, NULL, _version, _info, \
|
||||
_size)
|
||||
|
||||
#define VMSTATE_BOOL_V(_f, _s, _v) \
|
||||
VMSTATE_SINGLE(_f, _s, _v, vmstate_info_bool, bool)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user