summaryrefslogtreecommitdiffstats
path: root/hw/ppc
diff options
context:
space:
mode:
Diffstat (limited to 'hw/ppc')
-rw-r--r--hw/ppc/e500.c19
-rw-r--r--hw/ppc/mac_newworld.c40
-rw-r--r--hw/ppc/mac_oldworld.c10
-rw-r--r--hw/ppc/pnv.c27
-rw-r--r--hw/ppc/pnv_core.c4
-rw-r--r--hw/ppc/pnv_psi.c7
-rw-r--r--hw/ppc/ppc405_boards.c16
-rw-r--r--hw/ppc/ppc405_uc.c6
-rw-r--r--hw/ppc/ppc440_bamboo.c7
-rw-r--r--hw/ppc/ppc4xx_devs.c3
-rw-r--r--hw/ppc/prep.c4
-rw-r--r--hw/ppc/sam460ex.c4
-rw-r--r--hw/ppc/spapr.c448
-rw-r--r--hw/ppc/spapr_cpu_core.c11
-rw-r--r--hw/ppc/spapr_hcall.c93
-rw-r--r--hw/ppc/spapr_iommu.c4
-rw-r--r--hw/ppc/spapr_irq.c439
-rw-r--r--hw/ppc/spapr_pci.c44
-rw-r--r--hw/ppc/spapr_rtas_ddw.c19
-rw-r--r--hw/ppc/spapr_vio.c2
-rw-r--r--hw/ppc/trace-events3
-rw-r--r--hw/ppc/virtex_ml507.c2
22 files changed, 851 insertions, 361 deletions
diff --git a/hw/ppc/e500.c b/hw/ppc/e500.c
index e6747fce28..0581e9e3d4 100644
--- a/hw/ppc/e500.c
+++ b/hw/ppc/e500.c
@@ -685,7 +685,7 @@ static void ppce500_cpu_reset(void *opaque)
}
static DeviceState *ppce500_init_mpic_qemu(PPCE500MachineState *pms,
- qemu_irq **irqs)
+ IrqLines *irqs)
{
DeviceState *dev;
SysBusDevice *s;
@@ -705,7 +705,7 @@ static DeviceState *ppce500_init_mpic_qemu(PPCE500MachineState *pms,
k = 0;
for (i = 0; i < smp_cpus; i++) {
for (j = 0; j < OPENPIC_OUTPUT_NB; j++) {
- sysbus_connect_irq(s, k++, irqs[i][j]);
+ sysbus_connect_irq(s, k++, irqs[i].irq[j]);
}
}
@@ -713,7 +713,7 @@ static DeviceState *ppce500_init_mpic_qemu(PPCE500MachineState *pms,
}
static DeviceState *ppce500_init_mpic_kvm(const PPCE500MachineClass *pmc,
- qemu_irq **irqs, Error **errp)
+ IrqLines *irqs, Error **errp)
{
Error *err = NULL;
DeviceState *dev;
@@ -742,7 +742,7 @@ static DeviceState *ppce500_init_mpic_kvm(const PPCE500MachineClass *pmc,
static DeviceState *ppce500_init_mpic(PPCE500MachineState *pms,
MemoryRegion *ccsr,
- qemu_irq **irqs)
+ IrqLines *irqs)
{
MachineState *machine = MACHINE(pms);
const PPCE500MachineClass *pmc = PPCE500_MACHINE_GET_CLASS(pms);
@@ -806,15 +806,14 @@ void ppce500_init(MachineState *machine)
/* irq num for pin INTA, INTB, INTC and INTD is 1, 2, 3 and
* 4 respectively */
unsigned int pci_irq_nrs[PCI_NUM_PINS] = {1, 2, 3, 4};
- qemu_irq **irqs;
+ IrqLines *irqs;
DeviceState *dev, *mpicdev;
CPUPPCState *firstenv = NULL;
MemoryRegion *ccsr_addr_space;
SysBusDevice *s;
PPCE500CCSRState *ccsr;
- irqs = g_malloc0(smp_cpus * sizeof(qemu_irq *));
- irqs[0] = g_malloc0(smp_cpus * sizeof(qemu_irq) * OPENPIC_OUTPUT_NB);
+ irqs = g_new0(IrqLines, smp_cpus);
for (i = 0; i < smp_cpus; i++) {
PowerPCCPU *cpu;
CPUState *cs;
@@ -834,10 +833,9 @@ void ppce500_init(MachineState *machine)
firstenv = env;
}
- irqs[i] = irqs[0] + (i * OPENPIC_OUTPUT_NB);
input = (qemu_irq *)env->irq_inputs;
- irqs[i][OPENPIC_OUTPUT_INT] = input[PPCE500_INPUT_INT];
- irqs[i][OPENPIC_OUTPUT_CINT] = input[PPCE500_INPUT_CINT];
+ irqs[i].irq[OPENPIC_OUTPUT_INT] = input[PPCE500_INPUT_INT];
+ irqs[i].irq[OPENPIC_OUTPUT_CINT] = input[PPCE500_INPUT_CINT];
env->spr_cb[SPR_BOOKE_PIR].default_value = cs->cpu_index = i;
env->mpic_iack = pmc->ccsrbar_base + MPC8544_MPIC_REGS_OFFSET + 0xa0;
@@ -997,6 +995,7 @@ void ppce500_init(MachineState *machine)
* Hrm. No ELF image? Try a uImage, maybe someone is giving us an
* ePAPR compliant kernel
*/
+ loadaddr = LOAD_UIMAGE_LOADADDR_INVALID;
payload_size = load_uimage(filename, &bios_entry, &loadaddr, NULL,
NULL, NULL);
if (payload_size < 0) {
diff --git a/hw/ppc/mac_newworld.c b/hw/ppc/mac_newworld.c
index 14273a123e..bb19eaba36 100644
--- a/hw/ppc/mac_newworld.c
+++ b/hw/ppc/mac_newworld.c
@@ -115,7 +115,7 @@ static void ppc_core99_init(MachineState *machine)
PowerPCCPU *cpu = NULL;
CPUPPCState *env = NULL;
char *filename;
- qemu_irq **openpic_irqs;
+ IrqLines *openpic_irqs;
int linux_boot, i, j, k;
MemoryRegion *ram = g_new(MemoryRegion, 1), *bios = g_new(MemoryRegion, 1);
hwaddr kernel_base, initrd_base, cmdline_base = 0;
@@ -127,8 +127,7 @@ static void ppc_core99_init(MachineState *machine)
MACIOIDEState *macio_ide;
BusState *adb_bus;
MacIONVRAMState *nvr;
- int bios_size, ndrv_size;
- uint8_t *ndrv_file;
+ int bios_size;
int ppc_boot_device;
DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
void *fw_cfg;
@@ -249,41 +248,37 @@ static void ppc_core99_init(MachineState *machine)
memory_region_add_subregion(get_system_memory(), 0xf8000000,
sysbus_mmio_get_region(s, 0));
- openpic_irqs = g_malloc0(smp_cpus * sizeof(qemu_irq *));
- openpic_irqs[0] =
- g_malloc0(smp_cpus * sizeof(qemu_irq) * OPENPIC_OUTPUT_NB);
+ openpic_irqs = g_new0(IrqLines, smp_cpus);
for (i = 0; i < smp_cpus; i++) {
/* Mac99 IRQ connection between OpenPIC outputs pins
* and PowerPC input pins
*/
switch (PPC_INPUT(env)) {
case PPC_FLAGS_INPUT_6xx:
- openpic_irqs[i] = openpic_irqs[0] + (i * OPENPIC_OUTPUT_NB);
- openpic_irqs[i][OPENPIC_OUTPUT_INT] =
+ openpic_irqs[i].irq[OPENPIC_OUTPUT_INT] =
((qemu_irq *)env->irq_inputs)[PPC6xx_INPUT_INT];
- openpic_irqs[i][OPENPIC_OUTPUT_CINT] =
+ openpic_irqs[i].irq[OPENPIC_OUTPUT_CINT] =
((qemu_irq *)env->irq_inputs)[PPC6xx_INPUT_INT];
- openpic_irqs[i][OPENPIC_OUTPUT_MCK] =
+ openpic_irqs[i].irq[OPENPIC_OUTPUT_MCK] =
((qemu_irq *)env->irq_inputs)[PPC6xx_INPUT_MCP];
/* Not connected ? */
- openpic_irqs[i][OPENPIC_OUTPUT_DEBUG] = NULL;
+ openpic_irqs[i].irq[OPENPIC_OUTPUT_DEBUG] = NULL;
/* Check this */
- openpic_irqs[i][OPENPIC_OUTPUT_RESET] =
+ openpic_irqs[i].irq[OPENPIC_OUTPUT_RESET] =
((qemu_irq *)env->irq_inputs)[PPC6xx_INPUT_HRESET];
break;
#if defined(TARGET_PPC64)
case PPC_FLAGS_INPUT_970:
- openpic_irqs[i] = openpic_irqs[0] + (i * OPENPIC_OUTPUT_NB);
- openpic_irqs[i][OPENPIC_OUTPUT_INT] =
+ openpic_irqs[i].irq[OPENPIC_OUTPUT_INT] =
((qemu_irq *)env->irq_inputs)[PPC970_INPUT_INT];
- openpic_irqs[i][OPENPIC_OUTPUT_CINT] =
+ openpic_irqs[i].irq[OPENPIC_OUTPUT_CINT] =
((qemu_irq *)env->irq_inputs)[PPC970_INPUT_INT];
- openpic_irqs[i][OPENPIC_OUTPUT_MCK] =
+ openpic_irqs[i].irq[OPENPIC_OUTPUT_MCK] =
((qemu_irq *)env->irq_inputs)[PPC970_INPUT_MCP];
/* Not connected ? */
- openpic_irqs[i][OPENPIC_OUTPUT_DEBUG] = NULL;
+ openpic_irqs[i].irq[OPENPIC_OUTPUT_DEBUG] = NULL;
/* Check this */
- openpic_irqs[i][OPENPIC_OUTPUT_RESET] =
+ openpic_irqs[i].irq[OPENPIC_OUTPUT_RESET] =
((qemu_irq *)env->irq_inputs)[PPC970_INPUT_HRESET];
break;
#endif /* defined(TARGET_PPC64) */
@@ -300,7 +295,7 @@ static void ppc_core99_init(MachineState *machine)
k = 0;
for (i = 0; i < smp_cpus; i++) {
for (j = 0; j < OPENPIC_OUTPUT_NB; j++) {
- sysbus_connect_irq(s, k++, openpic_irqs[i][j]);
+ sysbus_connect_irq(s, k++, openpic_irqs[i].irq[j]);
}
}
g_free(openpic_irqs);
@@ -510,11 +505,10 @@ static void ppc_core99_init(MachineState *machine)
/* MacOS NDRV VGA driver */
filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, NDRV_VGA_FILENAME);
if (filename) {
- ndrv_size = get_image_size(filename);
- if (ndrv_size != -1) {
- ndrv_file = g_malloc(ndrv_size);
- ndrv_size = load_image(filename, ndrv_file);
+ gchar *ndrv_file;
+ gsize ndrv_size;
+ if (g_file_get_contents(filename, &ndrv_file, &ndrv_size, NULL)) {
fw_cfg_add_file(fw_cfg, "ndrv/qemu_vga.ndrv", ndrv_file, ndrv_size);
}
g_free(filename);
diff --git a/hw/ppc/mac_oldworld.c b/hw/ppc/mac_oldworld.c
index 9891c325a9..817f70e52c 100644
--- a/hw/ppc/mac_oldworld.c
+++ b/hw/ppc/mac_oldworld.c
@@ -99,8 +99,7 @@ static void ppc_heathrow_init(MachineState *machine)
SysBusDevice *s;
DeviceState *dev, *pic_dev;
BusState *adb_bus;
- int bios_size, ndrv_size;
- uint8_t *ndrv_file;
+ int bios_size;
uint16_t ppc_boot_device;
DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
void *fw_cfg;
@@ -361,11 +360,10 @@ static void ppc_heathrow_init(MachineState *machine)
/* MacOS NDRV VGA driver */
filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, NDRV_VGA_FILENAME);
if (filename) {
- ndrv_size = get_image_size(filename);
- if (ndrv_size != -1) {
- ndrv_file = g_malloc(ndrv_size);
- ndrv_size = load_image(filename, ndrv_file);
+ gchar *ndrv_file;
+ gsize ndrv_size;
+ if (g_file_get_contents(filename, &ndrv_file, &ndrv_size, NULL)) {
fw_cfg_add_file(fw_cfg, "ndrv/qemu_vga.ndrv", ndrv_file, ndrv_size);
}
g_free(filename);
diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c
index 346f5e7aed..d84acef55b 100644
--- a/hw/ppc/pnv.c
+++ b/hw/ppc/pnv.c
@@ -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++) {
diff --git a/hw/ppc/pnv_core.c b/hw/ppc/pnv_core.c
index ad1bcc7990..b98f277f1e 100644
--- a/hw/ppc/pnv_core.c
+++ b/hw/ppc/pnv_core.c
@@ -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));
}
diff --git a/hw/ppc/pnv_psi.c b/hw/ppc/pnv_psi.c
index 5b969127c3..8ced095063 100644
--- a/hw/ppc/pnv_psi.c
+++ b/hw/ppc/pnv_psi.c
@@ -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);
diff --git a/hw/ppc/ppc405_boards.c b/hw/ppc/ppc405_boards.c
index 3be3fe4432..f47b15f10e 100644
--- a/hw/ppc/ppc405_boards.c
+++ b/hw/ppc/ppc405_boards.c
@@ -149,7 +149,7 @@ static void ref405ep_init(MachineState *machine)
MemoryRegion *bios;
MemoryRegion *sram = g_new(MemoryRegion, 1);
ram_addr_t bdloc;
- MemoryRegion *ram_memories = g_malloc(2 * sizeof(*ram_memories));
+ MemoryRegion *ram_memories = g_new(MemoryRegion, 2);
hwaddr ram_bases[2], ram_sizes[2];
target_ulong sram_size;
long bios_size;
@@ -219,9 +219,11 @@ static void ref405ep_init(MachineState *machine)
bios_name = BIOS_FILENAME;
filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
if (filename) {
- bios_size = load_image(filename, memory_region_get_ram_ptr(bios));
+ bios_size = load_image_size(filename,
+ memory_region_get_ram_ptr(bios),
+ BIOS_SIZE);
g_free(filename);
- if (bios_size < 0 || bios_size > BIOS_SIZE) {
+ if (bios_size < 0) {
error_report("Could not load PowerPC BIOS '%s'", bios_name);
exit(1);
}
@@ -446,7 +448,7 @@ static void taihu_405ep_init(MachineState *machine)
qemu_irq *pic;
MemoryRegion *sysmem = get_system_memory();
MemoryRegion *bios;
- MemoryRegion *ram_memories = g_malloc(2 * sizeof(*ram_memories));
+ MemoryRegion *ram_memories = g_new(MemoryRegion, 2);
MemoryRegion *ram = g_malloc0(sizeof(*ram));
hwaddr ram_bases[2], ram_sizes[2];
long bios_size;
@@ -515,9 +517,11 @@ static void taihu_405ep_init(MachineState *machine)
&error_fatal);
filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
if (filename) {
- bios_size = load_image(filename, memory_region_get_ram_ptr(bios));
+ bios_size = load_image_size(filename,
+ memory_region_get_ram_ptr(bios),
+ BIOS_SIZE);
g_free(filename);
- if (bios_size < 0 || bios_size > BIOS_SIZE) {
+ if (bios_size < 0) {
error_report("Could not load PowerPC BIOS '%s'", bios_name);
exit(1);
}
diff --git a/hw/ppc/ppc405_uc.c b/hw/ppc/ppc405_uc.c
index 5c58415cf1..8d3a797cb8 100644
--- a/hw/ppc/ppc405_uc.c
+++ b/hw/ppc/ppc405_uc.c
@@ -1519,7 +1519,7 @@ CPUPPCState *ppc405cr_init(MemoryRegion *address_space_mem,
/* OBP arbitrer */
ppc4xx_opba_init(0xef600600);
/* Universal interrupt controller */
- irqs = g_malloc0(sizeof(qemu_irq) * PPCUIC_OUTPUT_NB);
+ irqs = g_new0(qemu_irq, PPCUIC_OUTPUT_NB);
irqs[PPCUIC_OUTPUT_INT] =
((qemu_irq *)env->irq_inputs)[PPC40x_INPUT_INT];
irqs[PPCUIC_OUTPUT_CINT] =
@@ -1877,7 +1877,7 @@ CPUPPCState *ppc405ep_init(MemoryRegion *address_space_mem,
/* Initialize timers */
ppc_booke_timers_init(cpu, sysclk, 0);
/* Universal interrupt controller */
- irqs = g_malloc0(sizeof(qemu_irq) * PPCUIC_OUTPUT_NB);
+ irqs = g_new0(qemu_irq, PPCUIC_OUTPUT_NB);
irqs[PPCUIC_OUTPUT_INT] =
((qemu_irq *)env->irq_inputs)[PPC40x_INPUT_INT];
irqs[PPCUIC_OUTPUT_CINT] =
@@ -1885,7 +1885,7 @@ CPUPPCState *ppc405ep_init(MemoryRegion *address_space_mem,
pic = ppcuic_init(env, irqs, 0x0C0, 0, 1);
*picp = pic;
/* SDRAM controller */
- /* XXX 405EP has no ECC interrupt */
+ /* XXX 405EP has no ECC interrupt */
ppc4xx_sdram_init(env, pic[17], 2, ram_memories,
ram_bases, ram_sizes, do_init);
/* External bus controller */
diff --git a/hw/ppc/ppc440_bamboo.c b/hw/ppc/ppc440_bamboo.c
index f5720f979e..fc06191588 100644
--- a/hw/ppc/ppc440_bamboo.c
+++ b/hw/ppc/ppc440_bamboo.c
@@ -169,8 +169,7 @@ static void bamboo_init(MachineState *machine)
unsigned int pci_irq_nrs[4] = { 28, 27, 26, 25 };
MemoryRegion *address_space_mem = get_system_memory();
MemoryRegion *isa = g_new(MemoryRegion, 1);
- MemoryRegion *ram_memories
- = g_malloc(PPC440EP_SDRAM_NR_BANKS * sizeof(*ram_memories));
+ MemoryRegion *ram_memories = g_new(MemoryRegion, PPC440EP_SDRAM_NR_BANKS);
hwaddr ram_bases[PPC440EP_SDRAM_NR_BANKS];
hwaddr ram_sizes[PPC440EP_SDRAM_NR_BANKS];
qemu_irq *pic;
@@ -180,7 +179,7 @@ static void bamboo_init(MachineState *machine)
CPUPPCState *env;
uint64_t elf_entry;
uint64_t elf_lowaddr;
- hwaddr loadaddr = 0;
+ hwaddr loadaddr = LOAD_UIMAGE_LOADADDR_INVALID;
target_long initrd_size = 0;
DeviceState *dev;
int success;
@@ -200,7 +199,7 @@ static void bamboo_init(MachineState *machine)
ppc_dcr_init(env, NULL, NULL);
/* interrupt controller */
- irqs = g_malloc0(sizeof(qemu_irq) * PPCUIC_OUTPUT_NB);
+ irqs = g_new0(qemu_irq, PPCUIC_OUTPUT_NB);
irqs[PPCUIC_OUTPUT_INT] = ((qemu_irq *)env->irq_inputs)[PPC40x_INPUT_INT];
irqs[PPCUIC_OUTPUT_CINT] = ((qemu_irq *)env->irq_inputs)[PPC40x_INPUT_CINT];
pic = ppcuic_init(env, irqs, 0x0C0, 0, 1);
diff --git a/hw/ppc/ppc4xx_devs.c b/hw/ppc/ppc4xx_devs.c
index 8c6f3c9577..9b6e4c60fa 100644
--- a/hw/ppc/ppc4xx_devs.c
+++ b/hw/ppc/ppc4xx_devs.c
@@ -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__)
diff --git a/hw/ppc/prep.c b/hw/ppc/prep.c
index 2afb7f437e..7bda86a7d0 100644
--- a/hw/ppc/prep.c
+++ b/hw/ppc/prep.c
@@ -538,7 +538,7 @@ static void ppc_prep_init(MachineState *machine)
nb_nics1 = NE2000_NB_MAX;
for(i = 0; i < nb_nics1; i++) {
if (nd_table[i].model == NULL) {
- nd_table[i].model = g_strdup("ne2k_isa");
+ nd_table[i].model = g_strdup("ne2k_isa");
}
if (strcmp(nd_table[i].model, "ne2k_isa") == 0) {
isa_ne2000_init(isa_bus, ne2000_io[i], ne2000_irq[i],
@@ -552,7 +552,7 @@ static void ppc_prep_init(MachineState *machine)
for(i = 0; i < MAX_IDE_BUS; i++) {
isa_ide_init(isa_bus, ide_iobase[i], ide_iobase2[i], ide_irq[i],
hd[2 * i],
- hd[2 * i + 1]);
+ hd[2 * i + 1]);
}
cpu = POWERPC_CPU(first_cpu);
diff --git a/hw/ppc/sam460ex.c b/hw/ppc/sam460ex.c
index 5aac58f36e..84ea592749 100644
--- a/hw/ppc/sam460ex.c
+++ b/hw/ppc/sam460ex.c
@@ -402,7 +402,7 @@ static void sam460ex_init(MachineState *machine)
CPUPPCState *env;
PPC4xxI2CState *i2c[2];
hwaddr entry = UBOOT_ENTRY;
- hwaddr loadaddr = 0;
+ hwaddr loadaddr = LOAD_UIMAGE_LOADADDR_INVALID;
target_long initrd_size = 0;
DeviceState *dev;
SysBusDevice *sbdev;
@@ -430,7 +430,7 @@ static void sam460ex_init(MachineState *machine)
ppc4xx_plb_init(env);
/* interrupt controllers */
- irqs = g_malloc0(sizeof(*irqs) * PPCUIC_OUTPUT_NB);
+ irqs = g_new0(qemu_irq, PPCUIC_OUTPUT_NB);
irqs[PPCUIC_OUTPUT_INT] = ((qemu_irq *)env->irq_inputs)[PPC40x_INPUT_INT];
irqs[PPCUIC_OUTPUT_CINT] = ((qemu_irq *)env->irq_inputs)[PPC40x_INPUT_CINT];
uic[0] = ppcuic_init(env, irqs, 0xc0, 0, 1);
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index 7afd1a175b..0942f35bf8 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -70,7 +70,6 @@
#include "hw/nmi.h"
#include "hw/intc/intc.h"
-#include "hw/compat.h"
#include "qemu/cutils.h"
#include "hw/ppc/spapr_cpu_core.h"
#include "hw/mem/memory-device.h"
@@ -150,7 +149,7 @@ static void pre_2_10_vmstate_unregister_dummy_icp(int i)
(void *)(uintptr_t) i);
}
-static int xics_max_server_number(sPAPRMachineState *spapr)
+int spapr_max_server_number(sPAPRMachineState *spapr)
{
assert(spapr->vsmt);
return DIV_ROUND_UP(max_cpus * spapr->vsmt, smp_threads);
@@ -889,8 +888,6 @@ static int spapr_populate_drconf_memory(sPAPRMachineState *spapr, void *fdt)
/* ibm,associativity-lookup-arrays */
buf_len = (nr_nodes * 4 + 2) * sizeof(uint32_t);
cur_index = int_buf = g_malloc0(buf_len);
-
- cur_index = int_buf;
int_buf[0] = cpu_to_be32(nr_nodes);
int_buf[1] = cpu_to_be32(4); /* Number of entries per associativity list */
cur_index += 2;
@@ -1033,7 +1030,7 @@ static void spapr_dt_rtas(sPAPRMachineState *spapr, void *fdt)
cpu_to_be32(0),
cpu_to_be32(0),
cpu_to_be32(0),
- cpu_to_be32(nb_numa_nodes ? nb_numa_nodes - 1 : 0),
+ cpu_to_be32(nb_numa_nodes ? nb_numa_nodes : 1),
};
_FDT(rtas = fdt_add_subnode(fdt, 0, "rtas"));
@@ -1051,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()) {
@@ -1097,15 +1095,18 @@ static void spapr_dt_rtas(sPAPRMachineState *spapr, void *fdt)
spapr_dt_rtas_tokens(fdt, rtas);
}
-/* Prepare ibm,arch-vec-5-platform-support, which indicates the MMU features
- * that the guest may request and thus the valid values for bytes 24..26 of
- * option vector 5: */
-static void spapr_dt_ov5_platform_support(void *fdt, int chosen)
+/*
+ * Prepare ibm,arch-vec-5-platform-support, which indicates the MMU
+ * and the XIVE features that the guest may request and thus the valid
+ * values for bytes 23..26 of option vector 5:
+ */
+static void spapr_dt_ov5_platform_support(sPAPRMachineState *spapr, void *fdt,
+ int chosen)
{
PowerPCCPU *first_ppc_cpu = POWERPC_CPU(first_cpu);
char val[2 * 4] = {
- 23, 0x00, /* Xive mode, filled in below. */
+ 23, spapr->irq->ov5, /* Xive mode. */
24, 0x00, /* Hash/Radix, filled in below. */
25, 0x00, /* Hash options: Segment Tables == no, GTSE == no. */
26, 0x40, /* Radix options: GTSE == yes. */
@@ -1113,7 +1114,11 @@ static void spapr_dt_ov5_platform_support(void *fdt, int chosen)
if (!ppc_check_compat(first_ppc_cpu, CPU_POWERPC_LOGICAL_3_00, 0,
first_ppc_cpu->compat_pvr)) {
- /* If we're in a pre POWER9 compat mode then the guest should do hash */
+ /*
+ * If we're in a pre POWER9 compat mode then the guest should
+ * do hash and use the legacy interrupt mode
+ */
+ val[1] = 0x00; /* XICS */
val[3] = 0x00; /* Hash */
} else if (kvm_enabled()) {
if (kvmppc_has_cap_mmu_radix() && kvmppc_has_cap_mmu_hash_v3()) {
@@ -1191,7 +1196,7 @@ static void spapr_dt_chosen(sPAPRMachineState *spapr, void *fdt)
_FDT(fdt_setprop_string(fdt, chosen, "stdout-path", stdout_path));
}
- spapr_dt_ov5_platform_support(fdt, chosen);
+ spapr_dt_ov5_platform_support(spapr, fdt, chosen);
g_free(stdout_path);
g_free(bootlist);
@@ -1270,7 +1275,8 @@ static void *spapr_build_fdt(sPAPRMachineState *spapr,
_FDT(fdt_setprop_cell(fdt, 0, "#size-cells", 2));
/* /interrupt controller */
- spapr_dt_xics(xics_max_server_number(spapr), fdt, PHANDLE_XICP);
+ spapr->irq->dt_populate(spapr, spapr_max_server_number(spapr), fdt,
+ PHANDLE_XICP);
ret = spapr_populate_memory(spapr, fdt);
if (ret < 0) {
@@ -1290,7 +1296,8 @@ static void *spapr_build_fdt(sPAPRMachineState *spapr,
}
QLIST_FOREACH(phb, &spapr->phbs, list) {
- ret = spapr_populate_pci_dt(phb, PHANDLE_XICP, fdt, smc->irq->nr_msis);
+ ret = spapr_populate_pci_dt(phb, PHANDLE_XICP, fdt,
+ spapr->irq->nr_msis);
if (ret < 0) {
error_report("couldn't setup PCI devices in fdt");
exit(1);
@@ -1620,6 +1627,12 @@ static void spapr_machine_reset(void)
qemu_devices_reset();
+ /*
+ * This is fixing some of the default configuration of the XIVE
+ * devices. To be called after the reset of the machine devices.
+ */
+ spapr_irq_reset(spapr, &error_fatal);
+
/* DRC reset may cause a device to be unplugged. This will cause troubles
* if this device is used by another device (eg, a running vhost backend
* will crash QEMU if the DIMM holding the vring goes away). To avoid such
@@ -1656,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);
@@ -1731,20 +1747,17 @@ static int spapr_post_load(void *opaque, int version_id)
return err;
}
- if (!object_dynamic_cast(OBJECT(spapr->ics), TYPE_ICS_KVM)) {
- CPUState *cs;
- CPU_FOREACH(cs) {
- PowerPCCPU *cpu = POWERPC_CPU(cs);
- icp_resend(ICP(cpu->intc));
- }
- }
-
- /* 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) {
@@ -1759,6 +1772,11 @@ static int spapr_post_load(void *opaque, int version_id)
}
}
+ err = spapr_irq_post_load(spapr, version_id);
+ if (err) {
+ return err;
+ }
+
return err;
}
@@ -1910,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,
@@ -1939,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
}
};
@@ -2466,15 +2518,10 @@ static void spapr_init_cpus(sPAPRMachineState *spapr)
boot_cores_nr = possible_cpus->len;
}
- /* VSMT must be set in order to be able to compute VCPU ids, ie to
- * call xics_max_server_number() or spapr_vcpu_id().
- */
- spapr_set_vsmt_mode(spapr, &error_fatal);
-
if (smc->pre_2_10_has_unused_icps) {
int i;
- for (i = 0; i < xics_max_server_number(spapr); i++) {
+ for (i = 0; i < spapr_max_server_number(spapr); i++) {
/* Dummy entries get deregistered when real ICPState objects
* are registered during CPU core hotplug.
*/
@@ -2510,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)
{
@@ -2593,8 +2651,14 @@ static void spapr_machine_init(MachineState *machine)
/* Setup a load limit for the ramdisk leaving room for SLOF and FDT */
load_limit = MIN(spapr->rma_size, RTAS_MAX_ADDR) - FW_OVERHEAD;
+ /*
+ * VSMT must be set in order to be able to compute VCPU ids, ie to
+ * call spapr_max_server_number() or spapr_vcpu_id().
+ */
+ spapr_set_vsmt_mode(spapr, &error_fatal);
+
/* Set up Interrupt Controller before we create the VCPUs */
- smc->irq->init(spapr, &error_fatal);
+ spapr_irq_init(spapr, &error_fatal);
/* Set up containers for ibm,client-architecture-support negotiated options
*/
@@ -2621,6 +2685,17 @@ static void spapr_machine_init(MachineState *machine)
/* advertise support for ibm,dyamic-memory-v2 */
spapr_ovec_set(spapr->ov5, OV5_DRMEM_V2);
+ /* advertise XIVE on POWER9 machines */
+ 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 if (spapr->irq->ov5 & SPAPR_OV5_XIVE_EXPLOIT) {
+ error_report("XIVE-only machines require a POWER9 CPU");
+ exit(1);
+ }
+ }
+
/* init CPUs */
spapr_init_cpus(spapr);
@@ -2725,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];
@@ -3031,9 +3106,42 @@ static void spapr_set_vsmt(Object *obj, Visitor *v, const char *name,
visit_type_uint32(v, name, (uint32_t *)opaque, errp);
}
+static char *spapr_get_ic_mode(Object *obj, Error **errp)
+{
+ sPAPRMachineState *spapr = SPAPR_MACHINE(obj);
+
+ if (spapr->irq == &spapr_irq_xics_legacy) {
+ return g_strdup("legacy");
+ } else if (spapr->irq == &spapr_irq_xics) {
+ 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();
+}
+
+static void spapr_set_ic_mode(Object *obj, const char *value, Error **errp)
+{
+ sPAPRMachineState *spapr = SPAPR_MACHINE(obj);
+
+ /* The legacy IRQ backend can not be set */
+ if (strcmp(value, "xics") == 0) {
+ 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");
+ }
+}
+
static void spapr_instance_init(Object *obj)
{
sPAPRMachineState *spapr = SPAPR_MACHINE(obj);
+ sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
spapr->htab_fd = -1;
spapr->use_hotplug_event_source = true;
@@ -3067,6 +3175,14 @@ static void spapr_instance_init(Object *obj)
" the host's SMT mode", &error_abort);
object_property_add_bool(obj, "vfio-no-msix-emulation",
spapr_get_msix_emulation, NULL, NULL);
+
+ /* The machine class defines the default interrupt controller mode */
+ spapr->irq = smc->irq;
+ 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, dual)",
+ NULL);
}
static void spapr_machine_finalizefn(Object *obj)
@@ -3733,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 */
@@ -3782,16 +3896,15 @@ 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,
Monitor *mon)
{
sPAPRMachineState *spapr = SPAPR_MACHINE(obj);
- sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
- smc->irq->print_info(spapr, mon);
+ spapr->irq->print_info(spapr, mon);
}
int spapr_get_vcpu_id(PowerPCCPU *cpu)
@@ -3873,7 +3986,8 @@ static void spapr_machine_class_init(ObjectClass *oc, void *data)
hc->unplug = spapr_machine_device_unplug;
smc->dr_lmb_enabled = true;
- mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power8_v2.0");
+ 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;
fwc->get_dev_path = spapr_get_fw_dev_path;
@@ -3939,16 +4053,10 @@ static const TypeInfo spapr_machine_info = {
mc->is_default = 1; \
} \
} \
- static void spapr_machine_##suffix##_instance_init(Object *obj) \
- { \
- MachineState *machine = MACHINE(obj); \
- spapr_machine_##suffix##_instance_options(machine); \
- } \
static const TypeInfo spapr_machine_##suffix##_info = { \
.name = MACHINE_TYPE_NAME("pseries-" verstr), \
.parent = TYPE_SPAPR_MACHINE, \
.class_init = spapr_machine_##suffix##_class_init, \
- .instance_init = spapr_machine_##suffix##_instance_init, \
}; \
static void spapr_machine_register_##suffix(void) \
{ \
@@ -3956,37 +4064,41 @@ static const TypeInfo spapr_machine_info = {
} \
type_init(spapr_machine_register_##suffix)
- /*
- * pseries-3.1
+/*
+ * pseries-4.0
*/
-static void spapr_machine_3_1_instance_options(MachineState *machine)
+static void spapr_machine_4_0_class_options(MachineClass *mc)
{
+ /* Defaults for the latest behaviour inherited from the base class */
}
+DEFINE_SPAPR_MACHINE(4_0, "4.0", true);
+
+/*
+ * pseries-3.1
+ */
static void spapr_machine_3_1_class_options(MachineClass *mc)
{
- /* Defaults for the latest behaviour inherited from the base class */
+ 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", true);
+DEFINE_SPAPR_MACHINE(3_1, "3.1", false);
/*
* pseries-3.0
*/
-#define SPAPR_COMPAT_3_0 \
- HW_COMPAT_3_0
-
-static void spapr_machine_3_0_instance_options(MachineState *machine)
-{
- spapr_machine_3_1_instance_options(machine);
-}
static void spapr_machine_3_0_class_options(MachineClass *mc)
{
sPAPRMachineClass *smc = SPAPR_MACHINE_CLASS(mc);
spapr_machine_3_1_class_options(mc);
- SET_MACHINE_COMPAT(mc, SPAPR_COMPAT_3_0);
+ compat_props_add(mc->compat_props, hw_compat_3_0, hw_compat_3_0_len);
smc->legacy_irq_allocation = true;
smc->irq = &spapr_irq_xics_legacy;
@@ -3997,30 +4109,17 @@ DEFINE_SPAPR_MACHINE(3_0, "3.0", false);
/*
* pseries-2.12
*/
-#define SPAPR_COMPAT_2_12 \
- HW_COMPAT_2_12 \
- { \
- .driver = TYPE_POWERPC_CPU, \
- .property = "pre-3.0-migration", \
- .value = "on", \
- }, \
- { \
- .driver = TYPE_SPAPR_CPU_CORE, \
- .property = "pre-3.0-migration", \
- .value = "on", \
- },
-
-static void spapr_machine_2_12_instance_options(MachineState *machine)
-{
- spapr_machine_3_0_instance_options(machine);
-}
-
static void spapr_machine_2_12_class_options(MachineClass *mc)
{
sPAPRMachineClass *smc = SPAPR_MACHINE_CLASS(mc);
+ static GlobalProperty compat[] = {
+ { TYPE_POWERPC_CPU, "pre-3.0-migration", "on" },
+ { TYPE_SPAPR_CPU_CORE, "pre-3.0-migration", "on" },
+ };
spapr_machine_3_0_class_options(mc);
- SET_MACHINE_COMPAT(mc, SPAPR_COMPAT_2_12);
+ compat_props_add(mc->compat_props, hw_compat_2_12, hw_compat_2_12_len);
+ compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat));
/* We depend on kvm_enabled() to choose a default value for the
* hpt-max-page-size capability. Of course we can't do it here
@@ -4032,11 +4131,6 @@ static void spapr_machine_2_12_class_options(MachineClass *mc)
DEFINE_SPAPR_MACHINE(2_12, "2.12", false);
-static void spapr_machine_2_12_sxxm_instance_options(MachineState *machine)
-{
- spapr_machine_2_12_instance_options(machine);
-}
-
static void spapr_machine_2_12_sxxm_class_options(MachineClass *mc)
{
sPAPRMachineClass *smc = SPAPR_MACHINE_CLASS(mc);
@@ -4052,13 +4146,6 @@ DEFINE_SPAPR_MACHINE(2_12_sxxm, "2.12-sxxm", false);
/*
* pseries-2.11
*/
-#define SPAPR_COMPAT_2_11 \
- HW_COMPAT_2_11
-
-static void spapr_machine_2_11_instance_options(MachineState *machine)
-{
- spapr_machine_2_12_instance_options(machine);
-}
static void spapr_machine_2_11_class_options(MachineClass *mc)
{
@@ -4066,7 +4153,7 @@ static void spapr_machine_2_11_class_options(MachineClass *mc)
spapr_machine_2_12_class_options(mc);
smc->default_caps.caps[SPAPR_CAP_HTM] = SPAPR_CAP_ON;
- SET_MACHINE_COMPAT(mc, SPAPR_COMPAT_2_11);
+ compat_props_add(mc->compat_props, hw_compat_2_11, hw_compat_2_11_len);
}
DEFINE_SPAPR_MACHINE(2_11, "2.11", false);
@@ -4074,18 +4161,11 @@ DEFINE_SPAPR_MACHINE(2_11, "2.11", false);
/*
* pseries-2.10
*/
-#define SPAPR_COMPAT_2_10 \
- HW_COMPAT_2_10
-
-static void spapr_machine_2_10_instance_options(MachineState *machine)
-{
- spapr_machine_2_11_instance_options(machine);
-}
static void spapr_machine_2_10_class_options(MachineClass *mc)
{
spapr_machine_2_11_class_options(mc);
- SET_MACHINE_COMPAT(mc, SPAPR_COMPAT_2_10);
+ compat_props_add(mc->compat_props, hw_compat_2_10, hw_compat_2_10_len);
}
DEFINE_SPAPR_MACHINE(2_10, "2.10", false);
@@ -4093,25 +4173,17 @@ DEFINE_SPAPR_MACHINE(2_10, "2.10", false);
/*
* pseries-2.9
*/
-#define SPAPR_COMPAT_2_9 \
- HW_COMPAT_2_9 \
- { \
- .driver = TYPE_POWERPC_CPU, \
- .property = "pre-2.10-migration", \
- .value = "on", \
- }, \
-
-static void spapr_machine_2_9_instance_options(MachineState *machine)
-{
- spapr_machine_2_10_instance_options(machine);
-}
static void spapr_machine_2_9_class_options(MachineClass *mc)
{
sPAPRMachineClass *smc = SPAPR_MACHINE_CLASS(mc);
+ static GlobalProperty compat[] = {
+ { TYPE_POWERPC_CPU, "pre-2.10-migration", "on" },
+ };
spapr_machine_2_10_class_options(mc);
- SET_MACHINE_COMPAT(mc, SPAPR_COMPAT_2_9);
+ compat_props_add(mc->compat_props, hw_compat_2_9, hw_compat_2_9_len);
+ compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat));
mc->numa_auto_assign_ram = numa_legacy_auto_assign_ram;
smc->pre_2_10_has_unused_icps = true;
smc->resize_hpt_default = SPAPR_RESIZE_HPT_DISABLED;
@@ -4122,23 +4194,16 @@ DEFINE_SPAPR_MACHINE(2_9, "2.9", false);
/*
* pseries-2.8
*/
-#define SPAPR_COMPAT_2_8 \
- HW_COMPAT_2_8 \
- { \
- .driver = TYPE_SPAPR_PCI_HOST_BRIDGE, \
- .property = "pcie-extended-configuration-space", \
- .value = "off", \
- },
-
-static void spapr_machine_2_8_instance_options(MachineState *machine)
-{
- spapr_machine_2_9_instance_options(machine);
-}
static void spapr_machine_2_8_class_options(MachineClass *mc)
{
+ static GlobalProperty compat[] = {
+ { TYPE_SPAPR_PCI_HOST_BRIDGE, "pcie-extended-configuration-space", "off" },
+ };
+
spapr_machine_2_9_class_options(mc);
- SET_MACHINE_COMPAT(mc, SPAPR_COMPAT_2_8);
+ compat_props_add(mc->compat_props, hw_compat_2_8, hw_compat_2_8_len);
+ compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat));
mc->numa_mem_align_shift = 23;
}
@@ -4147,28 +4212,6 @@ DEFINE_SPAPR_MACHINE(2_8, "2.8", false);
/*
* pseries-2.7
*/
-#define SPAPR_COMPAT_2_7 \
- HW_COMPAT_2_7 \
- { \
- .driver = TYPE_SPAPR_PCI_HOST_BRIDGE, \
- .property = "mem_win_size", \
- .value = stringify(SPAPR_PCI_2_7_MMIO_WIN_SIZE),\
- }, \
- { \
- .driver = TYPE_SPAPR_PCI_HOST_BRIDGE, \
- .property = "mem64_win_size", \
- .value = "0", \
- }, \
- { \
- .driver = TYPE_POWERPC_CPU, \
- .property = "pre-2.8-migration", \
- .value = "on", \
- }, \
- { \
- .driver = TYPE_SPAPR_PCI_HOST_BRIDGE, \
- .property = "pre-2.8-migration", \
- .value = "on", \
- },
static void phb_placement_2_7(sPAPRMachineState *spapr, uint32_t index,
uint64_t *buid, hwaddr *pio,
@@ -4219,21 +4262,21 @@ static void phb_placement_2_7(sPAPRMachineState *spapr, uint32_t index,
*/
}
-static void spapr_machine_2_7_instance_options(MachineState *machine)
-{
- sPAPRMachineState *spapr = SPAPR_MACHINE(machine);
-
- spapr_machine_2_8_instance_options(machine);
- spapr->use_hotplug_event_source = false;
-}
-
static void spapr_machine_2_7_class_options(MachineClass *mc)
{
sPAPRMachineClass *smc = SPAPR_MACHINE_CLASS(mc);
+ static GlobalProperty compat[] = {
+ { TYPE_SPAPR_PCI_HOST_BRIDGE, "mem_win_size", "0xf80000000", },
+ { TYPE_SPAPR_PCI_HOST_BRIDGE, "mem64_win_size", "0", },
+ { TYPE_POWERPC_CPU, "pre-2.8-migration", "on", },
+ { TYPE_SPAPR_PCI_HOST_BRIDGE, "pre-2.8-migration", "on", },
+ };
spapr_machine_2_8_class_options(mc);
mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power7_v2.3");
- SET_MACHINE_COMPAT(mc, SPAPR_COMPAT_2_7);
+ mc->default_machine_opts = "modern-hotplug-events=off";
+ compat_props_add(mc->compat_props, hw_compat_2_7, hw_compat_2_7_len);
+ compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat));
smc->phb_placement = phb_placement_2_7;
}
@@ -4242,24 +4285,17 @@ DEFINE_SPAPR_MACHINE(2_7, "2.7", false);
/*
* pseries-2.6
*/
-#define SPAPR_COMPAT_2_6 \
- HW_COMPAT_2_6 \
- { \
- .driver = TYPE_SPAPR_PCI_HOST_BRIDGE,\
- .property = "ddw",\
- .value = stringify(off),\
- },
-
-static void spapr_machine_2_6_instance_options(MachineState *machine)
-{
- spapr_machine_2_7_instance_options(machine);
-}
static void spapr_machine_2_6_class_options(MachineClass *mc)
{
+ static GlobalProperty compat[] = {
+ { TYPE_SPAPR_PCI_HOST_BRIDGE, "ddw", "off" },
+ };
+
spapr_machine_2_7_class_options(mc);
mc->has_hotpluggable_cpus = false;
- SET_MACHINE_COMPAT(mc, SPAPR_COMPAT_2_6);
+ compat_props_add(mc->compat_props, hw_compat_2_6, hw_compat_2_6_len);
+ compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat));
}
DEFINE_SPAPR_MACHINE(2_6, "2.6", false);
@@ -4267,26 +4303,18 @@ DEFINE_SPAPR_MACHINE(2_6, "2.6", false);
/*
* pseries-2.5
*/
-#define SPAPR_COMPAT_2_5 \
- HW_COMPAT_2_5 \
- { \
- .driver = "spapr-vlan", \
- .property = "use-rx-buffer-pools", \
- .value = "off", \
- },
-
-static void spapr_machine_2_5_instance_options(MachineState *machine)
-{
- spapr_machine_2_6_instance_options(machine);
-}
static void spapr_machine_2_5_class_options(MachineClass *mc)
{
sPAPRMachineClass *smc = SPAPR_MACHINE_CLASS(mc);
+ static GlobalProperty compat[] = {
+ { "spapr-vlan", "use-rx-buffer-pools", "off" },
+ };
spapr_machine_2_6_class_options(mc);
smc->use_ohci_by_default = true;
- SET_MACHINE_COMPAT(mc, SPAPR_COMPAT_2_5);
+ compat_props_add(mc->compat_props, hw_compat_2_5, hw_compat_2_5_len);
+ compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat));
}
DEFINE_SPAPR_MACHINE(2_5, "2.5", false);
@@ -4294,13 +4322,6 @@ DEFINE_SPAPR_MACHINE(2_5, "2.5", false);
/*
* pseries-2.4
*/
-#define SPAPR_COMPAT_2_4 \
- HW_COMPAT_2_4
-
-static void spapr_machine_2_4_instance_options(MachineState *machine)
-{
- spapr_machine_2_5_instance_options(machine);
-}
static void spapr_machine_2_4_class_options(MachineClass *mc)
{
@@ -4308,7 +4329,7 @@ static void spapr_machine_2_4_class_options(MachineClass *mc)
spapr_machine_2_5_class_options(mc);
smc->dr_lmb_enabled = false;
- SET_MACHINE_COMPAT(mc, SPAPR_COMPAT_2_4);
+ compat_props_add(mc->compat_props, hw_compat_2_4, hw_compat_2_4_len);
}
DEFINE_SPAPR_MACHINE(2_4, "2.4", false);
@@ -4316,23 +4337,15 @@ DEFINE_SPAPR_MACHINE(2_4, "2.4", false);
/*
* pseries-2.3
*/
-#define SPAPR_COMPAT_2_3 \
- HW_COMPAT_2_3 \
- {\
- .driver = "spapr-pci-host-bridge",\
- .property = "dynamic-reconfiguration",\
- .value = "off",\
- },
-
-static void spapr_machine_2_3_instance_options(MachineState *machine)
-{
- spapr_machine_2_4_instance_options(machine);
-}
static void spapr_machine_2_3_class_options(MachineClass *mc)
{
+ static GlobalProperty compat[] = {
+ { "spapr-pci-host-bridge", "dynamic-reconfiguration", "off" },
+ };
spapr_machine_2_4_class_options(mc);
- SET_MACHINE_COMPAT(mc, SPAPR_COMPAT_2_3);
+ compat_props_add(mc->compat_props, hw_compat_2_3, hw_compat_2_3_len);
+ compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat));
}
DEFINE_SPAPR_MACHINE(2_3, "2.3", false);
@@ -4340,42 +4353,27 @@ DEFINE_SPAPR_MACHINE(2_3, "2.3", false);
* pseries-2.2
*/
-#define SPAPR_COMPAT_2_2 \
- HW_COMPAT_2_2 \
- {\
- .driver = TYPE_SPAPR_PCI_HOST_BRIDGE,\
- .property = "mem_win_size",\
- .value = "0x20000000",\
- },
-
-static void spapr_machine_2_2_instance_options(MachineState *machine)
-{
- spapr_machine_2_3_instance_options(machine);
- machine->suppress_vmdesc = true;
-}
-
static void spapr_machine_2_2_class_options(MachineClass *mc)
{
+ static GlobalProperty compat[] = {
+ { TYPE_SPAPR_PCI_HOST_BRIDGE, "mem_win_size", "0x20000000" },
+ };
+
spapr_machine_2_3_class_options(mc);
- SET_MACHINE_COMPAT(mc, SPAPR_COMPAT_2_2);
+ compat_props_add(mc->compat_props, hw_compat_2_2, hw_compat_2_2_len);
+ compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat));
+ mc->default_machine_opts = "modern-hotplug-events=off,suppress-vmdesc=on";
}
DEFINE_SPAPR_MACHINE(2_2, "2.2", false);
/*
* pseries-2.1
*/
-#define SPAPR_COMPAT_2_1 \
- HW_COMPAT_2_1
-
-static void spapr_machine_2_1_instance_options(MachineState *machine)
-{
- spapr_machine_2_2_instance_options(machine);
-}
static void spapr_machine_2_1_class_options(MachineClass *mc)
{
spapr_machine_2_2_class_options(mc);
- SET_MACHINE_COMPAT(mc, SPAPR_COMPAT_2_1);
+ compat_props_add(mc->compat_props, hw_compat_2_1, hw_compat_2_1_len);
}
DEFINE_SPAPR_MACHINE(2_1, "2.1", false);
diff --git a/hw/ppc/spapr_cpu_core.c b/hw/ppc/spapr_cpu_core.c
index 2398ce62c0..0405306d1e 100644
--- a/hw/ppc/spapr_cpu_core.c
+++ b/hw/ppc/spapr_cpu_core.c
@@ -11,7 +11,6 @@
#include "hw/ppc/spapr_cpu_core.h"
#include "target/ppc/cpu.h"
#include "hw/ppc/spapr.h"
-#include "hw/ppc/xics.h" /* for icp_create() - to be removed */
#include "hw/boards.h"
#include "qapi/error.h"
#include "sysemu/cpus.h"
@@ -195,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));
}
@@ -233,8 +237,7 @@ static void spapr_realize_vcpu(PowerPCCPU *cpu, sPAPRMachineState *spapr,
qemu_register_reset(spapr_cpu_reset, cpu);
spapr_cpu_reset(cpu);
- cpu->intc = icp_create(OBJECT(cpu), spapr->icp_type, XICS_FABRIC(spapr),
- &local_err);
+ spapr->irq->cpu_intc_create(spapr, cpu, &local_err);
if (local_err) {
goto error_unregister;
}
diff --git a/hw/ppc/spapr_hcall.c b/hw/ppc/spapr_hcall.c
index ae913d070f..17bcaa3822 100644
--- a/hw/ppc/spapr_hcall.c
+++ b/hw/ppc/spapr_hcall.c
@@ -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)
diff --git a/hw/ppc/spapr_iommu.c b/hw/ppc/spapr_iommu.c
index 1b0880ac9e..37e98f9321 100644
--- a/hw/ppc/spapr_iommu.c
+++ b/hw/ppc/spapr_iommu.c
@@ -42,7 +42,7 @@ enum sPAPRTCEAccess {
#define IOMMU_PAGE_SIZE(shift) (1ULL << (shift))
#define IOMMU_PAGE_MASK(shift) (~(IOMMU_PAGE_SIZE(shift) - 1))
-static QLIST_HEAD(spapr_tce_tables, sPAPRTCETable) spapr_tce_tables;
+static QLIST_HEAD(, sPAPRTCETable) spapr_tce_tables;
sPAPRTCETable *spapr_tce_find_by_liobn(target_ulong liobn)
{
@@ -93,7 +93,7 @@ static uint64_t *spapr_tce_alloc_table(uint32_t liobn,
if (!table) {
*fd = -1;
- table = g_malloc0(nb_table * sizeof(uint64_t));
+ table = g_new0(uint64_t, nb_table);
}
trace_spapr_iommu_new_table(liobn, table, *fd);
diff --git a/hw/ppc/spapr_irq.c b/hw/ppc/spapr_irq.c
index e77b94cc68..1da7a32348 100644
--- a/hw/ppc/spapr_irq.c
+++ b/hw/ppc/spapr_irq.c
@@ -12,7 +12,9 @@
#include "qemu/error-report.h"
#include "qapi/error.h"
#include "hw/ppc/spapr.h"
+#include "hw/ppc/spapr_xive.h"
#include "hw/ppc/xics.h"
+#include "hw/ppc/xics_spapr.h"
#include "sysemu/kvm.h"
#include "trace.h"
@@ -93,15 +95,9 @@ error:
static void spapr_irq_init_xics(sPAPRMachineState *spapr, Error **errp)
{
MachineState *machine = MACHINE(spapr);
- sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
- int nr_irqs = smc->irq->nr_irqs;
+ int nr_irqs = spapr->irq->nr_irqs;
Error *local_err = NULL;
- /* Initialize the MSI IRQ allocator. */
- if (!SPAPR_MACHINE_GET_CLASS(spapr)->legacy_irq_allocation) {
- spapr_irq_msi_init(spapr, smc->irq->nr_msis);
- }
-
if (kvm_enabled()) {
if (machine_kernel_irqchip_allowed(machine) &&
!xics_kvm_init(spapr, &local_err)) {
@@ -176,7 +172,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;
@@ -189,12 +185,57 @@ 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 void spapr_irq_cpu_intc_create_xics(sPAPRMachineState *spapr,
+ PowerPCCPU *cpu, Error **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)
+{
+ if (!object_dynamic_cast(OBJECT(spapr->ics), TYPE_ICS_KVM)) {
+ CPUState *cs;
+ CPU_FOREACH(cs) {
+ PowerPCCPU *cpu = POWERPC_CPU(cs);
+ 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)
@@ -202,37 +243,396 @@ static void spapr_irq_print_info_xics(sPAPRMachineState *spapr, Monitor *mon)
sPAPRIrq spapr_irq_xics = {
.nr_irqs = SPAPR_IRQ_XICS_NR_IRQS,
.nr_msis = SPAPR_IRQ_XICS_NR_MSIS,
+ .ov5 = SPAPR_OV5_XIVE_LEGACY,
.init = spapr_irq_init_xics,
.claim = spapr_irq_claim_xics,
.free = spapr_irq_free_xics,
.qirq = spapr_qirq_xics,
.print_info = spapr_irq_print_info_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,
+};
+
+/*
+ * XIVE IRQ backend.
+ */
+static void spapr_irq_init_xive(sPAPRMachineState *spapr, Error **errp)
+{
+ MachineState *machine = MACHINE(spapr);
+ uint32_t nr_servers = spapr_max_server_number(spapr);
+ DeviceState *dev;
+ int i;
+
+ /* KVM XIVE device not yet available */
+ if (kvm_enabled()) {
+ if (machine_kernel_irqchip_required(machine)) {
+ error_setg(errp, "kernel_irqchip requested. no KVM XIVE support");
+ return;
+ }
+ }
+
+ dev = qdev_create(NULL, TYPE_SPAPR_XIVE);
+ qdev_prop_set_uint32(dev, "nr-irqs", spapr->irq->nr_irqs);
+ /*
+ * 8 XIVE END structures per CPU. One for each available priority
+ */
+ qdev_prop_set_uint32(dev, "nr-ends", nr_servers << 3);
+ qdev_init_nofail(dev);
+
+ spapr->xive = SPAPR_XIVE(dev);
+
+ /* Enable the CPU IPIs */
+ for (i = 0; i < nr_servers; ++i) {
+ spapr_xive_irq_claim(spapr->xive, SPAPR_IRQ_IPI + i, false);
+ }
+
+ spapr_xive_hcall_init(spapr);
+}
+
+static int spapr_irq_claim_xive(sPAPRMachineState *spapr, int irq, bool lsi,
+ Error **errp)
+{
+ if (!spapr_xive_irq_claim(spapr->xive, irq, lsi)) {
+ error_setg(errp, "IRQ %d is invalid", irq);
+ return -1;
+ }
+ return 0;
+}
+
+static void spapr_irq_free_xive(sPAPRMachineState *spapr, int irq, int num)
+{
+ int i;
+
+ for (i = irq; i < irq + num; ++i) {
+ spapr_xive_irq_free(spapr->xive, i);
+ }
+}
+
+static qemu_irq spapr_qirq_xive(sPAPRMachineState *spapr, int 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,
+ Monitor *mon)
+{
+ CPUState *cs;
+
+ CPU_FOREACH(cs) {
+ PowerPCCPU *cpu = POWERPC_CPU(cs);
+
+ xive_tctx_pic_print_info(cpu->tctx, mon);
+ }
+
+ spapr_xive_pic_print_info(spapr->xive, mon);
+}
+
+static void spapr_irq_cpu_intc_create_xive(sPAPRMachineState *spapr,
+ PowerPCCPU *cpu, Error **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 beneficiate from the reset of the XIVE IRQ backend
+ */
+ spapr_xive_set_tctx_os_cam(cpu->tctx);
+}
+
+static int spapr_irq_post_load_xive(sPAPRMachineState *spapr, int version_id)
+{
+ return 0;
+}
+
+static void spapr_irq_reset_xive(sPAPRMachineState *spapr, Error **errp)
+{
+ CPUState *cs;
+
+ CPU_FOREACH(cs) {
+ PowerPCCPU *cpu = POWERPC_CPU(cs);
+
+ /* (TCG) Set the OS CAM line of the thread interrupt context. */
+ 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);
+}
+
+/*
+ * XIVE uses the full IRQ number space. Set it to 8K to be compatible
+ * with XICS.
+ */
+
+#define SPAPR_IRQ_XIVE_NR_IRQS 0x2000
+#define SPAPR_IRQ_XIVE_NR_MSIS (SPAPR_IRQ_XIVE_NR_IRQS - SPAPR_IRQ_MSI)
+
+sPAPRIrq spapr_irq_xive = {
+ .nr_irqs = SPAPR_IRQ_XIVE_NR_IRQS,
+ .nr_msis = SPAPR_IRQ_XIVE_NR_MSIS,
+ .ov5 = SPAPR_OV5_XIVE_EXPLOIT,
+
+ .init = spapr_irq_init_xive,
+ .claim = spapr_irq_claim_xive,
+ .free = spapr_irq_free_xive,
+ .qirq = spapr_qirq_xive,
+ .print_info = spapr_irq_print_info_xive,
+ .dt_populate = spapr_dt_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
};
/*
* sPAPR IRQ frontend routines for devices
*/
+void spapr_irq_init(sPAPRMachineState *spapr, Error **errp)
+{
+ /* Initialize the MSI IRQ allocator. */
+ if (!SPAPR_MACHINE_GET_CLASS(spapr)->legacy_irq_allocation) {
+ spapr_irq_msi_init(spapr, spapr->irq->nr_msis);
+ }
+
+ 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)
{
- sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
-
- return smc->irq->claim(spapr, irq, lsi, errp);
+ return spapr->irq->claim(spapr, irq, lsi, errp);
}
void spapr_irq_free(sPAPRMachineState *spapr, int irq, int num)
{
- sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
-
- smc->irq->free(spapr, irq, num);
+ spapr->irq->free(spapr, irq, num);
}
qemu_irq spapr_qirq(sPAPRMachineState *spapr, int irq)
{
- sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
+ return spapr->irq->qirq(spapr, irq);
+}
+
+int spapr_irq_post_load(sPAPRMachineState *spapr, int version_id)
+{
+ return spapr->irq->post_load(spapr, version_id);
+}
- return smc->irq->qirq(spapr, irq);
+void spapr_irq_reset(sPAPRMachineState *spapr, Error **errp)
+{
+ if (spapr->irq->reset) {
+ spapr->irq->reset(spapr, errp);
+ }
}
/*
@@ -295,10 +695,15 @@ int spapr_irq_find(sPAPRMachineState *spapr, int num, bool align, Error **errp)
sPAPRIrq spapr_irq_xics_legacy = {
.nr_irqs = SPAPR_IRQ_XICS_LEGACY_NR_IRQS,
.nr_msis = SPAPR_IRQ_XICS_LEGACY_NR_IRQS,
+ .ov5 = SPAPR_OV5_XIVE_LEGACY,
.init = spapr_irq_init_xics,
.claim = spapr_irq_claim_xics,
.free = spapr_irq_free_xics,
.qirq = spapr_qirq_xics,
.print_info = spapr_irq_print_info_xics,
+ .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,
};
diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c
index 2374d55fc1..b74f2632ec 100644
--- a/hw/ppc/spapr_pci.c
+++ b/hw/ppc/spapr_pci.c
@@ -1370,18 +1370,9 @@ static int spapr_create_pci_child_dt(sPAPRPHBState *phb, PCIDevice *dev,
/* Callback to be called during DRC release. */
void spapr_phb_remove_pci_device_cb(DeviceState *dev)
{
- /* some version guests do not wait for completion of a device
- * cleanup (generally done asynchronously by the kernel) before
- * signaling to QEMU that the device is safe, but instead sleep
- * for some 'safe' period of time. unfortunately on a busy host
- * this sleep isn't guaranteed to be long enough, resulting in
- * bad things like IRQ lines being left asserted during final
- * device removal. to deal with this we call reset just prior
- * to finalizing the device, which will put the device back into
- * an 'idle' state, as the device cleanup code expects.
- */
- pci_device_reset(PCI_DEVICE(dev));
- object_unparent(OBJECT(dev));
+ HotplugHandler *hotplug_ctrl = qdev_get_hotplug_handler(dev);
+
+ hotplug_handler_unplug(hotplug_ctrl, dev, &error_abort);
}
static sPAPRDRConnector *spapr_phb_get_pci_func_drc(sPAPRPHBState *phb,
@@ -1490,6 +1481,23 @@ out:
}
}
+static void spapr_pci_unplug(HotplugHandler *plug_handler,
+ DeviceState *plugged_dev, Error **errp)
+{
+ /* some version guests do not wait for completion of a device
+ * cleanup (generally done asynchronously by the kernel) before
+ * signaling to QEMU that the device is safe, but instead sleep
+ * for some 'safe' period of time. unfortunately on a busy host
+ * this sleep isn't guaranteed to be long enough, resulting in
+ * bad things like IRQ lines being left asserted during final
+ * device removal. to deal with this we call reset just prior
+ * to finalizing the device, which will put the device back into
+ * an 'idle' state, as the device cleanup code expects.
+ */
+ pci_device_reset(PCI_DEVICE(plugged_dev));
+ object_unparent(OBJECT(plugged_dev));
+}
+
static void spapr_pci_unplug_request(HotplugHandler *plug_handler,
DeviceState *plugged_dev, Error **errp)
{
@@ -1965,6 +1973,7 @@ static void spapr_phb_class_init(ObjectClass *klass, void *data)
dc->user_creatable = true;
set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
hp->plug = spapr_pci_plug;
+ hp->unplug = spapr_pci_unplug;
hp->unplug_request = spapr_pci_unplug_request;
}
@@ -1979,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;
diff --git a/hw/ppc/spapr_rtas_ddw.c b/hw/ppc/spapr_rtas_ddw.c
index 329feb148f..cb8a410359 100644
--- a/hw/ppc/spapr_rtas_ddw.c
+++ b/hw/ppc/spapr_rtas_ddw.c
@@ -96,9 +96,8 @@ static void rtas_ibm_query_pe_dma_window(PowerPCCPU *cpu,
uint32_t nret, target_ulong rets)
{
sPAPRPHBState *sphb;
- uint64_t buid, max_window_size;
+ uint64_t buid;
uint32_t avail, addr, pgmask = 0;
- MachineState *machine = MACHINE(spapr);
if ((nargs != 3) || (nret != 5)) {
goto param_error_exit;
@@ -114,27 +113,15 @@ static void rtas_ibm_query_pe_dma_window(PowerPCCPU *cpu,
/* Translate page mask to LoPAPR format */
pgmask = spapr_page_mask_to_query_mask(sphb->page_size_mask);
- /*
- * This is "Largest contiguous block of TCEs allocated specifically
- * for (that is, are reserved for) this PE".
- * Return the maximum number as maximum supported RAM size was in 4K pages.
- */
- if (machine->ram_size == machine->maxram_size) {
- max_window_size = machine->ram_size;
- } else {
- max_window_size = machine->device_memory->base +
- memory_region_size(&machine->device_memory->mr);
- }
-
avail = SPAPR_PCI_DMA_MAX_WINDOWS - spapr_phb_get_active_win_num(sphb);
rtas_st(rets, 0, RTAS_OUT_SUCCESS);
rtas_st(rets, 1, avail);
- rtas_st(rets, 2, max_window_size >> SPAPR_TCE_PAGE_SHIFT);
+ rtas_st(rets, 2, 0x80000000); /* The largest window we can possibly have */
rtas_st(rets, 3, pgmask);
rtas_st(rets, 4, 0); /* DMA migration mask, not supported */
- trace_spapr_iommu_ddw_query(buid, addr, avail, max_window_size, pgmask);
+ trace_spapr_iommu_ddw_query(buid, addr, avail, 0x80000000, pgmask);
return;
param_error_exit:
diff --git a/hw/ppc/spapr_vio.c b/hw/ppc/spapr_vio.c
index 840d4a3c45..7e8a9ad093 100644
--- a/hw/ppc/spapr_vio.c
+++ b/hw/ppc/spapr_vio.c
@@ -730,7 +730,7 @@ void spapr_dt_vdevice(VIOsPAPRBus *bus, void *fdt)
}
/* Copy out into an array of pointers */
- qdevs = g_malloc(sizeof(qdev) * num);
+ qdevs = g_new(DeviceState *, num);
num = 0;
QTAILQ_FOREACH(kid, &bus->bus.children, sibling) {
qdevs[num++] = kid->child;
diff --git a/hw/ppc/trace-events b/hw/ppc/trace-events
index dc5e65aee9..0af155ed32 100644
--- a/hw/ppc/trace-events
+++ b/hw/ppc/trace-events
@@ -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
diff --git a/hw/ppc/virtex_ml507.c b/hw/ppc/virtex_ml507.c
index ee9b4b4490..5177120574 100644
--- a/hw/ppc/virtex_ml507.c
+++ b/hw/ppc/virtex_ml507.c
@@ -105,7 +105,7 @@ static PowerPCCPU *ppc440_init_xilinx(ram_addr_t *ram_size,
ppc_dcr_init(env, NULL, NULL);
/* interrupt controller */
- irqs = g_malloc0(sizeof(qemu_irq) * PPCUIC_OUTPUT_NB);
+ irqs = g_new0(qemu_irq, PPCUIC_OUTPUT_NB);
irqs[PPCUIC_OUTPUT_INT] = ((qemu_irq *)env->irq_inputs)[PPC40x_INPUT_INT];
irqs[PPCUIC_OUTPUT_CINT] = ((qemu_irq *)env->irq_inputs)[PPC40x_INPUT_CINT];
ppcuic_init(env, irqs, 0x0C0, 0, 1);