Commit 506179e4 authored by Peter Maydell's avatar Peter Maydell
Browse files

Merge remote-tracking branch 'remotes/dgibson/tags/ppc-for-4.1-20190702' into staging



ppc patch queue 2019-07-2

Here's my next pull request for qemu-4.1.  I'm not sure if this will
squeak in just before the soft freeze, or just after.  I don't think
it really matters - most of this is bugfixes anyway.  There's some
cleanups which aren't stictly bugfixes, but which I think are safe
enough improvements to go in the soft freeze.  There's no true feature
work.

Unfortunately, I wasn't able to complete a few of my standard battery
of pre-pull tests, due to some failures that appear to also be in
master.  I'm hoping that hasn't missed anything important in here.

Highlights are:
  * A number of fixe and cleanups for the XIVE implementation
  * Cleanups to the XICS interrupt controller to fit better with the new
    XIVE code
  * Numerous fixes and improvements to TCG handling of ppc vector
    instructions
  * Remove a number of unnnecessary #ifdef CONFIG_KVM guards
  * Fix some errors in the PCI hotplug paths
  * Assorted other fixes

# gpg: Signature made Tue 02 Jul 2019 07:07:15 BST
# gpg:                using RSA key 75F46586AE61A66CC44E87DC6C38CACA20D9B392
# gpg: Good signature from "David Gibson <david@gibson.dropbear.id.au>" [full]
# gpg:                 aka "David Gibson (Red Hat) <dgibson@redhat.com>" [full]
# gpg:                 aka "David Gibson (ozlabs.org) <dgibson@ozlabs.org>" [full]
# gpg:                 aka "David Gibson (kernel.org) <dwg@kernel.org>" [unknown]
# Primary key fingerprint: 75F4 6586 AE61 A66C C44E  87DC 6C38 CACA 20D9 B392

* remotes/dgibson/tags/ppc-for-4.1-20190702: (49 commits)
  spapr/xive: Add proper rollback to kvmppc_xive_connect()
  ppc/xive: Fix TM_PULL_POOL_CTX special operation
  ppc/pnv: Rework cache watch model of PnvXIVE
  ppc/xive: Make the PIPR register readonly
  ppc/xive: Force the Physical CAM line value to group mode
  spapr/xive: simplify spapr_irq_init_device() to remove the emulated init
  spapr/xive: rework the mapping the KVM memory regions
  spapr_pci: Unregister listeners before destroying the IOMMU address space
  target/ppc: improve VSX_FMADD with new GEN_VSX_HELPER_VSX_MADD macro
  target/ppc: decode target register in VSX_EXTRACT_INSERT at translation time
  target/ppc: decode target register in VSX_VECTOR_LOAD_STORE_LENGTH at translation time
  target/ppc: introduce GEN_VSX_HELPER_R2_AB macro to fpu_helper.c
  target/ppc: introduce GEN_VSX_HELPER_R2 macro to fpu_helper.c
  target/ppc: introduce GEN_VSX_HELPER_R3 macro to fpu_helper.c
  target/ppc: introduce GEN_VSX_HELPER_X1 macro to fpu_helper.c
  target/ppc: introduce GEN_VSX_HELPER_X2_AB macro to fpu_helper.c
  target/ppc: introduce GEN_VSX_HELPER_X2 macro to fpu_helper.c
  target/ppc: introduce separate generator and helper for xscvqpdp
  target/ppc: introduce GEN_VSX_HELPER_X3 macro to fpu_helper.c
  target/ppc: introduce separate VSX_CMP macro for xvcmp* instructions
  ...

Signed-off-by: default avatarPeter Maydell <peter.maydell@linaro.org>
parents efa85a4d 1c3d4a8f
Loading
Loading
Loading
Loading
+106 −6
Original line number Diff line number Diff line
@@ -34,19 +34,118 @@ CAS Negotiation
---------------

QEMU advertises the supported interrupt modes in the device tree
property "ibm,arch-vec-5-platform-support" in byte 23 and the OS
Selection for XIVE is indicated in the "ibm,architecture-vec-5"
property ``ibm,arch-vec-5-platform-support`` in byte 23 and the OS
Selection for XIVE is indicated in the ``ibm,architecture-vec-5``
property byte 23.

The interrupt modes supported by the machine depend on the CPU type
(POWER9 is required for XIVE) but also on the machine property
``ic-mode`` which can be set on the command line. It can take the
following values: ``xics``, ``xive``, ``dual`` and currently ``xics``
is the default but it may change in the future.
following values: ``xics``, ``xive``, and ``dual`` which is the
default mode. ``dual`` means that both modes XICS **and** XIVE are
supported and if the guest OS supports XIVE, this mode will be
selected.

The choosen interrupt mode is activated after a reconfiguration done
in a machine reset.

KVM negotiation
---------------

When the guest starts under KVM, the capabilities of the host kernel
and QEMU are also negotiated. Depending on the version of the host
kernel, KVM will advertise the XIVE capability to QEMU or not.

Nevertheless, the available interrupt modes in the machine should not
depend on the XIVE KVM capability of the host. On older kernels
without XIVE KVM support, QEMU will use the emulated XIVE device as a
fallback and on newer kernels (>=5.2), the KVM XIVE device.

As a final refinement, the user can also switch the use of the KVM
device with the machine option ``kernel_irqchip``.


XIVE support in KVM
~~~~~~~~~~~~~~~~~~~

For guest OSes supporting XIVE, the resulting interrupt modes on host
kernels with XIVE KVM support are the following:

==============  =============  =============  ================
ic-mode                            kernel_irqchip
--------------  ----------------------------------------------
/               allowed        off            on
                (default)
==============  =============  =============  ================
dual (default)  XIVE KVM       XIVE emul.     XIVE KVM
xive            XIVE KVM       XIVE emul.     XIVE KVM
xics            XICS KVM       XICS emul.     XICS KVM
==============  =============  =============  ================

For legacy guest OSes without XIVE support, the resulting interrupt
modes are the following:

==============  =============  =============  ================
ic-mode                            kernel_irqchip
--------------  ----------------------------------------------
/               allowed        off            on
                (default)
==============  =============  =============  ================
dual (default)  XICS KVM       XICS emul.     XICS KVM
xive            QEMU error(3)  QEMU error(3)  QEMU error(3)
xics            XICS KVM       XICS emul.     XICS KVM
==============  =============  =============  ================

(3) QEMU fails at CAS with ``Guest requested unavailable interrupt
    mode (XICS), either don't set the ic-mode machine property or try
    ic-mode=xics or ic-mode=dual``


No XIVE support in KVM
~~~~~~~~~~~~~~~~~~~~~~

For guest OSes supporting XIVE, the resulting interrupt modes on host
kernels without XIVE KVM support are the following:

==============  =============  =============  ================
ic-mode                            kernel_irqchip
--------------  ----------------------------------------------
/               allowed        off            on
                (default)
==============  =============  =============  ================
dual (default)  XIVE emul.(1)  XIVE emul.     QEMU error (2)
xive            XIVE emul.(1)  XIVE emul.     QEMU error (2)
xics            XICS KVM       XICS emul.     XICS KVM
==============  =============  =============  ================


(1) QEMU warns with ``warning: kernel_irqchip requested but unavailable:
    IRQ_XIVE capability must be present for KVM``
(2) QEMU fails with ``kernel_irqchip requested but unavailable:
    IRQ_XIVE capability must be present for KVM``


For legacy guest OSes without XIVE support, the resulting interrupt
modes are the following:

==============  =============  =============  ================
ic-mode                            kernel_irqchip
--------------  ----------------------------------------------
/               allowed        off            on
                (default)
==============  =============  =============  ================
dual (default)  QEMU error(4)  XICS emul.     QEMU error(4)
xive            QEMU error(3)  QEMU error(3)  QEMU error(3)
xics            XICS KVM       XICS emul.     XICS KVM
==============  =============  =============  ================

(3) QEMU fails at CAS with ``Guest requested unavailable interrupt
    mode (XICS), either don't set the ic-mode machine property or try
    ic-mode=xics or ic-mode=dual``
(4) QEMU/KVM incompatibility due to device destruction in reset. QEMU fails
    with ``KVM is too old to support ic-mode=dual,kernel-irqchip=on``


XIVE Device tree properties
---------------------------

@@ -92,10 +191,11 @@ for both interrupt mode. The different ranges are defined as follow :
- ``0x0000 .. 0x0FFF`` 4K CPU IPIs (only used under XIVE)
- ``0x1000 .. 0x1000`` 1 EPOW
- ``0x1001 .. 0x1001`` 1 HOTPLUG
- ``0x1002 .. 0x10FF`` unused
- ``0x1100 .. 0x11FF`` 256 VIO devices
- ``0x1200 .. 0x127F`` 32 PHBs devices
- ``0x1200 .. 0x127F`` 32x4 LSIs for PHB devices
- ``0x1280 .. 0x12FF`` unused
- ``0x1300 .. 0x1FFF`` PHB MSIs
- ``0x1300 .. 0x1FFF`` PHB MSIs (dynamically allocated)

Monitoring XIVE
---------------
+5 −4
Original line number Diff line number Diff line
@@ -20,10 +20,11 @@ The XIVE IC is composed of three sub-engines, each taking care of a
processing layer of external interrupts:

- Interrupt Virtualization Source Engine (IVSE), or Source Controller
  (SC). These are found in PCI PHBs, in the PSI host bridge
  controller, but also inside the main controller for the core IPIs
  and other sub-chips (NX, CAP, NPU) of the chip/processor. They are
  configured to feed the IVRE with events.
  (SC). These are found in PCI PHBs, in the Processor Service
  Interface (PSI) host bridge Controller, but also inside the main
  controller for the core IPIs and other sub-chips (NX, CAP, NPU) of
  the chip/processor. They are configured to feed the IVRE with
  events.
- Interrupt Virtualization Routing Engine (IVRE) or Virtualization
  Controller (VC). It handles event coalescing and perform interrupt
  routing by matching an event source number with an Event
+107 −38
Original line number Diff line number Diff line
@@ -169,7 +169,7 @@ static uint64_t pnv_xive_vst_addr_indirect(PnvXive *xive, uint32_t type,
    vsd = ldq_be_dma(&address_space_memory, vsd_addr);

    if (!(vsd & VSD_ADDRESS_MASK)) {
        xive_error(xive, "VST: invalid %s entry %x !?", info->name, 0);
        xive_error(xive, "VST: invalid %s entry %x !?", info->name, idx);
        return 0;
    }

@@ -190,7 +190,7 @@ static uint64_t pnv_xive_vst_addr_indirect(PnvXive *xive, uint32_t type,
        vsd = ldq_be_dma(&address_space_memory, vsd_addr);

        if (!(vsd & VSD_ADDRESS_MASK)) {
            xive_error(xive, "VST: invalid %s entry %x !?", info->name, 0);
            xive_error(xive, "VST: invalid %s entry %x !?", info->name, idx);
            return 0;
        }

@@ -294,8 +294,12 @@ static int pnv_xive_write_end(XiveRouter *xrtr, uint8_t blk, uint32_t idx,
                              word_number);
}

static int pnv_xive_end_update(PnvXive *xive, uint8_t blk, uint32_t idx)
static int pnv_xive_end_update(PnvXive *xive)
{
    uint8_t  blk = GETFIELD(VC_EQC_CWATCH_BLOCKID,
                           xive->regs[(VC_EQC_CWATCH_SPEC >> 3)]);
    uint32_t idx = GETFIELD(VC_EQC_CWATCH_OFFSET,
                           xive->regs[(VC_EQC_CWATCH_SPEC >> 3)]);
    int i;
    uint64_t eqc_watch[4];

@@ -307,6 +311,24 @@ static int pnv_xive_end_update(PnvXive *xive, uint8_t blk, uint32_t idx)
                              XIVE_VST_WORD_ALL);
}

static void pnv_xive_end_cache_load(PnvXive *xive)
{
    uint8_t  blk = GETFIELD(VC_EQC_CWATCH_BLOCKID,
                           xive->regs[(VC_EQC_CWATCH_SPEC >> 3)]);
    uint32_t idx = GETFIELD(VC_EQC_CWATCH_OFFSET,
                           xive->regs[(VC_EQC_CWATCH_SPEC >> 3)]);
    uint64_t eqc_watch[4] = { 0 };
    int i;

    if (pnv_xive_vst_read(xive, VST_TSEL_EQDT, blk, idx, eqc_watch)) {
        xive_error(xive, "VST: no END entry %x/%x !?", blk, idx);
    }

    for (i = 0; i < ARRAY_SIZE(eqc_watch); i++) {
        xive->regs[(VC_EQC_CWATCH_DAT0 >> 3) + i] = be64_to_cpu(eqc_watch[i]);
    }
}

static int pnv_xive_get_nvt(XiveRouter *xrtr, uint8_t blk, uint32_t idx,
                            XiveNVT *nvt)
{
@@ -320,8 +342,12 @@ static int pnv_xive_write_nvt(XiveRouter *xrtr, uint8_t blk, uint32_t idx,
                              word_number);
}

static int pnv_xive_nvt_update(PnvXive *xive, uint8_t blk, uint32_t idx)
static int pnv_xive_nvt_update(PnvXive *xive)
{
    uint8_t  blk = GETFIELD(PC_VPC_CWATCH_BLOCKID,
                           xive->regs[(PC_VPC_CWATCH_SPEC >> 3)]);
    uint32_t idx = GETFIELD(PC_VPC_CWATCH_OFFSET,
                           xive->regs[(PC_VPC_CWATCH_SPEC >> 3)]);
    int i;
    uint64_t vpc_watch[8];

@@ -333,6 +359,24 @@ static int pnv_xive_nvt_update(PnvXive *xive, uint8_t blk, uint32_t idx)
                              XIVE_VST_WORD_ALL);
}

static void pnv_xive_nvt_cache_load(PnvXive *xive)
{
    uint8_t  blk = GETFIELD(PC_VPC_CWATCH_BLOCKID,
                           xive->regs[(PC_VPC_CWATCH_SPEC >> 3)]);
    uint32_t idx = GETFIELD(PC_VPC_CWATCH_OFFSET,
                           xive->regs[(PC_VPC_CWATCH_SPEC >> 3)]);
    uint64_t vpc_watch[8] = { 0 };
    int i;

    if (pnv_xive_vst_read(xive, VST_TSEL_VPDT, blk, idx, vpc_watch)) {
        xive_error(xive, "VST: no NVT entry %x/%x !?", blk, idx);
    }

    for (i = 0; i < ARRAY_SIZE(vpc_watch); i++) {
        xive->regs[(PC_VPC_CWATCH_DAT0 >> 3) + i] = be64_to_cpu(vpc_watch[i]);
    }
}

static int pnv_xive_get_eas(XiveRouter *xrtr, uint8_t blk, uint32_t idx,
                            XiveEAS *eas)
{
@@ -346,12 +390,6 @@ static int pnv_xive_get_eas(XiveRouter *xrtr, uint8_t blk, uint32_t idx,
    return pnv_xive_vst_read(xive, VST_TSEL_IVT, blk, idx, eas);
}

static int pnv_xive_eas_update(PnvXive *xive, uint8_t blk, uint32_t idx)
{
    /* All done. */
    return 0;
}

static XiveTCTX *pnv_xive_get_tctx(XiveRouter *xrtr, CPUState *cs)
{
    PowerPCCPU *cpu = POWERPC_CPU(cs);
@@ -781,8 +819,7 @@ static void pnv_xive_ic_reg_write(void *opaque, hwaddr offset,
         * support recently though)
         */
        if (val & (VC_SBC_CONF_CPLX_CIST | VC_SBC_CONF_CIST_BOTH)) {
            object_property_set_int(OBJECT(&xive->ipi_source),
                                    XIVE_SRC_STORE_EOI, "flags", &error_fatal);
            xive->ipi_source.esb_flags |= XIVE_SRC_STORE_EOI;
        }
        break;

@@ -951,28 +988,43 @@ static void pnv_xive_ic_reg_write(void *opaque, hwaddr offset,
     * XIVE PC & VC cache updates for EAS, NVT and END
     */
    case VC_IVC_SCRUB_MASK:
        break;
    case VC_IVC_SCRUB_TRIG:
        pnv_xive_eas_update(xive, GETFIELD(PC_SCRUB_BLOCK_ID, val),
                            GETFIELD(VC_SCRUB_OFFSET, val));
        break;

    case VC_EQC_SCRUB_MASK:
    case VC_EQC_CWATCH_SPEC:
    case VC_EQC_CWATCH_DAT0 ... VC_EQC_CWATCH_DAT3:
        val &= ~VC_EQC_CWATCH_CONFLICT; /* HW resets this bit */
        break;
    case VC_EQC_CWATCH_DAT1 ... VC_EQC_CWATCH_DAT3:
        break;
    case VC_EQC_CWATCH_DAT0:
        /* writing to DATA0 triggers the cache write */
        xive->regs[reg] = val;
        pnv_xive_end_update(xive);
        break;
    case VC_EQC_SCRUB_MASK:
    case VC_EQC_SCRUB_TRIG:
        pnv_xive_end_update(xive, GETFIELD(VC_SCRUB_BLOCK_ID, val),
                            GETFIELD(VC_SCRUB_OFFSET, val));
        /*
         * The scrubbing registers flush the cache in RAM and can also
         * invalidate.
         */
        break;

    case PC_VPC_SCRUB_MASK:
    case PC_VPC_CWATCH_SPEC:
    case PC_VPC_CWATCH_DAT0 ... PC_VPC_CWATCH_DAT7:
        val &= ~PC_VPC_CWATCH_CONFLICT; /* HW resets this bit */
        break;
    case PC_VPC_CWATCH_DAT1 ... PC_VPC_CWATCH_DAT7:
        break;
    case PC_VPC_CWATCH_DAT0:
        /* writing to DATA0 triggers the cache write */
        xive->regs[reg] = val;
        pnv_xive_nvt_update(xive);
        break;
    case PC_VPC_SCRUB_MASK:
    case PC_VPC_SCRUB_TRIG:
        pnv_xive_nvt_update(xive, GETFIELD(PC_SCRUB_BLOCK_ID, val),
                           GETFIELD(PC_SCRUB_OFFSET, val));
        /*
         * The scrubbing registers flush the cache in RAM and can also
         * invalidate.
         */
        break;


@@ -1023,15 +1075,6 @@ static uint64_t pnv_xive_ic_reg_read(void *opaque, hwaddr offset, unsigned size)
    case PC_GLOBAL_CONFIG:

    case PC_VPC_SCRUB_MASK:
    case PC_VPC_CWATCH_SPEC:
    case PC_VPC_CWATCH_DAT0:
    case PC_VPC_CWATCH_DAT1:
    case PC_VPC_CWATCH_DAT2:
    case PC_VPC_CWATCH_DAT3:
    case PC_VPC_CWATCH_DAT4:
    case PC_VPC_CWATCH_DAT5:
    case PC_VPC_CWATCH_DAT6:
    case PC_VPC_CWATCH_DAT7:

    case VC_GLOBAL_CONFIG:
    case VC_AIB_TX_ORDER_TAG2:
@@ -1044,12 +1087,6 @@ static uint64_t pnv_xive_ic_reg_read(void *opaque, hwaddr offset, unsigned size)
    case VC_IRQ_CONFIG_IPI_CASC:

    case VC_EQC_SCRUB_MASK:
    case VC_EQC_CWATCH_DAT0:
    case VC_EQC_CWATCH_DAT1:
    case VC_EQC_CWATCH_DAT2:
    case VC_EQC_CWATCH_DAT3:

    case VC_EQC_CWATCH_SPEC:
    case VC_IVC_SCRUB_MASK:
    case VC_SBC_CONFIG:
    case VC_AT_MACRO_KILL_MASK:
@@ -1081,6 +1118,38 @@ static uint64_t pnv_xive_ic_reg_read(void *opaque, hwaddr offset, unsigned size)
    /*
     * XIVE PC & VC cache updates for EAS, NVT and END
     */
    case VC_EQC_CWATCH_SPEC:
        xive->regs[reg] = ~(VC_EQC_CWATCH_FULL | VC_EQC_CWATCH_CONFLICT);
        val = xive->regs[reg];
        break;
    case VC_EQC_CWATCH_DAT0:
        /*
         * Load DATA registers from cache with data requested by the
         * SPEC register
         */
        pnv_xive_end_cache_load(xive);
        val = xive->regs[reg];
        break;
    case VC_EQC_CWATCH_DAT1 ... VC_EQC_CWATCH_DAT3:
        val = xive->regs[reg];
        break;

    case PC_VPC_CWATCH_SPEC:
        xive->regs[reg] = ~(PC_VPC_CWATCH_FULL | PC_VPC_CWATCH_CONFLICT);
        val = xive->regs[reg];
        break;
    case PC_VPC_CWATCH_DAT0:
        /*
         * Load DATA registers from cache with data requested by the
         * SPEC register
         */
        pnv_xive_nvt_cache_load(xive);
        val = xive->regs[reg];
        break;
    case PC_VPC_CWATCH_DAT1 ... PC_VPC_CWATCH_DAT7:
        val = xive->regs[reg];
        break;

    case PC_VPC_SCRUB_TRIG:
    case VC_IVC_SCRUB_TRIG:
    case VC_EQC_SCRUB_TRIG:
+10 −28
Original line number Diff line number Diff line
@@ -194,13 +194,6 @@ void spapr_xive_pic_print_info(SpaprXive *xive, Monitor *mon)
    }
}

void spapr_xive_map_mmio(SpaprXive *xive)
{
    sysbus_mmio_map(SYS_BUS_DEVICE(xive), 0, xive->vc_base);
    sysbus_mmio_map(SYS_BUS_DEVICE(xive), 1, xive->end_base);
    sysbus_mmio_map(SYS_BUS_DEVICE(xive), 2, xive->tm_base);
}

void spapr_xive_mmio_set_enabled(SpaprXive *xive, bool enable)
{
    memory_region_set_enabled(&xive->source.esb_mmio, enable);
@@ -305,6 +298,7 @@ static void spapr_xive_realize(DeviceState *dev, Error **errp)
        error_propagate(errp, local_err);
        return;
    }
    sysbus_init_mmio(SYS_BUS_DEVICE(xive), &xsrc->esb_mmio);

    /*
     * Initialize the END ESB source
@@ -318,6 +312,7 @@ static void spapr_xive_realize(DeviceState *dev, Error **errp)
        error_propagate(errp, local_err);
        return;
    }
    sysbus_init_mmio(SYS_BUS_DEVICE(xive), &end_xsrc->esb_mmio);

    /* Set the mapping address of the END ESB pages after the source ESBs */
    xive->end_base = xive->vc_base + (1ull << xsrc->esb_shift) * xsrc->nr_irqs;
@@ -333,31 +328,18 @@ static void spapr_xive_realize(DeviceState *dev, Error **errp)

    qemu_register_reset(spapr_xive_reset, dev);

    /* Define all XIVE MMIO regions on SysBus */
    sysbus_init_mmio(SYS_BUS_DEVICE(xive), &xsrc->esb_mmio);
    sysbus_init_mmio(SYS_BUS_DEVICE(xive), &end_xsrc->esb_mmio);
    sysbus_init_mmio(SYS_BUS_DEVICE(xive), &xive->tm_mmio);
}

void spapr_xive_init(SpaprXive *xive, Error **errp)
{
    XiveSource *xsrc = &xive->source;

    /*
     * The emulated XIVE device can only be initialized once. If the
     * ESB memory region has been already mapped, it means we have been
     * through there.
     */
    if (memory_region_is_mapped(&xsrc->esb_mmio)) {
        return;
    }

    /* TIMA initialization */
    memory_region_init_io(&xive->tm_mmio, OBJECT(xive), &xive_tm_ops, xive,
                          "xive.tima", 4ull << TM_SHIFT);
    sysbus_init_mmio(SYS_BUS_DEVICE(xive), &xive->tm_mmio);

    /* Map all regions */
    spapr_xive_map_mmio(xive);
    /*
     * Map all regions. These will be enabled or disabled at reset and
     * can also be overridden by KVM memory regions if active
     */
    sysbus_mmio_map(SYS_BUS_DEVICE(xive), 0, xive->vc_base);
    sysbus_mmio_map(SYS_BUS_DEVICE(xive), 1, xive->end_base);
    sysbus_mmio_map(SYS_BUS_DEVICE(xive), 2, xive->tm_base);
}

static int spapr_xive_get_eas(XiveRouter *xrtr, uint8_t eas_blk,
+34 −21
Original line number Diff line number Diff line
@@ -724,12 +724,13 @@ void kvmppc_xive_connect(SpaprXive *xive, Error **errp)
    xsrc->esb_mmap = kvmppc_xive_mmap(xive, KVM_XIVE_ESB_PAGE_OFFSET, esb_len,
                                      &local_err);
    if (local_err) {
        error_propagate(errp, local_err);
        return;
        goto fail;
    }

    memory_region_init_ram_device_ptr(&xsrc->esb_mmio, OBJECT(xsrc),
    memory_region_init_ram_device_ptr(&xsrc->esb_mmio_kvm, OBJECT(xsrc),
                                      "xive.esb", esb_len, xsrc->esb_mmap);
    memory_region_add_subregion_overlap(&xsrc->esb_mmio, 0,
                                        &xsrc->esb_mmio_kvm, 1);

    /*
     * 2. END ESB pages (No KVM support yet)
@@ -741,11 +742,12 @@ void kvmppc_xive_connect(SpaprXive *xive, Error **errp)
    xive->tm_mmap = kvmppc_xive_mmap(xive, KVM_XIVE_TIMA_PAGE_OFFSET, tima_len,
                                     &local_err);
    if (local_err) {
        error_propagate(errp, local_err);
        return;
        goto fail;
    }
    memory_region_init_ram_device_ptr(&xive->tm_mmio, OBJECT(xive),
    memory_region_init_ram_device_ptr(&xive->tm_mmio_kvm, OBJECT(xive),
                                      "xive.tima", tima_len, xive->tm_mmap);
    memory_region_add_subregion_overlap(&xive->tm_mmio, 0,
                                        &xive->tm_mmio_kvm, 1);

    xive->change = qemu_add_vm_change_state_handler(
        kvmppc_xive_change_state_handler, xive);
@@ -756,24 +758,24 @@ void kvmppc_xive_connect(SpaprXive *xive, Error **errp)

        kvmppc_xive_cpu_connect(spapr_cpu_state(cpu)->tctx, &local_err);
        if (local_err) {
            error_propagate(errp, local_err);
            return;
            goto fail;
        }
    }

    /* Update the KVM sources */
    kvmppc_xive_source_reset(xsrc, &local_err);
    if (local_err) {
            error_propagate(errp, local_err);
            return;
        goto fail;
    }

    kvm_kernel_irqchip = true;
    kvm_msi_via_irqfd_allowed = true;
    kvm_gsi_direct_mapping = true;
    return;

    /* Map all regions */
    spapr_xive_map_mmio(xive);
fail:
    error_propagate(errp, local_err);
    kvmppc_xive_disconnect(xive, NULL);
}

void kvmppc_xive_disconnect(SpaprXive *xive, Error **errp)
@@ -795,21 +797,29 @@ void kvmppc_xive_disconnect(SpaprXive *xive, Error **errp)
    xsrc = &xive->source;
    esb_len = (1ull << xsrc->esb_shift) * xsrc->nr_irqs;

    sysbus_mmio_unmap(SYS_BUS_DEVICE(xive), 0);
    if (xsrc->esb_mmap) {
        memory_region_del_subregion(&xsrc->esb_mmio, &xsrc->esb_mmio_kvm);
        object_unparent(OBJECT(&xsrc->esb_mmio_kvm));
        munmap(xsrc->esb_mmap, esb_len);
        xsrc->esb_mmap = NULL;
    }

    sysbus_mmio_unmap(SYS_BUS_DEVICE(xive), 1);

    sysbus_mmio_unmap(SYS_BUS_DEVICE(xive), 2);
    if (xive->tm_mmap) {
        memory_region_del_subregion(&xive->tm_mmio, &xive->tm_mmio_kvm);
        object_unparent(OBJECT(&xive->tm_mmio_kvm));
        munmap(xive->tm_mmap, 4ull << TM_SHIFT);
        xive->tm_mmap = NULL;
    }

    /*
     * When the KVM device fd is closed, the KVM device is destroyed
     * and removed from the list of devices of the VM. The VCPU
     * presenters are also detached from the device.
     */
    if (xive->fd != -1) {
        close(xive->fd);
        xive->fd = -1;
    }

    kvm_kernel_irqchip = false;
    kvm_msi_via_irqfd_allowed = false;
@@ -819,5 +829,8 @@ void kvmppc_xive_disconnect(SpaprXive *xive, Error **errp)
    kvm_cpu_disable_all();

    /* VM Change state handler is not needed anymore */
    if (xive->change) {
        qemu_del_vm_change_state_handler(xive->change);
        xive->change = NULL;
    }
}
Loading