diff options
Diffstat (limited to 'hw/ppc')
-rw-r--r-- | hw/ppc/Makefile.objs | 2 | ||||
-rw-r--r-- | hw/ppc/e500.c | 2 | ||||
-rw-r--r-- | hw/ppc/e500.h | 2 | ||||
-rw-r--r-- | hw/ppc/e500plat.c | 1 | ||||
-rw-r--r-- | hw/ppc/mac.h | 7 | ||||
-rw-r--r-- | hw/ppc/mac_newworld.c | 1 | ||||
-rw-r--r-- | hw/ppc/mac_oldworld.c | 2 | ||||
-rw-r--r-- | hw/ppc/ppc.c | 65 | ||||
-rw-r--r-- | hw/ppc/ppc405.h | 6 | ||||
-rw-r--r-- | hw/ppc/ppc4xx_devs.c | 1 | ||||
-rw-r--r-- | hw/ppc/ppce500_spin.c | 9 | ||||
-rw-r--r-- | hw/ppc/prep.c | 3 | ||||
-rw-r--r-- | hw/ppc/spapr.c | 373 | ||||
-rw-r--r-- | hw/ppc/spapr_cpu_core.c | 432 | ||||
-rw-r--r-- | hw/ppc/spapr_drc.c | 25 | ||||
-rw-r--r-- | hw/ppc/spapr_events.c | 11 | ||||
-rw-r--r-- | hw/ppc/spapr_hcall.c | 90 | ||||
-rw-r--r-- | hw/ppc/spapr_iommu.c | 211 | ||||
-rw-r--r-- | hw/ppc/spapr_pci.c | 123 | ||||
-rw-r--r-- | hw/ppc/spapr_pci_vfio.c | 7 | ||||
-rw-r--r-- | hw/ppc/spapr_rtas.c | 26 | ||||
-rw-r--r-- | hw/ppc/spapr_rtas_ddw.c | 295 | ||||
-rw-r--r-- | hw/ppc/spapr_vio.c | 18 | ||||
-rw-r--r-- | hw/ppc/trace-events | 43 | ||||
-rw-r--r-- | hw/ppc/virtex_ml507.c | 1 |
25 files changed, 273 insertions, 1483 deletions
diff --git a/hw/ppc/Makefile.objs b/hw/ppc/Makefile.objs index 91a3420f4..c1ffc7771 100644 --- a/hw/ppc/Makefile.objs +++ b/hw/ppc/Makefile.objs @@ -4,11 +4,9 @@ obj-y += ppc.o ppc_booke.o obj-$(CONFIG_PSERIES) += spapr.o spapr_vio.o spapr_events.o obj-$(CONFIG_PSERIES) += spapr_hcall.o spapr_iommu.o spapr_rtas.o obj-$(CONFIG_PSERIES) += spapr_pci.o spapr_rtc.o spapr_drc.o spapr_rng.o -obj-$(CONFIG_PSERIES) += spapr_cpu_core.o ifeq ($(CONFIG_PCI)$(CONFIG_PSERIES)$(CONFIG_LINUX), yyy) obj-y += spapr_pci_vfio.o endif -obj-$(CONFIG_PSERIES) += spapr_rtas_ddw.o # PowerPC 4xx boards obj-y += ppc405_boards.o ppc4xx_devs.o ppc405_uc.o ppc440_bamboo.o obj-y += ppc4xx_pci.o diff --git a/hw/ppc/e500.c b/hw/ppc/e500.c index 0cd534df5..ee1c60b82 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. */ -hwaddr booke206_page_size_to_tlb(uint64_t size) +static inline 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 70ba1d8f4..ef224ea5e 100644 --- a/hw/ppc/e500.h +++ b/hw/ppc/e500.h @@ -26,6 +26,4 @@ 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/e500plat.c b/hw/ppc/e500plat.c index 94b454551..b00565c3d 100644 --- a/hw/ppc/e500plat.c +++ b/hw/ppc/e500plat.c @@ -14,7 +14,6 @@ #include "e500.h" #include "hw/boards.h" #include "sysemu/device_tree.h" -#include "sysemu/kvm.h" #include "hw/pci/pci.h" #include "hw/ppc/openpic.h" #include "kvm_ppc.h" diff --git a/hw/ppc/mac.h b/hw/ppc/mac.h index 20cbddb4e..5764b86c2 100644 --- a/hw/ppc/mac.h +++ b/hw/ppc/mac.h @@ -22,9 +22,8 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ - -#ifndef PPC_MAC_H -#define PPC_MAC_H +#if !defined(__PPC_MAC_H__) +#define __PPC_MAC_H__ #include "exec/memory.h" #include "hw/sysbus.h" @@ -185,4 +184,4 @@ typedef struct MacIONVRAMState { } MacIONVRAMState; void pmac_format_nvram_partition (MacIONVRAMState *nvr, int len); -#endif /* PPC_MAC_H */ +#endif /* !defined(__PPC_MAC_H__) */ diff --git a/hw/ppc/mac_newworld.c b/hw/ppc/mac_newworld.c index 7d2510658..32e88b378 100644 --- a/hw/ppc/mac_newworld.c +++ b/hw/ppc/mac_newworld.c @@ -380,7 +380,6 @@ static void ppc_core99_init(MachineState *machine) pci_bus = pci_pmac_init(pic, get_system_memory(), get_system_io()); machine_arch = ARCH_MAC99; } - object_property_set_bool(OBJECT(pci_bus), true, "realized", &error_abort); machine->usb |= defaults_enabled() && !machine->usb_disabled; diff --git a/hw/ppc/mac_oldworld.c b/hw/ppc/mac_oldworld.c index 447948746..a9bb1c27d 100644 --- a/hw/ppc/mac_oldworld.c +++ b/hw/ppc/mac_oldworld.c @@ -309,7 +309,7 @@ static void ppc_heathrow_init(MachineState *machine) dev = qdev_create(adb_bus, TYPE_ADB_MOUSE); qdev_init_nofail(dev); - if (machine_usb(machine)) { + if (usb_enabled()) { pci_create_simple(pci_bus, -1, "pci-ohci"); } diff --git a/hw/ppc/ppc.c b/hw/ppc/ppc.c index 894586900..38ff2e159 100644 --- a/hw/ppc/ppc.c +++ b/hw/ppc/ppc.c @@ -33,7 +33,6 @@ #include "hw/timer/m48t59.h" #include "qemu/log.h" #include "qemu/error-report.h" -#include "qapi/error.h" #include "hw/loader.h" #include "sysemu/kvm.h" #include "kvm_ppc.h" @@ -165,9 +164,9 @@ static void ppc6xx_set_irq(void *opaque, int pin, int level) } } -void ppc6xx_irq_init(PowerPCCPU *cpu) +void ppc6xx_irq_init(CPUPPCState *env) { - CPUPPCState *env = &cpu->env; + PowerPCCPU *cpu = ppc_env_get_cpu(env); env->irq_inputs = (void **)qemu_allocate_irqs(&ppc6xx_set_irq, cpu, PPC6xx_INPUT_NB); @@ -252,9 +251,9 @@ static void ppc970_set_irq(void *opaque, int pin, int level) } } -void ppc970_irq_init(PowerPCCPU *cpu) +void ppc970_irq_init(CPUPPCState *env) { - CPUPPCState *env = &cpu->env; + PowerPCCPU *cpu = ppc_env_get_cpu(env); env->irq_inputs = (void **)qemu_allocate_irqs(&ppc970_set_irq, cpu, PPC970_INPUT_NB); @@ -288,9 +287,9 @@ static void power7_set_irq(void *opaque, int pin, int level) } } -void ppcPOWER7_irq_init(PowerPCCPU *cpu) +void ppcPOWER7_irq_init(CPUPPCState *env) { - CPUPPCState *env = &cpu->env; + PowerPCCPU *cpu = ppc_env_get_cpu(env); env->irq_inputs = (void **)qemu_allocate_irqs(&power7_set_irq, cpu, POWER7_INPUT_NB); @@ -373,9 +372,9 @@ static void ppc40x_set_irq(void *opaque, int pin, int level) } } -void ppc40x_irq_init(PowerPCCPU *cpu) +void ppc40x_irq_init(CPUPPCState *env) { - CPUPPCState *env = &cpu->env; + PowerPCCPU *cpu = ppc_env_get_cpu(env); env->irq_inputs = (void **)qemu_allocate_irqs(&ppc40x_set_irq, cpu, PPC40x_INPUT_NB); @@ -437,9 +436,9 @@ static void ppce500_set_irq(void *opaque, int pin, int level) } } -void ppce500_irq_init(PowerPCCPU *cpu) +void ppce500_irq_init(CPUPPCState *env) { - CPUPPCState *env = &cpu->env; + PowerPCCPU *cpu = ppc_env_get_cpu(env); env->irq_inputs = (void **)qemu_allocate_irqs(&ppce500_set_irq, cpu, PPCE500_INPUT_NB); @@ -700,18 +699,9 @@ 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 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); - } + LOG_TB("raise decrementer exception\n"); + ppc_set_irq(cpu, PPC_INTERRUPT_HDECR, 1); } static inline void cpu_ppc_hdecr_lower(PowerPCCPU *cpu) @@ -890,7 +880,7 @@ static int timebase_post_load(void *opaque, int version_id) host_ns = qemu_clock_get_ns(QEMU_CLOCK_HOST); ns_diff = MAX(0, host_ns - tb_remote->time_of_the_day_ns); migration_duration_ns = MIN(NANOSECONDS_PER_SECOND, ns_diff); - migration_duration_tb = muldiv64(freq, migration_duration_ns, + migration_duration_tb = muldiv64(migration_duration_ns, freq, NANOSECONDS_PER_SECOND); guest_tb = tb_remote->guest_timebase + MIN(0, migration_duration_tb); @@ -938,7 +928,9 @@ 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 (env->has_hv_mode) { + if (0) { + /* XXX: find a suitable condition to enable the hypervisor decrementer + */ tb_env->hdecr_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, &cpu_ppc_hdecr_cb, cpu); } else { @@ -1351,28 +1343,3 @@ PowerPCCPU *ppc_get_vcpu_by_dt_id(int cpu_dt_id) return NULL; } - -void ppc_cpu_parse_features(const char *cpu_model) -{ - CPUClass *cc; - ObjectClass *oc; - const char *typename; - gchar **model_pieces; - - model_pieces = g_strsplit(cpu_model, ",", 2); - if (!model_pieces[0]) { - error_report("Invalid/empty CPU model name"); - exit(1); - } - - oc = cpu_class_by_name(TYPE_POWERPC_CPU, model_pieces[0]); - if (oc == NULL) { - error_report("Unable to find CPU definition: %s", model_pieces[0]); - exit(1); - } - - typename = object_class_get_name(oc); - cc = CPU_CLASS(oc); - cc->parse_features(typename, model_pieces[1], &error_fatal); - g_strfreev(model_pieces); -} diff --git a/hw/ppc/ppc405.h b/hw/ppc/ppc405.h index c67febca2..1c5f04fae 100644 --- a/hw/ppc/ppc405.h +++ b/hw/ppc/ppc405.h @@ -22,8 +22,8 @@ * THE SOFTWARE. */ -#ifndef PPC405_H -#define PPC405_H +#if !defined(PPC_405_H) +#define PPC_405_H #include "hw/ppc/ppc4xx.h" @@ -78,4 +78,4 @@ CPUPPCState *ppc_stb025_init (MemoryRegion ram_memories[2], uint32_t sysclk, qemu_irq **picp, ram_addr_t *offsetp); -#endif /* PPC405_H */ +#endif /* !defined(PPC_405_H) */ diff --git a/hw/ppc/ppc4xx_devs.c b/hw/ppc/ppc4xx_devs.c index e7f413e49..7d59018fc 100644 --- a/hw/ppc/ppc4xx_devs.c +++ b/hw/ppc/ppc4xx_devs.c @@ -22,7 +22,6 @@ * THE SOFTWARE. */ #include "qemu/osdep.h" -#include "cpu.h" #include "hw/hw.h" #include "hw/ppc/ppc.h" #include "hw/ppc/ppc4xx.h" diff --git a/hw/ppc/ppce500_spin.c b/hw/ppc/ppce500_spin.c index 22c584eb8..76bd78bfd 100644 --- a/hw/ppc/ppce500_spin.c +++ b/hw/ppc/ppce500_spin.c @@ -32,7 +32,6 @@ #include "sysemu/sysemu.h" #include "hw/sysbus.h" #include "sysemu/kvm.h" -#include "e500.h" #define MAX_CPUS 32 @@ -73,6 +72,12 @@ 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, @@ -99,7 +104,7 @@ static void spin_kick(void *data) hwaddr map_start; cpu_synchronize_state(cpu); - stl_p(&curspin->pir, env->spr[SPR_BOOKE_PIR]); + stl_p(&curspin->pir, env->spr[SPR_PIR]); env->nip = ldq_p(&curspin->addr) & (map_size - 1); env->gpr[3] = ldq_p(&curspin->r3); env->gpr[4] = 0; diff --git a/hw/ppc/prep.c b/hw/ppc/prep.c index 054af1e8b..3ffb85e60 100644 --- a/hw/ppc/prep.c +++ b/hw/ppc/prep.c @@ -22,7 +22,6 @@ * THE SOFTWARE. */ #include "qemu/osdep.h" -#include "cpu.h" #include "hw/hw.h" #include "hw/timer/m48t59.h" #include "hw/i386/pc.h" @@ -649,7 +648,7 @@ static void ppc_prep_init(MachineState *machine) memory_region_add_subregion(sysmem, 0xFEFF0000, xcsr); #endif - if (machine_usb(machine)) { + if (usb_enabled()) { pci_create_simple(pci_bus, -1, "pci-ohci"); } diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index 30d6800ab..b69995e0d 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -29,7 +29,6 @@ #include "sysemu/sysemu.h" #include "sysemu/numa.h" #include "hw/hw.h" -#include "qemu/log.h" #include "hw/fw-path-provider.h" #include "elf.h" #include "net/net.h" @@ -66,8 +65,6 @@ #include "hw/compat.h" #include "qemu/cutils.h" -#include "hw/ppc/spapr_cpu_core.h" -#include "qmp-commands.h" #include <libfdt.h> @@ -91,6 +88,8 @@ #define MIN_RMA_SLOF 128UL +#define TIMEBASE_FREQ 512000000ULL + #define PHANDLE_XICP 0x00001111 #define HTAB_SIZE(spapr) (1ULL << ((spapr)->htab_shift)) @@ -116,16 +115,15 @@ 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 *xics = NULL; + XICSState *icp = NULL; if (kvm_enabled()) { Error *err = NULL; if (machine_kernel_irqchip_allowed(machine)) { - xics = try_create_xics(TYPE_XICS_SPAPR_KVM, nr_servers, nr_irqs, - &err); + icp = try_create_xics(TYPE_KVM_XICS, nr_servers, nr_irqs, &err); } - if (machine_kernel_irqchip_required(machine) && !xics) { + if (machine_kernel_irqchip_required(machine) && !icp) { error_reportf_err(err, "kernel_irqchip requested but unavailable: "); } else { @@ -133,11 +131,11 @@ static XICSState *xics_system_init(MachineState *machine, } } - if (!xics) { - xics = try_create_xics(TYPE_XICS_SPAPR, nr_servers, nr_irqs, errp); + if (!icp) { + icp = try_create_xics(TYPE_XICS, nr_servers, nr_irqs, errp); } - return xics; + return icp; } static int spapr_fixup_cpu_smt_dt(void *fdt, int offset, PowerPCCPU *cpu, @@ -340,9 +338,6 @@ 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); @@ -603,23 +598,12 @@ static void spapr_populate_cpu_dt(CPUState *cs, void *fdt, int offset, int index = ppc_get_vcpu_dt_id(cpu); uint32_t segs[] = {cpu_to_be32(28), cpu_to_be32(40), 0xffffffff, 0xffffffff}; - uint32_t tbfreq = kvm_enabled() ? kvmppc_get_tbfreq() - : SPAPR_TIMEBASE_FREQ; + uint32_t tbfreq = kvm_enabled() ? kvmppc_get_tbfreq() : TIMEBASE_FREQ; uint32_t cpufreq = kvm_enabled() ? kvmppc_get_clockfreq() : 1000000000; uint32_t page_sizes_prop[64]; size_t page_sizes_prop_size; uint32_t vcpus_per_socket = smp_threads * smp_cores; uint32_t pft_size_prop[] = {0, cpu_to_be32(spapr->htab_shift)}; - sPAPRDRConnector *drc; - sPAPRDRConnectorClass *drck; - int drc_index; - - drc = spapr_dr_connector_by_id(SPAPR_DR_CONNECTOR_TYPE_CPU, index); - if (drc) { - drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc); - drc_index = drck->get_index(drc); - _FDT((fdt_setprop_cell(fdt, offset, "ibm,my-drc-index", drc_index))); - } /* Note: we keep CI large pages off for now because a 64K capable guest * provisioned with large pages might otherwise try to map a qemu @@ -777,17 +761,14 @@ static int spapr_populate_drconf_memory(sPAPRMachineState *spapr, void *fdt) int ret, i, offset; uint64_t lmb_size = SPAPR_MEMORY_BLOCK_SIZE; uint32_t prop_lmb_size[] = {0, cpu_to_be32(lmb_size)}; - uint32_t hotplug_lmb_start = spapr->hotplug_memory.base / lmb_size; - uint32_t nr_lmbs = (spapr->hotplug_memory.base + - memory_region_size(&spapr->hotplug_memory.mr)) / - lmb_size; + uint32_t nr_lmbs = (machine->maxram_size - machine->ram_size)/lmb_size; uint32_t *int_buf, *cur_index, buf_len; int nr_nodes = nb_numa_nodes ? nb_numa_nodes : 1; /* - * Don't create the node if there is no hotpluggable memory + * Don't create the node if there are no DR LMBs. */ - if (machine->ram_size == machine->maxram_size) { + if (!nr_lmbs) { return 0; } @@ -821,40 +802,26 @@ static int spapr_populate_drconf_memory(sPAPRMachineState *spapr, void *fdt) int_buf[0] = cpu_to_be32(nr_lmbs); cur_index++; for (i = 0; i < nr_lmbs; i++) { - uint64_t addr = i * lmb_size; + sPAPRDRConnector *drc; + sPAPRDRConnectorClass *drck; + uint64_t addr = i * lmb_size + spapr->hotplug_memory.base;; uint32_t *dynamic_memory = cur_index; - if (i >= hotplug_lmb_start) { - sPAPRDRConnector *drc; - sPAPRDRConnectorClass *drck; - - drc = spapr_dr_connector_by_id(SPAPR_DR_CONNECTOR_TYPE_LMB, i); - g_assert(drc); - drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc); - - dynamic_memory[0] = cpu_to_be32(addr >> 32); - dynamic_memory[1] = cpu_to_be32(addr & 0xffffffff); - dynamic_memory[2] = cpu_to_be32(drck->get_index(drc)); - dynamic_memory[3] = cpu_to_be32(0); /* reserved */ - dynamic_memory[4] = cpu_to_be32(numa_get_node(addr, NULL)); - if (memory_region_present(get_system_memory(), addr)) { - dynamic_memory[5] = cpu_to_be32(SPAPR_LMB_FLAGS_ASSIGNED); - } else { - dynamic_memory[5] = cpu_to_be32(0); - } + drc = spapr_dr_connector_by_id(SPAPR_DR_CONNECTOR_TYPE_LMB, + addr/lmb_size); + g_assert(drc); + drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc); + + dynamic_memory[0] = cpu_to_be32(addr >> 32); + dynamic_memory[1] = cpu_to_be32(addr & 0xffffffff); + dynamic_memory[2] = cpu_to_be32(drck->get_index(drc)); + dynamic_memory[3] = cpu_to_be32(0); /* reserved */ + dynamic_memory[4] = cpu_to_be32(numa_get_node(addr, NULL)); + if (addr < machine->ram_size || + memory_region_present(get_system_memory(), addr)) { + dynamic_memory[5] = cpu_to_be32(SPAPR_LMB_FLAGS_ASSIGNED); } else { - /* - * LMB information for RMA, boot time RAM and gap b/n RAM and - * hotplug memory region -- all these are marked as reserved - * and as having no valid DRC. - */ - dynamic_memory[0] = cpu_to_be32(addr >> 32); - dynamic_memory[1] = cpu_to_be32(addr & 0xffffffff); - dynamic_memory[2] = cpu_to_be32(0); - dynamic_memory[3] = cpu_to_be32(0); /* reserved */ - dynamic_memory[4] = cpu_to_be32(-1); - dynamic_memory[5] = cpu_to_be32(SPAPR_LMB_FLAGS_RESERVED | - SPAPR_LMB_FLAGS_DRC_INVALID); + dynamic_memory[5] = cpu_to_be32(0); } cur_index += SPAPR_DR_LMB_LIST_ENTRY_SIZE; @@ -938,7 +905,6 @@ static void spapr_finalize_fdt(sPAPRMachineState *spapr, hwaddr rtas_size) { MachineState *machine = MACHINE(qdev_get_machine()); - MachineClass *mc = MACHINE_GET_CLASS(machine); sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(machine); const char *boot_device = machine->boot_order; int ret, i; @@ -1021,16 +987,6 @@ static void spapr_finalize_fdt(sPAPRMachineState *spapr, _FDT(spapr_drc_populate_dt(fdt, 0, NULL, SPAPR_DR_CONNECTOR_TYPE_LMB)); } - if (mc->query_hotpluggable_cpus) { - int offset = fdt_path_offset(fdt, "/cpus"); - ret = spapr_drc_populate_dt(fdt, offset, NULL, - SPAPR_DR_CONNECTOR_TYPE_CPU); - if (ret < 0) { - error_report("Couldn't set up CPU DR device tree properties"); - exit(1); - } - } - _FDT((fdt_pack(fdt))); if (fdt_totalsize(fdt) > FDT_MAX_SIZE) { @@ -1224,6 +1180,26 @@ static void ppc_spapr_reset(void) } +static void spapr_cpu_reset(void *opaque) +{ + sPAPRMachineState *spapr = SPAPR_MACHINE(qdev_get_machine()); + PowerPCCPU *cpu = opaque; + CPUState *cs = CPU(cpu); + CPUPPCState *env = &cpu->env; + + cpu_reset(cs); + + /* All CPUs start halted. CPU0 is unhalted from the machine level + * reset code and the rest are explicitly started up by the guest + * using an RTAS call */ + cs->halted = 1; + + env->spr[SPR_HIOR] = 0; + + ppc_hash64_set_external_hpt(cpu, spapr->htab, spapr->htab_shift, + &error_fatal); +} + static void spapr_create_nvram(sPAPRMachineState *spapr) { DeviceState *dev = qdev_create(&spapr->vio_bus->bus, "spapr-nvram"); @@ -1513,6 +1489,7 @@ static int htab_save_complete(QEMUFile *f, void *opaque) if (rc < 0) { return rc; } + close_htab_fd(spapr); } else { if (spapr->htab_first_pass) { htab_save_first_pass(f, spapr, -1); @@ -1614,18 +1591,10 @@ static int htab_load(QEMUFile *f, void *opaque, int version_id) return 0; } -static void htab_cleanup(void *opaque) -{ - sPAPRMachineState *spapr = opaque; - - close_htab_fd(spapr); -} - static SaveVMHandlers savevm_htab_handlers = { .save_live_setup = htab_save_setup, .save_live_iterate = htab_save_iterate, .save_live_complete_precopy = htab_save_complete, - .cleanup = htab_cleanup, .load_state = htab_load, }; @@ -1636,6 +1605,32 @@ static void spapr_boot_set(void *opaque, const char *boot_device, machine->boot_order = g_strdup(boot_device); } +static void spapr_cpu_init(sPAPRMachineState *spapr, PowerPCCPU *cpu, + Error **errp) +{ + CPUPPCState *env = &cpu->env; + + /* Set time-base frequency to 512 MHz */ + cpu_ppc_tb_init(env, TIMEBASE_FREQ); + + /* Enable PAPR mode in TCG or KVM */ + cpu_ppc_set_papr(cpu); + + if (cpu->max_compat) { + Error *local_err = NULL; + + ppc_set_compat(cpu, cpu->max_compat, &local_err); + if (local_err) { + error_propagate(errp, local_err); + return; + } + } + + xics_cpu_setup(spapr->icp, cpu); + + qemu_register_reset(spapr_cpu_reset, cpu); +} + /* * Reset routine for LMB DR devices. * @@ -1713,11 +1708,11 @@ static void spapr_validate_node_memory(MachineState *machine, Error **errp) static void ppc_spapr_init(MachineState *machine) { sPAPRMachineState *spapr = SPAPR_MACHINE(machine); - MachineClass *mc = MACHINE_GET_CLASS(machine); sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(machine); const char *kernel_filename = machine->kernel_filename; const char *kernel_cmdline = machine->kernel_cmdline; const char *initrd_filename = machine->initrd_filename; + PowerPCCPU *cpu; PCIHostState *phb; int i; MemoryRegion *sysmem = get_system_memory(); @@ -1731,22 +1726,6 @@ static void ppc_spapr_init(MachineState *machine) long load_limit, fw_size; bool kernel_le = false; char *filename; - int smt = kvmppc_smt_threads(); - int spapr_cores = smp_cpus / smp_threads; - int spapr_max_cores = max_cpus / smp_threads; - - if (mc->query_hotpluggable_cpus) { - if (smp_cpus % smp_threads) { - error_report("smp_cpus (%u) must be multiple of threads (%u)", - smp_cpus, smp_threads); - exit(1); - } - if (max_cpus % smp_threads) { - error_report("max_cpus (%u) must be multiple of threads (%u)", - max_cpus, smp_threads); - exit(1); - } - } msi_nonbroken = true; @@ -1780,13 +1759,6 @@ static void ppc_spapr_init(MachineState *machine) spapr->vrma_adjust = 1; spapr->rma_size = MIN(spapr->rma_size, 0x10000000); } - - /* Actually we don't support unbounded RMA anymore since we - * added proper emulation of HV mode. The max we can get is - * 16G which also happens to be what we configure for PAPR - * mode so make sure we don't do anything bigger than that - */ - spapr->rma_size = MIN(spapr->rma_size, 0x400000000ull); } if (spapr->rma_size > node0_size) { @@ -1799,9 +1771,10 @@ 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->xics = xics_system_init(machine, - DIV_ROUND_UP(max_cpus * smt, smp_threads), - XICS_IRQS_SPAPR, &error_fatal); + spapr->icp = xics_system_init(machine, + DIV_ROUND_UP(max_cpus * kvmppc_smt_threads(), + smp_threads), + XICS_IRQS, &error_fatal); if (smc->dr_lmb_enabled) { spapr_validate_node_memory(machine, &error_fatal); @@ -1811,46 +1784,13 @@ static void ppc_spapr_init(MachineState *machine) if (machine->cpu_model == NULL) { machine->cpu_model = kvm_enabled() ? "host" : "POWER7"; } - - ppc_cpu_parse_features(machine->cpu_model); - - if (mc->query_hotpluggable_cpus) { - char *type = spapr_get_cpu_core_type(machine->cpu_model); - - if (type == NULL) { - error_report("Unable to find sPAPR CPU Core definition"); + for (i = 0; i < smp_cpus; i++) { + cpu = cpu_ppc_init(machine->cpu_model); + if (cpu == NULL) { + error_report("Unable to find PowerPC CPU definition"); exit(1); } - - spapr->cores = g_new0(Object *, spapr_max_cores); - for (i = 0; i < spapr_max_cores; i++) { - int core_id = i * smp_threads; - sPAPRDRConnector *drc = - spapr_dr_connector_new(OBJECT(spapr), - SPAPR_DR_CONNECTOR_TYPE_CPU, - (core_id / smp_threads) * smt); - - qemu_register_reset(spapr_drc_reset, drc); - - if (i < spapr_cores) { - Object *core = object_new(type); - object_property_set_int(core, smp_threads, "nr-threads", - &error_fatal); - object_property_set_int(core, core_id, CPU_CORE_PROP_CORE_ID, - &error_fatal); - object_property_set_bool(core, true, "realized", &error_fatal); - } - } - g_free(type); - } else { - for (i = 0; i < smp_cpus; i++) { - PowerPCCPU *cpu = cpu_ppc_init(machine->cpu_model); - if (cpu == NULL) { - error_report("Unable to find PowerPC CPU definition"); - exit(1); - } - spapr_cpu_init(spapr, cpu, &error_fatal); - } + spapr_cpu_init(spapr, cpu, &error_fatal); } if (kvm_enabled()) { @@ -1875,21 +1815,11 @@ static void ppc_spapr_init(MachineState *machine) /* initialize hotplug memory address space */ if (machine->ram_size < machine->maxram_size) { ram_addr_t hotplug_mem_size = machine->maxram_size - machine->ram_size; - /* - * Limit the number of hotpluggable memory slots to half the number - * slots that KVM supports, leaving the other half for PCI and other - * devices. However ensure that number of slots doesn't drop below 32. - */ - int max_memslots = kvm_enabled() ? kvm_get_max_memslots() / 2 : - SPAPR_MAX_RAM_SLOTS; - if (max_memslots < SPAPR_MAX_RAM_SLOTS) { - max_memslots = SPAPR_MAX_RAM_SLOTS; - } - if (machine->ram_slots > max_memslots) { + if (machine->ram_slots > SPAPR_MAX_RAM_SLOTS) { error_report("Specified number of memory slots %" PRIu64" exceeds max supported %d", - machine->ram_slots, max_memslots); + machine->ram_slots, SPAPR_MAX_RAM_SLOTS); exit(1); } @@ -1911,10 +1841,6 @@ static void ppc_spapr_init(MachineState *machine) exit(1); } spapr->rtas_size = get_image_size(filename); - if (spapr->rtas_size < 0) { - error_report("Could not get size of LPAR rtas '%s'", filename); - exit(1); - } spapr->rtas_blob = g_malloc(spapr->rtas_size); if (load_image_size(filename, spapr->rtas_blob, spapr->rtas_size) < 0) { error_report("Could not load LPAR rtas '%s'", filename); @@ -2205,6 +2131,15 @@ static void spapr_add_lmbs(DeviceState *dev, uint64_t addr, uint64_t size, int i, fdt_offset, fdt_size; void *fdt; + /* + * Check for DRC connectors and send hotplug notification to the + * guest only in case of hotplugged memory. This allows cold plugged + * memory to be specified at boot time. + */ + if (!dev->hotplugged) { + return; + } + for (i = 0; i < nr_lmbs; i++) { drc = spapr_dr_connector_by_id(SPAPR_DR_CONNECTOR_TYPE_LMB, addr/SPAPR_MEMORY_BLOCK_SIZE); @@ -2218,12 +2153,7 @@ static void spapr_add_lmbs(DeviceState *dev, uint64_t addr, uint64_t size, drck->attach(drc, dev, fdt, fdt_offset, !dev->hotplugged, errp); addr += SPAPR_MEMORY_BLOCK_SIZE; } - /* send hotplug notification to the - * guest only in case of hotplugged memory - */ - if (dev->hotplugged) { - spapr_hotplug_req_add_by_count(SPAPR_DR_CONNECTOR_TYPE_LMB, nr_lmbs); - } + spapr_hotplug_req_add_by_count(SPAPR_DR_CONNECTOR_TYPE_LMB, nr_lmbs); } static void spapr_memory_plug(HotplugHandler *hotplug_dev, DeviceState *dev, @@ -2261,27 +2191,6 @@ out: error_propagate(errp, local_err); } -void *spapr_populate_hotplug_cpu_dt(CPUState *cs, int *fdt_offset, - sPAPRMachineState *spapr) -{ - PowerPCCPU *cpu = POWERPC_CPU(cs); - DeviceClass *dc = DEVICE_GET_CLASS(cs); - int id = ppc_get_vcpu_dt_id(cpu); - void *fdt; - int offset, fdt_size; - char *nodename; - - fdt = create_device_tree(&fdt_size); - nodename = g_strdup_printf("%s@%x", dc->fw_name, id); - offset = fdt_add_subnode(fdt, 0, nodename); - - spapr_populate_cpu_dt(cs, fdt, offset, spapr); - g_free(nodename); - - *fdt_offset = offset; - return fdt; -} - static void spapr_machine_device_plug(HotplugHandler *hotplug_dev, DeviceState *dev, Error **errp) { @@ -2326,40 +2235,21 @@ static void spapr_machine_device_plug(HotplugHandler *hotplug_dev, } spapr_memory_plug(hotplug_dev, dev, node, errp); - } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_CPU_CORE)) { - spapr_core_plug(hotplug_dev, dev, errp); } } static void spapr_machine_device_unplug(HotplugHandler *hotplug_dev, DeviceState *dev, Error **errp) { - MachineClass *mc = MACHINE_GET_CLASS(qdev_get_machine()); - if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { error_setg(errp, "Memory hot unplug not supported by sPAPR"); - } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_CPU_CORE)) { - if (!mc->query_hotpluggable_cpus) { - error_setg(errp, "CPU hot unplug not supported on this machine"); - return; - } - spapr_core_unplug(hotplug_dev, dev, errp); - } -} - -static void spapr_machine_device_pre_plug(HotplugHandler *hotplug_dev, - DeviceState *dev, Error **errp) -{ - if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_CPU_CORE)) { - spapr_core_pre_plug(hotplug_dev, dev, errp); } } static HotplugHandler *spapr_get_hotpug_handler(MachineState *machine, DeviceState *dev) { - if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM) || - object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_CPU_CORE)) { + if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { return HOTPLUG_HANDLER(machine); } return NULL; @@ -2372,37 +2262,6 @@ static unsigned spapr_cpu_index_to_socket_id(unsigned cpu_index) return cpu_index / smp_threads / smp_cores; } -static HotpluggableCPUList *spapr_query_hotpluggable_cpus(MachineState *machine) -{ - int i; - HotpluggableCPUList *head = NULL; - sPAPRMachineState *spapr = SPAPR_MACHINE(machine); - int spapr_max_cores = max_cpus / smp_threads; - - for (i = 0; i < spapr_max_cores; i++) { - HotpluggableCPUList *list_item = g_new0(typeof(*list_item), 1); - HotpluggableCPU *cpu_item = g_new0(typeof(*cpu_item), 1); - CpuInstanceProperties *cpu_props = g_new0(typeof(*cpu_props), 1); - - cpu_item->type = spapr_get_cpu_core_type(machine->cpu_model); - cpu_item->vcpus_count = smp_threads; - cpu_props->has_core_id = true; - cpu_props->core_id = i * smp_threads; - /* TODO: add 'has_node/node' here to describe - to which node core belongs */ - - cpu_item->props = cpu_props; - if (spapr->cores[i]) { - cpu_item->has_qom_path = true; - cpu_item->qom_path = object_get_canonical_path(spapr->cores[i]); - } - list_item->value = cpu_item; - list_item->next = head; - head = list_item; - } - return head; -} - static void spapr_machine_class_init(ObjectClass *oc, void *data) { MachineClass *mc = MACHINE_CLASS(oc); @@ -2429,13 +2288,11 @@ static void spapr_machine_class_init(ObjectClass *oc, void *data) mc->has_dynamic_sysbus = true; mc->pci_allow_0_address = true; mc->get_hotplug_handler = spapr_get_hotpug_handler; - hc->pre_plug = spapr_machine_device_pre_plug; hc->plug = spapr_machine_device_plug; hc->unplug = spapr_machine_device_unplug; mc->cpu_index_to_socket_id = spapr_cpu_index_to_socket_id; smc->dr_lmb_enabled = true; - mc->query_hotpluggable_cpus = spapr_query_hotpluggable_cpus; fwc->get_dev_path = spapr_get_fw_dev_path; nc->nmi_monitor_handler = spapr_nmi; } @@ -2486,42 +2343,18 @@ static const TypeInfo spapr_machine_info = { type_init(spapr_machine_register_##suffix) /* - * pseries-2.7 - */ -static void spapr_machine_2_7_instance_options(MachineState *machine) -{ -} - -static void spapr_machine_2_7_class_options(MachineClass *mc) -{ - /* Defaults for the latest behaviour inherited from the base class */ -} - -DEFINE_SPAPR_MACHINE(2_7, "2.7", true); - -/* * 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) { } static void spapr_machine_2_6_class_options(MachineClass *mc) { - spapr_machine_2_7_class_options(mc); - mc->query_hotpluggable_cpus = NULL; - SET_MACHINE_COMPAT(mc, SPAPR_COMPAT_2_6); + /* Defaults for the latest behaviour inherited from the base class */ } -DEFINE_SPAPR_MACHINE(2_6, "2.6", false); +DEFINE_SPAPR_MACHINE(2_6, "2.6", true); /* * pseries-2.5 @@ -2553,6 +2386,7 @@ DEFINE_SPAPR_MACHINE(2_5, "2.5", false); * pseries-2.4 */ #define SPAPR_COMPAT_2_4 \ + SPAPR_COMPAT_2_5 \ HW_COMPAT_2_4 static void spapr_machine_2_4_instance_options(MachineState *machine) @@ -2575,6 +2409,7 @@ DEFINE_SPAPR_MACHINE(2_4, "2.4", false); * pseries-2.3 */ #define SPAPR_COMPAT_2_3 \ + SPAPR_COMPAT_2_4 \ HW_COMPAT_2_3 \ {\ .driver = "spapr-pci-host-bridge",\ @@ -2602,6 +2437,7 @@ DEFINE_SPAPR_MACHINE(2_3, "2.3", false); */ #define SPAPR_COMPAT_2_2 \ + SPAPR_COMPAT_2_3 \ HW_COMPAT_2_2 \ {\ .driver = TYPE_SPAPR_PCI_HOST_BRIDGE,\ @@ -2626,6 +2462,7 @@ DEFINE_SPAPR_MACHINE(2_2, "2.2", false); * pseries-2.1 */ #define SPAPR_COMPAT_2_1 \ + SPAPR_COMPAT_2_2 \ HW_COMPAT_2_1 static void spapr_machine_2_1_instance_options(MachineState *machine) diff --git a/hw/ppc/spapr_cpu_core.c b/hw/ppc/spapr_cpu_core.c deleted file mode 100644 index bcb483dbe..000000000 --- a/hw/ppc/spapr_cpu_core.c +++ /dev/null @@ -1,432 +0,0 @@ -/* - * sPAPR CPU core device, acts as container of CPU thread devices. - * - * Copyright (C) 2016 Bharata B Rao <bharata@linux.vnet.ibm.com> - * - * This work is licensed under the terms of the GNU GPL, version 2 or later. - * See the COPYING file in the top-level directory. - */ -#include "hw/cpu/core.h" -#include "hw/ppc/spapr_cpu_core.h" -#include "target-ppc/cpu.h" -#include "hw/ppc/spapr.h" -#include "hw/boards.h" -#include "qapi/error.h" -#include "sysemu/cpus.h" -#include "target-ppc/kvm_ppc.h" -#include "hw/ppc/ppc.h" -#include "target-ppc/mmu-hash64.h" -#include "sysemu/numa.h" - -static void spapr_cpu_reset(void *opaque) -{ - sPAPRMachineState *spapr = SPAPR_MACHINE(qdev_get_machine()); - PowerPCCPU *cpu = opaque; - CPUState *cs = CPU(cpu); - CPUPPCState *env = &cpu->env; - - cpu_reset(cs); - - /* All CPUs start halted. CPU0 is unhalted from the machine level - * reset code and the rest are explicitly started up by the guest - * using an RTAS call */ - cs->halted = 1; - - env->spr[SPR_HIOR] = 0; - - ppc_hash64_set_external_hpt(cpu, spapr->htab, spapr->htab_shift, - &error_fatal); -} - -static void spapr_cpu_destroy(PowerPCCPU *cpu) -{ - sPAPRMachineState *spapr = SPAPR_MACHINE(qdev_get_machine()); - - xics_cpu_destroy(spapr->xics, cpu); - qemu_unregister_reset(spapr_cpu_reset, cpu); -} - -void spapr_cpu_init(sPAPRMachineState *spapr, PowerPCCPU *cpu, Error **errp) -{ - CPUPPCState *env = &cpu->env; - CPUState *cs = CPU(cpu); - int i; - - /* Set time-base frequency to 512 MHz */ - cpu_ppc_tb_init(env, SPAPR_TIMEBASE_FREQ); - - /* Enable PAPR mode in TCG or KVM */ - cpu_ppc_set_papr(cpu); - - if (cpu->max_compat) { - Error *local_err = NULL; - - ppc_set_compat(cpu, cpu->max_compat, &local_err); - if (local_err) { - error_propagate(errp, local_err); - return; - } - } - - /* Set NUMA node for the added CPUs */ - for (i = 0; i < nb_numa_nodes; i++) { - if (test_bit(cs->cpu_index, numa_info[i].node_cpu)) { - cs->numa_node = i; - break; - } - } - - xics_cpu_setup(spapr->xics, cpu); - - qemu_register_reset(spapr_cpu_reset, cpu); - spapr_cpu_reset(cpu); -} - -/* - * Return the sPAPR CPU core type for @model which essentially is the CPU - * model specified with -cpu cmdline option. - */ -char *spapr_get_cpu_core_type(const char *model) -{ - char *core_type; - gchar **model_pieces = g_strsplit(model, ",", 2); - - core_type = g_strdup_printf("%s-%s", model_pieces[0], TYPE_SPAPR_CPU_CORE); - g_strfreev(model_pieces); - - /* Check whether it exists or whether we have to look up an alias name */ - if (!object_class_by_name(core_type)) { - const char *realmodel; - - g_free(core_type); - realmodel = ppc_cpu_lookup_alias(model); - if (realmodel) { - return spapr_get_cpu_core_type(realmodel); - } - return NULL; - } - - return core_type; -} - -static void spapr_core_release(DeviceState *dev, void *opaque) -{ - sPAPRCPUCore *sc = SPAPR_CPU_CORE(OBJECT(dev)); - 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()); - CPUCore *cc = CPU_CORE(dev); - int i; - - for (i = 0; i < cc->nr_threads; i++) { - void *obj = sc->threads + i * size; - DeviceState *dev = DEVICE(obj); - CPUState *cs = CPU(dev); - PowerPCCPU *cpu = POWERPC_CPU(cs); - - spapr_cpu_destroy(cpu); - cpu_remove_sync(cs); - object_unparent(obj); - } - - spapr->cores[cc->core_id / smp_threads] = NULL; - - g_free(sc->threads); - object_unparent(OBJECT(dev)); -} - -void spapr_core_unplug(HotplugHandler *hotplug_dev, DeviceState *dev, - Error **errp) -{ - CPUCore *cc = CPU_CORE(dev); - int smt = kvmppc_smt_threads(); - int index = cc->core_id / smp_threads; - sPAPRDRConnector *drc = - spapr_dr_connector_by_id(SPAPR_DR_CONNECTOR_TYPE_CPU, index * smt); - sPAPRDRConnectorClass *drck; - Error *local_err = NULL; - - if (index == 0) { - error_setg(errp, "Boot CPU core may not be unplugged"); - return; - } - - g_assert(drc); - - drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc); - drck->detach(drc, dev, spapr_core_release, NULL, &local_err); - if (local_err) { - error_propagate(errp, local_err); - return; - } - - spapr_hotplug_req_remove_by_index(drc); -} - -void spapr_core_plug(HotplugHandler *hotplug_dev, DeviceState *dev, - Error **errp) -{ - sPAPRMachineState *spapr = SPAPR_MACHINE(OBJECT(hotplug_dev)); - sPAPRCPUCore *core = SPAPR_CPU_CORE(OBJECT(dev)); - CPUCore *cc = CPU_CORE(dev); - CPUState *cs = CPU(core->threads); - sPAPRDRConnector *drc; - sPAPRDRConnectorClass *drck; - Error *local_err = NULL; - void *fdt = NULL; - int fdt_offset = 0; - int index = cc->core_id / smp_threads; - int smt = kvmppc_smt_threads(); - - drc = spapr_dr_connector_by_id(SPAPR_DR_CONNECTOR_TYPE_CPU, index * smt); - spapr->cores[index] = OBJECT(dev); - - g_assert(drc); - - /* - * Setup CPU DT entries only for hotplugged CPUs. For boot time or - * coldplugged CPUs DT entries are setup in spapr_finalize_fdt(). - */ - if (dev->hotplugged) { - fdt = spapr_populate_hotplug_cpu_dt(cs, &fdt_offset, spapr); - } - - drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc); - drck->attach(drc, dev, fdt, fdt_offset, !dev->hotplugged, &local_err); - if (local_err) { - g_free(fdt); - spapr->cores[index] = NULL; - error_propagate(errp, local_err); - return; - } - - if (dev->hotplugged) { - /* - * Send hotplug notification interrupt to the guest only in case - * of hotplugged CPUs. - */ - spapr_hotplug_req_add_by_index(drc); - } else { - /* - * Set the right DRC states for cold plugged CPU. - */ - drck->set_allocation_state(drc, SPAPR_DR_ALLOCATION_STATE_USABLE); - drck->set_isolation_state(drc, SPAPR_DR_ISOLATION_STATE_UNISOLATED); - } -} - -void spapr_core_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev, - Error **errp) -{ - MachineState *machine = MACHINE(OBJECT(hotplug_dev)); - MachineClass *mc = MACHINE_GET_CLASS(hotplug_dev); - sPAPRMachineState *spapr = SPAPR_MACHINE(OBJECT(hotplug_dev)); - int spapr_max_cores = max_cpus / smp_threads; - int index; - Error *local_err = NULL; - CPUCore *cc = CPU_CORE(dev); - char *base_core_type = spapr_get_cpu_core_type(machine->cpu_model); - const char *type = object_get_typename(OBJECT(dev)); - - if (!mc->query_hotpluggable_cpus) { - error_setg(&local_err, "CPU hotplug not supported for this machine"); - goto out; - } - - if (strcmp(base_core_type, type)) { - error_setg(&local_err, "CPU core type should be %s", base_core_type); - goto out; - } - - if (cc->nr_threads != smp_threads) { - error_setg(&local_err, "threads must be %d", smp_threads); - goto out; - } - - if (cc->core_id % smp_threads) { - error_setg(&local_err, "invalid core id %d", cc->core_id); - goto out; - } - - index = cc->core_id / smp_threads; - if (index < 0 || index >= spapr_max_cores) { - error_setg(&local_err, "core id %d out of range", cc->core_id); - goto out; - } - - if (spapr->cores[index]) { - error_setg(&local_err, "core %d already populated", cc->core_id); - goto out; - } - -out: - g_free(base_core_type); - error_propagate(errp, local_err); -} - -static void spapr_cpu_core_realize_child(Object *child, Error **errp) -{ - Error *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", &local_err); - if (local_err) { - error_propagate(errp, local_err); - return; - } - - spapr_cpu_init(spapr, cpu, &local_err); - if (local_err) { - error_propagate(errp, local_err); - return; - } -} - -static void spapr_cpu_core_realize(DeviceState *dev, Error **errp) -{ - sPAPRCPUCore *sc = SPAPR_CPU_CORE(OBJECT(dev)); - CPUCore *cc = CPU_CORE(OBJECT(dev)); - const char *typename = object_class_get_name(sc->cpu_class); - size_t size = object_type_get_instance_size(typename); - Error *local_err = NULL; - void *obj; - int i, j; - - sc->threads = g_malloc0(size * cc->nr_threads); - for (i = 0; i < cc->nr_threads; i++) { - char id[32]; - CPUState *cs; - - obj = sc->threads + i * size; - - object_initialize(obj, size, typename); - cs = CPU(obj); - cs->cpu_index = cc->core_id + i; - snprintf(id, sizeof(id), "thread[%d]", i); - object_property_add_child(OBJECT(sc), id, obj, &local_err); - if (local_err) { - goto err; - } - object_unref(obj); - } - - for (j = 0; j < cc->nr_threads; j++) { - obj = sc->threads + j * size; - - spapr_cpu_core_realize_child(obj, &local_err); - if (local_err) { - goto err; - } - } - return; - -err: - while (--i >= 0) { - obj = sc->threads + i * size; - object_unparent(obj); - } - g_free(sc->threads); - error_propagate(errp, local_err); -} - -static void spapr_cpu_core_class_init(ObjectClass *oc, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(oc); - dc->realize = spapr_cpu_core_realize; -} - -/* - * instance_init routines from different flavours of sPAPR CPU cores. - */ -#define SPAPR_CPU_CORE_INITFN(_type, _fname) \ -static void glue(glue(spapr_cpu_core_, _fname), _initfn(Object *obj)) \ -{ \ - sPAPRCPUCore *core = SPAPR_CPU_CORE(obj); \ - char *name = g_strdup_printf("%s-" TYPE_POWERPC_CPU, stringify(_type)); \ - ObjectClass *oc = object_class_by_name(name); \ - g_assert(oc); \ - g_free((void *)name); \ - 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; - void (*initfn)(Object *obj); -} SPAPRCoreInfo; - -static const SPAPRCoreInfo spapr_cores[] = { - /* 970 */ - { .name = "970_v2.2", .initfn = spapr_cpu_core_970_initfn }, - - /* 970MP variants */ - { .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 }, - - /* POWER5+ */ - { .name = "POWER5+_v2.1", .initfn = spapr_cpu_core_POWER5plus_initfn }, - - /* POWER7 */ - { .name = "POWER7_v2.3", .initfn = spapr_cpu_core_POWER7_initfn }, - - /* POWER7+ */ - { .name = "POWER7+_v2.1", .initfn = spapr_cpu_core_POWER7plus_initfn }, - - /* POWER8 */ - { .name = "POWER8_v2.0", .initfn = spapr_cpu_core_POWER8_initfn }, - - /* POWER8E */ - { .name = "POWER8E_v2.1", .initfn = spapr_cpu_core_POWER8E_initfn }, - - /* POWER8NVL */ - { .name = "POWER8NVL_v1.0", .initfn = spapr_cpu_core_POWER8NVL_initfn }, - - { .name = NULL } -}; - -static void spapr_cpu_core_register(const SPAPRCoreInfo *info) -{ - TypeInfo type_info = { - .parent = TYPE_SPAPR_CPU_CORE, - .instance_size = sizeof(sPAPRCPUCore), - .instance_init = info->initfn, - }; - - type_info.name = g_strdup_printf("%s-" TYPE_SPAPR_CPU_CORE, info->name); - type_register(&type_info); - g_free((void *)type_info.name); -} - -static const TypeInfo spapr_cpu_core_type_info = { - .name = TYPE_SPAPR_CPU_CORE, - .parent = TYPE_CPU_CORE, - .abstract = true, - .instance_size = sizeof(sPAPRCPUCore), - .class_init = spapr_cpu_core_class_init, -}; - -static void spapr_cpu_core_register_types(void) -{ - const SPAPRCoreInfo *info = spapr_cores; - - type_register_static(&spapr_cpu_core_type_info); - while (info->name) { - spapr_cpu_core_register(info); - info++; - } -} - -type_init(spapr_cpu_core_register_types) diff --git a/hw/ppc/spapr_drc.c b/hw/ppc/spapr_drc.c index 26a067951..1f5f1d790 100644 --- a/hw/ppc/spapr_drc.c +++ b/hw/ppc/spapr_drc.c @@ -140,8 +140,6 @@ static uint32_t set_allocation_state(sPAPRDRConnector *drc, DPRINTFN("finalizing device removal"); drck->detach(drc, DEVICE(drc->dev), drc->detach_cb, drc->detach_cb_opaque, NULL); - } else if (drc->allocation_state == SPAPR_DR_ALLOCATION_STATE_USABLE) { - drc->awaiting_allocation = false; } } return RTAS_OUT_SUCCESS; @@ -271,7 +269,11 @@ static void prop_get_fdt(Object *obj, Visitor *v, const char *name, void *fdt; if (!drc->fdt) { - visit_type_null(v, NULL, errp); + visit_start_struct(v, name, NULL, 0, &err); + if (!err) { + visit_end_struct(v, &err); + } + error_propagate(errp, err); return; } @@ -299,8 +301,7 @@ static void prop_get_fdt(Object *obj, Visitor *v, const char *name, case FDT_END_NODE: /* shouldn't ever see an FDT_END_NODE before FDT_BEGIN_NODE */ g_assert(fdt_depth > 0); - visit_check_struct(v, &err); - visit_end_struct(v, NULL); + visit_end_struct(v, &err); if (err) { error_propagate(errp, err); return; @@ -311,7 +312,7 @@ static void prop_get_fdt(Object *obj, Visitor *v, const char *name, int i; prop = fdt_get_property_by_offset(fdt, fdt_offset, &prop_len); name = fdt_string(fdt, fdt32_to_cpu(prop->nameoff)); - visit_start_list(v, name, NULL, 0, &err); + visit_start_list(v, name, &err); if (err) { error_propagate(errp, err); return; @@ -323,7 +324,7 @@ static void prop_get_fdt(Object *obj, Visitor *v, const char *name, return; } } - visit_end_list(v, NULL); + visit_end_list(v); break; } default: @@ -375,10 +376,6 @@ static void attach(sPAPRDRConnector *drc, DeviceState *d, void *fdt, drc->signalled = (drc->type != SPAPR_DR_CONNECTOR_TYPE_PCI) ? true : coldplug; - if (drc->type != SPAPR_DR_CONNECTOR_TYPE_PCI) { - drc->awaiting_allocation = true; - } - object_property_add_link(OBJECT(drc), "device", object_get_typename(OBJECT(drc->dev)), (Object **)(&drc->dev), @@ -427,12 +424,6 @@ static void detach(sPAPRDRConnector *drc, DeviceState *d, return; } - if (drc->awaiting_allocation) { - drc->awaiting_release = true; - DPRINTFN("awaiting allocation to complete before removal"); - return; - } - drc->indicator_state = SPAPR_DR_INDICATOR_STATE_INACTIVE; if (drc->detach_cb) { diff --git a/hw/ppc/spapr_events.c b/hw/ppc/spapr_events.c index b0668b34a..049fb1b32 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->xics, spapr->check_exception_irq)); + qemu_irq_pulse(xics_get_qirq(spapr->icp, spapr->check_exception_irq)); } static void spapr_hotplug_set_signalled(uint32_t drc_index) @@ -449,9 +449,6 @@ static void spapr_hotplug_req_event(uint8_t hp_id, uint8_t hp_action, case SPAPR_DR_CONNECTOR_TYPE_LMB: hp->hotplug_type = RTAS_LOG_V6_HP_TYPE_MEMORY; break; - case SPAPR_DR_CONNECTOR_TYPE_CPU: - hp->hotplug_type = RTAS_LOG_V6_HP_TYPE_CPU; - break; default: /* we shouldn't be signaling hotplug events for resources * that don't support them @@ -468,7 +465,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->xics, spapr->check_exception_irq)); + qemu_irq_pulse(xics_get_qirq(spapr->icp, spapr->check_exception_irq)); } void spapr_hotplug_req_add_by_index(sPAPRDRConnector *drc) @@ -551,7 +548,7 @@ static void check_exception(PowerPCCPU *cpu, sPAPRMachineState *spapr, * interrupts. */ if (rtas_event_log_contains(mask, true)) { - qemu_irq_pulse(xics_get_qirq(spapr->xics, spapr->check_exception_irq)); + qemu_irq_pulse(xics_get_qirq(spapr->icp, spapr->check_exception_irq)); } return; @@ -603,7 +600,7 @@ out_no_events: void spapr_events_init(sPAPRMachineState *spapr) { QTAILQ_INIT(&spapr->pending_events); - spapr->check_exception_irq = xics_spapr_alloc(spapr->xics, 0, 0, false, + spapr->check_exception_irq = xics_alloc(spapr->icp, 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_hcall.c b/hw/ppc/spapr_hcall.c index 73af112e1..8f40602a5 100644 --- a/hw/ppc/spapr_hcall.c +++ b/hw/ppc/spapr_hcall.c @@ -1,15 +1,12 @@ #include "qemu/osdep.h" #include "qapi/error.h" #include "sysemu/sysemu.h" -#include "qemu/log.h" #include "cpu.h" -#include "exec/exec-all.h" #include "helper_regs.h" #include "hw/ppc/spapr.h" #include "mmu-hash64.h" #include "cpu-models.h" #include "trace.h" -#include "sysemu/kvm.h" #include "kvm_ppc.h" struct SPRSyncState { @@ -83,12 +80,12 @@ static target_ulong h_enter(PowerPCCPU *cpu, sPAPRMachineState *spapr, target_ulong pte_index = args[1]; target_ulong pteh = args[2]; target_ulong ptel = args[3]; - unsigned apshift; + unsigned apshift, spshift; target_ulong raddr; target_ulong index; uint64_t token; - apshift = ppc_hash64_hpte_page_shift_noslb(cpu, pteh, ptel); + apshift = ppc_hash64_hpte_page_shift_noslb(cpu, pteh, ptel, &spshift); if (!apshift) { /* Bad page size encoding */ return H_PARAMETER; @@ -102,15 +99,11 @@ static target_ulong h_enter(PowerPCCPU *cpu, sPAPRMachineState *spapr, return H_PARAMETER; } } else { - target_ulong wimg_flags; /* Looks like an IO address */ /* FIXME: What WIMG combinations could be sensible for IO? * For now we allow WIMG=010x, but are there others? */ /* FIXME: Should we check against registered IO addresses? */ - wimg_flags = (ptel & (HPTE64_R_W | HPTE64_R_I | HPTE64_R_M)); - - if (wimg_flags != HPTE64_R_I && - wimg_flags != (HPTE64_R_I | HPTE64_R_M)) { + if ((ptel & (HPTE64_R_W | HPTE64_R_I | HPTE64_R_M)) != HPTE64_R_I) { return H_PARAMETER; } } @@ -190,7 +183,6 @@ static RemoveResult remove_hpte(PowerPCCPU *cpu, target_ulong ptex, static target_ulong h_remove(PowerPCCPU *cpu, sPAPRMachineState *spapr, target_ulong opcode, target_ulong *args) { - CPUPPCState *env = &cpu->env; target_ulong flags = args[0]; target_ulong pte_index = args[1]; target_ulong avpn = args[2]; @@ -201,7 +193,6 @@ static target_ulong h_remove(PowerPCCPU *cpu, sPAPRMachineState *spapr, switch (ret) { case REMOVE_SUCCESS: - check_tlb_flush(env); return H_SUCCESS; case REMOVE_NOT_FOUND: @@ -238,9 +229,7 @@ static target_ulong h_remove(PowerPCCPU *cpu, sPAPRMachineState *spapr, static target_ulong h_bulk_remove(PowerPCCPU *cpu, sPAPRMachineState *spapr, target_ulong opcode, target_ulong *args) { - CPUPPCState *env = &cpu->env; int i; - target_ulong rc = H_SUCCESS; for (i = 0; i < H_BULK_REMOVE_MAX_BATCH; i++) { target_ulong *tsh = &args[i*2]; @@ -273,18 +262,14 @@ static target_ulong h_bulk_remove(PowerPCCPU *cpu, sPAPRMachineState *spapr, break; case REMOVE_PARM: - rc = H_PARAMETER; - goto exit; + return H_PARAMETER; case REMOVE_HW: - rc = H_HARDWARE; - goto exit; + return H_HARDWARE; } } - exit: - check_tlb_flush(env); - return rc; + return H_SUCCESS; } static target_ulong h_protect(PowerPCCPU *cpu, sPAPRMachineState *spapr, @@ -926,41 +911,6 @@ static void do_set_compat(void *arg) ((cpuver) == CPU_POWERPC_LOGICAL_2_06_PLUS) ? 2061 : \ ((cpuver) == CPU_POWERPC_LOGICAL_2_07) ? 2070 : 0) -static void cas_handle_compat_cpu(PowerPCCPUClass *pcc, uint32_t pvr, - unsigned max_lvl, unsigned *compat_lvl, - unsigned *cpu_version) -{ - unsigned lvl = get_compat_level(pvr); - bool is205, is206, is207; - - if (!lvl) { - return; - } - - /* If it is a logical PVR, try to determine the highest level */ - is205 = (pcc->pcr_supported & PCR_COMPAT_2_05) && - (lvl == get_compat_level(CPU_POWERPC_LOGICAL_2_05)); - is206 = (pcc->pcr_supported & PCR_COMPAT_2_06) && - ((lvl == get_compat_level(CPU_POWERPC_LOGICAL_2_06)) || - (lvl == get_compat_level(CPU_POWERPC_LOGICAL_2_06_PLUS))); - is207 = (pcc->pcr_supported & PCR_COMPAT_2_07) && - (lvl == get_compat_level(CPU_POWERPC_LOGICAL_2_07)); - - if (is205 || is206 || is207) { - if (!max_lvl) { - /* User did not set the level, choose the highest */ - if (*compat_lvl <= lvl) { - *compat_lvl = lvl; - *cpu_version = pvr; - } - } else if (max_lvl >= lvl) { - /* User chose the level, don't set higher than this */ - *compat_lvl = lvl; - *cpu_version = pvr; - } - } -} - #define OV5_DRCONF_MEMORY 0x20 static target_ulong h_client_architecture_support(PowerPCCPU *cpu_, @@ -970,7 +920,7 @@ static target_ulong h_client_architecture_support(PowerPCCPU *cpu_, { target_ulong list = ppc64_phys_to_real(args[0]); target_ulong ov_table, ov5; - PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu_); + PowerPCCPUClass *pcc_ = POWERPC_CPU_GET_CLASS(cpu_); CPUState *cs; bool cpu_match = false, cpu_update = true, memory_update = false; unsigned old_cpu_version = cpu_->cpu_version; @@ -997,7 +947,29 @@ static target_ulong h_client_architecture_support(PowerPCCPU *cpu_, cpu_match = true; cpu_version = cpu_->cpu_version; } else if (!cpu_match) { - cas_handle_compat_cpu(pcc, pvr, max_lvl, &compat_lvl, &cpu_version); + /* If it is a logical PVR, try to determine the highest level */ + unsigned lvl = get_compat_level(pvr); + if (lvl) { + bool is205 = (pcc_->pcr_mask & PCR_COMPAT_2_05) && + (lvl == get_compat_level(CPU_POWERPC_LOGICAL_2_05)); + bool is206 = (pcc_->pcr_mask & PCR_COMPAT_2_06) && + ((lvl == get_compat_level(CPU_POWERPC_LOGICAL_2_06)) || + (lvl == get_compat_level(CPU_POWERPC_LOGICAL_2_06_PLUS))); + + if (is205 || is206) { + if (!max_lvl) { + /* User did not set the level, choose the highest */ + if (compat_lvl <= lvl) { + compat_lvl = lvl; + cpu_version = pvr; + } + } else if (max_lvl >= lvl) { + /* User chose the level, don't set higher than this */ + compat_lvl = lvl; + cpu_version = pvr; + } + } + } } /* Terminator record */ if (~pvr_mask & pvr) { @@ -1007,7 +979,7 @@ static target_ulong h_client_architecture_support(PowerPCCPU *cpu_, /* Parsing finished */ trace_spapr_cas_pvr(cpu_->cpu_version, cpu_match, - cpu_version, pcc->pcr_mask); + cpu_version, pcc_->pcr_mask); /* Update CPUs */ if (old_cpu_version != cpu_version) { diff --git a/hw/ppc/spapr_iommu.c b/hw/ppc/spapr_iommu.c index 6bc4d4db3..7dd458846 100644 --- a/hw/ppc/spapr_iommu.c +++ b/hw/ppc/spapr_iommu.c @@ -17,9 +17,7 @@ * License along with this library; if not, see <http://www.gnu.org/licenses/>. */ #include "qemu/osdep.h" -#include "qemu/error-report.h" #include "hw/hw.h" -#include "qemu/log.h" #include "sysemu/kvm.h" #include "hw/qdev.h" #include "kvm_ppc.h" @@ -77,37 +75,6 @@ static IOMMUAccessFlags spapr_tce_iommu_access_flags(uint64_t tce) } } -static uint64_t *spapr_tce_alloc_table(uint32_t liobn, - uint32_t page_shift, - uint32_t nb_table, - int *fd, - bool need_vfio) -{ - uint64_t *table = NULL; - uint64_t window_size = (uint64_t)nb_table << page_shift; - - if (kvm_enabled() && !(window_size >> 32)) { - table = kvmppc_create_spapr_tce(liobn, window_size, fd, need_vfio); - } - - if (!table) { - *fd = -1; - table = g_malloc0(nb_table * sizeof(uint64_t)); - } - - trace_spapr_iommu_new_table(liobn, table, *fd); - - return table; -} - -static void spapr_tce_free_table(uint64_t *table, int fd, uint32_t nb_table) -{ - if (!kvm_enabled() || - (kvmppc_remove_spapr_tce(table, fd, nb_table) != 0)) { - g_free(table); - } -} - /* Called from RCU critical section */ static IOMMUTLBEntry spapr_tce_translate_iommu(MemoryRegion *iommu, hwaddr addr, bool is_write) @@ -138,131 +105,61 @@ static IOMMUTLBEntry spapr_tce_translate_iommu(MemoryRegion *iommu, hwaddr addr, return ret; } -static void spapr_tce_table_pre_save(void *opaque) -{ - sPAPRTCETable *tcet = SPAPR_TCE_TABLE(opaque); - - tcet->mig_table = tcet->table; - tcet->mig_nb_table = tcet->nb_table; - - trace_spapr_iommu_pre_save(tcet->liobn, tcet->mig_nb_table, - tcet->bus_offset, tcet->page_shift); -} - -static uint64_t spapr_tce_get_min_page_size(MemoryRegion *iommu) -{ - sPAPRTCETable *tcet = container_of(iommu, sPAPRTCETable, iommu); - - return 1ULL << tcet->page_shift; -} - -static void spapr_tce_notify_started(MemoryRegion *iommu) -{ - spapr_tce_set_need_vfio(container_of(iommu, sPAPRTCETable, iommu), true); -} - -static void spapr_tce_notify_stopped(MemoryRegion *iommu) -{ - spapr_tce_set_need_vfio(container_of(iommu, sPAPRTCETable, iommu), false); -} - static int spapr_tce_table_post_load(void *opaque, int version_id) { sPAPRTCETable *tcet = SPAPR_TCE_TABLE(opaque); - uint32_t old_nb_table = tcet->nb_table; - uint64_t old_bus_offset = tcet->bus_offset; - uint32_t old_page_shift = tcet->page_shift; if (tcet->vdev) { spapr_vio_set_bypass(tcet->vdev, tcet->bypass); } - if (tcet->mig_nb_table != tcet->nb_table) { - spapr_tce_table_disable(tcet); - } - - if (tcet->mig_nb_table) { - if (!tcet->nb_table) { - spapr_tce_table_enable(tcet, old_page_shift, old_bus_offset, - tcet->mig_nb_table); - } - - memcpy(tcet->table, tcet->mig_table, - tcet->nb_table * sizeof(tcet->table[0])); - - free(tcet->mig_table); - tcet->mig_table = NULL; - } - - trace_spapr_iommu_post_load(tcet->liobn, old_nb_table, tcet->nb_table, - tcet->bus_offset, tcet->page_shift); - return 0; } -static bool spapr_tce_table_ex_needed(void *opaque) -{ - sPAPRTCETable *tcet = opaque; - - return tcet->bus_offset || tcet->page_shift != 0xC; -} - -static const VMStateDescription vmstate_spapr_tce_table_ex = { - .name = "spapr_iommu_ex", - .version_id = 1, - .minimum_version_id = 1, - .needed = spapr_tce_table_ex_needed, - .fields = (VMStateField[]) { - VMSTATE_UINT64(bus_offset, sPAPRTCETable), - VMSTATE_UINT32(page_shift, sPAPRTCETable), - VMSTATE_END_OF_LIST() - }, -}; - static const VMStateDescription vmstate_spapr_tce_table = { .name = "spapr_iommu", .version_id = 2, .minimum_version_id = 2, - .pre_save = spapr_tce_table_pre_save, .post_load = spapr_tce_table_post_load, .fields = (VMStateField []) { /* Sanity check */ VMSTATE_UINT32_EQUAL(liobn, sPAPRTCETable), + VMSTATE_UINT32_EQUAL(nb_table, sPAPRTCETable), /* IOMMU state */ - VMSTATE_UINT32(mig_nb_table, sPAPRTCETable), VMSTATE_BOOL(bypass, sPAPRTCETable), - VMSTATE_VARRAY_UINT32_ALLOC(mig_table, sPAPRTCETable, mig_nb_table, 0, - vmstate_info_uint64, uint64_t), + VMSTATE_VARRAY_UINT32(table, sPAPRTCETable, nb_table, 0, vmstate_info_uint64, uint64_t), VMSTATE_END_OF_LIST() }, - .subsections = (const VMStateDescription*[]) { - &vmstate_spapr_tce_table_ex, - NULL - } }; static MemoryRegionIOMMUOps spapr_iommu_ops = { .translate = spapr_tce_translate_iommu, - .get_min_page_size = spapr_tce_get_min_page_size, - .notify_started = spapr_tce_notify_started, - .notify_stopped = spapr_tce_notify_stopped, }; static int spapr_tce_table_realize(DeviceState *dev) { sPAPRTCETable *tcet = SPAPR_TCE_TABLE(dev); - Object *tcetobj = OBJECT(tcet); - char tmp[32]; + uint64_t window_size = (uint64_t)tcet->nb_table << tcet->page_shift; - tcet->fd = -1; - tcet->need_vfio = false; - snprintf(tmp, sizeof(tmp), "tce-root-%x", tcet->liobn); - memory_region_init(&tcet->root, tcetobj, tmp, UINT64_MAX); + if (kvm_enabled() && !(window_size >> 32)) { + tcet->table = kvmppc_create_spapr_tce(tcet->liobn, + window_size, + &tcet->fd, + tcet->need_vfio); + } + + if (!tcet->table) { + size_t table_size = tcet->nb_table * sizeof(uint64_t); + tcet->table = g_malloc0(table_size); + } - snprintf(tmp, sizeof(tmp), "tce-iommu-%x", tcet->liobn); - memory_region_init_iommu(&tcet->iommu, tcetobj, &spapr_iommu_ops, tmp, 0); + trace_spapr_iommu_new_table(tcet->liobn, tcet, tcet->table, tcet->fd); + + memory_region_init_iommu(&tcet->iommu, OBJECT(dev), &spapr_iommu_ops, + "iommu-spapr", + (uint64_t)tcet->nb_table << tcet->page_shift); QLIST_INSERT_HEAD(&spapr_tce_tables, tcet, list); @@ -304,10 +201,14 @@ void spapr_tce_set_need_vfio(sPAPRTCETable *tcet, bool need_vfio) tcet->table = newtable; } -sPAPRTCETable *spapr_tce_new_table(DeviceState *owner, uint32_t liobn) +sPAPRTCETable *spapr_tce_new_table(DeviceState *owner, uint32_t liobn, + uint64_t bus_offset, + uint32_t page_shift, + uint32_t nb_table, + bool need_vfio) { sPAPRTCETable *tcet; - char tmp[32]; + char tmp[64]; if (spapr_tce_find_by_liobn(liobn)) { fprintf(stderr, "Attempted to create TCE table with duplicate" @@ -315,8 +216,16 @@ sPAPRTCETable *spapr_tce_new_table(DeviceState *owner, uint32_t liobn) return NULL; } + if (!nb_table) { + return NULL; + } + tcet = SPAPR_TCE_TABLE(object_new(TYPE_SPAPR_TCE_TABLE)); tcet->liobn = liobn; + tcet->bus_offset = bus_offset; + tcet->page_shift = page_shift; + tcet->nb_table = nb_table; + tcet->need_vfio = need_vfio; snprintf(tmp, sizeof(tmp), "tce-table-%x", liobn); object_property_add_child(OBJECT(owner), tmp, OBJECT(tcet), NULL); @@ -326,58 +235,22 @@ sPAPRTCETable *spapr_tce_new_table(DeviceState *owner, uint32_t liobn) return tcet; } -void spapr_tce_table_enable(sPAPRTCETable *tcet, - uint32_t page_shift, uint64_t bus_offset, - uint32_t nb_table) -{ - if (tcet->nb_table) { - error_report("Warning: trying to enable already enabled TCE table"); - return; - } - - tcet->bus_offset = bus_offset; - tcet->page_shift = page_shift; - tcet->nb_table = nb_table; - tcet->table = spapr_tce_alloc_table(tcet->liobn, - tcet->page_shift, - tcet->nb_table, - &tcet->fd, - tcet->need_vfio); - - memory_region_set_size(&tcet->iommu, - (uint64_t)tcet->nb_table << tcet->page_shift); - memory_region_add_subregion(&tcet->root, tcet->bus_offset, &tcet->iommu); -} - -void spapr_tce_table_disable(sPAPRTCETable *tcet) -{ - if (!tcet->nb_table) { - return; - } - - memory_region_del_subregion(&tcet->root, &tcet->iommu); - memory_region_set_size(&tcet->iommu, 0); - - spapr_tce_free_table(tcet->table, tcet->fd, tcet->nb_table); - tcet->fd = -1; - tcet->table = NULL; - tcet->bus_offset = 0; - tcet->page_shift = 0; - tcet->nb_table = 0; -} - static void spapr_tce_table_unrealize(DeviceState *dev, Error **errp) { sPAPRTCETable *tcet = SPAPR_TCE_TABLE(dev); QLIST_REMOVE(tcet, list); - spapr_tce_table_disable(tcet); + if (!kvm_enabled() || + (kvmppc_remove_spapr_tce(tcet->table, tcet->fd, + tcet->nb_table) != 0)) { + g_free(tcet->table); + } } MemoryRegion *spapr_tce_get_iommu(sPAPRTCETable *tcet) { - return &tcet->root; + return &tcet->iommu; } static void spapr_tce_reset(DeviceState *dev) @@ -385,9 +258,7 @@ static void spapr_tce_reset(DeviceState *dev) sPAPRTCETable *tcet = SPAPR_TCE_TABLE(dev); size_t table_size = tcet->nb_table * sizeof(uint64_t); - if (tcet->nb_table) { - memset(tcet->table, 0, table_size); - } + memset(tcet->table, 0, table_size); } static target_ulong put_tce_emu(sPAPRTCETable *tcet, target_ulong ioba, @@ -406,7 +277,7 @@ static target_ulong put_tce_emu(sPAPRTCETable *tcet, target_ulong ioba, tcet->table[index] = tce; entry.target_as = &address_space_memory, - entry.iova = (ioba - tcet->bus_offset) & page_mask; + entry.iova = ioba & page_mask; entry.translated_addr = tce & page_mask; entry.addr_mask = ~page_mask; entry.perm = spapr_tce_iommu_access_flags(tce); diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c index 949c44fec..573e635bf 100644 --- a/hw/ppc/spapr_pci.c +++ b/hw/ppc/spapr_pci.c @@ -35,7 +35,6 @@ #include "hw/ppc/spapr.h" #include "hw/pci-host/spapr.h" #include "exec/address-spaces.h" -#include "exec/ram_addr.h" #include <libfdt.h> #include "trace.h" #include "qemu/error-report.h" @@ -45,8 +44,6 @@ #include "hw/pci/pci_bus.h" #include "hw/ppc/spapr_drc.h" #include "sysemu/device_tree.h" -#include "sysemu/kvm.h" -#include "sysemu/hostmem.h" #include "hw/vfio/vfio.h" @@ -324,7 +321,7 @@ static void rtas_ibm_change_msi(PowerPCCPU *cpu, sPAPRMachineState *spapr, return; } - xics_spapr_free(spapr->xics, msi->first_irq, msi->num); + xics_free(spapr->icp, msi->first_irq, msi->num); if (msi_present(pdev)) { spapr_msi_setmsg(pdev, 0, false, 0, 0); } @@ -362,7 +359,7 @@ static void rtas_ibm_change_msi(PowerPCCPU *cpu, sPAPRMachineState *spapr, } /* Allocate MSIs */ - irq = xics_spapr_alloc_block(spapr->xics, 0, req_num, false, + irq = xics_alloc_block(spapr->icp, 0, req_num, false, ret_intr_type == RTAS_TYPE_MSI, &err); if (err) { error_reportf_err(err, "Can't allocate MSIs for device %x: ", @@ -373,7 +370,7 @@ static void rtas_ibm_change_msi(PowerPCCPU *cpu, sPAPRMachineState *spapr, /* Release previous MSIs */ if (msi) { - xics_spapr_free(spapr->xics, msi->first_irq, msi->num); + xics_free(spapr->icp, msi->first_irq, msi->num); g_hash_table_remove(phb->msi, &config_addr); } @@ -735,7 +732,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->xics, irq)); + qemu_irq_pulse(xics_get_qirq(spapr->icp, irq)); } static const MemoryRegionOps spapr_msi_ops = { @@ -1089,11 +1086,19 @@ static void spapr_phb_add_pci_device(sPAPRDRConnector *drc, void *fdt = NULL; int fdt_start_offset = 0, fdt_size; - fdt = create_device_tree(&fdt_size); - fdt_start_offset = spapr_create_pci_child_dt(phb, pdev, fdt, 0); - if (!fdt_start_offset) { - error_setg(errp, "Failed to create pci child device tree node"); - goto out; + if (object_dynamic_cast(OBJECT(pdev), "vfio-pci")) { + sPAPRTCETable *tcet = spapr_tce_find_by_liobn(phb->dma_liobn); + + spapr_tce_set_need_vfio(tcet, true); + } + + if (dev->hotplugged) { + fdt = create_device_tree(&fdt_size); + fdt_start_offset = spapr_create_pci_child_dt(phb, pdev, fdt, 0); + if (!fdt_start_offset) { + error_setg(errp, "Failed to create pci child device tree node"); + goto out; + } } drck->attach(drc, DEVICE(pdev), @@ -1306,14 +1311,12 @@ static void spapr_phb_realize(DeviceState *dev, Error **errp) PCIBus *bus; uint64_t msi_window_size = 4096; sPAPRTCETable *tcet; - const unsigned windows_supported = - sphb->ddw_enabled ? SPAPR_PCI_DMA_MAX_WINDOWS : 1; + uint32_t nb_table; if (sphb->index != (uint32_t)-1) { hwaddr windows_base; - if ((sphb->buid != (uint64_t)-1) || (sphb->dma_liobn[0] != (uint32_t)-1) - || (sphb->dma_liobn[1] != (uint32_t)-1 && windows_supported == 2) + if ((sphb->buid != (uint64_t)-1) || (sphb->dma_liobn != (uint32_t)-1) || (sphb->mem_win_addr != (hwaddr)-1) || (sphb->io_win_addr != (hwaddr)-1)) { error_setg(errp, "Either \"index\" or other parameters must" @@ -1328,9 +1331,7 @@ static void spapr_phb_realize(DeviceState *dev, Error **errp) } sphb->buid = SPAPR_PCI_BASE_BUID + sphb->index; - for (i = 0; i < windows_supported; ++i) { - sphb->dma_liobn[i] = SPAPR_PCI_LIOBN(sphb->index, i); - } + sphb->dma_liobn = SPAPR_PCI_LIOBN(sphb->index, 0); windows_base = SPAPR_PCI_WINDOW_BASE + sphb->index * SPAPR_PCI_WINDOW_SPACING; @@ -1343,9 +1344,8 @@ static void spapr_phb_realize(DeviceState *dev, Error **errp) return; } - if ((sphb->dma_liobn[0] == (uint32_t)-1) || - ((sphb->dma_liobn[1] == (uint32_t)-1) && (windows_supported > 1))) { - error_setg(errp, "LIOBN(s) not specified for PHB"); + if (sphb->dma_liobn == (uint32_t)-1) { + error_setg(errp, "LIOBN not specified for PHB"); return; } @@ -1444,8 +1444,7 @@ static void spapr_phb_realize(DeviceState *dev, Error **errp) uint32_t irq; Error *local_err = NULL; - irq = xics_spapr_alloc_block(spapr->xics, 0, 1, true, false, - &local_err); + irq = xics_alloc_block(spapr->icp, 0, 1, true, false, &local_err); if (local_err) { error_propagate(errp, local_err); error_prepend(errp, "can't allocate LSIs: "); @@ -1464,18 +1463,19 @@ static void spapr_phb_realize(DeviceState *dev, Error **errp) } } - /* DMA setup */ - for (i = 0; i < windows_supported; ++i) { - tcet = spapr_tce_new_table(DEVICE(sphb), sphb->dma_liobn[i]); - if (!tcet) { - error_setg(errp, "Creating window#%d failed for %s", - i, sphb->dtbusname); - return; - } - memory_region_add_subregion_overlap(&sphb->iommu_root, 0, - spapr_tce_get_iommu(tcet), 0); + nb_table = sphb->dma_win_size >> SPAPR_TCE_PAGE_SHIFT; + tcet = spapr_tce_new_table(DEVICE(sphb), sphb->dma_liobn, + 0, SPAPR_TCE_PAGE_SHIFT, nb_table, false); + if (!tcet) { + error_setg(errp, "Unable to create TCE table for %s", + sphb->dtbusname); + return; } + /* Register default 32bit DMA window */ + memory_region_add_subregion(&sphb->iommu_root, sphb->dma_win_addr, + spapr_tce_get_iommu(tcet)); + sphb->msi = g_hash_table_new_full(g_int_hash, g_int_equal, g_free, g_free); } @@ -1490,31 +1490,8 @@ static int spapr_phb_children_reset(Object *child, void *opaque) return 0; } -void spapr_phb_dma_reset(sPAPRPHBState *sphb) -{ - int i; - sPAPRTCETable *tcet; - - for (i = 0; i < SPAPR_PCI_DMA_MAX_WINDOWS; ++i) { - tcet = spapr_tce_find_by_liobn(sphb->dma_liobn[i]); - - if (tcet && tcet->nb_table) { - spapr_tce_table_disable(tcet); - } - } - - /* Register default 32bit DMA window */ - tcet = spapr_tce_find_by_liobn(sphb->dma_liobn[0]); - spapr_tce_table_enable(tcet, SPAPR_TCE_PAGE_SHIFT, sphb->dma_win_addr, - sphb->dma_win_size >> SPAPR_TCE_PAGE_SHIFT); -} - static void spapr_phb_reset(DeviceState *qdev) { - sPAPRPHBState *sphb = SPAPR_PCI_HOST_BRIDGE(qdev); - - spapr_phb_dma_reset(sphb); - /* Reset the IOMMU state */ object_child_foreach(OBJECT(qdev), spapr_phb_children_reset, NULL); @@ -1526,8 +1503,7 @@ static void spapr_phb_reset(DeviceState *qdev) static Property spapr_phb_properties[] = { DEFINE_PROP_UINT32("index", sPAPRPHBState, index, -1), DEFINE_PROP_UINT64("buid", sPAPRPHBState, buid, -1), - DEFINE_PROP_UINT32("liobn", sPAPRPHBState, dma_liobn[0], -1), - DEFINE_PROP_UINT32("liobn64", sPAPRPHBState, dma_liobn[1], -1), + DEFINE_PROP_UINT32("liobn", sPAPRPHBState, dma_liobn, -1), DEFINE_PROP_UINT64("mem_win_addr", sPAPRPHBState, mem_win_addr, -1), DEFINE_PROP_UINT64("mem_win_size", sPAPRPHBState, mem_win_size, SPAPR_PCI_MMIO_WIN_SIZE), @@ -1539,11 +1515,6 @@ static Property spapr_phb_properties[] = { /* Default DMA window is 0..1GB */ DEFINE_PROP_UINT64("dma_win_addr", sPAPRPHBState, dma_win_addr, 0), DEFINE_PROP_UINT64("dma_win_size", sPAPRPHBState, dma_win_size, 0x40000000), - DEFINE_PROP_UINT64("dma64_win_addr", sPAPRPHBState, dma64_win_addr, - 0x800000000000000ULL), - DEFINE_PROP_BOOL("ddw", sPAPRPHBState, ddw_enabled, true), - DEFINE_PROP_UINT64("pgsz", sPAPRPHBState, page_size_mask, - (1ULL << 12) | (1ULL << 16)), DEFINE_PROP_END_OF_LIST(), }; @@ -1620,7 +1591,7 @@ static const VMStateDescription vmstate_spapr_pci = { .post_load = spapr_pci_post_load, .fields = (VMStateField[]) { VMSTATE_UINT64_EQUAL(buid, sPAPRPHBState), - VMSTATE_UINT32_EQUAL(dma_liobn[0], sPAPRPHBState), + VMSTATE_UINT32_EQUAL(dma_liobn, sPAPRPHBState), VMSTATE_UINT64_EQUAL(mem_win_addr, sPAPRPHBState), VMSTATE_UINT64_EQUAL(mem_win_size, sPAPRPHBState), VMSTATE_UINT64_EQUAL(io_win_addr, sPAPRPHBState), @@ -1654,6 +1625,7 @@ static void spapr_phb_class_init(ObjectClass *klass, void *data) dc->reset = spapr_phb_reset; dc->vmsd = &vmstate_spapr_pci; set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories); + dc->cannot_instantiate_with_device_add_yet = false; hp->plug = spapr_phb_hot_plug_child; hp->unplug = spapr_phb_hot_unplug_child; } @@ -1796,15 +1768,6 @@ int spapr_populate_pci_dt(sPAPRPHBState *phb, uint32_t interrupt_map_mask[] = { cpu_to_be32(b_ddddd(-1)|b_fff(0)), 0x0, 0x0, cpu_to_be32(-1)}; uint32_t interrupt_map[PCI_SLOT_MAX * PCI_NUM_PINS][7]; - uint32_t ddw_applicable[] = { - cpu_to_be32(RTAS_IBM_QUERY_PE_DMA_WINDOW), - cpu_to_be32(RTAS_IBM_CREATE_PE_DMA_WINDOW), - cpu_to_be32(RTAS_IBM_REMOVE_PE_DMA_WINDOW) - }; - uint32_t ddw_extensions[] = { - cpu_to_be32(1), - cpu_to_be32(RTAS_IBM_RESET_PE_DMA_WINDOW) - }; sPAPRTCETable *tcet; PCIBus *bus = PCI_HOST_BRIDGE(phb)->bus; sPAPRFDT s_fdt; @@ -1827,15 +1790,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_SPAPR)); - - /* Dynamic DMA window */ - if (phb->ddw_enabled) { - _FDT(fdt_setprop(fdt, bus_off, "ibm,ddw-applicable", &ddw_applicable, - sizeof(ddw_applicable))); - _FDT(fdt_setprop(fdt, bus_off, "ibm,ddw-extensions", - &ddw_extensions, sizeof(ddw_extensions))); - } + _FDT(fdt_setprop_cell(fdt, bus_off, "ibm,pe-total-#msi", XICS_IRQS)); /* Build the interrupt-map, this must matches what is done * in pci_spapr_map_irq @@ -1860,7 +1815,7 @@ int spapr_populate_pci_dt(sPAPRPHBState *phb, _FDT(fdt_setprop(fdt, bus_off, "interrupt-map", &interrupt_map, sizeof(interrupt_map))); - tcet = spapr_tce_find_by_liobn(phb->dma_liobn[0]); + tcet = spapr_tce_find_by_liobn(SPAPR_PCI_LIOBN(phb->index, 0)); if (!tcet) { return -1; } diff --git a/hw/ppc/spapr_pci_vfio.c b/hw/ppc/spapr_pci_vfio.c index 8448e0b02..cbd3d23c9 100644 --- a/hw/ppc/spapr_pci_vfio.c +++ b/hw/ppc/spapr_pci_vfio.c @@ -18,16 +18,15 @@ */ #include "qemu/osdep.h" -#include <linux/vfio.h> #include "qapi/error.h" #include "qemu-common.h" #include "cpu.h" #include "hw/ppc/spapr.h" #include "hw/pci-host/spapr.h" #include "hw/pci/msix.h" +#include "linux/vfio.h" #include "hw/vfio/vfio.h" #include "qemu/error-report.h" -#include "sysemu/qtest.h" #define TYPE_SPAPR_PCI_VFIO_HOST_BRIDGE "spapr-pci-vfio-host-bridge" @@ -49,9 +48,7 @@ static Property spapr_phb_vfio_properties[] = { static void spapr_phb_vfio_instance_init(Object *obj) { - if (!qtest_enabled()) { - error_report("spapr-pci-vfio-host-bridge is deprecated"); - } + error_report("spapr-pci-vfio-host-bridge is deprecated"); } bool spapr_phb_eeh_available(sPAPRPHBState *sphb) diff --git a/hw/ppc/spapr_rtas.c b/hw/ppc/spapr_rtas.c index dc058e512..f07325831 100644 --- a/hw/ppc/spapr_rtas.c +++ b/hw/ppc/spapr_rtas.c @@ -26,17 +26,14 @@ */ #include "qemu/osdep.h" #include "cpu.h" -#include "qemu/log.h" #include "sysemu/sysemu.h" #include "sysemu/char.h" #include "hw/qdev.h" #include "sysemu/device_tree.h" #include "sysemu/cpus.h" -#include "sysemu/kvm.h" #include "hw/ppc/spapr.h" #include "hw/ppc/spapr_vio.h" -#include "hw/ppc/ppc.h" #include "qapi-event.h" #include "hw/boards.h" @@ -165,27 +162,6 @@ static void rtas_query_cpu_stopped_state(PowerPCCPU *cpu_, rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR); } -/* - * Set the timebase offset of the CPU to that of first CPU. - * This helps hotplugged CPU to have the correct timebase offset. - */ -static void spapr_cpu_update_tb_offset(PowerPCCPU *cpu) -{ - PowerPCCPU *fcpu = POWERPC_CPU(first_cpu); - - cpu->env.tb_env->tb_offset = fcpu->env.tb_env->tb_offset; -} - -static void spapr_cpu_set_endianness(PowerPCCPU *cpu) -{ - PowerPCCPU *fcpu = POWERPC_CPU(first_cpu); - PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(fcpu); - - if (!pcc->interrupts_big_endian(fcpu)) { - cpu->env.spr[SPR_LPCR] |= LPCR_ILE; - } -} - static void rtas_start_cpu(PowerPCCPU *cpu_, sPAPRMachineState *spapr, uint32_t token, uint32_t nargs, target_ulong args, @@ -222,8 +198,6 @@ static void rtas_start_cpu(PowerPCCPU *cpu_, sPAPRMachineState *spapr, env->nip = start; env->gpr[3] = r3; cs->halted = 0; - spapr_cpu_set_endianness(cpu); - spapr_cpu_update_tb_offset(cpu); qemu_cpu_kick(cs); diff --git a/hw/ppc/spapr_rtas_ddw.c b/hw/ppc/spapr_rtas_ddw.c deleted file mode 100644 index 177dcffc9..000000000 --- a/hw/ppc/spapr_rtas_ddw.c +++ /dev/null @@ -1,295 +0,0 @@ -/* - * QEMU sPAPR Dynamic DMA windows support - * - * Copyright (c) 2015 Alexey Kardashevskiy, IBM Corporation. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, - * or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, see <http://www.gnu.org/licenses/>. - */ - -#include "qemu/osdep.h" -#include "cpu.h" -#include "qemu/error-report.h" -#include "hw/ppc/spapr.h" -#include "hw/pci-host/spapr.h" -#include "trace.h" - -static int spapr_phb_get_active_win_num_cb(Object *child, void *opaque) -{ - sPAPRTCETable *tcet; - - tcet = (sPAPRTCETable *) object_dynamic_cast(child, TYPE_SPAPR_TCE_TABLE); - if (tcet && tcet->nb_table) { - ++*(unsigned *)opaque; - } - return 0; -} - -static unsigned spapr_phb_get_active_win_num(sPAPRPHBState *sphb) -{ - unsigned ret = 0; - - object_child_foreach(OBJECT(sphb), spapr_phb_get_active_win_num_cb, &ret); - - return ret; -} - -static int spapr_phb_get_free_liobn_cb(Object *child, void *opaque) -{ - sPAPRTCETable *tcet; - - tcet = (sPAPRTCETable *) object_dynamic_cast(child, TYPE_SPAPR_TCE_TABLE); - if (tcet && !tcet->nb_table) { - *(uint32_t *)opaque = tcet->liobn; - return 1; - } - return 0; -} - -static unsigned spapr_phb_get_free_liobn(sPAPRPHBState *sphb) -{ - uint32_t liobn = 0; - - object_child_foreach(OBJECT(sphb), spapr_phb_get_free_liobn_cb, &liobn); - - return liobn; -} - -static uint32_t spapr_page_mask_to_query_mask(uint64_t page_mask) -{ - int i; - uint32_t mask = 0; - const struct { int shift; uint32_t mask; } masks[] = { - { 12, RTAS_DDW_PGSIZE_4K }, - { 16, RTAS_DDW_PGSIZE_64K }, - { 24, RTAS_DDW_PGSIZE_16M }, - { 25, RTAS_DDW_PGSIZE_32M }, - { 26, RTAS_DDW_PGSIZE_64M }, - { 27, RTAS_DDW_PGSIZE_128M }, - { 28, RTAS_DDW_PGSIZE_256M }, - { 34, RTAS_DDW_PGSIZE_16G }, - }; - - for (i = 0; i < ARRAY_SIZE(masks); ++i) { - if (page_mask & (1ULL << masks[i].shift)) { - mask |= masks[i].mask; - } - } - - return mask; -} - -static void rtas_ibm_query_pe_dma_window(PowerPCCPU *cpu, - sPAPRMachineState *spapr, - uint32_t token, uint32_t nargs, - target_ulong args, - uint32_t nret, target_ulong rets) -{ - sPAPRPHBState *sphb; - uint64_t buid, max_window_size; - uint32_t avail, addr, pgmask = 0; - MachineState *machine = MACHINE(spapr); - - if ((nargs != 3) || (nret != 5)) { - goto param_error_exit; - } - - buid = ((uint64_t)rtas_ld(args, 1) << 32) | rtas_ld(args, 2); - addr = rtas_ld(args, 0); - sphb = spapr_pci_find_phb(spapr, buid); - if (!sphb || !sphb->ddw_enabled) { - goto param_error_exit; - } - - /* 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 { - MemoryHotplugState *hpms = &spapr->hotplug_memory; - - max_window_size = hpms->base + memory_region_size(&hpms->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, 3, pgmask); - rtas_st(rets, 4, 0); /* DMA migration mask, not supported */ - - trace_spapr_iommu_ddw_query(buid, addr, avail, max_window_size, pgmask); - return; - -param_error_exit: - rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR); -} - -static void rtas_ibm_create_pe_dma_window(PowerPCCPU *cpu, - sPAPRMachineState *spapr, - uint32_t token, uint32_t nargs, - target_ulong args, - uint32_t nret, target_ulong rets) -{ - sPAPRPHBState *sphb; - sPAPRTCETable *tcet = NULL; - uint32_t addr, page_shift, window_shift, liobn; - uint64_t buid, win_addr; - int windows; - - if ((nargs != 5) || (nret != 4)) { - goto param_error_exit; - } - - buid = ((uint64_t)rtas_ld(args, 1) << 32) | rtas_ld(args, 2); - addr = rtas_ld(args, 0); - sphb = spapr_pci_find_phb(spapr, buid); - if (!sphb || !sphb->ddw_enabled) { - goto param_error_exit; - } - - page_shift = rtas_ld(args, 3); - window_shift = rtas_ld(args, 4); - liobn = spapr_phb_get_free_liobn(sphb); - windows = spapr_phb_get_active_win_num(sphb); - - if (!(sphb->page_size_mask & (1ULL << page_shift)) || - (window_shift < page_shift)) { - goto param_error_exit; - } - - if (!liobn || !sphb->ddw_enabled || windows == SPAPR_PCI_DMA_MAX_WINDOWS) { - goto hw_error_exit; - } - - tcet = spapr_tce_find_by_liobn(liobn); - if (!tcet) { - goto hw_error_exit; - } - - win_addr = (windows == 0) ? sphb->dma_win_addr : sphb->dma64_win_addr; - spapr_tce_table_enable(tcet, page_shift, win_addr, - 1ULL << (window_shift - page_shift)); - if (!tcet->nb_table) { - goto hw_error_exit; - } - - trace_spapr_iommu_ddw_create(buid, addr, 1ULL << page_shift, - 1ULL << window_shift, tcet->bus_offset, liobn); - - rtas_st(rets, 0, RTAS_OUT_SUCCESS); - rtas_st(rets, 1, liobn); - rtas_st(rets, 2, tcet->bus_offset >> 32); - rtas_st(rets, 3, tcet->bus_offset & ((uint32_t) -1)); - - return; - -hw_error_exit: - rtas_st(rets, 0, RTAS_OUT_HW_ERROR); - return; - -param_error_exit: - rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR); -} - -static void rtas_ibm_remove_pe_dma_window(PowerPCCPU *cpu, - sPAPRMachineState *spapr, - uint32_t token, uint32_t nargs, - target_ulong args, - uint32_t nret, target_ulong rets) -{ - sPAPRPHBState *sphb; - sPAPRTCETable *tcet; - uint32_t liobn; - - if ((nargs != 1) || (nret != 1)) { - goto param_error_exit; - } - - liobn = rtas_ld(args, 0); - tcet = spapr_tce_find_by_liobn(liobn); - if (!tcet) { - goto param_error_exit; - } - - sphb = SPAPR_PCI_HOST_BRIDGE(OBJECT(tcet)->parent); - if (!sphb || !sphb->ddw_enabled || !tcet->nb_table) { - goto param_error_exit; - } - - spapr_tce_table_disable(tcet); - trace_spapr_iommu_ddw_remove(liobn); - - rtas_st(rets, 0, RTAS_OUT_SUCCESS); - return; - -param_error_exit: - rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR); -} - -static void rtas_ibm_reset_pe_dma_window(PowerPCCPU *cpu, - sPAPRMachineState *spapr, - uint32_t token, uint32_t nargs, - target_ulong args, - uint32_t nret, target_ulong rets) -{ - sPAPRPHBState *sphb; - uint64_t buid; - uint32_t addr; - - if ((nargs != 3) || (nret != 1)) { - goto param_error_exit; - } - - buid = ((uint64_t)rtas_ld(args, 1) << 32) | rtas_ld(args, 2); - addr = rtas_ld(args, 0); - sphb = spapr_pci_find_phb(spapr, buid); - if (!sphb || !sphb->ddw_enabled) { - goto param_error_exit; - } - - spapr_phb_dma_reset(sphb); - trace_spapr_iommu_ddw_reset(buid, addr); - - rtas_st(rets, 0, RTAS_OUT_SUCCESS); - - return; - -param_error_exit: - rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR); -} - -static void spapr_rtas_ddw_init(void) -{ - spapr_rtas_register(RTAS_IBM_QUERY_PE_DMA_WINDOW, - "ibm,query-pe-dma-window", - rtas_ibm_query_pe_dma_window); - spapr_rtas_register(RTAS_IBM_CREATE_PE_DMA_WINDOW, - "ibm,create-pe-dma-window", - rtas_ibm_create_pe_dma_window); - spapr_rtas_register(RTAS_IBM_REMOVE_PE_DMA_WINDOW, - "ibm,remove-pe-dma-window", - rtas_ibm_remove_pe_dma_window); - spapr_rtas_register(RTAS_IBM_RESET_PE_DMA_WINDOW, - "ibm,reset-pe-dma-window", - rtas_ibm_reset_pe_dma_window); -} - -type_init(spapr_rtas_ddw_init) diff --git a/hw/ppc/spapr_vio.c b/hw/ppc/spapr_vio.c index f93244d7c..8aa021fde 100644 --- a/hw/ppc/spapr_vio.c +++ b/hw/ppc/spapr_vio.c @@ -22,7 +22,6 @@ #include "qemu/osdep.h" #include "qapi/error.h" #include "hw/hw.h" -#include "qemu/log.h" #include "sysemu/sysemu.h" #include "hw/boards.h" #include "hw/loader.h" @@ -57,9 +56,12 @@ static char *spapr_vio_get_dev_name(DeviceState *qdev) { VIOsPAPRDevice *dev = VIO_SPAPR_DEVICE(qdev); VIOsPAPRDeviceClass *pc = VIO_SPAPR_DEVICE_GET_CLASS(dev); + char *name; /* Device tree style name device@reg */ - return g_strdup_printf("%s@%x", pc->dt_name, dev->reg); + name = g_strdup_printf("%s@%x", pc->dt_name, dev->reg); + + return name; } static void spapr_vio_bus_class_init(ObjectClass *klass, void *data) @@ -463,7 +465,7 @@ static void spapr_vio_busdev_realize(DeviceState *qdev, Error **errp) dev->qdev.id = id; } - dev->irq = xics_spapr_alloc(spapr->xics, 0, dev->irq, false, &local_err); + dev->irq = xics_alloc(spapr->icp, 0, dev->irq, false, &local_err); if (local_err) { error_propagate(errp, local_err); return; @@ -480,9 +482,11 @@ static void spapr_vio_busdev_realize(DeviceState *qdev, Error **errp) memory_region_add_subregion_overlap(&dev->mrroot, 0, &dev->mrbypass, 1); address_space_init(&dev->as, &dev->mrroot, qdev->id); - dev->tcet = spapr_tce_new_table(qdev, liobn); - spapr_tce_table_enable(dev->tcet, SPAPR_TCE_PAGE_SHIFT, 0, - pc->rtce_window_size >> SPAPR_TCE_PAGE_SHIFT); + dev->tcet = spapr_tce_new_table(qdev, liobn, + 0, + SPAPR_TCE_PAGE_SHIFT, + pc->rtce_window_size >> + SPAPR_TCE_PAGE_SHIFT, false); dev->tcet->vdev = dev; memory_region_add_subregion_overlap(&dev->mrroot, 0, spapr_tce_get_iommu(dev->tcet), 2); @@ -580,7 +584,7 @@ const VMStateDescription vmstate_spapr_vio = { VMSTATE_UINT32_EQUAL(irq, VIOsPAPRDevice), /* General VIO device state */ - VMSTATE_UINT64(signal_state, VIOsPAPRDevice), + VMSTATE_UINTTL(signal_state, VIOsPAPRDevice), VMSTATE_UINT64(crq.qladdr, VIOsPAPRDevice), VMSTATE_UINT32(crq.qsize, VIOsPAPRDevice), VMSTATE_UINT32(crq.qnext, VIOsPAPRDevice), diff --git a/hw/ppc/trace-events b/hw/ppc/trace-events deleted file mode 100644 index dfeab9308..000000000 --- a/hw/ppc/trace-events +++ /dev/null @@ -1,43 +0,0 @@ -# See docs/tracing.txt for syntax documentation. - -# hw/ppc/spapr_pci.c -spapr_pci_msi(const char *msg, uint32_t ca) "%s (cfg=%x)" -spapr_pci_msi_setup(const char *name, unsigned vector, uint64_t addr) "dev\"%s\" vector %u, addr=%"PRIx64 -spapr_pci_rtas_ibm_change_msi(unsigned cfg, unsigned func, unsigned req, unsigned first) "cfgaddr %x func %u, requested %u, first irq %u" -spapr_pci_rtas_ibm_query_interrupt_source_number(unsigned ioa, unsigned intr) "queries for #%u, IRQ%u" -spapr_pci_msi_write(uint64_t addr, uint64_t data, uint32_t dt_irq) "@%"PRIx64"<=%"PRIx64" IRQ %u" -spapr_pci_lsi_set(const char *busname, int pin, uint32_t irq) "%s PIN%d IRQ %u" -spapr_pci_msi_retry(unsigned config_addr, unsigned req_num, unsigned max_irqs) "Guest device at %x asked %u, have only %u" - -# hw/ppc/spapr.c -spapr_cas_failed(unsigned long n) "DT diff buffer is too small: %ld bytes" -spapr_cas_continue(unsigned long n) "Copy changes to the guest: %ld bytes" - -# hw/ppc/spapr_hcall.c -spapr_cas_pvr_try(uint32_t pvr) "%x" -spapr_cas_pvr(uint32_t cur_pvr, bool cpu_match, uint32_t new_pvr, uint64_t pcr) "current=%x, cpu_match=%u, new=%x, compat flags=%"PRIx64 - -# hw/ppc/spapr_iommu.c -spapr_iommu_put(uint64_t liobn, uint64_t ioba, uint64_t tce, uint64_t ret) "liobn=%"PRIx64" ioba=0x%"PRIx64" tce=0x%"PRIx64" ret=%"PRId64 -spapr_iommu_get(uint64_t liobn, uint64_t ioba, uint64_t ret, uint64_t tce) "liobn=%"PRIx64" ioba=0x%"PRIx64" ret=%"PRId64" tce=0x%"PRIx64 -spapr_iommu_indirect(uint64_t liobn, uint64_t ioba, uint64_t tce, uint64_t iobaN, uint64_t tceN, uint64_t ret) "liobn=%"PRIx64" ioba=0x%"PRIx64" tcelist=0x%"PRIx64" iobaN=0x%"PRIx64" tceN=0x%"PRIx64" ret=%"PRId64 -spapr_iommu_stuff(uint64_t liobn, uint64_t ioba, uint64_t tce_value, uint64_t npages, uint64_t ret) "liobn=%"PRIx64" ioba=0x%"PRIx64" tcevalue=0x%"PRIx64" npages=%"PRId64" ret=%"PRId64 -spapr_iommu_pci_put(uint64_t liobn, uint64_t ioba, uint64_t tce, uint64_t ret) "liobn=%"PRIx64" ioba=0x%"PRIx64" tce=0x%"PRIx64" ret=%"PRId64 -spapr_iommu_pci_get(uint64_t liobn, uint64_t ioba, uint64_t ret, uint64_t tce) "liobn=%"PRIx64" ioba=0x%"PRIx64" ret=%"PRId64" tce=0x%"PRIx64 -spapr_iommu_pci_indirect(uint64_t liobn, uint64_t ioba, uint64_t tce, uint64_t iobaN, uint64_t tceN, uint64_t ret) "liobn=%"PRIx64" ioba=0x%"PRIx64" tcelist=0x%"PRIx64" iobaN=0x%"PRIx64" tceN=0x%"PRIx64" ret=%"PRId64 -spapr_iommu_pci_stuff(uint64_t liobn, uint64_t ioba, uint64_t tce_value, uint64_t npages, uint64_t ret) "liobn=%"PRIx64" ioba=0x%"PRIx64" tcevalue=0x%"PRIx64" npages=%"PRId64" ret=%"PRId64 -spapr_iommu_xlate(uint64_t liobn, uint64_t ioba, uint64_t tce, unsigned perm, unsigned pgsize) "liobn=%"PRIx64" 0x%"PRIx64" -> 0x%"PRIx64" perm=%u mask=%x" -spapr_iommu_new_table(uint64_t liobn, void *table, int fd) "liobn=%"PRIx64" table=%p fd=%d" -spapr_iommu_pre_save(uint64_t liobn, uint32_t nb, uint64_t offs, uint32_t ps) "liobn=%"PRIx64" %"PRIx32" bus_offset=%"PRIx64" ps=%"PRIu32 -spapr_iommu_post_load(uint64_t liobn, uint32_t pre_nb, uint32_t post_nb, uint64_t offs, uint32_t ps) "liobn=%"PRIx64" %"PRIx32" => %"PRIx32" bus_offset=%"PRIx64" ps=%"PRIu32 -spapr_iommu_ddw_query(uint64_t buid, uint32_t cfgaddr, unsigned wa, uint64_t win_size, uint32_t pgmask) "buid=%"PRIx64" addr=%"PRIx32", %u windows available, max window size=%"PRIx64", mask=%"PRIx32 -spapr_iommu_ddw_create(uint64_t buid, uint32_t cfgaddr, uint64_t pg_size, uint64_t req_size, uint64_t start, uint32_t liobn) "buid=%"PRIx64" addr=%"PRIx32", page size=0x%"PRIx64", requested=0x%"PRIx64", start addr=%"PRIx64", liobn=%"PRIx32 -spapr_iommu_ddw_remove(uint32_t liobn) "liobn=%"PRIx32 -spapr_iommu_ddw_reset(uint64_t buid, uint32_t cfgaddr) "buid=%"PRIx64" addr=%"PRIx32 - -# hw/ppc/ppc.c -ppc_tb_adjust(uint64_t offs1, uint64_t offs2, int64_t diff, int64_t seconds) "adjusted from 0x%"PRIx64" to 0x%"PRIx64", diff %"PRId64" (%"PRId64"s)" - -# hw/ppc/prep.c -prep_io_800_writeb(uint32_t addr, uint32_t val) "0x%08" PRIx32 " => 0x%02" PRIx32 -prep_io_800_readb(uint32_t addr, uint32_t retval) "0x%08" PRIx32 " <= 0x%02" PRIx32 diff --git a/hw/ppc/virtex_ml507.c b/hw/ppc/virtex_ml507.c index b97d96685..b807a08c2 100644 --- a/hw/ppc/virtex_ml507.c +++ b/hw/ppc/virtex_ml507.c @@ -23,7 +23,6 @@ */ #include "qemu/osdep.h" -#include "cpu.h" #include "hw/sysbus.h" #include "hw/hw.h" #include "hw/char/serial.h" |