Merge remote-tracking branch 'remotes/dgibson/tags/ppc-for-4.0-20190109' into staging

ppc patch queue 2019-01-09

Second main pull request for qemu-4.0.  Highlights are:
 * Final parts of XIVE support for pseries (without KVM)
 * Preliminary work for PHB hotplug
 * Starting to use TCG vector operations

This includes some changes in the PCI core, which Michael Tsirkin
requested come through this tree, since they're primarily of interest
for ppc.

# gpg: Signature made Tue 08 Jan 2019 22:44:10 GMT
# gpg:                using RSA key 6C38CACA20D9B392
# gpg: Good signature from "David Gibson <david@gibson.dropbear.id.au>"
# gpg:                 aka "David Gibson (Red Hat) <dgibson@redhat.com>"
# gpg:                 aka "David Gibson (ozlabs.org) <dgibson@ozlabs.org>"
# gpg:                 aka "David Gibson (kernel.org) <dwg@kernel.org>"
# Primary key fingerprint: 75F4 6586 AE61 A66C C44E  87DC 6C38 CACA 20D9 B392

* remotes/dgibson/tags/ppc-for-4.0-20190109: (29 commits)
  spapr: enable XIVE MMIOs at reset
  spapr: introduce a new sPAPR IRQ backend supporting XIVE and XICS
  ppc/xics: allow ICSState to have an offset 0
  spapr: move the qemu_irq array under the machine
  pnv/psi: move the ICSState qemu_irq array under the PSI device model
  ppc: export the XICS and XIVE set_irq handlers
  spapr: return from post_load method when RTC import fails
  ppc: replace the 'Object *intc' by a 'ICPState *icp' pointer under the CPU
  ppc/xive: introduce a XiveTCTX pointer under PowerPCCPU
  spapr: modify the prototype of the cpu_intc_create() method
  spapr/xive: simplify the sPAPR IRQ qirq method for XIVE
  spapr_pci: Define SPAPR_MAX_PHBS in hw/pci-host/spapr.h
  pci: allow cleanup/unregistration of PCI root buses
  spapr: move spapr_create_phb() to core machine code
  MAINTAINERS: add qemu_vga.ndrv file entry for Mac machines
  MAINTAINERS: Add some missing ppc-related files
  target/ppc: replace AVR* macros with Vsr* macros
  target/ppc: move FP and VMX registers into aligned vsr register array
  target/ppc: merge ppc_vsr_t and ppc_avr_t union types
  target/ppc: switch FPR, VMX and VSX helpers to access data directly from cpu_env
  ...

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell
2019-01-09 16:08:31 +00:00
42 changed files with 1926 additions and 654 deletions
+15 -2
View File
@@ -962,6 +962,7 @@ L: qemu-ppc@nongnu.org
S: Odd Fixes
F: hw/ppc/e500.[hc]
F: hw/ppc/e500plat.c
F: hw/gpio/mpc8xxx.c
F: include/hw/ppc/ppc_e500.h
F: include/hw/pci-host/ppce500.h
F: pc-bios/u-boot.e500
@@ -973,7 +974,7 @@ S: Odd Fixes
F: hw/ppc/mpc8544ds.c
F: hw/ppc/mpc8544_guts.c
New World
New World (mac99)
M: David Gibson <david@gibson.dropbear.id.au>
L: qemu-ppc@nongnu.org
S: Odd Fixes
@@ -983,12 +984,15 @@ F: hw/pci-bridge/dec.[hc]
F: hw/misc/macio/
F: hw/misc/mos6522.c
F: hw/nvram/mac_nvram.c
F: hw/input/adb*
F: include/hw/misc/macio/
F: include/hw/misc/mos6522.h
F: include/hw/ppc/mac_dbdma.h
F: include/hw/pci-host/uninorth.h
F: include/hw/input/adb*
F: pc-bios/qemu_vga.ndrv
Old World
Old World (g3beige)
M: David Gibson <david@gibson.dropbear.id.au>
L: qemu-ppc@nongnu.org
S: Odd Fixes
@@ -996,7 +1000,10 @@ F: hw/ppc/mac_oldworld.c
F: hw/pci-host/grackle.c
F: hw/misc/macio/
F: hw/intc/heathrow_pic.c
F: hw/input/adb*
F: include/hw/intc/heathrow_pic.h
F: include/hw/input/adb*
F: pc-bios/qemu_vga.ndrv
PReP
M: Hervé Poussineau <hpoussin@reactos.org>
@@ -1052,8 +1059,14 @@ sam460ex
M: BALATON Zoltan <balaton@eik.bme.hu>
L: qemu-ppc@nongnu.org
S: Maintained
F: hw/ppc/sam460ex.c
F: hw/ppc/ppc440_pcix.c
F: hw/display/sm501*
F: hw/ide/sii3112.c
F: hw/timer/m41t80.c
F: pc-bios/canyonlands.dt[sb]
F: pc-bios/u-boot-sam460ex-20100605.bin
F: roms/u-boot-sam460ex
SH4 Machines
------------
Vendored
+1 -1
View File
@@ -3939,7 +3939,7 @@ if test "$fdt" != "no" ; then
cat > $TMPC << EOF
#include <libfdt.h>
#include <libfdt_env.h>
int main(void) { fdt_first_subnode(0, 0); return 0; }
int main(void) { fdt_check_full(NULL, 0); return 0; }
EOF
if compile_prog "" "$fdt_libs" ; then
# system DTC is good - use it
+9 -14
View File
@@ -179,6 +179,15 @@ static void spapr_xive_map_mmio(sPAPRXive *xive)
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);
memory_region_set_enabled(&xive->tm_mmio, enable);
/* Disable the END ESBs until a guest OS makes use of them */
memory_region_set_enabled(&xive->end_source.esb_mmio, false);
}
/*
* When a Virtual Processor is scheduled to run on a HW thread, the
* hypervisor pushes its identifier in the OS CAM line. Emulate the
@@ -488,20 +497,6 @@ bool spapr_xive_irq_free(sPAPRXive *xive, uint32_t lisn)
return true;
}
qemu_irq spapr_xive_qirq(sPAPRXive *xive, uint32_t lisn)
{
XiveSource *xsrc = &xive->source;
if (lisn >= xive->nr_irqs) {
return NULL;
}
/* The sPAPR machine/device should have claimed the IRQ before */
assert(xive_eas_is_valid(&xive->eat[lisn]));
return xive_source_qirq(xsrc, lisn);
}
/*
* XIVE hcalls
*
+1 -3
View File
@@ -461,7 +461,7 @@ static void ics_simple_set_irq_lsi(ICSState *ics, int srcno, int val)
ics_simple_resend_lsi(ics, srcno);
}
static void ics_simple_set_irq(void *opaque, int srcno, int val)
void ics_simple_set_irq(void *opaque, int srcno, int val)
{
ICSState *ics = (ICSState *)opaque;
@@ -571,8 +571,6 @@ static void ics_simple_realize(DeviceState *dev, Error **errp)
return;
}
ics->qirqs = qemu_allocate_irqs(ics_simple_set_irq, ics, ics->nr_irqs);
qemu_register_reset(ics_simple_reset_handler, ics);
}
+1 -2
View File
@@ -298,7 +298,7 @@ static int ics_set_kvm_state(ICSState *ics, int version_id)
return 0;
}
static void ics_kvm_set_irq(void *opaque, int srcno, int val)
void ics_kvm_set_irq(void *opaque, int srcno, int val)
{
ICSState *ics = opaque;
struct kvm_irq_level args;
@@ -344,7 +344,6 @@ static void ics_kvm_realize(DeviceState *dev, Error **errp)
error_propagate(errp, local_err);
return;
}
ics->qirqs = qemu_allocate_irqs(ics_kvm_set_irq, ics, ics->nr_irqs);
qemu_register_reset(ics_kvm_reset_handler, ics);
}
+5 -5
View File
@@ -44,7 +44,7 @@ static target_ulong h_cppr(PowerPCCPU *cpu, sPAPRMachineState *spapr,
{
target_ulong cppr = args[0];
icp_set_cppr(ICP(cpu->intc), cppr);
icp_set_cppr(cpu->icp, cppr);
return H_SUCCESS;
}
@@ -65,7 +65,7 @@ static target_ulong h_ipi(PowerPCCPU *cpu, sPAPRMachineState *spapr,
static target_ulong h_xirr(PowerPCCPU *cpu, sPAPRMachineState *spapr,
target_ulong opcode, target_ulong *args)
{
uint32_t xirr = icp_accept(ICP(cpu->intc));
uint32_t xirr = icp_accept(cpu->icp);
args[0] = xirr;
return H_SUCCESS;
@@ -74,7 +74,7 @@ static target_ulong h_xirr(PowerPCCPU *cpu, sPAPRMachineState *spapr,
static target_ulong h_xirr_x(PowerPCCPU *cpu, sPAPRMachineState *spapr,
target_ulong opcode, target_ulong *args)
{
uint32_t xirr = icp_accept(ICP(cpu->intc));
uint32_t xirr = icp_accept(cpu->icp);
args[0] = xirr;
args[1] = cpu_get_host_ticks();
@@ -86,7 +86,7 @@ static target_ulong h_eoi(PowerPCCPU *cpu, sPAPRMachineState *spapr,
{
target_ulong xirr = args[0];
icp_eoi(ICP(cpu->intc), xirr);
icp_eoi(cpu->icp, xirr);
return H_SUCCESS;
}
@@ -94,7 +94,7 @@ static target_ulong h_ipoll(PowerPCCPU *cpu, sPAPRMachineState *spapr,
target_ulong opcode, target_ulong *args)
{
uint32_t mfrr;
uint32_t xirr = icp_ipoll(ICP(cpu->intc), &mfrr);
uint32_t xirr = icp_ipoll(cpu->icp, &mfrr);
args[0] = xirr;
args[1] = mfrr;
+4 -7
View File
@@ -321,7 +321,7 @@ static void xive_tm_write(void *opaque, hwaddr offset,
uint64_t value, unsigned size)
{
PowerPCCPU *cpu = POWERPC_CPU(current_cpu);
XiveTCTX *tctx = XIVE_TCTX(cpu->intc);
XiveTCTX *tctx = cpu->tctx;
const XiveTmOp *xto;
/*
@@ -360,7 +360,7 @@ static void xive_tm_write(void *opaque, hwaddr offset,
static uint64_t xive_tm_read(void *opaque, hwaddr offset, unsigned size)
{
PowerPCCPU *cpu = POWERPC_CPU(current_cpu);
XiveTCTX *tctx = XIVE_TCTX(cpu->intc);
XiveTCTX *tctx = cpu->tctx;
const XiveTmOp *xto;
/*
@@ -845,7 +845,7 @@ static const MemoryRegionOps xive_source_esb_ops = {
},
};
static void xive_source_set_irq(void *opaque, int srcno, int val)
void xive_source_set_irq(void *opaque, int srcno, int val)
{
XiveSource *xsrc = XIVE_SOURCE(opaque);
bool notify = false;
@@ -932,9 +932,6 @@ static void xive_source_realize(DeviceState *dev, Error **errp)
&xive_source_esb_ops, xsrc, "xive.esb",
(1ull << xsrc->esb_shift) * xsrc->nr_irqs);
xsrc->qirqs = qemu_allocate_irqs(xive_source_set_irq, xsrc,
xsrc->nr_irqs);
qemu_register_reset(xive_source_reset, dev);
}
@@ -1186,7 +1183,7 @@ static bool xive_presenter_match(XiveRouter *xrtr, uint8_t format,
CPU_FOREACH(cs) {
PowerPCCPU *cpu = POWERPC_CPU(cs);
XiveTCTX *tctx = XIVE_TCTX(cpu->intc);
XiveTCTX *tctx = cpu->tctx;
int ring;
/*
+33
View File
@@ -333,6 +333,13 @@ static void pci_host_bus_register(DeviceState *host)
QLIST_INSERT_HEAD(&pci_host_bridges, host_bridge, next);
}
static void pci_host_bus_unregister(DeviceState *host)
{
PCIHostState *host_bridge = PCI_HOST_BRIDGE(host);
QLIST_REMOVE(host_bridge, next);
}
PCIBus *pci_device_root_bus(const PCIDevice *d)
{
PCIBus *bus = pci_get_bus(d);
@@ -379,6 +386,11 @@ static void pci_root_bus_init(PCIBus *bus, DeviceState *parent,
pci_host_bus_register(parent);
}
static void pci_bus_uninit(PCIBus *bus)
{
pci_host_bus_unregister(BUS(bus)->parent);
}
bool pci_bus_is_express(PCIBus *bus)
{
return object_dynamic_cast(OBJECT(bus), TYPE_PCIE_BUS);
@@ -413,6 +425,12 @@ PCIBus *pci_root_bus_new(DeviceState *parent, const char *name,
return bus;
}
void pci_root_bus_cleanup(PCIBus *bus)
{
pci_bus_uninit(bus);
object_unparent(OBJECT(bus));
}
void pci_bus_irqs(PCIBus *bus, pci_set_irq_fn set_irq, pci_map_irq_fn map_irq,
void *irq_opaque, int nirq)
{
@@ -423,6 +441,15 @@ void pci_bus_irqs(PCIBus *bus, pci_set_irq_fn set_irq, pci_map_irq_fn map_irq,
bus->irq_count = g_malloc0(nirq * sizeof(bus->irq_count[0]));
}
void pci_bus_irqs_cleanup(PCIBus *bus)
{
bus->set_irq = NULL;
bus->map_irq = NULL;
bus->irq_opaque = NULL;
bus->nirq = 0;
g_free(bus->irq_count);
}
PCIBus *pci_register_root_bus(DeviceState *parent, const char *name,
pci_set_irq_fn set_irq, pci_map_irq_fn map_irq,
void *irq_opaque,
@@ -439,6 +466,12 @@ PCIBus *pci_register_root_bus(DeviceState *parent, const char *name,
return bus;
}
void pci_unregister_root_bus(PCIBus *bus)
{
pci_bus_irqs_cleanup(bus);
pci_root_bus_cleanup(bus);
}
int pci_bus_num(PCIBus *s)
{
return PCI_BUS_GET_CLASS(s)->bus_num(s);
+18 -9
View File
@@ -668,11 +668,20 @@ static uint32_t pnv_chip_core_pir_p8(PnvChip *chip, uint32_t core_id)
return (chip->chip_id << 7) | (core_id << 3);
}
static Object *pnv_chip_power8_intc_create(PnvChip *chip, Object *child,
Error **errp)
static void pnv_chip_power8_intc_create(PnvChip *chip, PowerPCCPU *cpu,
Error **errp)
{
return icp_create(child, TYPE_PNV_ICP, XICS_FABRIC(qdev_get_machine()),
errp);
Error *local_err = NULL;
Object *obj;
obj = icp_create(OBJECT(cpu), TYPE_PNV_ICP, XICS_FABRIC(qdev_get_machine()),
&local_err);
if (local_err) {
error_propagate(errp, local_err);
return;
}
cpu->icp = ICP(obj);
}
/*
@@ -690,10 +699,10 @@ static uint32_t pnv_chip_core_pir_p9(PnvChip *chip, uint32_t core_id)
return (chip->chip_id << 8) | (core_id << 2);
}
static Object *pnv_chip_power9_intc_create(PnvChip *chip, Object *child,
Error **errp)
static void pnv_chip_power9_intc_create(PnvChip *chip, PowerPCCPU *cpu,
Error **errp)
{
return NULL;
return;
}
/* Allowed core identifiers on a POWER8 Processor Chip :
@@ -1090,7 +1099,7 @@ static ICPState *pnv_icp_get(XICSFabric *xi, int pir)
{
PowerPCCPU *cpu = ppc_get_vcpu_by_pir(pir);
return cpu ? ICP(cpu->intc) : NULL;
return cpu ? cpu->icp : NULL;
}
static void pnv_pic_print_info(InterruptStatsProvider *obj,
@@ -1103,7 +1112,7 @@ static void pnv_pic_print_info(InterruptStatsProvider *obj,
CPU_FOREACH(cs) {
PowerPCCPU *cpu = POWERPC_CPU(cs);
icp_pic_print_info(ICP(cpu->intc), mon);
icp_pic_print_info(cpu->icp, mon);
}
for (i = 0; i < pnv->num_chips; i++) {
+2 -2
View File
@@ -114,7 +114,7 @@ static void pnv_realize_vcpu(PowerPCCPU *cpu, PnvChip *chip, Error **errp)
return;
}
cpu->intc = pcc->intc_create(chip, OBJECT(cpu), &local_err);
pcc->intc_create(chip, cpu, &local_err);
if (local_err) {
error_propagate(errp, local_err);
return;
@@ -190,7 +190,7 @@ err:
static void pnv_unrealize_vcpu(PowerPCCPU *cpu)
{
qemu_unregister_reset(pnv_cpu_reset, cpu);
object_unparent(cpu->intc);
object_unparent(OBJECT(cpu->icp));
cpu_remove_sync(CPU(cpu));
object_unparent(OBJECT(cpu));
}
+4 -3
View File
@@ -207,7 +207,6 @@ static const uint64_t stat_bits[] = {
void pnv_psi_irq_set(PnvPsi *psi, PnvPsiIrq irq, bool state)
{
ICSState *ics = &psi->ics;
uint32_t xivr_reg;
uint32_t stat_reg;
uint32_t src;
@@ -227,14 +226,14 @@ void pnv_psi_irq_set(PnvPsi *psi, PnvPsiIrq irq, bool state)
/* TODO: optimization, check mask here. That means
* re-evaluating when unmasking
*/
qemu_irq_raise(ics->qirqs[src]);
qemu_irq_raise(psi->qirqs[src]);
} else {
psi->regs[stat_reg] &= ~stat_bits[irq];
/* FSP and PSI are muxed so don't lower if either is still set */
if (stat_reg != PSIHB_XSCOM_CR ||
!(psi->regs[stat_reg] & (PSIHB_CR_PSI_IRQ | PSIHB_CR_FSP_IRQ))) {
qemu_irq_lower(ics->qirqs[src]);
qemu_irq_lower(psi->qirqs[src]);
} else {
state = true;
}
@@ -491,6 +490,8 @@ static void pnv_psi_realize(DeviceState *dev, Error **errp)
ics_set_irq_type(ics, i, true);
}
psi->qirqs = qemu_allocate_irqs(ics_simple_set_irq, ics, ics->nr_irqs);
/* XSCOM region for PSI registers */
pnv_xscom_region_init(&psi->xscom_regs, OBJECT(dev), &pnv_psi_xscom_ops,
psi, "xscom-psi", PNV_XSCOM_PSIHB_SIZE);
+1 -2
View File
@@ -32,8 +32,7 @@
#include "exec/address-spaces.h"
#include "qemu/error-report.h"
#define DEBUG_UIC
/*#define DEBUG_UIC*/
#ifdef DEBUG_UIC
# define LOG_UIC(...) qemu_log_mask(CPU_LOG_INT, ## __VA_ARGS__)
+70 -10
View File
@@ -1048,6 +1048,7 @@ static void spapr_dt_rtas(sPAPRMachineState *spapr, void *fdt)
add_str(hypertas, "hcall-sprg0");
add_str(hypertas, "hcall-copy");
add_str(hypertas, "hcall-debug");
add_str(hypertas, "hcall-vphn");
add_str(qemu_hypertas, "hcall-memop1");
if (!kvm_enabled() || kvmppc_spapr_use_multitce()) {
@@ -1668,7 +1669,10 @@ static void spapr_machine_reset(void)
/* Load the fdt */
qemu_fdt_dumpdtb(fdt, fdt_totalsize(fdt));
cpu_physical_memory_write(fdt_addr, fdt, fdt_totalsize(fdt));
g_free(fdt);
g_free(spapr->fdt_blob);
spapr->fdt_size = fdt_totalsize(fdt);
spapr->fdt_initial_size = spapr->fdt_size;
spapr->fdt_blob = fdt;
/* Set up the entry state */
spapr_cpu_set_entry_state(first_ppc_cpu, SPAPR_ENTRY_POINT, fdt_addr);
@@ -1743,12 +1747,17 @@ static int spapr_post_load(void *opaque, int version_id)
return err;
}
/* In earlier versions, there was no separate qdev for the PAPR
/*
* In earlier versions, there was no separate qdev for the PAPR
* RTC, so the RTC offset was stored directly in sPAPREnvironment.
* So when migrating from those versions, poke the incoming offset
* value into the RTC device */
* value into the RTC device
*/
if (version_id < 3) {
err = spapr_rtc_import_offset(&spapr->rtc, spapr->rtc_offset);
if (err) {
return err;
}
}
if (kvm_enabled() && spapr->patb_entry) {
@@ -1919,6 +1928,39 @@ static const VMStateDescription vmstate_spapr_irq_map = {
},
};
static bool spapr_dtb_needed(void *opaque)
{
sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(opaque);
return smc->update_dt_enabled;
}
static int spapr_dtb_pre_load(void *opaque)
{
sPAPRMachineState *spapr = (sPAPRMachineState *)opaque;
g_free(spapr->fdt_blob);
spapr->fdt_blob = NULL;
spapr->fdt_size = 0;
return 0;
}
static const VMStateDescription vmstate_spapr_dtb = {
.name = "spapr_dtb",
.version_id = 1,
.minimum_version_id = 1,
.needed = spapr_dtb_needed,
.pre_load = spapr_dtb_pre_load,
.fields = (VMStateField[]) {
VMSTATE_UINT32(fdt_initial_size, sPAPRMachineState),
VMSTATE_UINT32(fdt_size, sPAPRMachineState),
VMSTATE_VBUFFER_ALLOC_UINT32(fdt_blob, sPAPRMachineState, 0, NULL,
fdt_size),
VMSTATE_END_OF_LIST()
},
};
static const VMStateDescription vmstate_spapr = {
.name = "spapr",
.version_id = 3,
@@ -1948,6 +1990,7 @@ static const VMStateDescription vmstate_spapr = {
&vmstate_spapr_cap_ibs,
&vmstate_spapr_irq_map,
&vmstate_spapr_cap_nested_kvm_hv,
&vmstate_spapr_dtb,
NULL
}
};
@@ -2514,6 +2557,17 @@ static void spapr_init_cpus(sPAPRMachineState *spapr)
}
}
static PCIHostState *spapr_create_default_phb(void)
{
DeviceState *dev;
dev = qdev_create(NULL, TYPE_SPAPR_PCI_HOST_BRIDGE);
qdev_prop_set_uint32(dev, "index", 0);
qdev_init_nofail(dev);
return PCI_HOST_BRIDGE(dev);
}
/* pSeries LPAR / sPAPR hardware init */
static void spapr_machine_init(MachineState *machine)
{
@@ -2632,11 +2686,11 @@ static void spapr_machine_init(MachineState *machine)
spapr_ovec_set(spapr->ov5, OV5_DRMEM_V2);
/* advertise XIVE on POWER9 machines */
if (spapr->irq->ov5 & SPAPR_OV5_XIVE_EXPLOIT) {
if (spapr->irq->ov5 & (SPAPR_OV5_XIVE_EXPLOIT | SPAPR_OV5_XIVE_BOTH)) {
if (ppc_type_check_compat(machine->cpu_type, CPU_POWERPC_LOGICAL_3_00,
0, spapr->max_compat_pvr)) {
spapr_ovec_set(spapr->ov5, OV5_XIVE_EXPLOIT);
} else {
} else if (spapr->irq->ov5 & SPAPR_OV5_XIVE_EXPLOIT) {
error_report("XIVE-only machines require a POWER9 CPU");
exit(1);
}
@@ -2746,7 +2800,7 @@ static void spapr_machine_init(MachineState *machine)
/* Set up PCI */
spapr_pci_rtas_init();
phb = spapr_create_phb(spapr, 0);
phb = spapr_create_default_phb();
for (i = 0; i < nb_nics; i++) {
NICInfo *nd = &nd_table[i];
@@ -3062,6 +3116,8 @@ static char *spapr_get_ic_mode(Object *obj, Error **errp)
return g_strdup("xics");
} else if (spapr->irq == &spapr_irq_xive) {
return g_strdup("xive");
} else if (spapr->irq == &spapr_irq_dual) {
return g_strdup("dual");
}
g_assert_not_reached();
}
@@ -3075,6 +3131,8 @@ static void spapr_set_ic_mode(Object *obj, const char *value, Error **errp)
spapr->irq = &spapr_irq_xics;
} else if (strcmp(value, "xive") == 0) {
spapr->irq = &spapr_irq_xive;
} else if (strcmp(value, "dual") == 0) {
spapr->irq = &spapr_irq_dual;
} else {
error_setg(errp, "Bad value for \"ic-mode\" property");
}
@@ -3123,7 +3181,7 @@ static void spapr_instance_init(Object *obj)
object_property_add_str(obj, "ic-mode", spapr_get_ic_mode,
spapr_set_ic_mode, NULL);
object_property_set_description(obj, "ic-mode",
"Specifies the interrupt controller mode (xics, xive)",
"Specifies the interrupt controller mode (xics, xive, dual)",
NULL);
}
@@ -3791,8 +3849,6 @@ static void spapr_phb_placement(sPAPRMachineState *spapr, uint32_t index,
* 1TiB 64-bit MMIO windows for each PHB.
*/
const uint64_t base_buid = 0x800000020000000ULL;
#define SPAPR_MAX_PHBS ((SPAPR_PCI_LIMIT - SPAPR_PCI_BASE) / \
SPAPR_PCI_MEM64_WIN_SIZE - 1)
int i;
/* Sanity check natural alignments */
@@ -3840,7 +3896,7 @@ static ICPState *spapr_icp_get(XICSFabric *xi, int vcpu_id)
{
PowerPCCPU *cpu = spapr_find_cpu(vcpu_id);
return cpu ? ICP(cpu->intc) : NULL;
return cpu ? cpu->icp : NULL;
}
static void spapr_pic_print_info(InterruptStatsProvider *obj,
@@ -3930,6 +3986,7 @@ static void spapr_machine_class_init(ObjectClass *oc, void *data)
hc->unplug = spapr_machine_device_unplug;
smc->dr_lmb_enabled = true;
smc->update_dt_enabled = true;
mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power9_v2.0");
mc->has_hotpluggable_cpus = true;
smc->resize_hpt_default = SPAPR_RESIZE_HPT_ENABLED;
@@ -4022,9 +4079,12 @@ DEFINE_SPAPR_MACHINE(4_0, "4.0", true);
*/
static void spapr_machine_3_1_class_options(MachineClass *mc)
{
sPAPRMachineClass *smc = SPAPR_MACHINE_CLASS(mc);
spapr_machine_4_0_class_options(mc);
compat_props_add(mc->compat_props, hw_compat_3_1, hw_compat_3_1_len);
mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power8_v2.0");
smc->update_dt_enabled = false;
}
DEFINE_SPAPR_MACHINE(3_1, "3.1", false);
+7 -2
View File
@@ -194,7 +194,12 @@ static void spapr_unrealize_vcpu(PowerPCCPU *cpu, sPAPRCPUCore *sc)
vmstate_unregister(NULL, &vmstate_spapr_cpu_state, cpu->machine_data);
}
qemu_unregister_reset(spapr_cpu_reset, cpu);
object_unparent(cpu->intc);
if (cpu->icp) {
object_unparent(OBJECT(cpu->icp));
}
if (cpu->tctx) {
object_unparent(OBJECT(cpu->tctx));
}
cpu_remove_sync(CPU(cpu));
object_unparent(OBJECT(cpu));
}
@@ -232,7 +237,7 @@ static void spapr_realize_vcpu(PowerPCCPU *cpu, sPAPRMachineState *spapr,
qemu_register_reset(spapr_cpu_reset, cpu);
spapr_cpu_reset(cpu);
cpu->intc = spapr->irq->cpu_intc_create(spapr, OBJECT(cpu), &local_err);
spapr->irq->cpu_intc_create(spapr, cpu, &local_err);
if (local_err) {
goto error_unregister;
}
+93
View File
@@ -1654,6 +1654,17 @@ static target_ulong h_client_architecture_support(PowerPCCPU *cpu,
(spapr_h_cas_compose_response(spapr, args[1], args[2],
ov5_updates) != 0);
}
/*
* Generate a machine reset when we have an update of the
* interrupt mode. Only required when the machine supports both
* modes.
*/
if (!spapr->cas_reboot) {
spapr->cas_reboot = spapr_ovec_test(ov5_updates, OV5_XIVE_EXPLOIT)
&& spapr->irq->ov5 & SPAPR_OV5_XIVE_BOTH;
}
spapr_ovec_cleanup(ov5_updates);
if (spapr->cas_reboot) {
@@ -1663,6 +1674,42 @@ static target_ulong h_client_architecture_support(PowerPCCPU *cpu,
return H_SUCCESS;
}
static target_ulong h_home_node_associativity(PowerPCCPU *cpu,
sPAPRMachineState *spapr,
target_ulong opcode,
target_ulong *args)
{
target_ulong flags = args[0];
target_ulong procno = args[1];
PowerPCCPU *tcpu;
int idx;
/* only support procno from H_REGISTER_VPA */
if (flags != 0x1) {
return H_FUNCTION;
}
tcpu = spapr_find_cpu(procno);
if (tcpu == NULL) {
return H_P2;
}
/* sequence is the same as in the "ibm,associativity" property */
idx = 0;
#define ASSOCIATIVITY(a, b) (((uint64_t)(a) << 32) | \
((uint64_t)(b) & 0xffffffff))
args[idx++] = ASSOCIATIVITY(0, 0);
args[idx++] = ASSOCIATIVITY(0, tcpu->node_id);
args[idx++] = ASSOCIATIVITY(procno, -1);
for ( ; idx < 6; idx++) {
args[idx] = -1;
}
#undef ASSOCIATIVITY
return H_SUCCESS;
}
static target_ulong h_get_cpu_characteristics(PowerPCCPU *cpu,
sPAPRMachineState *spapr,
target_ulong opcode,
@@ -1717,6 +1764,46 @@ static target_ulong h_get_cpu_characteristics(PowerPCCPU *cpu,
args[0] = characteristics;
args[1] = behaviour;
return H_SUCCESS;
}
static target_ulong h_update_dt(PowerPCCPU *cpu, sPAPRMachineState *spapr,
target_ulong opcode, target_ulong *args)
{
target_ulong dt = ppc64_phys_to_real(args[0]);
struct fdt_header hdr = { 0 };
unsigned cb;
sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
void *fdt;
cpu_physical_memory_read(dt, &hdr, sizeof(hdr));
cb = fdt32_to_cpu(hdr.totalsize);
if (!smc->update_dt_enabled) {
return H_SUCCESS;
}
/* Check that the fdt did not grow out of proportion */
if (cb > spapr->fdt_initial_size * 2) {
trace_spapr_update_dt_failed_size(spapr->fdt_initial_size, cb,
fdt32_to_cpu(hdr.magic));
return H_PARAMETER;
}
fdt = g_malloc0(cb);
cpu_physical_memory_read(dt, fdt, cb);
/* Check the fdt consistency */
if (fdt_check_full(fdt, cb)) {
trace_spapr_update_dt_failed_check(spapr->fdt_initial_size, cb,
fdt32_to_cpu(hdr.magic));
return H_PARAMETER;
}
g_free(spapr->fdt_blob);
spapr->fdt_size = cb;
spapr->fdt_blob = fdt;
trace_spapr_update_dt(cb);
return H_SUCCESS;
}
@@ -1822,6 +1909,12 @@ static void hypercall_register_types(void)
/* ibm,client-architecture-support support */
spapr_register_hypercall(KVMPPC_H_CAS, h_client_architecture_support);
spapr_register_hypercall(KVMPPC_H_UPDATE_DT, h_update_dt);
/* Virtual Processor Home Node */
spapr_register_hypercall(H_HOME_NODE_ASSOCIATIVITY,
h_home_node_associativity);
}
type_init(hypercall_register_types)
+255 -15
View File
@@ -171,7 +171,7 @@ static qemu_irq spapr_qirq_xics(sPAPRMachineState *spapr, int irq)
uint32_t srcno = irq - ics->offset;
if (ics_valid_irq(ics, irq)) {
return ics->qirqs[srcno];
return spapr->qirqs[srcno];
}
return NULL;
@@ -184,16 +184,26 @@ static void spapr_irq_print_info_xics(sPAPRMachineState *spapr, Monitor *mon)
CPU_FOREACH(cs) {
PowerPCCPU *cpu = POWERPC_CPU(cs);
icp_pic_print_info(ICP(cpu->intc), mon);
icp_pic_print_info(cpu->icp, mon);
}
ics_pic_print_info(spapr->ics, mon);
}
static Object *spapr_irq_cpu_intc_create_xics(sPAPRMachineState *spapr,
Object *cpu, Error **errp)
static void spapr_irq_cpu_intc_create_xics(sPAPRMachineState *spapr,
PowerPCCPU *cpu, Error **errp)
{
return icp_create(cpu, spapr->icp_type, XICS_FABRIC(spapr), errp);
Error *local_err = NULL;
Object *obj;
obj = icp_create(OBJECT(cpu), spapr->icp_type, XICS_FABRIC(spapr),
&local_err);
if (local_err) {
error_propagate(errp, local_err);
return;
}
cpu->icp = ICP(obj);
}
static int spapr_irq_post_load_xics(sPAPRMachineState *spapr, int version_id)
@@ -202,12 +212,29 @@ static int spapr_irq_post_load_xics(sPAPRMachineState *spapr, int version_id)
CPUState *cs;
CPU_FOREACH(cs) {
PowerPCCPU *cpu = POWERPC_CPU(cs);
icp_resend(ICP(cpu->intc));
icp_resend(cpu->icp);
}
}
return 0;
}
static void spapr_irq_set_irq_xics(void *opaque, int srcno, int val)
{
sPAPRMachineState *spapr = opaque;
MachineState *machine = MACHINE(opaque);
if (kvm_enabled() && machine_kernel_irqchip_allowed(machine)) {
ics_kvm_set_irq(spapr->ics, srcno, val);
} else {
ics_simple_set_irq(spapr->ics, srcno, val);
}
}
static void spapr_irq_reset_xics(sPAPRMachineState *spapr, Error **errp)
{
/* TODO: create the KVM XICS device */
}
#define SPAPR_IRQ_XICS_NR_IRQS 0x1000
#define SPAPR_IRQ_XICS_NR_MSIS \
(XICS_IRQ_BASE + SPAPR_IRQ_XICS_NR_IRQS - SPAPR_IRQ_MSI)
@@ -225,6 +252,8 @@ sPAPRIrq spapr_irq_xics = {
.dt_populate = spapr_dt_xics,
.cpu_intc_create = spapr_irq_cpu_intc_create_xics,
.post_load = spapr_irq_post_load_xics,
.reset = spapr_irq_reset_xics,
.set_irq = spapr_irq_set_irq_xics,
};
/*
@@ -284,7 +313,16 @@ static void spapr_irq_free_xive(sPAPRMachineState *spapr, int irq, int num)
static qemu_irq spapr_qirq_xive(sPAPRMachineState *spapr, int irq)
{
return spapr_xive_qirq(spapr->xive, irq);
sPAPRXive *xive = spapr->xive;
if (irq >= xive->nr_irqs) {
return NULL;
}
/* The sPAPR machine/device should have claimed the IRQ before */
assert(xive_eas_is_valid(&xive->eat[irq]));
return spapr->qirqs[irq];
}
static void spapr_irq_print_info_xive(sPAPRMachineState *spapr,
@@ -295,23 +333,31 @@ static void spapr_irq_print_info_xive(sPAPRMachineState *spapr,
CPU_FOREACH(cs) {
PowerPCCPU *cpu = POWERPC_CPU(cs);
xive_tctx_pic_print_info(XIVE_TCTX(cpu->intc), mon);
xive_tctx_pic_print_info(cpu->tctx, mon);
}
spapr_xive_pic_print_info(spapr->xive, mon);
}
static Object *spapr_irq_cpu_intc_create_xive(sPAPRMachineState *spapr,
Object *cpu, Error **errp)
static void spapr_irq_cpu_intc_create_xive(sPAPRMachineState *spapr,
PowerPCCPU *cpu, Error **errp)
{
Object *obj = xive_tctx_create(cpu, XIVE_ROUTER(spapr->xive), errp);
Error *local_err = NULL;
Object *obj;
obj = xive_tctx_create(OBJECT(cpu), XIVE_ROUTER(spapr->xive), &local_err);
if (local_err) {
error_propagate(errp, local_err);
return;
}
cpu->tctx = XIVE_TCTX(obj);
/*
* (TCG) Early setting the OS CAM line for hotplugged CPUs as they
* don't benificiate from the reset of the XIVE IRQ backend
* don't beneficiate from the reset of the XIVE IRQ backend
*/
spapr_xive_set_tctx_os_cam(XIVE_TCTX(obj));
return obj;
spapr_xive_set_tctx_os_cam(cpu->tctx);
}
static int spapr_irq_post_load_xive(sPAPRMachineState *spapr, int version_id)
@@ -327,8 +373,18 @@ static void spapr_irq_reset_xive(sPAPRMachineState *spapr, Error **errp)
PowerPCCPU *cpu = POWERPC_CPU(cs);
/* (TCG) Set the OS CAM line of the thread interrupt context. */
spapr_xive_set_tctx_os_cam(XIVE_TCTX(cpu->intc));
spapr_xive_set_tctx_os_cam(cpu->tctx);
}
/* Activate the XIVE MMIOs */
spapr_xive_mmio_set_enabled(spapr->xive, true);
}
static void spapr_irq_set_irq_xive(void *opaque, int srcno, int val)
{
sPAPRMachineState *spapr = opaque;
xive_source_set_irq(&spapr->xive->source, srcno, val);
}
/*
@@ -353,6 +409,186 @@ sPAPRIrq spapr_irq_xive = {
.cpu_intc_create = spapr_irq_cpu_intc_create_xive,
.post_load = spapr_irq_post_load_xive,
.reset = spapr_irq_reset_xive,
.set_irq = spapr_irq_set_irq_xive,
};
/*
* Dual XIVE and XICS IRQ backend.
*
* Both interrupt mode, XIVE and XICS, objects are created but the
* machine starts in legacy interrupt mode (XICS). It can be changed
* by the CAS negotiation process and, in that case, the new mode is
* activated after an extra machine reset.
*/
/*
* Returns the sPAPR IRQ backend negotiated by CAS. XICS is the
* default.
*/
static sPAPRIrq *spapr_irq_current(sPAPRMachineState *spapr)
{
return spapr_ovec_test(spapr->ov5_cas, OV5_XIVE_EXPLOIT) ?
&spapr_irq_xive : &spapr_irq_xics;
}
static void spapr_irq_init_dual(sPAPRMachineState *spapr, Error **errp)
{
MachineState *machine = MACHINE(spapr);
Error *local_err = NULL;
if (kvm_enabled() && machine_kernel_irqchip_allowed(machine)) {
error_setg(errp, "No KVM support for the 'dual' machine");
return;
}
spapr_irq_xics.init(spapr, &local_err);
if (local_err) {
error_propagate(errp, local_err);
return;
}
/*
* Align the XICS and the XIVE IRQ number space under QEMU.
*
* However, the XICS KVM device still considers that the IRQ
* numbers should start at XICS_IRQ_BASE (0x1000). Either we
* should introduce a KVM device ioctl to set the offset or ignore
* the lower 4K numbers when using the get/set ioctl of the XICS
* KVM device. The second option seems the least intrusive.
*/
spapr->ics->offset = 0;
spapr_irq_xive.init(spapr, &local_err);
if (local_err) {
error_propagate(errp, local_err);
return;
}
}
static int spapr_irq_claim_dual(sPAPRMachineState *spapr, int irq, bool lsi,
Error **errp)
{
Error *local_err = NULL;
int ret;
ret = spapr_irq_xics.claim(spapr, irq, lsi, &local_err);
if (local_err) {
error_propagate(errp, local_err);
return ret;
}
ret = spapr_irq_xive.claim(spapr, irq, lsi, &local_err);
if (local_err) {
error_propagate(errp, local_err);
return ret;
}
return ret;
}
static void spapr_irq_free_dual(sPAPRMachineState *spapr, int irq, int num)
{
spapr_irq_xics.free(spapr, irq, num);
spapr_irq_xive.free(spapr, irq, num);
}
static qemu_irq spapr_qirq_dual(sPAPRMachineState *spapr, int irq)
{
sPAPRXive *xive = spapr->xive;
ICSState *ics = spapr->ics;
if (irq >= spapr->irq->nr_irqs) {
return NULL;
}
/*
* The IRQ number should have been claimed under both interrupt
* controllers.
*/
assert(!ICS_IRQ_FREE(ics, irq - ics->offset));
assert(xive_eas_is_valid(&xive->eat[irq]));
return spapr->qirqs[irq];
}
static void spapr_irq_print_info_dual(sPAPRMachineState *spapr, Monitor *mon)
{
spapr_irq_current(spapr)->print_info(spapr, mon);
}
static void spapr_irq_dt_populate_dual(sPAPRMachineState *spapr,
uint32_t nr_servers, void *fdt,
uint32_t phandle)
{
spapr_irq_current(spapr)->dt_populate(spapr, nr_servers, fdt, phandle);
}
static void spapr_irq_cpu_intc_create_dual(sPAPRMachineState *spapr,
PowerPCCPU *cpu, Error **errp)
{
Error *local_err = NULL;
spapr_irq_xive.cpu_intc_create(spapr, cpu, &local_err);
if (local_err) {
error_propagate(errp, local_err);
return;
}
spapr_irq_xics.cpu_intc_create(spapr, cpu, errp);
}
static int spapr_irq_post_load_dual(sPAPRMachineState *spapr, int version_id)
{
/*
* Force a reset of the XIVE backend after migration. The machine
* defaults to XICS at startup.
*/
if (spapr_ovec_test(spapr->ov5_cas, OV5_XIVE_EXPLOIT)) {
spapr_irq_xive.reset(spapr, &error_fatal);
}
return spapr_irq_current(spapr)->post_load(spapr, version_id);
}
static void spapr_irq_reset_dual(sPAPRMachineState *spapr, Error **errp)
{
/*
* Deactivate the XIVE MMIOs. The XIVE backend will reenable them
* if selected.
*/
spapr_xive_mmio_set_enabled(spapr->xive, false);
spapr_irq_current(spapr)->reset(spapr, errp);
}
static void spapr_irq_set_irq_dual(void *opaque, int srcno, int val)
{
sPAPRMachineState *spapr = opaque;
spapr_irq_current(spapr)->set_irq(spapr, srcno, val);
}
/*
* Define values in sync with the XIVE and XICS backend
*/
#define SPAPR_IRQ_DUAL_NR_IRQS 0x2000
#define SPAPR_IRQ_DUAL_NR_MSIS (SPAPR_IRQ_DUAL_NR_IRQS - SPAPR_IRQ_MSI)
sPAPRIrq spapr_irq_dual = {
.nr_irqs = SPAPR_IRQ_DUAL_NR_IRQS,
.nr_msis = SPAPR_IRQ_DUAL_NR_MSIS,
.ov5 = SPAPR_OV5_XIVE_BOTH,
.init = spapr_irq_init_dual,
.claim = spapr_irq_claim_dual,
.free = spapr_irq_free_dual,
.qirq = spapr_qirq_dual,
.print_info = spapr_irq_print_info_dual,
.dt_populate = spapr_irq_dt_populate_dual,
.cpu_intc_create = spapr_irq_cpu_intc_create_dual,
.post_load = spapr_irq_post_load_dual,
.reset = spapr_irq_reset_dual,
.set_irq = spapr_irq_set_irq_dual
};
/*
@@ -366,6 +602,9 @@ void spapr_irq_init(sPAPRMachineState *spapr, Error **errp)
}
spapr->irq->init(spapr, errp);
spapr->qirqs = qemu_allocate_irqs(spapr->irq->set_irq, spapr,
spapr->irq->nr_irqs);
}
int spapr_irq_claim(sPAPRMachineState *spapr, int irq, bool lsi, Error **errp)
@@ -465,4 +704,5 @@ sPAPRIrq spapr_irq_xics_legacy = {
.dt_populate = spapr_dt_xics,
.cpu_intc_create = spapr_irq_cpu_intc_create_xics,
.post_load = spapr_irq_post_load_xics,
.set_irq = spapr_irq_set_irq_xics,
};
-11
View File
@@ -1988,17 +1988,6 @@ static const TypeInfo spapr_phb_info = {
}
};
PCIHostState *spapr_create_phb(sPAPRMachineState *spapr, int index)
{
DeviceState *dev;
dev = qdev_create(NULL, TYPE_SPAPR_PCI_HOST_BRIDGE);
qdev_prop_set_uint32(dev, "index", index);
qdev_init_nofail(dev);
return PCI_HOST_BRIDGE(dev);
}
typedef struct sPAPRFDT {
void *fdt;
int node_off;
+3
View File
@@ -22,6 +22,9 @@ spapr_cas_pvr_try(uint32_t pvr) "0x%x"
spapr_cas_pvr(uint32_t cur_pvr, bool explicit_match, uint32_t new_pvr) "current=0x%x, explicit_match=%u, new=0x%x"
spapr_h_resize_hpt_prepare(uint64_t flags, uint64_t shift) "flags=0x%"PRIx64", shift=%"PRIu64
spapr_h_resize_hpt_commit(uint64_t flags, uint64_t shift) "flags=0x%"PRIx64", shift=%"PRIu64
spapr_update_dt(unsigned cb) "New blob %u bytes"
spapr_update_dt_failed_size(unsigned cbold, unsigned cbnew, unsigned magic) "Old blob %u bytes, new blob %u bytes, magic 0x%x"
spapr_update_dt_failed_check(unsigned cbold, unsigned cbnew, unsigned magic) "Old blob %u bytes, new blob %u bytes, magic 0x%x"
# hw/ppc/spapr_iommu.c
spapr_iommu_put(uint64_t liobn, uint64_t ioba, uint64_t tce, uint64_t ret) "liobn=0x%"PRIx64" ioba=0x%"PRIx64" tce=0x%"PRIx64" ret=%"PRId64
+4 -4
View File
@@ -94,11 +94,13 @@ struct sPAPRPHBState {
((1ULL << 32) - SPAPR_PCI_MEM_WIN_BUS_OFFSET)
#define SPAPR_PCI_MEM64_WIN_SIZE 0x10000000000ULL /* 1 TiB */
/* Without manual configuration, all PCI outbound windows will be
* within this range */
/* All PCI outbound windows will be within this range */
#define SPAPR_PCI_BASE (1ULL << 45) /* 32 TiB */
#define SPAPR_PCI_LIMIT (1ULL << 46) /* 64 TiB */
#define SPAPR_MAX_PHBS ((SPAPR_PCI_LIMIT - SPAPR_PCI_BASE) / \
SPAPR_PCI_MEM64_WIN_SIZE - 1)
#define SPAPR_PCI_2_7_MMIO_WIN_SIZE 0xf80000000
#define SPAPR_PCI_IO_WIN_SIZE 0x10000
@@ -111,8 +113,6 @@ static inline qemu_irq spapr_phb_lsi_qirq(struct sPAPRPHBState *phb, int pin)
return spapr_qirq(spapr, phb->lsi_table[pin].irq);
}
PCIHostState *spapr_create_phb(sPAPRMachineState *spapr, int index);
int spapr_populate_pci_dt(sPAPRPHBState *phb, uint32_t xics_phandle, void *fdt,
uint32_t nr_msis);
+3
View File
@@ -405,8 +405,10 @@ PCIBus *pci_root_bus_new(DeviceState *parent, const char *name,
MemoryRegion *address_space_mem,
MemoryRegion *address_space_io,
uint8_t devfn_min, const char *typename);
void pci_root_bus_cleanup(PCIBus *bus);
void pci_bus_irqs(PCIBus *bus, pci_set_irq_fn set_irq, pci_map_irq_fn map_irq,
void *irq_opaque, int nirq);
void pci_bus_irqs_cleanup(PCIBus *bus);
int pci_bus_get_irq_level(PCIBus *bus, int irq_num);
/* 0 <= pin <= 3 0 = INTA, 1 = INTB, 2 = INTC, 3 = INTD */
int pci_swizzle_map_irq_fn(PCIDevice *pci_dev, int pin);
@@ -417,6 +419,7 @@ PCIBus *pci_register_root_bus(DeviceState *parent, const char *name,
MemoryRegion *address_space_io,
uint8_t devfn_min, int nirq,
const char *typename);
void pci_unregister_root_bus(PCIBus *bus);
void pci_bus_set_route_irq_fn(PCIBus *, pci_route_irq_fn);
PCIINTxRoute pci_device_route_intx_to_irq(PCIDevice *dev, int pin);
bool pci_intx_route_changed(PCIINTxRoute *old, PCIINTxRoute *new);

Some files were not shown because too many files have changed in this diff Show More