mirror of
https://github.com/izzy2lost/xemu.git
synced 2026-07-06 00:20:22 -07:00
Merge remote-tracking branch 'remotes/mst/tags/for_upstream' into staging
pc, pci, virtio: new features, cleanups, fixes iommus can not be added with -device. cleanups and fixes all over the place Signed-off-by: Michael S. Tsirkin <mst@redhat.com> # gpg: Signature made Tue 05 Jul 2016 11:18:32 BST # gpg: using RSA key 0x281F0DB8D28D5469 # gpg: Good signature from "Michael S. Tsirkin <mst@kernel.org>" # gpg: aka "Michael S. Tsirkin <mst@redhat.com>" # Primary key fingerprint: 0270 606B 6F3C DF3D 0B17 0970 C350 3912 AFBE 8E67 # Subkey fingerprint: 5D09 FD08 71C8 F85B 94CA 8A0D 281F 0DB8 D28D 5469 * remotes/mst/tags/for_upstream: (30 commits) vmw_pvscsi: remove unnecessary internal msi state flag e1000e: remove unnecessary internal msi state flag vmxnet3: remove unnecessary internal msi state flag mptsas: remove unnecessary internal msi state flag megasas: remove unnecessary megasas_use_msi() pci: Convert msi_init() to Error and fix callers to check it pci bridge dev: change msi property type megasas: change msi/msix property type mptsas: change msi property type intel-hda: change msi property type usb xhci: change msi/msix property type change pvscsi_init_msi() type to void tests: add APIC.cphp and DSDT.cphp blobs tests: acpi: add CPU hotplug testcase log: Permit -dfilter 0..0xffffffffffffffff range: Replace internal representation of Range range: Eliminate direct Range member access log: Clean up misuse of Range for -dfilter pci_register_bar: cleanup Revert "virtio-net: unbreak self announcement and guest offloads after migration" ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
+23
-6
@@ -191,7 +191,7 @@ struct IntelHDAState {
|
||||
|
||||
/* properties */
|
||||
uint32_t debug;
|
||||
uint32_t msi;
|
||||
OnOffAuto msi;
|
||||
bool old_msi_addr;
|
||||
};
|
||||
|
||||
@@ -256,7 +256,7 @@ static void intel_hda_update_int_sts(IntelHDAState *d)
|
||||
|
||||
static void intel_hda_update_irq(IntelHDAState *d)
|
||||
{
|
||||
int msi = d->msi && msi_enabled(&d->pci);
|
||||
bool msi = msi_enabled(&d->pci);
|
||||
int level;
|
||||
|
||||
intel_hda_update_int_sts(d);
|
||||
@@ -1132,6 +1132,8 @@ static void intel_hda_realize(PCIDevice *pci, Error **errp)
|
||||
{
|
||||
IntelHDAState *d = INTEL_HDA(pci);
|
||||
uint8_t *conf = d->pci.config;
|
||||
Error *err = NULL;
|
||||
int ret;
|
||||
|
||||
d->name = object_get_typename(OBJECT(d));
|
||||
|
||||
@@ -1140,12 +1142,27 @@ static void intel_hda_realize(PCIDevice *pci, Error **errp)
|
||||
/* HDCTL off 0x40 bit 0 selects signaling mode (1-HDA, 0 - Ac97) 18.1.19 */
|
||||
conf[0x40] = 0x01;
|
||||
|
||||
if (d->msi != ON_OFF_AUTO_OFF) {
|
||||
ret = msi_init(&d->pci, d->old_msi_addr ? 0x50 : 0x60,
|
||||
1, true, false, &err);
|
||||
/* Any error other than -ENOTSUP(board's MSI support is broken)
|
||||
* is a programming error */
|
||||
assert(!ret || ret == -ENOTSUP);
|
||||
if (ret && d->msi == ON_OFF_AUTO_ON) {
|
||||
/* Can't satisfy user's explicit msi=on request, fail */
|
||||
error_append_hint(&err, "You have to use msi=auto (default) or "
|
||||
"msi=off with this machine type.\n");
|
||||
error_propagate(errp, err);
|
||||
return;
|
||||
}
|
||||
assert(!err || d->msi == ON_OFF_AUTO_AUTO);
|
||||
/* With msi=auto, we fall back to MSI off silently */
|
||||
error_free(err);
|
||||
}
|
||||
|
||||
memory_region_init_io(&d->mmio, OBJECT(d), &intel_hda_mmio_ops, d,
|
||||
"intel-hda", 0x4000);
|
||||
pci_register_bar(&d->pci, 0, 0, &d->mmio);
|
||||
if (d->msi) {
|
||||
msi_init(&d->pci, d->old_msi_addr ? 0x50 : 0x60, 1, true, false);
|
||||
}
|
||||
|
||||
hda_codec_bus_init(DEVICE(pci), &d->codecs, sizeof(d->codecs),
|
||||
intel_hda_response, intel_hda_xfer);
|
||||
@@ -1235,7 +1252,7 @@ static const VMStateDescription vmstate_intel_hda = {
|
||||
|
||||
static Property intel_hda_properties[] = {
|
||||
DEFINE_PROP_UINT32("debug", IntelHDAState, debug, 0),
|
||||
DEFINE_PROP_UINT32("msi", IntelHDAState, msi, 1),
|
||||
DEFINE_PROP_ON_OFF_AUTO("msi", IntelHDAState, msi, ON_OFF_AUTO_AUTO),
|
||||
DEFINE_PROP_BOOL("old_msi_addr", IntelHDAState, old_msi_addr, false),
|
||||
DEFINE_PROP_END_OF_LIST(),
|
||||
};
|
||||
|
||||
@@ -300,20 +300,6 @@ static void machine_set_firmware(Object *obj, const char *value, Error **errp)
|
||||
ms->firmware = g_strdup(value);
|
||||
}
|
||||
|
||||
static bool machine_get_iommu(Object *obj, Error **errp)
|
||||
{
|
||||
MachineState *ms = MACHINE(obj);
|
||||
|
||||
return ms->iommu;
|
||||
}
|
||||
|
||||
static void machine_set_iommu(Object *obj, bool value, Error **errp)
|
||||
{
|
||||
MachineState *ms = MACHINE(obj);
|
||||
|
||||
ms->iommu = value;
|
||||
}
|
||||
|
||||
static void machine_set_suppress_vmdesc(Object *obj, bool value, Error **errp)
|
||||
{
|
||||
MachineState *ms = MACHINE(obj);
|
||||
@@ -493,12 +479,6 @@ static void machine_initfn(Object *obj)
|
||||
object_property_set_description(obj, "firmware",
|
||||
"Firmware image",
|
||||
NULL);
|
||||
object_property_add_bool(obj, "iommu",
|
||||
machine_get_iommu,
|
||||
machine_set_iommu, NULL);
|
||||
object_property_set_description(obj, "iommu",
|
||||
"Set on/off to enable/disable Intel IOMMU (VT-d)",
|
||||
NULL);
|
||||
object_property_add_bool(obj, "suppress-vmdesc",
|
||||
machine_get_suppress_vmdesc,
|
||||
machine_set_suppress_vmdesc, NULL);
|
||||
|
||||
+24
-20
@@ -229,26 +229,27 @@ static Object *acpi_get_i386_pci_host(void)
|
||||
return OBJECT(host);
|
||||
}
|
||||
|
||||
static void acpi_get_pci_info(PcPciInfo *info)
|
||||
static void acpi_get_pci_holes(Range *hole, Range *hole64)
|
||||
{
|
||||
Object *pci_host;
|
||||
|
||||
|
||||
pci_host = acpi_get_i386_pci_host();
|
||||
g_assert(pci_host);
|
||||
|
||||
info->w32.begin = object_property_get_int(pci_host,
|
||||
range_set_bounds1(hole,
|
||||
object_property_get_int(pci_host,
|
||||
PCI_HOST_PROP_PCI_HOLE_START,
|
||||
NULL);
|
||||
info->w32.end = object_property_get_int(pci_host,
|
||||
PCI_HOST_PROP_PCI_HOLE_END,
|
||||
NULL);
|
||||
info->w64.begin = object_property_get_int(pci_host,
|
||||
NULL),
|
||||
object_property_get_int(pci_host,
|
||||
PCI_HOST_PROP_PCI_HOLE_END,
|
||||
NULL));
|
||||
range_set_bounds1(hole64,
|
||||
object_property_get_int(pci_host,
|
||||
PCI_HOST_PROP_PCI_HOLE64_START,
|
||||
NULL);
|
||||
info->w64.end = object_property_get_int(pci_host,
|
||||
PCI_HOST_PROP_PCI_HOLE64_END,
|
||||
NULL);
|
||||
NULL),
|
||||
object_property_get_int(pci_host,
|
||||
PCI_HOST_PROP_PCI_HOLE64_END,
|
||||
NULL));
|
||||
}
|
||||
|
||||
#define ACPI_PORT_SMI_CMD 0x00b2 /* TODO: this is APM_CNT_IOPORT */
|
||||
@@ -1890,7 +1891,7 @@ static Aml *build_q35_osc_method(void)
|
||||
static void
|
||||
build_dsdt(GArray *table_data, BIOSLinker *linker,
|
||||
AcpiPmInfo *pm, AcpiMiscInfo *misc,
|
||||
PcPciInfo *pci, MachineState *machine)
|
||||
Range *pci_hole, Range *pci_hole64, MachineState *machine)
|
||||
{
|
||||
CrsRangeEntry *entry;
|
||||
Aml *dsdt, *sb_scope, *scope, *dev, *method, *field, *pkg, *crs;
|
||||
@@ -2047,7 +2048,9 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
|
||||
AML_CACHEABLE, AML_READ_WRITE,
|
||||
0, 0x000A0000, 0x000BFFFF, 0, 0x00020000));
|
||||
|
||||
crs_replace_with_free_ranges(mem_ranges, pci->w32.begin, pci->w32.end - 1);
|
||||
crs_replace_with_free_ranges(mem_ranges,
|
||||
range_lob(pci_hole),
|
||||
range_upb(pci_hole));
|
||||
for (i = 0; i < mem_ranges->len; i++) {
|
||||
entry = g_ptr_array_index(mem_ranges, i);
|
||||
aml_append(crs,
|
||||
@@ -2057,12 +2060,12 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
|
||||
0, entry->limit - entry->base + 1));
|
||||
}
|
||||
|
||||
if (pci->w64.begin) {
|
||||
if (!range_is_empty(pci_hole64)) {
|
||||
aml_append(crs,
|
||||
aml_qword_memory(AML_POS_DECODE, AML_MIN_FIXED, AML_MAX_FIXED,
|
||||
AML_CACHEABLE, AML_READ_WRITE,
|
||||
0, pci->w64.begin, pci->w64.end - 1, 0,
|
||||
pci->w64.end - pci->w64.begin));
|
||||
0, range_lob(pci_hole64), range_upb(pci_hole64), 0,
|
||||
range_upb(pci_hole64) + 1 - range_lob(pci_hole64)));
|
||||
}
|
||||
|
||||
if (misc->tpm_version != TPM_VERSION_UNSPEC) {
|
||||
@@ -2554,7 +2557,7 @@ void acpi_build(AcpiBuildTables *tables, MachineState *machine)
|
||||
AcpiPmInfo pm;
|
||||
AcpiMiscInfo misc;
|
||||
AcpiMcfgInfo mcfg;
|
||||
PcPciInfo pci;
|
||||
Range pci_hole, pci_hole64;
|
||||
uint8_t *u;
|
||||
size_t aml_len = 0;
|
||||
GArray *tables_blob = tables->table_data;
|
||||
@@ -2562,7 +2565,7 @@ void acpi_build(AcpiBuildTables *tables, MachineState *machine)
|
||||
|
||||
acpi_get_pm_info(&pm);
|
||||
acpi_get_misc_info(&misc);
|
||||
acpi_get_pci_info(&pci);
|
||||
acpi_get_pci_holes(&pci_hole, &pci_hole64);
|
||||
acpi_get_slic_oem(&slic_oem);
|
||||
|
||||
table_offsets = g_array_new(false, true /* clear */,
|
||||
@@ -2584,7 +2587,8 @@ void acpi_build(AcpiBuildTables *tables, MachineState *machine)
|
||||
|
||||
/* DSDT is pointed to by FADT */
|
||||
dsdt = tables_blob->len;
|
||||
build_dsdt(tables_blob, tables->linker, &pm, &misc, &pci, machine);
|
||||
build_dsdt(tables_blob, tables->linker, &pm, &misc,
|
||||
&pci_hole, &pci_hole64, machine);
|
||||
|
||||
/* Count the size of the DSDT and SSDT, we will need it for legacy
|
||||
* sizing of ACPI tables.
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#include "intel_iommu_internal.h"
|
||||
#include "hw/pci/pci.h"
|
||||
#include "hw/pci/pci_bus.h"
|
||||
#include "hw/i386/pc.h"
|
||||
|
||||
/*#define DEBUG_INTEL_IOMMU*/
|
||||
#ifdef DEBUG_INTEL_IOMMU
|
||||
@@ -2026,8 +2027,20 @@ static void vtd_reset(DeviceState *dev)
|
||||
vtd_init(s);
|
||||
}
|
||||
|
||||
static AddressSpace *vtd_host_dma_iommu(PCIBus *bus, void *opaque, int devfn)
|
||||
{
|
||||
IntelIOMMUState *s = opaque;
|
||||
VTDAddressSpace *vtd_as;
|
||||
|
||||
assert(0 <= devfn && devfn <= VTD_PCI_DEVFN_MAX);
|
||||
|
||||
vtd_as = vtd_find_add_as(s, bus, devfn);
|
||||
return &vtd_as->as;
|
||||
}
|
||||
|
||||
static void vtd_realize(DeviceState *dev, Error **errp)
|
||||
{
|
||||
PCIBus *bus = PC_MACHINE(qdev_get_machine())->bus;
|
||||
IntelIOMMUState *s = INTEL_IOMMU_DEVICE(dev);
|
||||
|
||||
VTD_DPRINTF(GENERAL, "");
|
||||
@@ -2041,6 +2054,8 @@ static void vtd_realize(DeviceState *dev, Error **errp)
|
||||
s->vtd_as_by_busptr = g_hash_table_new_full(vtd_uint64_hash, vtd_uint64_equal,
|
||||
g_free, g_free);
|
||||
vtd_init(s);
|
||||
sysbus_mmio_map(SYS_BUS_DEVICE(s), 0, Q35_HOST_BRIDGE_IOMMU_ADDR);
|
||||
pci_setup_iommu(bus, vtd_host_dma_iommu, dev);
|
||||
}
|
||||
|
||||
static void vtd_class_init(ObjectClass *klass, void *data)
|
||||
@@ -2051,6 +2066,7 @@ static void vtd_class_init(ObjectClass *klass, void *data)
|
||||
dc->realize = vtd_realize;
|
||||
dc->vmsd = &vtd_vmstate;
|
||||
dc->props = vtd_properties;
|
||||
dc->hotpluggable = false;
|
||||
}
|
||||
|
||||
static const TypeInfo vtd_info = {
|
||||
|
||||
+1
-1
@@ -1919,7 +1919,7 @@ static void pc_machine_initfn(Object *obj)
|
||||
pc_machine_get_hotplug_memory_region_size,
|
||||
NULL, NULL, NULL, &error_abort);
|
||||
|
||||
pcms->max_ram_below_4g = 0xe0000000; /* 3.5G */
|
||||
pcms->max_ram_below_4g = 0; /* use default */
|
||||
object_property_add(obj, PC_MACHINE_MAX_RAM_BELOW_4G, "size",
|
||||
pc_machine_get_max_ram_below_4g,
|
||||
pc_machine_set_max_ram_below_4g,
|
||||
|
||||
+29
-23
@@ -108,37 +108,43 @@ static void pc_init1(MachineState *machine,
|
||||
* so legacy non-PAE guests can get as much memory as possible in
|
||||
* the 32bit address space below 4G.
|
||||
*
|
||||
* - Note that Xen has its own ram setp code in xen_ram_init(),
|
||||
* called via xen_hvm_init().
|
||||
*
|
||||
* Examples:
|
||||
* qemu -M pc-1.7 -m 4G (old default) -> 3584M low, 512M high
|
||||
* qemu -M pc -m 4G (new default) -> 3072M low, 1024M high
|
||||
* qemu -M pc,max-ram-below-4g=2G -m 4G -> 2048M low, 2048M high
|
||||
* qemu -M pc,max-ram-below-4g=4G -m 3968M -> 3968M low (=4G-128M)
|
||||
*/
|
||||
lowmem = pcms->max_ram_below_4g;
|
||||
if (machine->ram_size >= pcms->max_ram_below_4g) {
|
||||
if (pcmc->gigabyte_align) {
|
||||
if (lowmem > 0xc0000000) {
|
||||
lowmem = 0xc0000000;
|
||||
}
|
||||
if (lowmem & ((1ULL << 30) - 1)) {
|
||||
error_report("Warning: Large machine and max_ram_below_4g "
|
||||
"(%" PRIu64 ") not a multiple of 1G; "
|
||||
"possible bad performance.",
|
||||
pcms->max_ram_below_4g);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (machine->ram_size >= lowmem) {
|
||||
pcms->above_4g_mem_size = machine->ram_size - lowmem;
|
||||
pcms->below_4g_mem_size = lowmem;
|
||||
} else {
|
||||
pcms->above_4g_mem_size = 0;
|
||||
pcms->below_4g_mem_size = machine->ram_size;
|
||||
}
|
||||
|
||||
if (xen_enabled()) {
|
||||
xen_hvm_init(pcms, &ram_memory);
|
||||
} else {
|
||||
if (!pcms->max_ram_below_4g) {
|
||||
pcms->max_ram_below_4g = 0xe0000000; /* default: 3.5G */
|
||||
}
|
||||
lowmem = pcms->max_ram_below_4g;
|
||||
if (machine->ram_size >= pcms->max_ram_below_4g) {
|
||||
if (pcmc->gigabyte_align) {
|
||||
if (lowmem > 0xc0000000) {
|
||||
lowmem = 0xc0000000;
|
||||
}
|
||||
if (lowmem & ((1ULL << 30) - 1)) {
|
||||
error_report("Warning: Large machine and max_ram_below_4g "
|
||||
"(%" PRIu64 ") not a multiple of 1G; "
|
||||
"possible bad performance.",
|
||||
pcms->max_ram_below_4g);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (machine->ram_size >= lowmem) {
|
||||
pcms->above_4g_mem_size = machine->ram_size - lowmem;
|
||||
pcms->below_4g_mem_size = lowmem;
|
||||
} else {
|
||||
pcms->above_4g_mem_size = 0;
|
||||
pcms->below_4g_mem_size = machine->ram_size;
|
||||
}
|
||||
}
|
||||
|
||||
pc_cpus_init(pcms);
|
||||
|
||||
+4
-1
@@ -94,6 +94,9 @@ static void pc_q35_init(MachineState *machine)
|
||||
/* Handle the machine opt max-ram-below-4g. It is basically doing
|
||||
* min(qemu limit, user limit).
|
||||
*/
|
||||
if (!pcms->max_ram_below_4g) {
|
||||
pcms->max_ram_below_4g = 1ULL << 32; /* default: 4G */;
|
||||
}
|
||||
if (lowmem > pcms->max_ram_below_4g) {
|
||||
lowmem = pcms->max_ram_below_4g;
|
||||
if (machine->ram_size - lowmem > lowmem &&
|
||||
@@ -176,7 +179,6 @@ static void pc_q35_init(MachineState *machine)
|
||||
qdev_init_nofail(DEVICE(q35_host));
|
||||
phb = PCI_HOST_BRIDGE(q35_host);
|
||||
host_bus = phb->bus;
|
||||
pcms->bus = phb->bus;
|
||||
/* create ISA bus */
|
||||
lpc = pci_create_simple_multifunction(host_bus, PCI_DEVFN(ICH9_LPC_DEV,
|
||||
ICH9_LPC_FUNC), true,
|
||||
@@ -287,6 +289,7 @@ static void pc_q35_machine_options(MachineClass *m)
|
||||
m->default_machine_opts = "firmware=bios-256k.bin";
|
||||
m->default_display = "std";
|
||||
m->no_floppy = 1;
|
||||
m->has_dynamic_sysbus = true;
|
||||
}
|
||||
|
||||
static void pc_q35_2_7_machine_options(MachineClass *m)
|
||||
|
||||
+5
-2
@@ -68,7 +68,6 @@
|
||||
#include <hw/isa/isa.h>
|
||||
#include "sysemu/block-backend.h"
|
||||
#include "sysemu/dma.h"
|
||||
|
||||
#include <hw/ide/pci.h>
|
||||
#include <hw/ide/ahci.h>
|
||||
|
||||
@@ -111,6 +110,7 @@ static void pci_ich9_ahci_realize(PCIDevice *dev, Error **errp)
|
||||
int sata_cap_offset;
|
||||
uint8_t *sata_cap;
|
||||
d = ICH_AHCI(dev);
|
||||
int ret;
|
||||
|
||||
ahci_realize(&d->ahci, DEVICE(dev), pci_get_address_space(dev), 6);
|
||||
|
||||
@@ -146,7 +146,10 @@ static void pci_ich9_ahci_realize(PCIDevice *dev, Error **errp)
|
||||
/* Although the AHCI 1.3 specification states that the first capability
|
||||
* should be PMCAP, the Intel ICH9 data sheet specifies that the ICH9
|
||||
* AHCI device puts the MSI capability first, pointing to 0x80. */
|
||||
msi_init(dev, ICH9_MSI_CAP_OFFSET, 1, true, false);
|
||||
ret = msi_init(dev, ICH9_MSI_CAP_OFFSET, 1, true, false, NULL);
|
||||
/* Any error other than -ENOTSUP(board's MSI support is broken)
|
||||
* is a programming error. Fall back to INTx silently on -ENOTSUP */
|
||||
assert(!ret || ret == -ENOTSUP);
|
||||
}
|
||||
|
||||
static void pci_ich9_uninit(PCIDevice *dev)
|
||||
|
||||
+7
-30
@@ -89,8 +89,7 @@ typedef struct E1000EState {
|
||||
#define E1000E_MSIX_TABLE (0x0000)
|
||||
#define E1000E_MSIX_PBA (0x2000)
|
||||
|
||||
#define E1000E_USE_MSI BIT(0)
|
||||
#define E1000E_USE_MSIX BIT(1)
|
||||
#define E1000E_USE_MSIX BIT(0)
|
||||
|
||||
static uint64_t
|
||||
e1000e_mmio_read(void *opaque, hwaddr addr, unsigned size)
|
||||
@@ -263,32 +262,6 @@ static void e1000e_core_realize(E1000EState *s)
|
||||
s->core.owner_nic = s->nic;
|
||||
}
|
||||
|
||||
static void
|
||||
e1000e_init_msi(E1000EState *s)
|
||||
{
|
||||
int res;
|
||||
|
||||
res = msi_init(PCI_DEVICE(s),
|
||||
0xD0, /* MSI capability offset */
|
||||
1, /* MAC MSI interrupts */
|
||||
true, /* 64-bit message addresses supported */
|
||||
false); /* Per vector mask supported */
|
||||
|
||||
if (res > 0) {
|
||||
s->intr_state |= E1000E_USE_MSI;
|
||||
} else {
|
||||
trace_e1000e_msi_init_fail(res);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
e1000e_cleanup_msi(E1000EState *s)
|
||||
{
|
||||
if (s->intr_state & E1000E_USE_MSI) {
|
||||
msi_uninit(PCI_DEVICE(s));
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
e1000e_unuse_msix_vectors(E1000EState *s, int num_vectors)
|
||||
{
|
||||
@@ -444,6 +417,7 @@ static void e1000e_pci_realize(PCIDevice *pci_dev, Error **errp)
|
||||
static const uint16_t e1000e_dsn_offset = 0x140;
|
||||
E1000EState *s = E1000E(pci_dev);
|
||||
uint8_t *macaddr;
|
||||
int ret;
|
||||
|
||||
trace_e1000e_cb_pci_realize();
|
||||
|
||||
@@ -493,7 +467,10 @@ static void e1000e_pci_realize(PCIDevice *pci_dev, Error **errp)
|
||||
hw_error("Failed to initialize PCIe capability");
|
||||
}
|
||||
|
||||
e1000e_init_msi(s);
|
||||
ret = msi_init(PCI_DEVICE(s), 0xD0, 1, true, false, NULL);
|
||||
if (ret) {
|
||||
trace_e1000e_msi_init_fail(ret);
|
||||
}
|
||||
|
||||
if (e1000e_add_pm_capability(pci_dev, e1000e_pmrb_offset,
|
||||
PCI_PM_CAP_DSI) < 0) {
|
||||
@@ -532,7 +509,7 @@ static void e1000e_pci_uninit(PCIDevice *pci_dev)
|
||||
qemu_del_nic(s->nic);
|
||||
|
||||
e1000e_cleanup_msix(s);
|
||||
e1000e_cleanup_msi(s);
|
||||
msi_uninit(pci_dev);
|
||||
}
|
||||
|
||||
static void e1000e_qdev_reset(DeviceState *dev)
|
||||
|
||||
+17
-23
@@ -1542,33 +1542,11 @@ static int virtio_net_load(QEMUFile *f, void *opaque, int version_id)
|
||||
{
|
||||
VirtIONet *n = opaque;
|
||||
VirtIODevice *vdev = VIRTIO_DEVICE(n);
|
||||
int ret;
|
||||
|
||||
if (version_id < 2 || version_id > VIRTIO_NET_VM_VERSION)
|
||||
return -EINVAL;
|
||||
|
||||
ret = virtio_load(vdev, f, version_id);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (virtio_vdev_has_feature(vdev, VIRTIO_NET_F_CTRL_GUEST_OFFLOADS)) {
|
||||
n->curr_guest_offloads = qemu_get_be64(f);
|
||||
} else {
|
||||
n->curr_guest_offloads = virtio_net_supported_guest_offloads(n);
|
||||
}
|
||||
|
||||
if (peer_has_vnet_hdr(n)) {
|
||||
virtio_net_apply_guest_offloads(n);
|
||||
}
|
||||
|
||||
if (virtio_vdev_has_feature(vdev, VIRTIO_NET_F_GUEST_ANNOUNCE) &&
|
||||
virtio_vdev_has_feature(vdev, VIRTIO_NET_F_CTRL_VQ)) {
|
||||
n->announce_counter = SELF_ANNOUNCE_ROUNDS;
|
||||
timer_mod(n->announce_timer, qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL));
|
||||
}
|
||||
|
||||
return 0;
|
||||
return virtio_load(vdev, f, version_id);
|
||||
}
|
||||
|
||||
static int virtio_net_load_device(VirtIODevice *vdev, QEMUFile *f,
|
||||
@@ -1665,6 +1643,16 @@ static int virtio_net_load_device(VirtIODevice *vdev, QEMUFile *f,
|
||||
}
|
||||
}
|
||||
|
||||
if (virtio_vdev_has_feature(vdev, VIRTIO_NET_F_CTRL_GUEST_OFFLOADS)) {
|
||||
n->curr_guest_offloads = qemu_get_be64(f);
|
||||
} else {
|
||||
n->curr_guest_offloads = virtio_net_supported_guest_offloads(n);
|
||||
}
|
||||
|
||||
if (peer_has_vnet_hdr(n)) {
|
||||
virtio_net_apply_guest_offloads(n);
|
||||
}
|
||||
|
||||
virtio_net_set_queues(n);
|
||||
|
||||
/* Find the first multicast entry in the saved MAC filter */
|
||||
@@ -1682,6 +1670,12 @@ static int virtio_net_load_device(VirtIODevice *vdev, QEMUFile *f,
|
||||
qemu_get_subqueue(n->nic, i)->link_down = link_down;
|
||||
}
|
||||
|
||||
if (virtio_vdev_has_feature(vdev, VIRTIO_NET_F_GUEST_ANNOUNCE) &&
|
||||
virtio_vdev_has_feature(vdev, VIRTIO_NET_F_CTRL_VQ)) {
|
||||
n->announce_counter = SELF_ANNOUNCE_ROUNDS;
|
||||
timer_mod(n->announce_timer, qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
+17
-35
@@ -283,8 +283,6 @@ typedef struct {
|
||||
|
||||
/* Whether MSI-X support was installed successfully */
|
||||
bool msix_used;
|
||||
/* Whether MSI support was installed successfully */
|
||||
bool msi_used;
|
||||
hwaddr drv_shmem;
|
||||
hwaddr temp_shared_guest_driver_memory;
|
||||
|
||||
@@ -366,7 +364,7 @@ static bool _vmxnet3_assert_interrupt_line(VMXNET3State *s, uint32_t int_idx)
|
||||
msix_notify(d, int_idx);
|
||||
return false;
|
||||
}
|
||||
if (s->msi_used && msi_enabled(d)) {
|
||||
if (msi_enabled(d)) {
|
||||
VMW_IRPRN("Sending MSI notification for vector %u", int_idx);
|
||||
msi_notify(d, int_idx);
|
||||
return false;
|
||||
@@ -390,7 +388,7 @@ static void _vmxnet3_deassert_interrupt_line(VMXNET3State *s, int lidx)
|
||||
* This function should never be called for MSI(X) interrupts
|
||||
* because deassertion never required for message interrupts
|
||||
*/
|
||||
assert(!s->msi_used || !msi_enabled(d));
|
||||
assert(!msi_enabled(d));
|
||||
|
||||
VMW_IRPRN("Deasserting line for interrupt %u", lidx);
|
||||
pci_irq_deassert(d);
|
||||
@@ -427,7 +425,7 @@ static void vmxnet3_trigger_interrupt(VMXNET3State *s, int lidx)
|
||||
goto do_automask;
|
||||
}
|
||||
|
||||
if (s->msi_used && msi_enabled(d) && s->auto_int_masking) {
|
||||
if (msi_enabled(d) && s->auto_int_masking) {
|
||||
goto do_automask;
|
||||
}
|
||||
|
||||
@@ -1425,8 +1423,8 @@ static void vmxnet3_update_features(VMXNET3State *s)
|
||||
|
||||
static bool vmxnet3_verify_intx(VMXNET3State *s, int intx)
|
||||
{
|
||||
return s->msix_used || s->msi_used || (intx ==
|
||||
(pci_get_byte(s->parent_obj.config + PCI_INTERRUPT_PIN) - 1));
|
||||
return s->msix_used || msi_enabled(PCI_DEVICE(s))
|
||||
|| intx == pci_get_byte(s->parent_obj.config + PCI_INTERRUPT_PIN) - 1;
|
||||
}
|
||||
|
||||
static void vmxnet3_validate_interrupt_idx(bool is_msix, int idx)
|
||||
@@ -2216,35 +2214,12 @@ vmxnet3_cleanup_msix(VMXNET3State *s)
|
||||
}
|
||||
}
|
||||
|
||||
#define VMXNET3_USE_64BIT (true)
|
||||
#define VMXNET3_PER_VECTOR_MASK (false)
|
||||
|
||||
static bool
|
||||
vmxnet3_init_msi(VMXNET3State *s)
|
||||
{
|
||||
PCIDevice *d = PCI_DEVICE(s);
|
||||
int res;
|
||||
|
||||
res = msi_init(d, VMXNET3_MSI_OFFSET(s), VMXNET3_MAX_NMSIX_INTRS,
|
||||
VMXNET3_USE_64BIT, VMXNET3_PER_VECTOR_MASK);
|
||||
if (0 > res) {
|
||||
VMW_WRPRN("Failed to initialize MSI, error %d", res);
|
||||
s->msi_used = false;
|
||||
} else {
|
||||
s->msi_used = true;
|
||||
}
|
||||
|
||||
return s->msi_used;
|
||||
}
|
||||
|
||||
static void
|
||||
vmxnet3_cleanup_msi(VMXNET3State *s)
|
||||
{
|
||||
PCIDevice *d = PCI_DEVICE(s);
|
||||
|
||||
if (s->msi_used) {
|
||||
msi_uninit(d);
|
||||
}
|
||||
msi_uninit(d);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -2298,10 +2273,15 @@ static uint64_t vmxnet3_device_serial_num(VMXNET3State *s)
|
||||
return dsn_payload;
|
||||
}
|
||||
|
||||
|
||||
#define VMXNET3_USE_64BIT (true)
|
||||
#define VMXNET3_PER_VECTOR_MASK (false)
|
||||
|
||||
static void vmxnet3_pci_realize(PCIDevice *pci_dev, Error **errp)
|
||||
{
|
||||
DeviceState *dev = DEVICE(pci_dev);
|
||||
VMXNET3State *s = VMXNET3(pci_dev);
|
||||
int ret;
|
||||
|
||||
VMW_CBPRN("Starting init...");
|
||||
|
||||
@@ -2325,14 +2305,16 @@ static void vmxnet3_pci_realize(PCIDevice *pci_dev, Error **errp)
|
||||
/* Interrupt pin A */
|
||||
pci_dev->config[PCI_INTERRUPT_PIN] = 0x01;
|
||||
|
||||
ret = msi_init(pci_dev, VMXNET3_MSI_OFFSET(s), VMXNET3_MAX_NMSIX_INTRS,
|
||||
VMXNET3_USE_64BIT, VMXNET3_PER_VECTOR_MASK, NULL);
|
||||
/* Any error other than -ENOTSUP(board's MSI support is broken)
|
||||
* is a programming error. Fall back to INTx silently on -ENOTSUP */
|
||||
assert(!ret || ret == -ENOTSUP);
|
||||
|
||||
if (!vmxnet3_init_msix(s)) {
|
||||
VMW_WRPRN("Failed to initialize MSI-X, configuration is inconsistent.");
|
||||
}
|
||||
|
||||
if (!vmxnet3_init_msi(s)) {
|
||||
VMW_WRPRN("Failed to initialize MSI, configuration is inconsistent.");
|
||||
}
|
||||
|
||||
vmxnet3_net_init(s);
|
||||
|
||||
if (pci_is_express(pci_dev)) {
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#include "hw/pci/msi.h"
|
||||
#include "hw/pci/pcie.h"
|
||||
#include "ioh3420.h"
|
||||
#include "qapi/error.h"
|
||||
|
||||
#define PCI_DEVICE_ID_IOH_EPORT 0x3420 /* D0:F0 express mode */
|
||||
#define PCI_DEVICE_ID_IOH_REV 0x2
|
||||
@@ -97,6 +98,7 @@ static int ioh3420_initfn(PCIDevice *d)
|
||||
PCIEPort *p = PCIE_PORT(d);
|
||||
PCIESlot *s = PCIE_SLOT(d);
|
||||
int rc;
|
||||
Error *err = NULL;
|
||||
|
||||
pci_bridge_initfn(d, TYPE_PCIE_BUS);
|
||||
pcie_port_init_reg(d);
|
||||
@@ -109,8 +111,10 @@ static int ioh3420_initfn(PCIDevice *d)
|
||||
|
||||
rc = msi_init(d, IOH_EP_MSI_OFFSET, IOH_EP_MSI_NR_VECTOR,
|
||||
IOH_EP_MSI_SUPPORTED_FLAGS & PCI_MSI_FLAGS_64BIT,
|
||||
IOH_EP_MSI_SUPPORTED_FLAGS & PCI_MSI_FLAGS_MASKBIT);
|
||||
IOH_EP_MSI_SUPPORTED_FLAGS & PCI_MSI_FLAGS_MASKBIT, &err);
|
||||
if (rc < 0) {
|
||||
assert(rc == -ENOTSUP);
|
||||
error_report_err(err);
|
||||
goto err_bridge;
|
||||
}
|
||||
|
||||
|
||||
@@ -42,9 +42,10 @@ struct PCIBridgeDev {
|
||||
|
||||
MemoryRegion bar;
|
||||
uint8_t chassis_nr;
|
||||
#define PCI_BRIDGE_DEV_F_MSI_REQ 0
|
||||
#define PCI_BRIDGE_DEV_F_SHPC_REQ 1
|
||||
#define PCI_BRIDGE_DEV_F_SHPC_REQ 0
|
||||
uint32_t flags;
|
||||
|
||||
OnOffAuto msi;
|
||||
};
|
||||
typedef struct PCIBridgeDev PCIBridgeDev;
|
||||
|
||||
@@ -53,6 +54,7 @@ static int pci_bridge_dev_initfn(PCIDevice *dev)
|
||||
PCIBridge *br = PCI_BRIDGE(dev);
|
||||
PCIBridgeDev *bridge_dev = PCI_BRIDGE_DEV(dev);
|
||||
int err;
|
||||
Error *local_err = NULL;
|
||||
|
||||
pci_bridge_initfn(dev, TYPE_PCI_BUS);
|
||||
|
||||
@@ -66,7 +68,7 @@ static int pci_bridge_dev_initfn(PCIDevice *dev)
|
||||
}
|
||||
} else {
|
||||
/* MSI is not applicable without SHPC */
|
||||
bridge_dev->flags &= ~(1 << PCI_BRIDGE_DEV_F_MSI_REQ);
|
||||
bridge_dev->msi = ON_OFF_AUTO_OFF;
|
||||
}
|
||||
|
||||
err = slotid_cap_init(dev, 0, bridge_dev->chassis_nr, 0);
|
||||
@@ -74,12 +76,23 @@ static int pci_bridge_dev_initfn(PCIDevice *dev)
|
||||
goto slotid_error;
|
||||
}
|
||||
|
||||
if ((bridge_dev->flags & (1 << PCI_BRIDGE_DEV_F_MSI_REQ)) &&
|
||||
msi_nonbroken) {
|
||||
err = msi_init(dev, 0, 1, true, true);
|
||||
if (err < 0) {
|
||||
if (bridge_dev->msi != ON_OFF_AUTO_OFF) {
|
||||
/* it means SHPC exists, because MSI is needed by SHPC */
|
||||
|
||||
err = msi_init(dev, 0, 1, true, true, &local_err);
|
||||
/* Any error other than -ENOTSUP(board's MSI support is broken)
|
||||
* is a programming error */
|
||||
assert(!err || err == -ENOTSUP);
|
||||
if (err && bridge_dev->msi == ON_OFF_AUTO_ON) {
|
||||
/* Can't satisfy user's explicit msi=on request, fail */
|
||||
error_append_hint(&local_err, "You have to use msi=auto (default) "
|
||||
"or msi=off with this machine type.\n");
|
||||
error_report_err(local_err);
|
||||
goto msi_error;
|
||||
}
|
||||
assert(!local_err || bridge_dev->msi == ON_OFF_AUTO_AUTO);
|
||||
/* With msi=auto, we fall back to MSI off silently */
|
||||
error_free(local_err);
|
||||
}
|
||||
|
||||
if (shpc_present(dev)) {
|
||||
@@ -147,8 +160,8 @@ static Property pci_bridge_dev_properties[] = {
|
||||
/* Note: 0 is not a legal chassis number. */
|
||||
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_ON_OFF_AUTO(PCI_BRIDGE_DEV_PROP_MSI, PCIBridgeDev, msi,
|
||||
ON_OFF_AUTO_AUTO),
|
||||
DEFINE_PROP_BIT(PCI_BRIDGE_DEV_PROP_SHPC, PCIBridgeDev, flags,
|
||||
PCI_BRIDGE_DEV_F_SHPC_REQ, true),
|
||||
DEFINE_PROP_END_OF_LIST(),
|
||||
|
||||
@@ -149,6 +149,8 @@ static void pxb_host_class_init(ObjectClass *class, void *data)
|
||||
PCIHostBridgeClass *hc = PCI_HOST_BRIDGE_CLASS(class);
|
||||
|
||||
dc->fw_name = "pci";
|
||||
/* Reason: Internal part of the pxb/pxb-pcie device, not usable by itself */
|
||||
dc->cannot_instantiate_with_device_add_yet = true;
|
||||
sbc->explicit_ofw_unit_address = pxb_host_ofw_unit_address;
|
||||
hc->root_bus_path = pxb_host_root_bus_path;
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include "hw/pci/msi.h"
|
||||
#include "hw/pci/pcie.h"
|
||||
#include "xio3130_downstream.h"
|
||||
#include "qapi/error.h"
|
||||
|
||||
#define PCI_DEVICE_ID_TI_XIO3130D 0x8233 /* downstream port */
|
||||
#define XIO3130_REVISION 0x1
|
||||
@@ -60,14 +61,17 @@ static int xio3130_downstream_initfn(PCIDevice *d)
|
||||
PCIEPort *p = PCIE_PORT(d);
|
||||
PCIESlot *s = PCIE_SLOT(d);
|
||||
int rc;
|
||||
Error *err = NULL;
|
||||
|
||||
pci_bridge_initfn(d, TYPE_PCIE_BUS);
|
||||
pcie_port_init_reg(d);
|
||||
|
||||
rc = msi_init(d, XIO3130_MSI_OFFSET, XIO3130_MSI_NR_VECTOR,
|
||||
XIO3130_MSI_SUPPORTED_FLAGS & PCI_MSI_FLAGS_64BIT,
|
||||
XIO3130_MSI_SUPPORTED_FLAGS & PCI_MSI_FLAGS_MASKBIT);
|
||||
XIO3130_MSI_SUPPORTED_FLAGS & PCI_MSI_FLAGS_MASKBIT, &err);
|
||||
if (rc < 0) {
|
||||
assert(rc == -ENOTSUP);
|
||||
error_report_err(err);
|
||||
goto err_bridge;
|
||||
}
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include "hw/pci/msi.h"
|
||||
#include "hw/pci/pcie.h"
|
||||
#include "xio3130_upstream.h"
|
||||
#include "qapi/error.h"
|
||||
|
||||
#define PCI_DEVICE_ID_TI_XIO3130U 0x8232 /* upstream port */
|
||||
#define XIO3130_REVISION 0x2
|
||||
@@ -56,14 +57,17 @@ static int xio3130_upstream_initfn(PCIDevice *d)
|
||||
{
|
||||
PCIEPort *p = PCIE_PORT(d);
|
||||
int rc;
|
||||
Error *err = NULL;
|
||||
|
||||
pci_bridge_initfn(d, TYPE_PCIE_BUS);
|
||||
pcie_port_init_reg(d);
|
||||
|
||||
rc = msi_init(d, XIO3130_MSI_OFFSET, XIO3130_MSI_NR_VECTOR,
|
||||
XIO3130_MSI_SUPPORTED_FLAGS & PCI_MSI_FLAGS_64BIT,
|
||||
XIO3130_MSI_SUPPORTED_FLAGS & PCI_MSI_FLAGS_MASKBIT);
|
||||
XIO3130_MSI_SUPPORTED_FLAGS & PCI_MSI_FLAGS_MASKBIT, &err);
|
||||
if (rc < 0) {
|
||||
assert(rc == -ENOTSUP);
|
||||
error_report_err(err);
|
||||
goto err_bridge;
|
||||
}
|
||||
|
||||
|
||||
+21
-11
@@ -48,7 +48,7 @@
|
||||
|
||||
typedef struct I440FXState {
|
||||
PCIHostState parent_obj;
|
||||
PcPciInfo pci_info;
|
||||
Range pci_hole;
|
||||
uint64_t pci_hole64_size;
|
||||
uint32_t short_root_bus;
|
||||
} I440FXState;
|
||||
@@ -221,8 +221,12 @@ static void i440fx_pcihost_get_pci_hole_start(Object *obj, Visitor *v,
|
||||
Error **errp)
|
||||
{
|
||||
I440FXState *s = I440FX_PCI_HOST_BRIDGE(obj);
|
||||
uint32_t value = s->pci_info.w32.begin;
|
||||
uint64_t val64;
|
||||
uint32_t value;
|
||||
|
||||
val64 = range_is_empty(&s->pci_hole) ? 0 : range_lob(&s->pci_hole);
|
||||
value = val64;
|
||||
assert(value == val64);
|
||||
visit_type_uint32(v, name, &value, errp);
|
||||
}
|
||||
|
||||
@@ -231,8 +235,12 @@ static void i440fx_pcihost_get_pci_hole_end(Object *obj, Visitor *v,
|
||||
Error **errp)
|
||||
{
|
||||
I440FXState *s = I440FX_PCI_HOST_BRIDGE(obj);
|
||||
uint32_t value = s->pci_info.w32.end;
|
||||
uint64_t val64;
|
||||
uint32_t value;
|
||||
|
||||
val64 = range_is_empty(&s->pci_hole) ? 0 : range_upb(&s->pci_hole) + 1;
|
||||
value = val64;
|
||||
assert(value == val64);
|
||||
visit_type_uint32(v, name, &value, errp);
|
||||
}
|
||||
|
||||
@@ -242,10 +250,11 @@ static void i440fx_pcihost_get_pci_hole64_start(Object *obj, Visitor *v,
|
||||
{
|
||||
PCIHostState *h = PCI_HOST_BRIDGE(obj);
|
||||
Range w64;
|
||||
uint64_t value;
|
||||
|
||||
pci_bus_get_w64_range(h->bus, &w64);
|
||||
|
||||
visit_type_uint64(v, name, &w64.begin, errp);
|
||||
value = range_is_empty(&w64) ? 0 : range_lob(&w64);
|
||||
visit_type_uint64(v, name, &value, errp);
|
||||
}
|
||||
|
||||
static void i440fx_pcihost_get_pci_hole64_end(Object *obj, Visitor *v,
|
||||
@@ -254,16 +263,16 @@ static void i440fx_pcihost_get_pci_hole64_end(Object *obj, Visitor *v,
|
||||
{
|
||||
PCIHostState *h = PCI_HOST_BRIDGE(obj);
|
||||
Range w64;
|
||||
uint64_t value;
|
||||
|
||||
pci_bus_get_w64_range(h->bus, &w64);
|
||||
|
||||
visit_type_uint64(v, name, &w64.end, errp);
|
||||
value = range_is_empty(&w64) ? 0 : range_upb(&w64) + 1;
|
||||
visit_type_uint64(v, name, &value, errp);
|
||||
}
|
||||
|
||||
static void i440fx_pcihost_initfn(Object *obj)
|
||||
{
|
||||
PCIHostState *s = PCI_HOST_BRIDGE(obj);
|
||||
I440FXState *d = I440FX_PCI_HOST_BRIDGE(obj);
|
||||
|
||||
memory_region_init_io(&s->conf_mem, obj, &pci_host_conf_le_ops, s,
|
||||
"pci-conf-idx", 4);
|
||||
@@ -285,8 +294,6 @@ static void i440fx_pcihost_initfn(Object *obj)
|
||||
object_property_add(obj, PCI_HOST_PROP_PCI_HOLE64_END, "int",
|
||||
i440fx_pcihost_get_pci_hole64_end,
|
||||
NULL, NULL, NULL, NULL);
|
||||
|
||||
d->pci_info.w32.end = IO_APIC_DEFAULT_ADDRESS;
|
||||
}
|
||||
|
||||
static void i440fx_pcihost_realize(DeviceState *dev, Error **errp)
|
||||
@@ -347,7 +354,8 @@ PCIBus *i440fx_init(const char *host_type, const char *pci_type,
|
||||
f->ram_memory = ram_memory;
|
||||
|
||||
i440fx = I440FX_PCI_HOST_BRIDGE(dev);
|
||||
i440fx->pci_info.w32.begin = below_4g_mem_size;
|
||||
range_set_bounds(&i440fx->pci_hole, below_4g_mem_size,
|
||||
IO_APIC_DEFAULT_ADDRESS - 1);
|
||||
|
||||
/* setup pci memory mapping */
|
||||
pc_pci_as_mapping_init(OBJECT(f), f->system_memory,
|
||||
@@ -865,6 +873,8 @@ static void i440fx_pcihost_class_init(ObjectClass *klass, void *data)
|
||||
dc->realize = i440fx_pcihost_realize;
|
||||
dc->fw_name = "pci";
|
||||
dc->props = i440fx_props;
|
||||
/* Reason: needs to be wired up by pc_init1 */
|
||||
dc->cannot_instantiate_with_device_add_yet = true;
|
||||
}
|
||||
|
||||
static const TypeInfo i440fx_pcihost_info = {
|
||||
|
||||
+30
-42
@@ -52,6 +52,7 @@ static void q35_host_realize(DeviceState *dev, Error **errp)
|
||||
pci->bus = pci_bus_new(DEVICE(s), "pcie.0",
|
||||
s->mch.pci_address_space, s->mch.address_space_io,
|
||||
0, TYPE_PCIE_BUS);
|
||||
PC_MACHINE(qdev_get_machine())->bus = pci->bus;
|
||||
qdev_set_parent_bus(DEVICE(&s->mch), BUS(pci->bus));
|
||||
qdev_init_nofail(DEVICE(&s->mch));
|
||||
}
|
||||
@@ -73,8 +74,13 @@ static void q35_host_get_pci_hole_start(Object *obj, Visitor *v,
|
||||
Error **errp)
|
||||
{
|
||||
Q35PCIHost *s = Q35_HOST_DEVICE(obj);
|
||||
uint32_t value = s->mch.pci_info.w32.begin;
|
||||
uint64_t val64;
|
||||
uint32_t value;
|
||||
|
||||
val64 = range_is_empty(&s->mch.pci_hole)
|
||||
? 0 : range_lob(&s->mch.pci_hole);
|
||||
value = val64;
|
||||
assert(value == val64);
|
||||
visit_type_uint32(v, name, &value, errp);
|
||||
}
|
||||
|
||||
@@ -83,8 +89,13 @@ static void q35_host_get_pci_hole_end(Object *obj, Visitor *v,
|
||||
Error **errp)
|
||||
{
|
||||
Q35PCIHost *s = Q35_HOST_DEVICE(obj);
|
||||
uint32_t value = s->mch.pci_info.w32.end;
|
||||
uint64_t val64;
|
||||
uint32_t value;
|
||||
|
||||
val64 = range_is_empty(&s->mch.pci_hole)
|
||||
? 0 : range_upb(&s->mch.pci_hole) + 1;
|
||||
value = val64;
|
||||
assert(value == val64);
|
||||
visit_type_uint32(v, name, &value, errp);
|
||||
}
|
||||
|
||||
@@ -94,10 +105,11 @@ static void q35_host_get_pci_hole64_start(Object *obj, Visitor *v,
|
||||
{
|
||||
PCIHostState *h = PCI_HOST_BRIDGE(obj);
|
||||
Range w64;
|
||||
uint64_t value;
|
||||
|
||||
pci_bus_get_w64_range(h->bus, &w64);
|
||||
|
||||
visit_type_uint64(v, name, &w64.begin, errp);
|
||||
value = range_is_empty(&w64) ? 0 : range_lob(&w64);
|
||||
visit_type_uint64(v, name, &value, errp);
|
||||
}
|
||||
|
||||
static void q35_host_get_pci_hole64_end(Object *obj, Visitor *v,
|
||||
@@ -106,10 +118,11 @@ static void q35_host_get_pci_hole64_end(Object *obj, Visitor *v,
|
||||
{
|
||||
PCIHostState *h = PCI_HOST_BRIDGE(obj);
|
||||
Range w64;
|
||||
uint64_t value;
|
||||
|
||||
pci_bus_get_w64_range(h->bus, &w64);
|
||||
|
||||
visit_type_uint64(v, name, &w64.end, errp);
|
||||
value = range_is_empty(&w64) ? 0 : range_upb(&w64) + 1;
|
||||
visit_type_uint64(v, name, &value, errp);
|
||||
}
|
||||
|
||||
static void q35_host_get_mmcfg_size(Object *obj, Visitor *v, const char *name,
|
||||
@@ -142,6 +155,8 @@ static void q35_host_class_init(ObjectClass *klass, void *data)
|
||||
hc->root_bus_path = q35_host_root_bus_path;
|
||||
dc->realize = q35_host_realize;
|
||||
dc->props = mch_props;
|
||||
/* Reason: needs to be wired up by pc_q35_init */
|
||||
dc->cannot_instantiate_with_device_add_yet = true;
|
||||
set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
|
||||
dc->fw_name = "pci";
|
||||
}
|
||||
@@ -202,9 +217,9 @@ static void q35_host_initfn(Object *obj)
|
||||
* it's not a power of two, which means an MTRR
|
||||
* can't cover it exactly.
|
||||
*/
|
||||
s->mch.pci_info.w32.begin = MCH_HOST_BRIDGE_PCIEXBAR_DEFAULT +
|
||||
MCH_HOST_BRIDGE_PCIEXBAR_MAX;
|
||||
s->mch.pci_info.w32.end = IO_APIC_DEFAULT_ADDRESS;
|
||||
range_set_bounds(&s->mch.pci_hole,
|
||||
MCH_HOST_BRIDGE_PCIEXBAR_DEFAULT + MCH_HOST_BRIDGE_PCIEXBAR_MAX,
|
||||
IO_APIC_DEFAULT_ADDRESS - 1);
|
||||
}
|
||||
|
||||
static const TypeInfo q35_host_info = {
|
||||
@@ -272,10 +287,7 @@ static void mch_update_pciexbar(MCHPCIState *mch)
|
||||
break;
|
||||
case MCH_HOST_BRIDGE_PCIEXBAR_LENGTH_RVD:
|
||||
default:
|
||||
enable = 0;
|
||||
length = 0;
|
||||
abort();
|
||||
break;
|
||||
}
|
||||
addr = pciexbar & addr_mask;
|
||||
pcie_host_mmcfg_update(pehb, enable, addr, length);
|
||||
@@ -285,9 +297,13 @@ static void mch_update_pciexbar(MCHPCIState *mch)
|
||||
* which means an MTRR can't cover it exactly.
|
||||
*/
|
||||
if (enable) {
|
||||
mch->pci_info.w32.begin = addr + length;
|
||||
range_set_bounds(&mch->pci_hole,
|
||||
addr + length,
|
||||
IO_APIC_DEFAULT_ADDRESS - 1);
|
||||
} else {
|
||||
mch->pci_info.w32.begin = MCH_HOST_BRIDGE_PCIEXBAR_DEFAULT;
|
||||
range_set_bounds(&mch->pci_hole,
|
||||
MCH_HOST_BRIDGE_PCIEXBAR_DEFAULT,
|
||||
IO_APIC_DEFAULT_ADDRESS - 1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -444,30 +460,6 @@ static void mch_reset(DeviceState *qdev)
|
||||
mch_update(mch);
|
||||
}
|
||||
|
||||
static AddressSpace *q35_host_dma_iommu(PCIBus *bus, void *opaque, int devfn)
|
||||
{
|
||||
IntelIOMMUState *s = opaque;
|
||||
VTDAddressSpace *vtd_as;
|
||||
|
||||
assert(0 <= devfn && devfn <= VTD_PCI_DEVFN_MAX);
|
||||
|
||||
vtd_as = vtd_find_add_as(s, bus, devfn);
|
||||
return &vtd_as->as;
|
||||
}
|
||||
|
||||
static void mch_init_dmar(MCHPCIState *mch)
|
||||
{
|
||||
PCIBus *pci_bus = PCI_BUS(qdev_get_parent_bus(DEVICE(mch)));
|
||||
|
||||
mch->iommu = INTEL_IOMMU_DEVICE(qdev_create(NULL, TYPE_INTEL_IOMMU_DEVICE));
|
||||
object_property_add_child(OBJECT(mch), "intel-iommu",
|
||||
OBJECT(mch->iommu), NULL);
|
||||
qdev_init_nofail(DEVICE(mch->iommu));
|
||||
sysbus_mmio_map(SYS_BUS_DEVICE(mch->iommu), 0, Q35_HOST_BRIDGE_IOMMU_ADDR);
|
||||
|
||||
pci_setup_iommu(pci_bus, q35_host_dma_iommu, mch->iommu);
|
||||
}
|
||||
|
||||
static void mch_realize(PCIDevice *d, Error **errp)
|
||||
{
|
||||
int i;
|
||||
@@ -526,10 +518,6 @@ static void mch_realize(PCIDevice *d, Error **errp)
|
||||
mch->pci_address_space, &mch->pam_regions[i+1],
|
||||
PAM_EXPAN_BASE + i * PAM_EXPAN_SIZE, PAM_EXPAN_SIZE);
|
||||
}
|
||||
/* Intel IOMMU (VT-d) */
|
||||
if (object_property_get_bool(qdev_get_machine(), "iommu", NULL)) {
|
||||
mch_init_dmar(mch);
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t mch_mcfg_base(void)
|
||||
|
||||
+8
-3
@@ -22,6 +22,7 @@
|
||||
#include "hw/pci/msi.h"
|
||||
#include "hw/xen/xen.h"
|
||||
#include "qemu/range.h"
|
||||
#include "qapi/error.h"
|
||||
|
||||
/* PCI_MSI_ADDRESS_LO */
|
||||
#define PCI_MSI_ADDRESS_LO_MASK (~0x3)
|
||||
@@ -173,7 +174,8 @@ bool msi_enabled(const PCIDevice *dev)
|
||||
* If @msi64bit, make the device capable of sending a 64-bit message
|
||||
* address.
|
||||
* If @msi_per_vector_mask, make the device support per-vector masking.
|
||||
* Return 0 on success, return -errno on error.
|
||||
* @errp is for returning errors.
|
||||
* Return 0 on success; set @errp and return -errno on error.
|
||||
*
|
||||
* -ENOTSUP means lacking msi support for a msi-capable platform.
|
||||
* -EINVAL means capability overlap, happens when @offset is non-zero,
|
||||
@@ -181,7 +183,8 @@ bool msi_enabled(const PCIDevice *dev)
|
||||
* if a real HW is broken.
|
||||
*/
|
||||
int msi_init(struct PCIDevice *dev, uint8_t offset,
|
||||
unsigned int nr_vectors, bool msi64bit, bool msi_per_vector_mask)
|
||||
unsigned int nr_vectors, bool msi64bit,
|
||||
bool msi_per_vector_mask, Error **errp)
|
||||
{
|
||||
unsigned int vectors_order;
|
||||
uint16_t flags;
|
||||
@@ -189,6 +192,7 @@ int msi_init(struct PCIDevice *dev, uint8_t offset,
|
||||
int config_offset;
|
||||
|
||||
if (!msi_nonbroken) {
|
||||
error_setg(errp, "MSI is not supported by interrupt controller");
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
@@ -212,7 +216,8 @@ int msi_init(struct PCIDevice *dev, uint8_t offset,
|
||||
}
|
||||
|
||||
cap_size = msi_cap_sizeof(flags);
|
||||
config_offset = pci_add_capability(dev, PCI_CAP_ID_MSI, offset, cap_size);
|
||||
config_offset = pci_add_capability2(dev, PCI_CAP_ID_MSI, offset,
|
||||
cap_size, errp);
|
||||
if (config_offset < 0) {
|
||||
return config_offset;
|
||||
}
|
||||
|
||||
+49
-25
@@ -78,10 +78,37 @@ static const VMStateDescription vmstate_pcibus = {
|
||||
}
|
||||
};
|
||||
|
||||
static void pci_init_bus_master(PCIDevice *pci_dev)
|
||||
{
|
||||
AddressSpace *dma_as = pci_device_iommu_address_space(pci_dev);
|
||||
|
||||
memory_region_init_alias(&pci_dev->bus_master_enable_region,
|
||||
OBJECT(pci_dev), "bus master",
|
||||
dma_as->root, 0, memory_region_size(dma_as->root));
|
||||
memory_region_set_enabled(&pci_dev->bus_master_enable_region, false);
|
||||
address_space_init(&pci_dev->bus_master_as,
|
||||
&pci_dev->bus_master_enable_region, pci_dev->name);
|
||||
}
|
||||
|
||||
static void pcibus_machine_done(Notifier *notifier, void *data)
|
||||
{
|
||||
PCIBus *bus = container_of(notifier, PCIBus, machine_done);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(bus->devices); ++i) {
|
||||
if (bus->devices[i]) {
|
||||
pci_init_bus_master(bus->devices[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void pci_bus_realize(BusState *qbus, Error **errp)
|
||||
{
|
||||
PCIBus *bus = PCI_BUS(qbus);
|
||||
|
||||
bus->machine_done.notify = pcibus_machine_done;
|
||||
qemu_add_machine_init_done_notifier(&bus->machine_done);
|
||||
|
||||
vmstate_register(NULL, -1, &vmstate_pcibus, bus);
|
||||
}
|
||||
|
||||
@@ -89,6 +116,8 @@ static void pci_bus_unrealize(BusState *qbus, Error **errp)
|
||||
{
|
||||
PCIBus *bus = PCI_BUS(qbus);
|
||||
|
||||
qemu_remove_machine_init_done_notifier(&bus->machine_done);
|
||||
|
||||
vmstate_unregister(NULL, &vmstate_pcibus, bus);
|
||||
}
|
||||
|
||||
@@ -920,7 +949,6 @@ static PCIDevice *do_pci_register_device(PCIDevice *pci_dev, PCIBus *bus,
|
||||
PCIConfigReadFunc *config_read = pc->config_read;
|
||||
PCIConfigWriteFunc *config_write = pc->config_write;
|
||||
Error *local_err = NULL;
|
||||
AddressSpace *dma_as;
|
||||
DeviceState *dev = DEVICE(pci_dev);
|
||||
|
||||
pci_dev->bus = bus;
|
||||
@@ -961,15 +989,10 @@ static PCIDevice *do_pci_register_device(PCIDevice *pci_dev, PCIBus *bus,
|
||||
|
||||
pci_dev->devfn = devfn;
|
||||
pci_dev->requester_id_cache = pci_req_id_cache_get(pci_dev);
|
||||
dma_as = pci_device_iommu_address_space(pci_dev);
|
||||
|
||||
memory_region_init_alias(&pci_dev->bus_master_enable_region,
|
||||
OBJECT(pci_dev), "bus master",
|
||||
dma_as->root, 0, memory_region_size(dma_as->root));
|
||||
memory_region_set_enabled(&pci_dev->bus_master_enable_region, false);
|
||||
address_space_init(&pci_dev->bus_master_as, &pci_dev->bus_master_enable_region,
|
||||
name);
|
||||
|
||||
if (qdev_hotplug) {
|
||||
pci_init_bus_master(pci_dev);
|
||||
}
|
||||
pstrcpy(pci_dev->name, sizeof(pci_dev->name), name);
|
||||
pci_dev->irq_state = 0;
|
||||
pci_config_alloc(pci_dev);
|
||||
@@ -1051,7 +1074,7 @@ void pci_register_bar(PCIDevice *pci_dev, int region_num,
|
||||
uint8_t type, MemoryRegion *memory)
|
||||
{
|
||||
PCIIORegion *r;
|
||||
uint32_t addr;
|
||||
uint32_t addr; /* offset in pci config space */
|
||||
uint64_t wmask;
|
||||
pcibus_t size = memory_region_size(memory);
|
||||
|
||||
@@ -1067,15 +1090,20 @@ void pci_register_bar(PCIDevice *pci_dev, int region_num,
|
||||
r->addr = PCI_BAR_UNMAPPED;
|
||||
r->size = size;
|
||||
r->type = type;
|
||||
r->memory = NULL;
|
||||
r->memory = memory;
|
||||
r->address_space = type & PCI_BASE_ADDRESS_SPACE_IO
|
||||
? pci_dev->bus->address_space_io
|
||||
: pci_dev->bus->address_space_mem;
|
||||
|
||||
wmask = ~(size - 1);
|
||||
addr = pci_bar(pci_dev, region_num);
|
||||
if (region_num == PCI_ROM_SLOT) {
|
||||
/* ROM enable bit is writable */
|
||||
wmask |= PCI_ROM_ADDRESS_ENABLE;
|
||||
}
|
||||
|
||||
addr = pci_bar(pci_dev, region_num);
|
||||
pci_set_long(pci_dev->config + addr, type);
|
||||
|
||||
if (!(r->type & PCI_BASE_ADDRESS_SPACE_IO) &&
|
||||
r->type & PCI_BASE_ADDRESS_MEM_TYPE_64) {
|
||||
pci_set_quad(pci_dev->wmask + addr, wmask);
|
||||
@@ -1084,11 +1112,6 @@ void pci_register_bar(PCIDevice *pci_dev, int region_num,
|
||||
pci_set_long(pci_dev->wmask + addr, wmask & 0xffffffff);
|
||||
pci_set_long(pci_dev->cmask + addr, 0xffffffff);
|
||||
}
|
||||
pci_dev->io_regions[region_num].memory = memory;
|
||||
pci_dev->io_regions[region_num].address_space
|
||||
= type & PCI_BASE_ADDRESS_SPACE_IO
|
||||
? pci_dev->bus->address_space_io
|
||||
: pci_dev->bus->address_space_mem;
|
||||
}
|
||||
|
||||
static void pci_update_vga(PCIDevice *pci_dev)
|
||||
@@ -2510,13 +2533,13 @@ static void pci_dev_get_w64(PCIBus *b, PCIDevice *dev, void *opaque)
|
||||
|
||||
if (limit >= base) {
|
||||
Range pref_range;
|
||||
pref_range.begin = base;
|
||||
pref_range.end = limit + 1;
|
||||
range_set_bounds(&pref_range, base, limit);
|
||||
range_extend(range, &pref_range);
|
||||
}
|
||||
}
|
||||
for (i = 0; i < PCI_NUM_REGIONS; ++i) {
|
||||
PCIIORegion *r = &dev->io_regions[i];
|
||||
pcibus_t lob, upb;
|
||||
Range region_range;
|
||||
|
||||
if (!r->size ||
|
||||
@@ -2524,16 +2547,17 @@ static void pci_dev_get_w64(PCIBus *b, PCIDevice *dev, void *opaque)
|
||||
!(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) {
|
||||
lob = pci_bar_address(dev, i, r->type, r->size);
|
||||
upb = lob + r->size - 1;
|
||||
if (lob == PCI_BAR_UNMAPPED) {
|
||||
continue;
|
||||
}
|
||||
|
||||
region_range.begin = MAX(region_range.begin, 0x1ULL << 32);
|
||||
lob = MAX(lob, 0x1ULL << 32);
|
||||
|
||||
if (region_range.end - 1 >= region_range.begin) {
|
||||
if (upb >= lob) {
|
||||
range_set_bounds(®ion_range, lob, upb);
|
||||
range_extend(range, ®ion_range);
|
||||
}
|
||||
}
|
||||
@@ -2541,7 +2565,7 @@ static void pci_dev_get_w64(PCIBus *b, PCIDevice *dev, void *opaque)
|
||||
|
||||
void pci_bus_get_w64_range(PCIBus *bus, Range *range)
|
||||
{
|
||||
range->begin = range->end = 0;
|
||||
range_make_empty(range);
|
||||
pci_for_each_device_under_bus(bus, pci_dev_get_w64, range);
|
||||
}
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user