70 changes: 0 additions & 70 deletions docs/specs/pci-ids.txt

This file was deleted.

37 changes: 37 additions & 0 deletions docs/specs/pci-serial.rst
@@ -0,0 +1,37 @@
=======================
QEMU PCI serial devices
=======================

QEMU implements some PCI serial devices which are simple PCI
wrappers around one or more 16550 UARTs.

There is one single-port variant and two multiport-variants. Linux
guests work out-of-the box with all cards. There is a Windows inf file
(``docs/qemupciserial.inf``) to set up the cards in Windows guests.


Single-port card
----------------

Name:
``pci-serial``
PCI ID:
1b36:0002
PCI Region 0:
IO bar, 8 bytes long, with the 16550 UART mapped to it.
Interrupt:
Wired to pin A.


Multiport cards
---------------

Name:
``pci-serial-2x``, ``pci-serial-4x``
PCI ID:
1b36:0003 (``-2x``) and 1b36:0004 (``-4x``)
PCI Region 0:
IO bar, with two or four 16550 UARTs mapped after each other.
The first is at offset 0, the second at offset 8, and so on.
Interrupt:
Wired to pin A.
34 changes: 0 additions & 34 deletions docs/specs/pci-serial.txt

This file was deleted.

39 changes: 39 additions & 0 deletions docs/specs/pci-testdev.rst
@@ -0,0 +1,39 @@
====================
QEMU PCI test device
====================

``pci-testdev`` is a device used for testing low level IO.

The device implements up to three BARs: BAR0, BAR1 and BAR2.
Each of BAR 0+1 can be memory or IO. Guests must detect
BAR types and act accordingly.

BAR 0+1 size is up to 4K bytes each.
BAR 0+1 starts with the following header:

.. code-block:: c
typedef struct PCITestDevHdr {
uint8_t test; /* write-only, starts a given test number */
uint8_t width_type; /*
* read-only, type and width of access for a given test.
* 1,2,4 for byte,word or long write.
* any other value if test not supported on this BAR
*/
uint8_t pad0[2];
uint32_t offset; /* read-only, offset in this BAR for a given test */
uint32_t data; /* read-only, data to use for a given test */
uint32_t count; /* for debugging. number of writes detected. */
uint8_t name[]; /* for debugging. 0-terminated ASCII string. */
} PCITestDevHdr;
All registers are little endian.

The device is expected to always implement tests 0 to N on each BAR, and to add new
tests with higher numbers. In this way a guest can scan test numbers until it
detects an access type that it does not support on this BAR, then stop.

BAR2 is a 64bit memory BAR, without backing storage. It is disabled
by default and can be enabled using the ``membar=<size>`` property. This
can be used to test whether guests handle PCI BARs of a specific
(possibly quite large) size correctly.
31 changes: 0 additions & 31 deletions docs/specs/pci-testdev.txt

This file was deleted.

11 changes: 6 additions & 5 deletions hw/acpi/cxl.c
Expand Up @@ -30,9 +30,10 @@
#include "qapi/error.h"
#include "qemu/uuid.h"

static void cedt_build_chbs(GArray *table_data, PXBDev *cxl)
static void cedt_build_chbs(GArray *table_data, PXBCXLDev *cxl)
{
SysBusDevice *sbd = SYS_BUS_DEVICE(cxl->cxl.cxl_host_bridge);
PXBDev *pxb = PXB_DEV(cxl);
SysBusDevice *sbd = SYS_BUS_DEVICE(cxl->cxl_host_bridge);
struct MemoryRegion *mr = sbd->mmio[0].memory;

/* Type */
Expand All @@ -45,7 +46,7 @@ static void cedt_build_chbs(GArray *table_data, PXBDev *cxl)
build_append_int_noprefix(table_data, 32, 2);

/* UID - currently equal to bus number */
build_append_int_noprefix(table_data, cxl->bus_nr, 4);
build_append_int_noprefix(table_data, pxb->bus_nr, 4);

/* Version */
build_append_int_noprefix(table_data, 1, 4);
Expand Down Expand Up @@ -112,7 +113,7 @@ static void cedt_build_cfmws(GArray *table_data, CXLState *cxls)
/* Host Bridge List (list of UIDs - currently bus_nr) */
for (i = 0; i < fw->num_targets; i++) {
g_assert(fw->target_hbs[i]);
build_append_int_noprefix(table_data, fw->target_hbs[i]->bus_nr, 4);
build_append_int_noprefix(table_data, PXB_DEV(fw->target_hbs[i])->bus_nr, 4);
}
}
}
Expand All @@ -121,7 +122,7 @@ static int cxl_foreach_pxb_hb(Object *obj, void *opaque)
{
Aml *cedt = opaque;

if (object_dynamic_cast(obj, TYPE_PXB_CXL_DEVICE)) {
if (object_dynamic_cast(obj, TYPE_PXB_CXL_DEV)) {
cedt_build_chbs(cedt->buf, PXB_CXL_DEV(obj));
}

Expand Down
10 changes: 10 additions & 0 deletions hw/acpi/pcihp.c
Expand Up @@ -357,6 +357,16 @@ void acpi_pcihp_device_unplug_request_cb(HotplugHandler *hotplug_dev,
* acpi_pcihp_eject_slot() when the operation is completed.
*/
pdev->qdev.pending_deleted_event = true;
/* if unplug was requested before OSPM is initialized,
* linux kernel will clear GPE0.sts[] bits during boot, which effectively
* hides unplug event. And than followup qmp_device_del() calls remain
* blocked by above flag permanently.
* Unblock qmp_device_del() by setting expire limit, so user can
* repeat unplug request later when OSPM has been booted.
*/
pdev->qdev.pending_deleted_expires_ms =
qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL); /* 1 msec */

s->acpi_pcihp_pci_status[bsel].down |= (1U << slot);
acpi_send_event(DEVICE(hotplug_dev), ACPI_PCI_HOTPLUG_STATUS);
}
Expand Down
2 changes: 1 addition & 1 deletion hw/char/serial-pci-multi.c
Expand Up @@ -25,7 +25,7 @@
* THE SOFTWARE.
*/

/* see docs/specs/pci-serial.txt */
/* see docs/specs/pci-serial.rst */

#include "qemu/osdep.h"
#include "qapi/error.h"
Expand Down
2 changes: 1 addition & 1 deletion hw/char/serial-pci.c
Expand Up @@ -23,7 +23,7 @@
* THE SOFTWARE.
*/

/* see docs/specs/pci-serial.txt */
/* see docs/specs/pci-serial.rst */

#include "qemu/osdep.h"
#include "qapi/error.h"
Expand Down
4 changes: 2 additions & 2 deletions hw/cxl/cxl-host.c
Expand Up @@ -84,7 +84,7 @@ void cxl_fmws_link_targets(CXLState *cxl_state, Error **errp)
bool ambig;

o = object_resolve_path_type(fw->targets[i],
TYPE_PXB_CXL_DEVICE,
TYPE_PXB_CXL_DEV,
&ambig);
if (!o) {
error_setg(errp, "Could not resolve CXLFM target %s",
Expand Down Expand Up @@ -141,7 +141,7 @@ static PCIDevice *cxl_cfmws_find_device(CXLFixedWindow *fw, hwaddr addr)
addr += fw->base;

rb_index = (addr / cxl_decode_ig(fw->enc_int_gran)) % fw->num_targets;
hb = PCI_HOST_BRIDGE(fw->target_hbs[rb_index]->cxl.cxl_host_bridge);
hb = PCI_HOST_BRIDGE(fw->target_hbs[rb_index]->cxl_host_bridge);
if (!hb || !hb->bus || !pci_bus_is_cxl(hb->bus)) {
return NULL;
}
Expand Down
12 changes: 8 additions & 4 deletions hw/i386/acpi-build.c
Expand Up @@ -2395,9 +2395,11 @@ build_amd_iommu(GArray *table_data, BIOSLinker *linker, const char *oem_id,
/* IVHD length */
build_append_int_noprefix(table_data, ivhd_table_len, 2);
/* DeviceID */
build_append_int_noprefix(table_data, s->devid, 2);
build_append_int_noprefix(table_data,
object_property_get_int(OBJECT(&s->pci), "addr",
&error_abort), 2);
/* Capability offset */
build_append_int_noprefix(table_data, s->capab_offset, 2);
build_append_int_noprefix(table_data, s->pci.capab_offset, 2);
/* IOMMU base address */
build_append_int_noprefix(table_data, s->mmio.addr, 8);
/* PCI Segment Group */
Expand Down Expand Up @@ -2695,7 +2697,8 @@ void acpi_build(AcpiBuildTables *tables, MachineState *machine)
int legacy_table_size =
ROUND_UP(tables_blob->len - aml_len + legacy_aml_len,
ACPI_BUILD_ALIGN_SIZE);
if (tables_blob->len > legacy_table_size) {
if ((tables_blob->len > legacy_table_size) &&
!pcmc->resizable_acpi_blob) {
/* Should happen only with PCI bridges and -M pc-i440fx-2.0. */
warn_report("ACPI table size %u exceeds %d bytes,"
" migration may not work",
Expand All @@ -2706,7 +2709,8 @@ void acpi_build(AcpiBuildTables *tables, MachineState *machine)
g_array_set_size(tables_blob, legacy_table_size);
} else {
/* Make sure we have a buffer in case we need to resize the tables. */
if (tables_blob->len > ACPI_BUILD_TABLE_SIZE / 2) {
if ((tables_blob->len > ACPI_BUILD_TABLE_SIZE / 2) &&
!pcmc->resizable_acpi_blob) {
/* As of QEMU 2.1, this fires with 160 VCPUs and 255 memory slots. */
warn_report("ACPI table size %u exceeds %d bytes,"
" migration may not work",
Expand Down
74 changes: 42 additions & 32 deletions hw/i386/amd_iommu.c
Expand Up @@ -1509,23 +1509,48 @@ static void amdvi_init(AMDVIState *s)
amdvi_set_quad(s, AMDVI_MMIO_EXT_FEATURES, AMDVI_EXT_FEATURES,
0xffffffffffffffef, 0);
amdvi_set_quad(s, AMDVI_MMIO_STATUS, 0, 0x98, 0x67);
}

static void amdvi_pci_realize(PCIDevice *pdev, Error **errp)
{
AMDVIPCIState *s = AMD_IOMMU_PCI(pdev);
int ret;

ret = pci_add_capability(pdev, AMDVI_CAPAB_ID_SEC, 0,
AMDVI_CAPAB_SIZE, errp);
if (ret < 0) {
return;
}
s->capab_offset = ret;

ret = pci_add_capability(pdev, PCI_CAP_ID_MSI, 0,
AMDVI_CAPAB_REG_SIZE, errp);
if (ret < 0) {
return;
}
ret = pci_add_capability(pdev, PCI_CAP_ID_HT, 0,
AMDVI_CAPAB_REG_SIZE, errp);
if (ret < 0) {
return;
}

if (msi_init(pdev, 0, 1, true, false, errp) < 0) {
return;
}

/* reset device ident */
pci_config_set_vendor_id(s->pci.dev.config, PCI_VENDOR_ID_AMD);
pci_config_set_prog_interface(s->pci.dev.config, 00);
pci_config_set_device_id(s->pci.dev.config, s->devid);
pci_config_set_class(s->pci.dev.config, 0x0806);
pci_config_set_prog_interface(pdev->config, 0);

/* reset AMDVI specific capabilities, all r/o */
pci_set_long(s->pci.dev.config + s->capab_offset, AMDVI_CAPAB_FEATURES);
pci_set_long(s->pci.dev.config + s->capab_offset + AMDVI_CAPAB_BAR_LOW,
s->mmio.addr & ~(0xffff0000));
pci_set_long(s->pci.dev.config + s->capab_offset + AMDVI_CAPAB_BAR_HIGH,
(s->mmio.addr & ~(0xffff)) >> 16);
pci_set_long(s->pci.dev.config + s->capab_offset + AMDVI_CAPAB_RANGE,
pci_set_long(pdev->config + s->capab_offset, AMDVI_CAPAB_FEATURES);
pci_set_long(pdev->config + s->capab_offset + AMDVI_CAPAB_BAR_LOW,
AMDVI_BASE_ADDR & ~(0xffff0000));
pci_set_long(pdev->config + s->capab_offset + AMDVI_CAPAB_BAR_HIGH,
(AMDVI_BASE_ADDR & ~(0xffff)) >> 16);
pci_set_long(pdev->config + s->capab_offset + AMDVI_CAPAB_RANGE,
0xff000000);
pci_set_long(s->pci.dev.config + s->capab_offset + AMDVI_CAPAB_MISC, 0);
pci_set_long(s->pci.dev.config + s->capab_offset + AMDVI_CAPAB_MISC,
pci_set_long(pdev->config + s->capab_offset + AMDVI_CAPAB_MISC, 0);
pci_set_long(pdev->config + s->capab_offset + AMDVI_CAPAB_MISC,
AMDVI_MAX_PH_ADDR | AMDVI_MAX_GVA_ADDR | AMDVI_MAX_VA_ADDR);
}

Expand All @@ -1539,7 +1564,6 @@ static void amdvi_sysbus_reset(DeviceState *dev)

static void amdvi_sysbus_realize(DeviceState *dev, Error **errp)
{
int ret = 0;
AMDVIState *s = AMD_IOMMU_DEVICE(dev);
MachineState *ms = MACHINE(qdev_get_machine());
PCMachineState *pcms = PC_MACHINE(ms);
Expand All @@ -1553,23 +1577,6 @@ static void amdvi_sysbus_realize(DeviceState *dev, Error **errp)
if (!qdev_realize(DEVICE(&s->pci), &bus->qbus, errp)) {
return;
}
ret = pci_add_capability(&s->pci.dev, AMDVI_CAPAB_ID_SEC, 0,
AMDVI_CAPAB_SIZE, errp);
if (ret < 0) {
return;
}
s->capab_offset = ret;

ret = pci_add_capability(&s->pci.dev, PCI_CAP_ID_MSI, 0,
AMDVI_CAPAB_REG_SIZE, errp);
if (ret < 0) {
return;
}
ret = pci_add_capability(&s->pci.dev, PCI_CAP_ID_HT, 0,
AMDVI_CAPAB_REG_SIZE, errp);
if (ret < 0) {
return;
}

/* Pseudo address space under root PCI bus. */
x86ms->ioapic_as = amdvi_host_dma_iommu(bus, s, AMDVI_IOAPIC_SB_DEVID);
Expand All @@ -1581,8 +1588,6 @@ static void amdvi_sysbus_realize(DeviceState *dev, Error **errp)
sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->mmio);
sysbus_mmio_map(SYS_BUS_DEVICE(s), 0, AMDVI_BASE_ADDR);
pci_setup_iommu(bus, amdvi_host_dma_iommu, s);
s->devid = object_property_get_int(OBJECT(&s->pci), "addr", &error_abort);
msi_init(&s->pci.dev, 0, 1, true, false, errp);
amdvi_init(s);
}

Expand Down Expand Up @@ -1625,6 +1630,11 @@ static const TypeInfo amdvi_sysbus = {
static void amdvi_pci_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);

k->vendor_id = PCI_VENDOR_ID_AMD;
k->class_id = 0x0806;
k->realize = amdvi_pci_realize;

set_bit(DEVICE_CATEGORY_MISC, dc->categories);
dc->desc = "AMD IOMMU (AMD-Vi) DMA Remapping device";
Expand Down
9 changes: 4 additions & 5 deletions hw/i386/amd_iommu.h
Expand Up @@ -300,27 +300,26 @@ struct irte_ga {
OBJECT_DECLARE_SIMPLE_TYPE(AMDVIState, AMD_IOMMU_DEVICE)

#define TYPE_AMD_IOMMU_PCI "AMDVI-PCI"
OBJECT_DECLARE_SIMPLE_TYPE(AMDVIPCIState, AMD_IOMMU_PCI)

#define TYPE_AMD_IOMMU_MEMORY_REGION "amd-iommu-iommu-memory-region"

typedef struct AMDVIAddressSpace AMDVIAddressSpace;

/* functions to steal PCI config space */
typedef struct AMDVIPCIState {
struct AMDVIPCIState {
PCIDevice dev; /* The PCI device itself */
} AMDVIPCIState;
uint32_t capab_offset; /* capability offset pointer */
};

struct AMDVIState {
X86IOMMUState iommu; /* IOMMU bus device */
AMDVIPCIState pci; /* IOMMU PCI device */

uint32_t version;
uint32_t capab_offset; /* capability offset pointer */

uint64_t mmio_addr;

uint32_t devid; /* auto-assigned devid */

bool enabled; /* IOMMU enabled */
bool ats_enabled; /* address translation enabled */
bool cmdbuf_enabled; /* command buffer enabled */
Expand Down
9 changes: 5 additions & 4 deletions hw/i386/intel_iommu.c
Expand Up @@ -64,8 +64,8 @@ struct vtd_as_key {
struct vtd_iotlb_key {
uint64_t gfn;
uint32_t pasid;
uint32_t level;
uint16_t sid;
uint8_t level;
};

static void vtd_address_space_refresh_all(IntelIOMMUState *s);
Expand Down Expand Up @@ -221,10 +221,11 @@ static gboolean vtd_iotlb_equal(gconstpointer v1, gconstpointer v2)
static guint vtd_iotlb_hash(gconstpointer v)
{
const struct vtd_iotlb_key *key = v;
uint64_t hash64 = key->gfn | ((uint64_t)(key->sid) << VTD_IOTLB_SID_SHIFT) |
(uint64_t)(key->level - 1) << VTD_IOTLB_LVL_SHIFT |
(uint64_t)(key->pasid) << VTD_IOTLB_PASID_SHIFT;

return key->gfn | ((key->sid) << VTD_IOTLB_SID_SHIFT) |
(key->level) << VTD_IOTLB_LVL_SHIFT |
(key->pasid) << VTD_IOTLB_PASID_SHIFT;
return (guint)((hash64 >> 32) ^ (hash64 & 0xffffffffU));
}

static gboolean vtd_as_equal(gconstpointer v1, gconstpointer v2)
Expand Down
6 changes: 3 additions & 3 deletions hw/i386/intel_iommu_internal.h
Expand Up @@ -114,9 +114,9 @@
VTD_INTERRUPT_ADDR_FIRST + 1)

/* The shift of source_id in the key of IOTLB hash table */
#define VTD_IOTLB_SID_SHIFT 20
#define VTD_IOTLB_LVL_SHIFT 28
#define VTD_IOTLB_PASID_SHIFT 30
#define VTD_IOTLB_SID_SHIFT 26
#define VTD_IOTLB_LVL_SHIFT 42
#define VTD_IOTLB_PASID_SHIFT 44
#define VTD_IOTLB_MAX_SIZE 1024 /* Max size of the hash table */

/* IOTLB_REG */
Expand Down
1 change: 1 addition & 0 deletions hw/i386/pc.c
Expand Up @@ -1946,6 +1946,7 @@ static void pc_machine_class_init(ObjectClass *oc, void *data)
pcmc->acpi_data_size = 0x20000 + 0x8000;
pcmc->pvh_enabled = true;
pcmc->kvmclock_create_always = true;
pcmc->resizable_acpi_blob = true;
assert(!mc->get_hotplug_handler);
mc->get_hotplug_handler = pc_get_hotplug_handler;
mc->hotplug_allowed = pc_hotplug_allowed;
Expand Down
1 change: 1 addition & 0 deletions hw/i386/pc_piix.c
Expand Up @@ -756,6 +756,7 @@ static void pc_i440fx_2_2_machine_options(MachineClass *m)
compat_props_add(m->compat_props, hw_compat_2_2, hw_compat_2_2_len);
compat_props_add(m->compat_props, pc_compat_2_2, pc_compat_2_2_len);
pcmc->rsdp_in_ram = false;
pcmc->resizable_acpi_blob = false;
}

DEFINE_I440FX_MACHINE(v2_2, "pc-i440fx-2.2", pc_compat_2_2_fn,
Expand Down
7 changes: 7 additions & 0 deletions hw/mem/pc-dimm.c
Expand Up @@ -81,6 +81,10 @@ void pc_dimm_plug(PCDIMMDevice *dimm, MachineState *machine)

memory_device_plug(MEMORY_DEVICE(dimm), machine);
vmstate_register_ram(vmstate_mr, DEVICE(dimm));
/* count only "real" DIMMs, not NVDIMMs */
if (!object_dynamic_cast(OBJECT(dimm), TYPE_NVDIMM)) {
machine->device_memory->dimm_size += memory_region_size(vmstate_mr);
}
}

void pc_dimm_unplug(PCDIMMDevice *dimm, MachineState *machine)
Expand All @@ -90,6 +94,9 @@ void pc_dimm_unplug(PCDIMMDevice *dimm, MachineState *machine)

memory_device_unplug(MEMORY_DEVICE(dimm), machine);
vmstate_unregister_ram(vmstate_mr, DEVICE(dimm));
if (!object_dynamic_cast(OBJECT(dimm), TYPE_NVDIMM)) {
machine->device_memory->dimm_size -= memory_region_size(vmstate_mr);
}
}

static int pc_dimm_slot2bitmap(Object *obj, void *opaque)
Expand Down
61 changes: 20 additions & 41 deletions hw/pci-bridge/pci_expander_bridge.c
Expand Up @@ -50,24 +50,8 @@ struct PXBBus {
char bus_path[8];
};

#define TYPE_PXB_DEVICE "pxb"
DECLARE_INSTANCE_CHECKER(PXBDev, PXB_DEV,
TYPE_PXB_DEVICE)

#define TYPE_PXB_PCIE_DEVICE "pxb-pcie"
DECLARE_INSTANCE_CHECKER(PXBDev, PXB_PCIE_DEV,
TYPE_PXB_PCIE_DEVICE)

static PXBDev *convert_to_pxb(PCIDevice *dev)
{
/* A CXL PXB's parent bus is PCIe, so the normal check won't work */
if (object_dynamic_cast(OBJECT(dev), TYPE_PXB_CXL_DEVICE)) {
return PXB_CXL_DEV(dev);
}

return pci_bus_is_express(pci_get_bus(dev))
? PXB_PCIE_DEV(dev) : PXB_DEV(dev);
}
#define TYPE_PXB_PCIE_DEV "pxb-pcie"
OBJECT_DECLARE_SIMPLE_TYPE(PXBPCIEDev, PXB_PCIE_DEV)

static GList *pxb_dev_list;

Expand All @@ -89,14 +73,14 @@ bool cxl_get_hb_passthrough(PCIHostState *hb)

static int pxb_bus_num(PCIBus *bus)
{
PXBDev *pxb = convert_to_pxb(bus->parent_dev);
PXBDev *pxb = PXB_DEV(bus->parent_dev);

return pxb->bus_nr;
}

static uint16_t pxb_bus_numa_node(PCIBus *bus)
{
PXBDev *pxb = convert_to_pxb(bus->parent_dev);
PXBDev *pxb = PXB_DEV(bus->parent_dev);

return pxb->numa_node;
}
Expand Down Expand Up @@ -154,7 +138,7 @@ static char *pxb_host_ofw_unit_address(const SysBusDevice *dev)

pxb_host = PCI_HOST_BRIDGE(dev);
pxb_bus = pxb_host->bus;
pxb_dev = convert_to_pxb(pxb_bus->parent_dev);
pxb_dev = PXB_DEV(pxb_bus->parent_dev);
position = g_list_index(pxb_dev_list, pxb_dev);
assert(position >= 0);

Expand Down Expand Up @@ -212,8 +196,8 @@ static void pxb_cxl_realize(DeviceState *dev, Error **errp)
*/
void pxb_cxl_hook_up_registers(CXLState *cxl_state, PCIBus *bus, Error **errp)
{
PXBDev *pxb = PXB_CXL_DEV(pci_bridge_get_device(bus));
CXLHost *cxl = pxb->cxl.cxl_host_bridge;
PXBCXLDev *pxb = PXB_CXL_DEV(pci_bridge_get_device(bus));
CXLHost *cxl = pxb->cxl_host_bridge;
CXLComponentState *cxl_cstate = &cxl->cxl_cstate;
struct MemoryRegion *mr = &cxl_cstate->crb.component_registers;
hwaddr offset;
Expand Down Expand Up @@ -299,7 +283,7 @@ static int pxb_map_irq_fn(PCIDevice *pci_dev, int pin)

static void pxb_cxl_dev_reset(DeviceState *dev)
{
CXLHost *cxl = PXB_CXL_DEV(dev)->cxl.cxl_host_bridge;
CXLHost *cxl = PXB_CXL_DEV(dev)->cxl_host_bridge;
CXLComponentState *cxl_cstate = &cxl->cxl_cstate;
PCIHostState *hb = PCI_HOST_BRIDGE(cxl);
uint32_t *reg_state = cxl_cstate->crb.cache_mem_registers;
Expand All @@ -311,7 +295,7 @@ static void pxb_cxl_dev_reset(DeviceState *dev)
* The CXL specification allows for host bridges with no HDM decoders
* if they only have a single root port.
*/
if (!PXB_DEV(dev)->hdm_for_passthrough) {
if (!PXB_CXL_DEV(dev)->hdm_for_passthrough) {
dsp_count = pcie_count_ds_ports(hb->bus);
}
/* Initial reset will have 0 dsp so wait until > 0 */
Expand All @@ -337,7 +321,7 @@ static gint pxb_compare(gconstpointer a, gconstpointer b)
static void pxb_dev_realize_common(PCIDevice *dev, enum BusType type,
Error **errp)
{
PXBDev *pxb = convert_to_pxb(dev);
PXBDev *pxb = PXB_DEV(dev);
DeviceState *ds, *bds = NULL;
PCIBus *bus;
const char *dev_name = NULL;
Expand Down Expand Up @@ -365,7 +349,7 @@ static void pxb_dev_realize_common(PCIDevice *dev, enum BusType type,
} else if (type == CXL) {
bus = pci_root_bus_new(ds, dev_name, NULL, NULL, 0, TYPE_PXB_CXL_BUS);
bus->flags |= PCI_BUS_CXL;
PXB_CXL_DEV(dev)->cxl.cxl_host_bridge = PXB_CXL_HOST(ds);
PXB_CXL_DEV(dev)->cxl_host_bridge = PXB_CXL_HOST(ds);
} else {
bus = pci_root_bus_new(ds, "pxb-internal", NULL, NULL, 0, TYPE_PXB_BUS);
bds = qdev_new("pci-bridge");
Expand Down Expand Up @@ -418,7 +402,7 @@ static void pxb_dev_realize(PCIDevice *dev, Error **errp)

static void pxb_dev_exitfn(PCIDevice *pci_dev)
{
PXBDev *pxb = convert_to_pxb(pci_dev);
PXBDev *pxb = PXB_DEV(pci_dev);

pxb_dev_list = g_list_remove(pxb_dev_list, pxb);
}
Expand Down Expand Up @@ -449,7 +433,7 @@ static void pxb_dev_class_init(ObjectClass *klass, void *data)
}

static const TypeInfo pxb_dev_info = {
.name = TYPE_PXB_DEVICE,
.name = TYPE_PXB_DEV,
.parent = TYPE_PCI_DEVICE,
.instance_size = sizeof(PXBDev),
.class_init = pxb_dev_class_init,
Expand Down Expand Up @@ -481,15 +465,14 @@ static void pxb_pcie_dev_class_init(ObjectClass *klass, void *data)
k->class_id = PCI_CLASS_BRIDGE_HOST;

dc->desc = "PCI Express Expander Bridge";
device_class_set_props(dc, pxb_dev_properties);
dc->hotpluggable = false;
set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
}

static const TypeInfo pxb_pcie_dev_info = {
.name = TYPE_PXB_PCIE_DEVICE,
.parent = TYPE_PCI_DEVICE,
.instance_size = sizeof(PXBDev),
.name = TYPE_PXB_PCIE_DEV,
.parent = TYPE_PXB_DEV,
.instance_size = sizeof(PXBPCIEDev),
.class_init = pxb_pcie_dev_class_init,
.interfaces = (InterfaceInfo[]) {
{ INTERFACE_CONVENTIONAL_PCI_DEVICE },
Expand All @@ -510,11 +493,7 @@ static void pxb_cxl_dev_realize(PCIDevice *dev, Error **errp)
}

static Property pxb_cxl_dev_properties[] = {
/* Note: 0 is not a legal PXB bus number. */
DEFINE_PROP_UINT8("bus_nr", PXBDev, bus_nr, 0),
DEFINE_PROP_UINT16("numa_node", PXBDev, numa_node, NUMA_NODE_UNASSIGNED),
DEFINE_PROP_BOOL("bypass_iommu", PXBDev, bypass_iommu, false),
DEFINE_PROP_BOOL("hdm_for_passthrough", PXBDev, hdm_for_passthrough, false),
DEFINE_PROP_BOOL("hdm_for_passthrough", PXBCXLDev, hdm_for_passthrough, false),
DEFINE_PROP_END_OF_LIST(),
};

Expand All @@ -540,9 +519,9 @@ static void pxb_cxl_dev_class_init(ObjectClass *klass, void *data)
}

static const TypeInfo pxb_cxl_dev_info = {
.name = TYPE_PXB_CXL_DEVICE,
.parent = TYPE_PCI_DEVICE,
.instance_size = sizeof(PXBDev),
.name = TYPE_PXB_CXL_DEV,
.parent = TYPE_PXB_PCIE_DEV,
.instance_size = sizeof(PXBCXLDev),
.class_init = pxb_cxl_dev_class_init,
.interfaces =
(InterfaceInfo[]){
Expand Down
15 changes: 15 additions & 0 deletions hw/pci/pci.c
Expand Up @@ -1116,6 +1116,21 @@ static bool pci_bus_devfn_reserved(PCIBus *bus, int devfn)
return bus->slot_reserved_mask & (1UL << PCI_SLOT(devfn));
}

uint32_t pci_bus_get_slot_reserved_mask(PCIBus *bus)
{
return bus->slot_reserved_mask;
}

void pci_bus_set_slot_reserved_mask(PCIBus *bus, uint32_t mask)
{
bus->slot_reserved_mask |= mask;
}

void pci_bus_clear_slot_reserved_mask(PCIBus *bus, uint32_t mask)
{
bus->slot_reserved_mask &= ~mask;
}

/* -1 for devfn means auto assign */
static PCIDevice *do_pci_register_device(PCIDevice *pci_dev,
const char *name, int devfn,
Expand Down
1 change: 1 addition & 0 deletions hw/s390x/virtio-ccw.c
Expand Up @@ -237,6 +237,7 @@ static int virtio_ccw_set_vqs(SubchDev *sch, VqInfoBlock *info,
return -EINVAL;
}
virtio_queue_set_num(vdev, index, num);
virtio_init_region_cache(vdev, index);
} else if (virtio_queue_get_num(vdev, index) > num) {
/* Fail if we don't have a big enough queue. */
return -EINVAL;
Expand Down
7 changes: 3 additions & 4 deletions hw/sparc64/sun4u.c
Expand Up @@ -31,7 +31,6 @@
#include "hw/irq.h"
#include "hw/pci/pci.h"
#include "hw/pci/pci_bridge.h"
#include "hw/pci/pci_bus.h"
#include "hw/pci/pci_host.h"
#include "hw/qdev-properties.h"
#include "hw/pci-host/sabre.h"
Expand Down Expand Up @@ -608,9 +607,9 @@ static void sun4uv_init(MemoryRegion *address_space_mem,
/* Only in-built Simba APBs can exist on the root bus, slot 0 on busA is
reserved (leaving no slots free after on-board devices) however slots
0-3 are free on busB */
pci_bus->slot_reserved_mask = 0xfffffffc;
pci_busA->slot_reserved_mask = 0xfffffff1;
pci_busB->slot_reserved_mask = 0xfffffff0;
pci_bus_set_slot_reserved_mask(pci_bus, 0xfffffffc);
pci_bus_set_slot_reserved_mask(pci_busA, 0xfffffff1);
pci_bus_set_slot_reserved_mask(pci_busB, 0xfffffff0);

ebus = pci_new_multifunction(PCI_DEVFN(1, 0), true, TYPE_EBUS);
qdev_prop_set_uint64(DEVICE(ebus), "console-serial-base",
Expand Down
16 changes: 16 additions & 0 deletions hw/virtio/vhost-user-i2c.c
Expand Up @@ -128,13 +128,29 @@ static void vu_i2c_guest_notifier_mask(VirtIODevice *vdev, int idx, bool mask)
{
VHostUserI2C *i2c = VHOST_USER_I2C(vdev);

/*
* We don't support interrupts, return early if index is set to
* VIRTIO_CONFIG_IRQ_IDX.
*/
if (idx == VIRTIO_CONFIG_IRQ_IDX) {
return;
}

vhost_virtqueue_mask(&i2c->vhost_dev, vdev, idx, mask);
}

static bool vu_i2c_guest_notifier_pending(VirtIODevice *vdev, int idx)
{
VHostUserI2C *i2c = VHOST_USER_I2C(vdev);

/*
* We don't support interrupts, return early if index is set to
* VIRTIO_CONFIG_IRQ_IDX.
*/
if (idx == VIRTIO_CONFIG_IRQ_IDX) {
return false;
}

return vhost_virtqueue_pending(&i2c->vhost_dev, idx);
}

Expand Down
14 changes: 0 additions & 14 deletions hw/virtio/vhost.c
Expand Up @@ -1291,18 +1291,6 @@ void vhost_virtqueue_stop(struct vhost_dev *dev,
0, virtio_queue_get_desc_size(vdev, idx));
}

static void vhost_eventfd_add(MemoryListener *listener,
MemoryRegionSection *section,
bool match_data, uint64_t data, EventNotifier *e)
{
}

static void vhost_eventfd_del(MemoryListener *listener,
MemoryRegionSection *section,
bool match_data, uint64_t data, EventNotifier *e)
{
}

static int vhost_virtqueue_set_busyloop_timeout(struct vhost_dev *dev,
int n, uint32_t timeout)
{
Expand Down Expand Up @@ -1457,8 +1445,6 @@ int vhost_dev_init(struct vhost_dev *hdev, void *opaque,
.log_sync = vhost_log_sync,
.log_global_start = vhost_log_global_start,
.log_global_stop = vhost_log_global_stop,
.eventfd_add = vhost_eventfd_add,
.eventfd_del = vhost_eventfd_del,
.priority = 10
};

Expand Down
33 changes: 5 additions & 28 deletions hw/virtio/virtio-balloon.c
Expand Up @@ -730,37 +730,14 @@ static void virtio_balloon_get_config(VirtIODevice *vdev, uint8_t *config_data)
memcpy(config_data, &config, virtio_balloon_config_size(dev));
}

static int build_dimm_list(Object *obj, void *opaque)
{
GSList **list = opaque;

if (object_dynamic_cast(obj, TYPE_PC_DIMM)) {
DeviceState *dev = DEVICE(obj);
if (dev->realized) { /* only realized DIMMs matter */
*list = g_slist_prepend(*list, dev);
}
}

object_child_foreach(obj, build_dimm_list, opaque);
return 0;
}

static ram_addr_t get_current_ram_size(void)
{
GSList *list = NULL, *item;
ram_addr_t size = current_machine->ram_size;

build_dimm_list(qdev_get_machine(), &list);
for (item = list; item; item = g_slist_next(item)) {
Object *obj = OBJECT(item->data);
if (!strcmp(object_get_typename(obj), TYPE_PC_DIMM)) {
size += object_property_get_int(obj, PC_DIMM_SIZE_PROP,
&error_abort);
}
MachineState *machine = MACHINE(qdev_get_machine());
if (machine->device_memory) {
return machine->ram_size + machine->device_memory->dimm_size;
} else {
return machine->ram_size;
}
g_slist_free(list);

return size;
}

static bool virtio_balloon_page_poison_support(void *opaque)
Expand Down
1 change: 1 addition & 0 deletions hw/virtio/virtio-mmio.c
Expand Up @@ -354,6 +354,7 @@ static void virtio_mmio_write(void *opaque, hwaddr offset, uint64_t value,
if (proxy->legacy) {
virtio_queue_update_rings(vdev, vdev->queue_sel);
} else {
virtio_init_region_cache(vdev, vdev->queue_sel);
proxy->vqs[vdev->queue_sel].num = value;
}
break;
Expand Down
1 change: 1 addition & 0 deletions hw/virtio/virtio-pci.c
Expand Up @@ -1554,6 +1554,7 @@ static void virtio_pci_common_write(void *opaque, hwaddr addr,
proxy->vqs[vdev->queue_sel].num = val;
virtio_queue_set_num(vdev, vdev->queue_sel,
proxy->vqs[vdev->queue_sel].num);
virtio_init_region_cache(vdev, vdev->queue_sel);
break;
case VIRTIO_PCI_COMMON_Q_MSIX:
vector = virtio_queue_vector(vdev, vdev->queue_sel);
Expand Down
2 changes: 1 addition & 1 deletion hw/virtio/virtio.c
Expand Up @@ -226,7 +226,7 @@ static void virtio_virtqueue_reset_region_cache(struct VirtQueue *vq)
}
}

static void virtio_init_region_cache(VirtIODevice *vdev, int n)
void virtio_init_region_cache(VirtIODevice *vdev, int n)
{
VirtQueue *vq = &vdev->vq[n];
VRingMemoryRegionCaches *old = vq->vring.caches;
Expand Down
7 changes: 3 additions & 4 deletions hw/xen/xen_pt.c
Expand Up @@ -57,7 +57,6 @@
#include <sys/ioctl.h>

#include "hw/pci/pci.h"
#include "hw/pci/pci_bus.h"
#include "hw/qdev-properties.h"
#include "hw/qdev-properties-system.h"
#include "xen_pt.h"
Expand Down Expand Up @@ -951,7 +950,7 @@ void xen_igd_reserve_slot(PCIBus *pci_bus)
}

XEN_PT_LOG(0, "Reserving PCI slot 2 for IGD\n");
pci_bus->slot_reserved_mask |= XEN_PCI_IGD_SLOT_MASK;
pci_bus_set_slot_reserved_mask(pci_bus, XEN_PCI_IGD_SLOT_MASK);
}

static void xen_igd_clear_slot(DeviceState *qdev, Error **errp)
Expand All @@ -971,7 +970,7 @@ static void xen_igd_clear_slot(DeviceState *qdev, Error **errp)
return;
}

if (!(pci_bus->slot_reserved_mask & XEN_PCI_IGD_SLOT_MASK)) {
if (!(pci_bus_get_slot_reserved_mask(pci_bus) & XEN_PCI_IGD_SLOT_MASK)) {
xpdc->pci_qdev_realize(qdev, errp);
return;
}
Expand All @@ -982,7 +981,7 @@ static void xen_igd_clear_slot(DeviceState *qdev, Error **errp)
s->real_device.dev == XEN_PCI_IGD_DEV &&
s->real_device.func == XEN_PCI_IGD_FN &&
s->real_device.vendor_id == PCI_VENDOR_ID_INTEL) {
pci_bus->slot_reserved_mask &= ~XEN_PCI_IGD_SLOT_MASK;
pci_bus_clear_slot_reserved_mask(pci_bus, XEN_PCI_IGD_SLOT_MASK);
XEN_PT_LOG(pci_dev, "Intel IGD found, using slot 2\n");
}
xpdc->pci_qdev_realize(qdev, errp);
Expand Down
2 changes: 2 additions & 0 deletions include/hw/boards.h
Expand Up @@ -292,10 +292,12 @@ struct MachineClass {
* @base: address in guest physical address space where the memory
* address space for memory devices starts
* @mr: address space container for memory devices
* @dimm_size: the sum of plugged DIMMs' sizes
*/
typedef struct DeviceMemoryState {
hwaddr base;
MemoryRegion mr;
uint64_t dimm_size;
} DeviceMemoryState;

/**
Expand Down
4 changes: 2 additions & 2 deletions include/hw/cxl/cxl.h
Expand Up @@ -23,12 +23,12 @@

#define CXL_WINDOW_MAX 10

typedef struct PXBDev PXBDev;
typedef struct PXBCXLDev PXBCXLDev;

typedef struct CXLFixedWindow {
uint64_t size;
char **targets;
PXBDev *target_hbs[8];
PXBCXLDev *target_hbs[8];
uint8_t num_targets;
uint8_t enc_int_ways;
uint8_t enc_int_gran;
Expand Down
3 changes: 3 additions & 0 deletions include/hw/i386/pc.h
Expand Up @@ -127,6 +127,9 @@ struct PCMachineClass {

/* create kvmclock device even when KVM PV features are not exposed */
bool kvmclock_create_always;

/* resizable acpi blob compat */
bool resizable_acpi_blob;
};

#define TYPE_PC_MACHINE "generic-pc-machine"
Expand Down
3 changes: 3 additions & 0 deletions include/hw/pci/pci.h
Expand Up @@ -287,6 +287,9 @@ void pci_bus_irqs(PCIBus *bus, pci_set_irq_fn set_irq,
void pci_bus_map_irqs(PCIBus *bus, pci_map_irq_fn map_irq);
void pci_bus_irqs_cleanup(PCIBus *bus);
int pci_bus_get_irq_level(PCIBus *bus, int irq_num);
uint32_t pci_bus_get_slot_reserved_mask(PCIBus *bus);
void pci_bus_set_slot_reserved_mask(PCIBus *bus, uint32_t mask);
void pci_bus_clear_slot_reserved_mask(PCIBus *bus, uint32_t mask);
/* 0 <= pin <= 3 0 = INTA, 1 = INTB, 2 = INTC, 3 = INTD */
static inline int pci_swizzle(int slot, int pin)
{
Expand Down
28 changes: 20 additions & 8 deletions include/hw/pci/pci_bridge.h
Expand Up @@ -84,23 +84,35 @@ struct PCIBridge {
#define PCI_BRIDGE_DEV_PROP_SHPC "shpc"
typedef struct CXLHost CXLHost;

struct PXBDev {
typedef struct PXBDev {
/*< private >*/
PCIDevice parent_obj;
/*< public >*/

uint8_t bus_nr;
uint16_t numa_node;
bool bypass_iommu;
} PXBDev;

typedef struct PXBPCIEDev {
/*< private >*/
PXBDev parent_obj;
} PXBPCIEDev;

#define TYPE_PXB_DEV "pxb"
OBJECT_DECLARE_SIMPLE_TYPE(PXBDev, PXB_DEV)

typedef struct PXBCXLDev {
/*< private >*/
PXBPCIEDev parent_obj;
/*< public >*/

bool hdm_for_passthrough;
struct cxl_dev {
CXLHost *cxl_host_bridge; /* Pointer to a CXLHost */
} cxl;
};
CXLHost *cxl_host_bridge; /* Pointer to a CXLHost */
} PXBCXLDev;

#define TYPE_PXB_CXL_DEVICE "pxb-cxl"
DECLARE_INSTANCE_CHECKER(PXBDev, PXB_CXL_DEV,
TYPE_PXB_CXL_DEVICE)
#define TYPE_PXB_CXL_DEV "pxb-cxl"
OBJECT_DECLARE_SIMPLE_TYPE(PXBCXLDev, PXB_CXL_DEV)

int pci_bridge_ssvid_init(PCIDevice *dev, uint8_t offset,
uint16_t svid, uint16_t ssid,
Expand Down
1 change: 1 addition & 0 deletions include/hw/virtio/virtio.h
Expand Up @@ -309,6 +309,7 @@ int virtio_get_num_queues(VirtIODevice *vdev);
void virtio_queue_set_rings(VirtIODevice *vdev, int n, hwaddr desc,
hwaddr avail, hwaddr used);
void virtio_queue_update_rings(VirtIODevice *vdev, int n);
void virtio_init_region_cache(VirtIODevice *vdev, int n);
void virtio_queue_set_align(VirtIODevice *vdev, int n, int align);
void virtio_queue_notify(VirtIODevice *vdev, int n);
uint16_t virtio_queue_vector(VirtIODevice *vdev, int n);
Expand Down
2 changes: 1 addition & 1 deletion meson_options.txt
Expand Up @@ -315,7 +315,7 @@ option('debug_mutex', type: 'boolean', value: false,
description: 'mutex debugging support')
option('debug_stack_usage', type: 'boolean', value: false,
description: 'measure coroutine stack usage')
option('qom_cast_debug', type: 'boolean', value: false,
option('qom_cast_debug', type: 'boolean', value: true,
description: 'cast debugging support')
option('gprof', type: 'boolean', value: false,
description: 'QEMU profiling with gprof',
Expand Down
3 changes: 2 additions & 1 deletion net/vhost-vdpa.c
Expand Up @@ -104,7 +104,8 @@ static const uint64_t vdpa_svq_device_features =
/* VHOST_F_LOG_ALL is exposed by SVQ */
BIT_ULL(VHOST_F_LOG_ALL) |
BIT_ULL(VIRTIO_NET_F_RSC_EXT) |
BIT_ULL(VIRTIO_NET_F_STANDBY);
BIT_ULL(VIRTIO_NET_F_STANDBY) |
BIT_ULL(VIRTIO_NET_F_SPEED_DUPLEX);

#define VHOST_VDPA_NET_CVQ_ASID 1

Expand Down
2 changes: 1 addition & 1 deletion scripts/meson-buildoptions.sh
Expand Up @@ -14,6 +14,7 @@ meson_options_help() {
printf "%s\n" ' use idef-parser to automatically generate TCG'
printf "%s\n" ' code for the Hexagon frontend'
printf "%s\n" ' --disable-install-blobs install provided firmware blobs'
printf "%s\n" ' --disable-qom-cast-debug cast debugging support'
printf "%s\n" ' --docdir=VALUE Base directory for documentation installation'
printf "%s\n" ' (can be empty) [share/doc]'
printf "%s\n" ' --enable-block-drv-whitelist-in-tools'
Expand All @@ -35,7 +36,6 @@ meson_options_help() {
printf "%s\n" ' --enable-module-upgrades try to load modules from alternate paths for'
printf "%s\n" ' upgrades'
printf "%s\n" ' --enable-profiler profiler support'
printf "%s\n" ' --enable-qom-cast-debug cast debugging support'
printf "%s\n" ' --enable-rng-none dummy RNG, avoid using /dev/(u)random and'
printf "%s\n" ' getrandom()'
printf "%s\n" ' --enable-strip Strip targets on install'
Expand Down
4 changes: 3 additions & 1 deletion scripts/tracetool/backend/ftrace.py
Expand Up @@ -12,6 +12,8 @@
__email__ = "stefanha@redhat.com"


import os.path

from tracetool import out


Expand Down Expand Up @@ -45,7 +47,7 @@ def generate_h(event, group):
args=event.args,
event_id="TRACE_" + event.name.upper(),
event_lineno=event.lineno,
event_filename=event.filename,
event_filename=os.path.relpath(event.filename),
fmt=event.fmt.rstrip("\n"),
argnames=argnames)

Expand Down
4 changes: 3 additions & 1 deletion scripts/tracetool/backend/log.py
Expand Up @@ -12,6 +12,8 @@
__email__ = "stefanha@redhat.com"


import os.path

from tracetool import out


Expand Down Expand Up @@ -53,7 +55,7 @@ def generate_h(event, group):
' }',
cond=cond,
event_lineno=event.lineno,
event_filename=event.filename,
event_filename=os.path.relpath(event.filename),
name=event.name,
fmt=event.fmt.rstrip("\n"),
argnames=argnames)
Expand Down
4 changes: 3 additions & 1 deletion scripts/tracetool/backend/syslog.py
Expand Up @@ -12,6 +12,8 @@
__email__ = "stefanha@redhat.com"


import os.path

from tracetool import out


Expand Down Expand Up @@ -41,7 +43,7 @@ def generate_h(event, group):
' }',
cond=cond,
event_lineno=event.lineno,
event_filename=event.filename,
event_filename=os.path.relpath(event.filename),
name=event.name,
fmt=event.fmt.rstrip("\n"),
argnames=argnames)
Expand Down
10 changes: 10 additions & 0 deletions subprojects/libvhost-user/libvhost-user.c
Expand Up @@ -2455,6 +2455,16 @@ void vu_queue_notify_sync(VuDev *dev, VuVirtq *vq)
_vu_queue_notify(dev, vq, true);
}

void vu_config_change_msg(VuDev *dev)
{
VhostUserMsg vmsg = {
.request = VHOST_USER_BACKEND_CONFIG_CHANGE_MSG,
.flags = VHOST_USER_VERSION,
};

vu_message_write(dev, dev->slave_fd, &vmsg);
}

static inline void
vring_used_flags_set_bit(VuVirtq *vq, int mask)
{
Expand Down
2 changes: 2 additions & 0 deletions subprojects/libvhost-user/libvhost-user.h
Expand Up @@ -585,6 +585,8 @@ bool vu_queue_empty(VuDev *dev, VuVirtq *vq);
*/
void vu_queue_notify(VuDev *dev, VuVirtq *vq);

void vu_config_change_msg(VuDev *dev);

/**
* vu_queue_notify_sync:
* @dev: a VuDev context
Expand Down