diff options
Diffstat (limited to 'hw/ppc')
-rw-r--r-- | hw/ppc/e500.c | 2 | ||||
-rw-r--r-- | hw/ppc/e500.h | 2 | ||||
-rw-r--r-- | hw/ppc/ppc.c | 17 | ||||
-rw-r--r-- | hw/ppc/ppce500_spin.c | 7 | ||||
-rw-r--r-- | hw/ppc/spapr.c | 22 | ||||
-rw-r--r-- | hw/ppc/spapr_cpu_core.c | 48 | ||||
-rw-r--r-- | hw/ppc/spapr_events.c | 8 | ||||
-rw-r--r-- | hw/ppc/spapr_pci.c | 13 | ||||
-rw-r--r-- | hw/ppc/spapr_vio.c | 2 |
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; |