aboutsummaryrefslogtreecommitdiff
path: root/hw/ppc
diff options
context:
space:
mode:
Diffstat (limited to 'hw/ppc')
-rw-r--r--hw/ppc/e500.c2
-rw-r--r--hw/ppc/e500.h2
-rw-r--r--hw/ppc/ppc.c17
-rw-r--r--hw/ppc/ppce500_spin.c7
-rw-r--r--hw/ppc/spapr.c22
-rw-r--r--hw/ppc/spapr_cpu_core.c48
-rw-r--r--hw/ppc/spapr_events.c8
-rw-r--r--hw/ppc/spapr_pci.c13
-rw-r--r--hw/ppc/spapr_vio.c2
9 files changed, 77 insertions, 44 deletions
diff --git a/hw/ppc/e500.c b/hw/ppc/e500.c
index ee1c60b820..0cd534df55 100644
--- a/hw/ppc/e500.c
+++ b/hw/ppc/e500.c
@@ -601,7 +601,7 @@ static int ppce500_prep_device_tree(MachineState *machine,
}
/* Create -kernel TLB entries for BookE. */
-static inline hwaddr booke206_page_size_to_tlb(uint64_t size)
+hwaddr booke206_page_size_to_tlb(uint64_t size)
{
return 63 - clz64(size >> 10);
}
diff --git a/hw/ppc/e500.h b/hw/ppc/e500.h
index ef224ea5e6..70ba1d8f4f 100644
--- a/hw/ppc/e500.h
+++ b/hw/ppc/e500.h
@@ -26,4 +26,6 @@ typedef struct PPCE500Params {
void ppce500_init(MachineState *machine, PPCE500Params *params);
+hwaddr booke206_page_size_to_tlb(uint64_t size);
+
#endif
diff --git a/hw/ppc/ppc.c b/hw/ppc/ppc.c
index 1bcf740f0e..e4252528a6 100644
--- a/hw/ppc/ppc.c
+++ b/hw/ppc/ppc.c
@@ -699,9 +699,18 @@ static inline void cpu_ppc_decr_lower(PowerPCCPU *cpu)
static inline void cpu_ppc_hdecr_excp(PowerPCCPU *cpu)
{
+ CPUPPCState *env = &cpu->env;
+
/* Raise it */
- LOG_TB("raise decrementer exception\n");
- ppc_set_irq(cpu, PPC_INTERRUPT_HDECR, 1);
+ LOG_TB("raise hv decrementer exception\n");
+
+ /* The architecture specifies that we don't deliver HDEC
+ * interrupts in a PM state. Not only they don't cause a
+ * wakeup but they also get effectively discarded.
+ */
+ if (!env->in_pm_state) {
+ ppc_set_irq(cpu, PPC_INTERRUPT_HDECR, 1);
+ }
}
static inline void cpu_ppc_hdecr_lower(PowerPCCPU *cpu)
@@ -928,9 +937,7 @@ clk_setup_cb cpu_ppc_tb_init (CPUPPCState *env, uint32_t freq)
}
/* Create new timer */
tb_env->decr_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, &cpu_ppc_decr_cb, cpu);
- if (0) {
- /* XXX: find a suitable condition to enable the hypervisor decrementer
- */
+ if (env->has_hv_mode) {
tb_env->hdecr_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, &cpu_ppc_hdecr_cb,
cpu);
} else {
diff --git a/hw/ppc/ppce500_spin.c b/hw/ppc/ppce500_spin.c
index 225177b5af..22c584eb8d 100644
--- a/hw/ppc/ppce500_spin.c
+++ b/hw/ppc/ppce500_spin.c
@@ -32,6 +32,7 @@
#include "sysemu/sysemu.h"
#include "hw/sysbus.h"
#include "sysemu/kvm.h"
+#include "e500.h"
#define MAX_CPUS 32
@@ -72,12 +73,6 @@ static void spin_reset(void *opaque)
}
}
-/* Create -kernel TLB entries for BookE, linearly spanning 256MB. */
-static inline hwaddr booke206_page_size_to_tlb(uint64_t size)
-{
- return ctz32(size >> 10) >> 1;
-}
-
static void mmubooke_create_initial_mapping(CPUPPCState *env,
target_ulong va,
hwaddr pa,
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index 0b6bb9ce1a..78ebd9ee38 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -116,15 +116,16 @@ static XICSState *try_create_xics(const char *type, int nr_servers,
static XICSState *xics_system_init(MachineState *machine,
int nr_servers, int nr_irqs, Error **errp)
{
- XICSState *icp = NULL;
+ XICSState *xics = NULL;
if (kvm_enabled()) {
Error *err = NULL;
if (machine_kernel_irqchip_allowed(machine)) {
- icp = try_create_xics(TYPE_KVM_XICS, nr_servers, nr_irqs, &err);
+ xics = try_create_xics(TYPE_XICS_SPAPR_KVM, nr_servers, nr_irqs,
+ &err);
}
- if (machine_kernel_irqchip_required(machine) && !icp) {
+ if (machine_kernel_irqchip_required(machine) && !xics) {
error_reportf_err(err,
"kernel_irqchip requested but unavailable: ");
} else {
@@ -132,11 +133,11 @@ static XICSState *xics_system_init(MachineState *machine,
}
}
- if (!icp) {
- icp = try_create_xics(TYPE_XICS, nr_servers, nr_irqs, errp);
+ if (!xics) {
+ xics = try_create_xics(TYPE_XICS_SPAPR, nr_servers, nr_irqs, errp);
}
- return icp;
+ return xics;
}
static int spapr_fixup_cpu_smt_dt(void *fdt, int offset, PowerPCCPU *cpu,
@@ -339,6 +340,9 @@ static void *spapr_create_fdt_skel(hwaddr initrd_base,
add_str(hypertas, "hcall-splpar");
add_str(hypertas, "hcall-bulk");
add_str(hypertas, "hcall-set-mode");
+ add_str(hypertas, "hcall-sprg0");
+ add_str(hypertas, "hcall-copy");
+ add_str(hypertas, "hcall-debug");
add_str(qemu_hypertas, "hcall-memop1");
fdt = g_malloc0(FDT_MAX_SIZE);
@@ -1779,9 +1783,9 @@ static void ppc_spapr_init(MachineState *machine)
load_limit = MIN(spapr->rma_size, RTAS_MAX_ADDR) - FW_OVERHEAD;
/* Set up Interrupt Controller before we create the VCPUs */
- spapr->icp = xics_system_init(machine,
- DIV_ROUND_UP(max_cpus * smt, smp_threads),
- XICS_IRQS, &error_fatal);
+ spapr->xics = xics_system_init(machine,
+ DIV_ROUND_UP(max_cpus * smt, smp_threads),
+ XICS_IRQS_SPAPR, &error_fatal);
if (smc->dr_lmb_enabled) {
spapr_validate_node_memory(machine, &error_fatal);
diff --git a/hw/ppc/spapr_cpu_core.c b/hw/ppc/spapr_cpu_core.c
index 3a5da09b99..a384db5204 100644
--- a/hw/ppc/spapr_cpu_core.c
+++ b/hw/ppc/spapr_cpu_core.c
@@ -42,7 +42,7 @@ static void spapr_cpu_destroy(PowerPCCPU *cpu)
{
sPAPRMachineState *spapr = SPAPR_MACHINE(qdev_get_machine());
- xics_cpu_destroy(spapr->icp, cpu);
+ xics_cpu_destroy(spapr->xics, cpu);
qemu_unregister_reset(spapr_cpu_reset, cpu);
}
@@ -76,7 +76,7 @@ void spapr_cpu_init(sPAPRMachineState *spapr, PowerPCCPU *cpu, Error **errp)
}
}
- xics_cpu_setup(spapr->icp, cpu);
+ xics_cpu_setup(spapr->xics, cpu);
qemu_register_reset(spapr_cpu_reset, cpu);
spapr_cpu_reset(cpu);
@@ -102,7 +102,6 @@ static void spapr_core_release(DeviceState *dev, void *opaque)
const char *typename = object_class_get_name(sc->cpu_class);
size_t size = object_type_get_instance_size(typename);
sPAPRMachineState *spapr = SPAPR_MACHINE(qdev_get_machine());
- sPAPRCPUCore *core = SPAPR_CPU_CORE(OBJECT(dev));
CPUCore *cc = CPU_CORE(dev);
int smt = kvmppc_smt_threads();
int i;
@@ -120,7 +119,7 @@ static void spapr_core_release(DeviceState *dev, void *opaque)
spapr->cores[cc->core_id / smt] = NULL;
- g_free(core->threads);
+ g_free(sc->threads);
object_unparent(OBJECT(dev));
}
@@ -262,18 +261,20 @@ out:
static int spapr_cpu_core_realize_child(Object *child, void *opaque)
{
- Error **errp = opaque;
+ Error **errp = opaque, *local_err = NULL;
sPAPRMachineState *spapr = SPAPR_MACHINE(qdev_get_machine());
CPUState *cs = CPU(child);
PowerPCCPU *cpu = POWERPC_CPU(cs);
- object_property_set_bool(child, true, "realized", errp);
- if (*errp) {
+ object_property_set_bool(child, true, "realized", &local_err);
+ if (local_err) {
+ error_propagate(errp, local_err);
return 1;
}
- spapr_cpu_init(spapr, cpu, errp);
- if (*errp) {
+ spapr_cpu_init(spapr, cpu, &local_err);
+ if (local_err) {
+ error_propagate(errp, local_err);
return 1;
}
return 0;
@@ -300,6 +301,7 @@ static void spapr_cpu_core_realize(DeviceState *dev, Error **errp)
if (local_err) {
goto err;
}
+ object_unref(obj);
}
object_child_foreach(OBJECT(dev), spapr_cpu_core_realize_child, &local_err);
if (local_err) {
@@ -309,10 +311,9 @@ static void spapr_cpu_core_realize(DeviceState *dev, Error **errp)
}
err:
- while (i >= 0) {
+ while (--i >= 0) {
obj = sc->threads + i * size;
object_unparent(obj);
- i--;
}
g_free(sc->threads);
error_propagate(errp, local_err);
@@ -326,7 +327,6 @@ static void spapr_cpu_core_class_init(ObjectClass *oc, void *data)
/*
* instance_init routines from different flavours of sPAPR CPU cores.
- * TODO: Add support for 'host' core type.
*/
#define SPAPR_CPU_CORE_INITFN(_type, _fname) \
static void glue(glue(spapr_cpu_core_, _fname), _initfn(Object *obj)) \
@@ -339,10 +339,15 @@ static void glue(glue(spapr_cpu_core_, _fname), _initfn(Object *obj)) \
core->cpu_class = oc; \
}
+SPAPR_CPU_CORE_INITFN(970mp_v1.0, 970MP_v10);
+SPAPR_CPU_CORE_INITFN(970mp_v1.1, 970MP_v11);
+SPAPR_CPU_CORE_INITFN(970_v2.2, 970);
+SPAPR_CPU_CORE_INITFN(POWER5+_v2.1, POWER5plus);
SPAPR_CPU_CORE_INITFN(POWER7_v2.3, POWER7);
SPAPR_CPU_CORE_INITFN(POWER7+_v2.1, POWER7plus);
SPAPR_CPU_CORE_INITFN(POWER8_v2.0, POWER8);
SPAPR_CPU_CORE_INITFN(POWER8E_v2.1, POWER8E);
+SPAPR_CPU_CORE_INITFN(POWER8NVL_v1.0, POWER8NVL);
typedef struct SPAPRCoreInfo {
const char *name;
@@ -350,6 +355,21 @@ typedef struct SPAPRCoreInfo {
} SPAPRCoreInfo;
static const SPAPRCoreInfo spapr_cores[] = {
+ /* 970 and aliaes */
+ { .name = "970_v2.2", .initfn = spapr_cpu_core_970_initfn },
+ { .name = "970", .initfn = spapr_cpu_core_970_initfn },
+
+ /* 970MP variants and aliases */
+ { .name = "970MP_v1.0", .initfn = spapr_cpu_core_970MP_v10_initfn },
+ { .name = "970mp_v1.0", .initfn = spapr_cpu_core_970MP_v10_initfn },
+ { .name = "970MP_v1.1", .initfn = spapr_cpu_core_970MP_v11_initfn },
+ { .name = "970mp_v1.1", .initfn = spapr_cpu_core_970MP_v11_initfn },
+ { .name = "970mp", .initfn = spapr_cpu_core_970MP_v11_initfn },
+
+ /* POWER5 and aliases */
+ { .name = "POWER5+_v2.1", .initfn = spapr_cpu_core_POWER5plus_initfn },
+ { .name = "POWER5+", .initfn = spapr_cpu_core_POWER5plus_initfn },
+
/* POWER7 and aliases */
{ .name = "POWER7_v2.3", .initfn = spapr_cpu_core_POWER7_initfn },
{ .name = "POWER7", .initfn = spapr_cpu_core_POWER7_initfn },
@@ -367,6 +387,10 @@ static const SPAPRCoreInfo spapr_cores[] = {
{ .name = "POWER8E_v2.1", .initfn = spapr_cpu_core_POWER8E_initfn },
{ .name = "POWER8E", .initfn = spapr_cpu_core_POWER8E_initfn },
+ /* POWER8NVL and aliases */
+ { .name = "POWER8NVL_v1.0", .initfn = spapr_cpu_core_POWER8NVL_initfn },
+ { .name = "POWER8NVL", .initfn = spapr_cpu_core_POWER8NVL_initfn },
+
{ .name = NULL }
};
diff --git a/hw/ppc/spapr_events.c b/hw/ppc/spapr_events.c
index af8099220e..b0668b34a9 100644
--- a/hw/ppc/spapr_events.c
+++ b/hw/ppc/spapr_events.c
@@ -386,7 +386,7 @@ static void spapr_powerdown_req(Notifier *n, void *opaque)
rtas_event_log_queue(RTAS_LOG_TYPE_EPOW, new_epow, true);
- qemu_irq_pulse(xics_get_qirq(spapr->icp, spapr->check_exception_irq));
+ qemu_irq_pulse(xics_get_qirq(spapr->xics, spapr->check_exception_irq));
}
static void spapr_hotplug_set_signalled(uint32_t drc_index)
@@ -468,7 +468,7 @@ static void spapr_hotplug_req_event(uint8_t hp_id, uint8_t hp_action,
rtas_event_log_queue(RTAS_LOG_TYPE_HOTPLUG, new_hp, true);
- qemu_irq_pulse(xics_get_qirq(spapr->icp, spapr->check_exception_irq));
+ qemu_irq_pulse(xics_get_qirq(spapr->xics, spapr->check_exception_irq));
}
void spapr_hotplug_req_add_by_index(sPAPRDRConnector *drc)
@@ -551,7 +551,7 @@ static void check_exception(PowerPCCPU *cpu, sPAPRMachineState *spapr,
* interrupts.
*/
if (rtas_event_log_contains(mask, true)) {
- qemu_irq_pulse(xics_get_qirq(spapr->icp, spapr->check_exception_irq));
+ qemu_irq_pulse(xics_get_qirq(spapr->xics, spapr->check_exception_irq));
}
return;
@@ -603,7 +603,7 @@ out_no_events:
void spapr_events_init(sPAPRMachineState *spapr)
{
QTAILQ_INIT(&spapr->pending_events);
- spapr->check_exception_irq = xics_alloc(spapr->icp, 0, 0, false,
+ spapr->check_exception_irq = xics_spapr_alloc(spapr->xics, 0, 0, false,
&error_fatal);
spapr->epow_notifier.notify = spapr_powerdown_req;
qemu_register_powerdown_notifier(&spapr->epow_notifier);
diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c
index 9f28fb3829..8c1e6b17c3 100644
--- a/hw/ppc/spapr_pci.c
+++ b/hw/ppc/spapr_pci.c
@@ -322,7 +322,7 @@ static void rtas_ibm_change_msi(PowerPCCPU *cpu, sPAPRMachineState *spapr,
return;
}
- xics_free(spapr->icp, msi->first_irq, msi->num);
+ xics_spapr_free(spapr->xics, msi->first_irq, msi->num);
if (msi_present(pdev)) {
spapr_msi_setmsg(pdev, 0, false, 0, 0);
}
@@ -360,7 +360,7 @@ static void rtas_ibm_change_msi(PowerPCCPU *cpu, sPAPRMachineState *spapr,
}
/* Allocate MSIs */
- irq = xics_alloc_block(spapr->icp, 0, req_num, false,
+ irq = xics_spapr_alloc_block(spapr->xics, 0, req_num, false,
ret_intr_type == RTAS_TYPE_MSI, &err);
if (err) {
error_reportf_err(err, "Can't allocate MSIs for device %x: ",
@@ -371,7 +371,7 @@ static void rtas_ibm_change_msi(PowerPCCPU *cpu, sPAPRMachineState *spapr,
/* Release previous MSIs */
if (msi) {
- xics_free(spapr->icp, msi->first_irq, msi->num);
+ xics_spapr_free(spapr->xics, msi->first_irq, msi->num);
g_hash_table_remove(phb->msi, &config_addr);
}
@@ -733,7 +733,7 @@ static void spapr_msi_write(void *opaque, hwaddr addr,
trace_spapr_pci_msi_write(addr, data, irq);
- qemu_irq_pulse(xics_get_qirq(spapr->icp, irq));
+ qemu_irq_pulse(xics_get_qirq(spapr->xics, irq));
}
static const MemoryRegionOps spapr_msi_ops = {
@@ -1442,7 +1442,8 @@ static void spapr_phb_realize(DeviceState *dev, Error **errp)
uint32_t irq;
Error *local_err = NULL;
- irq = xics_alloc_block(spapr->icp, 0, 1, true, false, &local_err);
+ irq = xics_spapr_alloc_block(spapr->xics, 0, 1, true, false,
+ &local_err);
if (local_err) {
error_propagate(errp, local_err);
error_prepend(errp, "can't allocate LSIs: ");
@@ -1801,7 +1802,7 @@ int spapr_populate_pci_dt(sPAPRPHBState *phb,
_FDT(fdt_setprop(fdt, bus_off, "ranges", &ranges, sizeof_ranges));
_FDT(fdt_setprop(fdt, bus_off, "reg", &bus_reg, sizeof(bus_reg)));
_FDT(fdt_setprop_cell(fdt, bus_off, "ibm,pci-config-space-type", 0x1));
- _FDT(fdt_setprop_cell(fdt, bus_off, "ibm,pe-total-#msi", XICS_IRQS));
+ _FDT(fdt_setprop_cell(fdt, bus_off, "ibm,pe-total-#msi", XICS_IRQS_SPAPR));
/* Build the interrupt-map, this must matches what is done
* in pci_spapr_map_irq
diff --git a/hw/ppc/spapr_vio.c b/hw/ppc/spapr_vio.c
index ae40db8fd2..f93244d7c1 100644
--- a/hw/ppc/spapr_vio.c
+++ b/hw/ppc/spapr_vio.c
@@ -463,7 +463,7 @@ static void spapr_vio_busdev_realize(DeviceState *qdev, Error **errp)
dev->qdev.id = id;
}
- dev->irq = xics_alloc(spapr->icp, 0, dev->irq, false, &local_err);
+ dev->irq = xics_spapr_alloc(spapr->xics, 0, dev->irq, false, &local_err);
if (local_err) {
error_propagate(errp, local_err);
return;