From b1a568c1c2192f090536b8ac76d135ce1f46a0ee Mon Sep 17 00:00:00 2001 From: Greg Kurz Date: Fri, 16 Feb 2018 19:58:06 +0100 Subject: [PATCH 01/30] spapr: fix missing CPU core nodes in DT when running with TCG MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit 5d0fb1508e2d "spapr: consolidate the VCPU id numbering logic in a single place" introduced a helper to detect thread0 of a virtual core based on its VCPU id. This is used to create CPU core nodes in the DT, but it is broken in TCG. $ qemu-system-ppc64 -nographic -accel tcg -machine dumpdtb=dtb.bin \ -smp cores=16,maxcpus=16,threads=1 $ dtc -f -O dts dtb.bin | grep POWER8 PowerPC,POWER8@0 { PowerPC,POWER8@8 { instead of the expected 16 cores that we get with KVM: $ dtc -f -O dts dtb.bin | grep POWER8 PowerPC,POWER8@0 { PowerPC,POWER8@8 { PowerPC,POWER8@10 { PowerPC,POWER8@18 { PowerPC,POWER8@20 { PowerPC,POWER8@28 { PowerPC,POWER8@30 { PowerPC,POWER8@38 { PowerPC,POWER8@40 { PowerPC,POWER8@48 { PowerPC,POWER8@50 { PowerPC,POWER8@58 { PowerPC,POWER8@60 { PowerPC,POWER8@68 { PowerPC,POWER8@70 { PowerPC,POWER8@78 { This happens because spapr_get_vcpu_id() maps VCPU ids to cs->cpu_index in TCG mode. This confuses the code in spapr_is_thread0_in_vcore(), since it assumes thread0 VCPU ids to have a spapr->vsmt spacing. spapr_get_vcpu_id(cpu) % spapr->vsmt == 0 Actually, there's no real reason to expose cs->cpu_index instead of the VCPU id, since we also generate it with TCG. Also we already set it explicitly in spapr_set_vcpu_id(), so there's no real reason either to call kvm_arch_vcpu_id() with KVM. This patch unifies spapr_get_vcpu_id() to always return the computed VCPU id both in TCG and KVM. This is one step forward towards KVM<->TCG migration. Fixes: 5d0fb1508e2d Reported-by: Cédric Le Goater Signed-off-by: Greg Kurz Signed-off-by: David Gibson --- hw/ppc/spapr.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index 83c9d66dd5..d6fd0e666e 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -3810,13 +3810,7 @@ static void spapr_pic_print_info(InterruptStatsProvider *obj, int spapr_get_vcpu_id(PowerPCCPU *cpu) { - CPUState *cs = CPU(cpu); - - if (kvm_enabled()) { - return kvm_arch_vcpu_id(cs); - } else { - return cs->cpu_index; - } + return cpu->vcpu_id; } void spapr_set_vcpu_id(PowerPCCPU *cpu, int cpu_index, Error **errp) From ff22e0eb259af531a75795c472beb5f1ff006679 Mon Sep 17 00:00:00 2001 From: BALATON Zoltan Date: Fri, 2 Mar 2018 22:43:23 +0100 Subject: [PATCH 02/30] ppc440_uc: Fix unintialized variable warning with older gcc Signed-off-by: BALATON Zoltan Signed-off-by: David Gibson --- hw/ppc/ppc440_uc.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/hw/ppc/ppc440_uc.c b/hw/ppc/ppc440_uc.c index 4e2523a64f..976ab2b5d8 100644 --- a/hw/ppc/ppc440_uc.c +++ b/hw/ppc/ppc440_uc.c @@ -1050,6 +1050,9 @@ static void ppc460ex_pcie_realize(DeviceState *dev, Error **errp) case DCRN_PCIE1_BASE: id = 1; break; + default: + error_setg(errp, "invalid PCIe DCRN base"); + return; } snprintf(buf, sizeof(buf), "pcie%d-io", id); memory_region_init(&s->iomem, OBJECT(s), buf, UINT64_MAX); From 7ccc89b5c8015b3f0d6220601a1e5e3010d8c2e1 Mon Sep 17 00:00:00 2001 From: BALATON Zoltan Date: Mon, 19 Feb 2018 11:34:25 +0100 Subject: [PATCH 03/30] ppc440: Add emulation of plb-pcix controller found in some 440 SoCs This is the PCIX controller found in newer 440 core SoCs e.g. the AMMC 460EX. The device tree refers to this as plb-pcix compared to the plb-pci controller in older 440 SoCs. Signed-off-by: BALATON Zoltan [dwg: Remove hwaddr from trace-events, that doesn't work with some trace backends] Signed-off-by: David Gibson --- hw/ppc/Makefile.objs | 2 +- hw/ppc/ppc440_pcix.c | 528 +++++++++++++++++++++++++++++++++++++++++++ hw/ppc/trace-events | 8 + 3 files changed, 537 insertions(+), 1 deletion(-) create mode 100644 hw/ppc/ppc440_pcix.c diff --git a/hw/ppc/Makefile.objs b/hw/ppc/Makefile.objs index ad1928c5d8..bddc742bfb 100644 --- a/hw/ppc/Makefile.objs +++ b/hw/ppc/Makefile.objs @@ -13,7 +13,7 @@ endif obj-$(CONFIG_PSERIES) += spapr_rtas_ddw.o # PowerPC 4xx boards obj-y += ppc4xx_devs.o ppc405_uc.o -obj-$(CONFIG_PPC4XX) += ppc4xx_pci.o ppc405_boards.o ppc440_bamboo.o +obj-$(CONFIG_PPC4XX) += ppc4xx_pci.o ppc405_boards.o ppc440_bamboo.o ppc440_pcix.o # PReP obj-$(CONFIG_PREP) += prep.o obj-$(CONFIG_PREP) += prep_systemio.o diff --git a/hw/ppc/ppc440_pcix.c b/hw/ppc/ppc440_pcix.c new file mode 100644 index 0000000000..ab2626a9de --- /dev/null +++ b/hw/ppc/ppc440_pcix.c @@ -0,0 +1,528 @@ +/* + * Emulation of the ibm,plb-pcix PCI controller + * This is found in some 440 SoCs e.g. the 460EX. + * + * Copyright (c) 2016-2018 BALATON Zoltan + * + * Derived from ppc4xx_pci.c and pci-host/ppce500.c + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License, version 2, as + * published by the Free Software Foundation. + * + * 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 . + */ + +#include "qemu/osdep.h" +#include "qemu/error-report.h" +#include "hw/hw.h" +#include "hw/ppc/ppc.h" +#include "hw/ppc/ppc4xx.h" +#include "hw/pci/pci.h" +#include "hw/pci/pci_host.h" +#include "exec/address-spaces.h" +#include "trace.h" + +struct PLBOutMap { + uint64_t la; + uint64_t pcia; + uint32_t sa; + MemoryRegion mr; +}; + +struct PLBInMap { + uint64_t sa; + uint64_t la; + MemoryRegion mr; +}; + +#define TYPE_PPC440_PCIX_HOST_BRIDGE "ppc440-pcix-host" +#define PPC440_PCIX_HOST_BRIDGE(obj) \ + OBJECT_CHECK(PPC440PCIXState, (obj), TYPE_PPC440_PCIX_HOST_BRIDGE) + +#define PPC440_PCIX_NR_POMS 3 +#define PPC440_PCIX_NR_PIMS 3 + +typedef struct PPC440PCIXState { + PCIHostState parent_obj; + + PCIDevice *dev; + struct PLBOutMap pom[PPC440_PCIX_NR_POMS]; + struct PLBInMap pim[PPC440_PCIX_NR_PIMS]; + uint32_t sts; + qemu_irq irq[PCI_NUM_PINS]; + AddressSpace bm_as; + MemoryRegion bm; + + MemoryRegion container; + MemoryRegion iomem; + MemoryRegion busmem; +} PPC440PCIXState; + +#define PPC440_REG_BASE 0x80000 +#define PPC440_REG_SIZE 0xff + +#define PCIC0_CFGADDR 0x0 +#define PCIC0_CFGDATA 0x4 + +#define PCIX0_POM0LAL 0x68 +#define PCIX0_POM0LAH 0x6c +#define PCIX0_POM0SA 0x70 +#define PCIX0_POM0PCIAL 0x74 +#define PCIX0_POM0PCIAH 0x78 +#define PCIX0_POM1LAL 0x7c +#define PCIX0_POM1LAH 0x80 +#define PCIX0_POM1SA 0x84 +#define PCIX0_POM1PCIAL 0x88 +#define PCIX0_POM1PCIAH 0x8c +#define PCIX0_POM2SA 0x90 + +#define PCIX0_PIM0SAL 0x98 +#define PCIX0_PIM0LAL 0x9c +#define PCIX0_PIM0LAH 0xa0 +#define PCIX0_PIM1SA 0xa4 +#define PCIX0_PIM1LAL 0xa8 +#define PCIX0_PIM1LAH 0xac +#define PCIX0_PIM2SAL 0xb0 +#define PCIX0_PIM2LAL 0xb4 +#define PCIX0_PIM2LAH 0xb8 +#define PCIX0_PIM0SAH 0xf8 +#define PCIX0_PIM2SAH 0xfc + +#define PCIX0_STS 0xe0 + +#define PCI_ALL_SIZE (PPC440_REG_BASE + PPC440_REG_SIZE) + +static void ppc440_pcix_clear_region(MemoryRegion *parent, + MemoryRegion *mem) +{ + if (memory_region_is_mapped(mem)) { + memory_region_del_subregion(parent, mem); + object_unparent(OBJECT(mem)); + } +} + +/* DMA mapping */ +static void ppc440_pcix_update_pim(PPC440PCIXState *s, int idx) +{ + MemoryRegion *mem = &s->pim[idx].mr; + char *name; + uint64_t size; + + /* Before we modify anything, unmap and destroy the region */ + ppc440_pcix_clear_region(&s->bm, mem); + + if (!(s->pim[idx].sa & 1)) { + /* Not enabled, nothing to do */ + return; + } + + name = g_strdup_printf("PCI Inbound Window %d", idx); + size = ~(s->pim[idx].sa & ~7ULL) + 1; + memory_region_init_alias(mem, OBJECT(s), name, get_system_memory(), + s->pim[idx].la, size); + memory_region_add_subregion_overlap(&s->bm, 0, mem, -1); + g_free(name); + + trace_ppc440_pcix_update_pim(idx, size, s->pim[idx].la); +} + +/* BAR mapping */ +static void ppc440_pcix_update_pom(PPC440PCIXState *s, int idx) +{ + MemoryRegion *mem = &s->pom[idx].mr; + MemoryRegion *address_space_mem = get_system_memory(); + char *name; + uint32_t size; + + /* Before we modify anything, unmap and destroy the region */ + ppc440_pcix_clear_region(address_space_mem, mem); + + if (!(s->pom[idx].sa & 1)) { + /* Not enabled, nothing to do */ + return; + } + + name = g_strdup_printf("PCI Outbound Window %d", idx); + size = ~(s->pom[idx].sa & 0xfffffffe) + 1; + if (!size) { + size = 0xffffffff; + } + memory_region_init_alias(mem, OBJECT(s), name, &s->busmem, + s->pom[idx].pcia, size); + memory_region_add_subregion(address_space_mem, s->pom[idx].la, mem); + g_free(name); + + trace_ppc440_pcix_update_pom(idx, size, s->pom[idx].la, s->pom[idx].pcia); +} + +static void ppc440_pcix_reg_write4(void *opaque, hwaddr addr, + uint64_t val, unsigned size) +{ + struct PPC440PCIXState *s = opaque; + + trace_ppc440_pcix_reg_read(addr, val); + switch (addr) { + case PCI_VENDOR_ID ... PCI_MAX_LAT: + stl_le_p(s->dev->config + addr, val); + break; + + case PCIX0_POM0LAL: + s->pom[0].la &= 0xffffffff00000000ULL; + s->pom[0].la |= val; + ppc440_pcix_update_pom(s, 0); + break; + case PCIX0_POM0LAH: + s->pom[0].la &= 0xffffffffULL; + s->pom[0].la |= val << 32; + ppc440_pcix_update_pom(s, 0); + break; + case PCIX0_POM0SA: + s->pom[0].sa = val; + ppc440_pcix_update_pom(s, 0); + break; + case PCIX0_POM0PCIAL: + s->pom[0].pcia &= 0xffffffff00000000ULL; + s->pom[0].pcia |= val; + ppc440_pcix_update_pom(s, 0); + break; + case PCIX0_POM0PCIAH: + s->pom[0].pcia &= 0xffffffffULL; + s->pom[0].pcia |= val << 32; + ppc440_pcix_update_pom(s, 0); + break; + case PCIX0_POM1LAL: + s->pom[1].la &= 0xffffffff00000000ULL; + s->pom[1].la |= val; + ppc440_pcix_update_pom(s, 1); + break; + case PCIX0_POM1LAH: + s->pom[1].la &= 0xffffffffULL; + s->pom[1].la |= val << 32; + ppc440_pcix_update_pom(s, 1); + break; + case PCIX0_POM1SA: + s->pom[1].sa = val; + ppc440_pcix_update_pom(s, 1); + break; + case PCIX0_POM1PCIAL: + s->pom[1].pcia &= 0xffffffff00000000ULL; + s->pom[1].pcia |= val; + ppc440_pcix_update_pom(s, 1); + break; + case PCIX0_POM1PCIAH: + s->pom[1].pcia &= 0xffffffffULL; + s->pom[1].pcia |= val << 32; + ppc440_pcix_update_pom(s, 1); + break; + case PCIX0_POM2SA: + s->pom[2].sa = val; + break; + + case PCIX0_PIM0SAL: + s->pim[0].sa &= 0xffffffff00000000ULL; + s->pim[0].sa |= val; + ppc440_pcix_update_pim(s, 0); + break; + case PCIX0_PIM0LAL: + s->pim[0].la &= 0xffffffff00000000ULL; + s->pim[0].la |= val; + ppc440_pcix_update_pim(s, 0); + break; + case PCIX0_PIM0LAH: + s->pim[0].la &= 0xffffffffULL; + s->pim[0].la |= val << 32; + ppc440_pcix_update_pim(s, 0); + break; + case PCIX0_PIM1SA: + s->pim[1].sa = val; + ppc440_pcix_update_pim(s, 1); + break; + case PCIX0_PIM1LAL: + s->pim[1].la &= 0xffffffff00000000ULL; + s->pim[1].la |= val; + ppc440_pcix_update_pim(s, 1); + break; + case PCIX0_PIM1LAH: + s->pim[1].la &= 0xffffffffULL; + s->pim[1].la |= val << 32; + ppc440_pcix_update_pim(s, 1); + break; + case PCIX0_PIM2SAL: + s->pim[2].sa &= 0xffffffff00000000ULL; + s->pim[2].sa = val; + ppc440_pcix_update_pim(s, 2); + break; + case PCIX0_PIM2LAL: + s->pim[2].la &= 0xffffffff00000000ULL; + s->pim[2].la |= val; + ppc440_pcix_update_pim(s, 2); + break; + case PCIX0_PIM2LAH: + s->pim[2].la &= 0xffffffffULL; + s->pim[2].la |= val << 32; + ppc440_pcix_update_pim(s, 2); + break; + + case PCIX0_STS: + s->sts = val; + break; + + case PCIX0_PIM0SAH: + s->pim[0].sa &= 0xffffffffULL; + s->pim[0].sa |= val << 32; + ppc440_pcix_update_pim(s, 0); + break; + case PCIX0_PIM2SAH: + s->pim[2].sa &= 0xffffffffULL; + s->pim[2].sa |= val << 32; + ppc440_pcix_update_pim(s, 2); + break; + + default: + error_report("%s: unhandled PCI internal register 0x%lx", __func__, + (unsigned long)addr); + break; + } +} + +static uint64_t ppc440_pcix_reg_read4(void *opaque, hwaddr addr, + unsigned size) +{ + struct PPC440PCIXState *s = opaque; + uint32_t val; + + switch (addr) { + case PCI_VENDOR_ID ... PCI_MAX_LAT: + val = ldl_le_p(s->dev->config + addr); + break; + + case PCIX0_POM0LAL: + val = s->pom[0].la; + break; + case PCIX0_POM0LAH: + val = s->pom[0].la >> 32; + break; + case PCIX0_POM0SA: + val = s->pom[0].sa; + break; + case PCIX0_POM0PCIAL: + val = s->pom[0].pcia; + break; + case PCIX0_POM0PCIAH: + val = s->pom[0].pcia >> 32; + break; + case PCIX0_POM1LAL: + val = s->pom[1].la; + break; + case PCIX0_POM1LAH: + val = s->pom[1].la >> 32; + break; + case PCIX0_POM1SA: + val = s->pom[1].sa; + break; + case PCIX0_POM1PCIAL: + val = s->pom[1].pcia; + break; + case PCIX0_POM1PCIAH: + val = s->pom[1].pcia >> 32; + break; + case PCIX0_POM2SA: + val = s->pom[2].sa; + break; + + case PCIX0_PIM0SAL: + val = s->pim[0].sa; + break; + case PCIX0_PIM0LAL: + val = s->pim[0].la; + break; + case PCIX0_PIM0LAH: + val = s->pim[0].la >> 32; + break; + case PCIX0_PIM1SA: + val = s->pim[1].sa; + break; + case PCIX0_PIM1LAL: + val = s->pim[1].la; + break; + case PCIX0_PIM1LAH: + val = s->pim[1].la >> 32; + break; + case PCIX0_PIM2SAL: + val = s->pim[2].sa; + break; + case PCIX0_PIM2LAL: + val = s->pim[2].la; + break; + case PCIX0_PIM2LAH: + val = s->pim[2].la >> 32; + break; + + case PCIX0_STS: + val = s->sts; + break; + + case PCIX0_PIM0SAH: + val = s->pim[0].sa >> 32; + break; + case PCIX0_PIM2SAH: + val = s->pim[2].sa >> 32; + break; + + default: + error_report("%s: invalid PCI internal register 0x%lx", __func__, + (unsigned long)addr); + val = 0; + } + + trace_ppc440_pcix_reg_read(addr, val); + return val; +} + +static const MemoryRegionOps pci_reg_ops = { + .read = ppc440_pcix_reg_read4, + .write = ppc440_pcix_reg_write4, + .endianness = DEVICE_LITTLE_ENDIAN, +}; + +static void ppc440_pcix_reset(DeviceState *dev) +{ + struct PPC440PCIXState *s = PPC440_PCIX_HOST_BRIDGE(dev); + int i; + + for (i = 0; i < PPC440_PCIX_NR_POMS; i++) { + ppc440_pcix_clear_region(get_system_memory(), &s->pom[i].mr); + } + for (i = 0; i < PPC440_PCIX_NR_PIMS; i++) { + ppc440_pcix_clear_region(&s->bm, &s->pim[i].mr); + } + memset(s->pom, 0, sizeof(s->pom)); + memset(s->pim, 0, sizeof(s->pim)); + for (i = 0; i < PPC440_PCIX_NR_PIMS; i++) { + s->pim[i].sa = 0xffffffff00000000ULL; + } + s->sts = 0; +} + +/* All pins from each slot are tied to a single board IRQ. + * This may need further refactoring for other boards. */ +static int ppc440_pcix_map_irq(PCIDevice *pci_dev, int irq_num) +{ + int slot = pci_dev->devfn >> 3; + trace_ppc440_pcix_map_irq(pci_dev->devfn, irq_num, slot); + return slot - 1; +} + +static void ppc440_pcix_set_irq(void *opaque, int irq_num, int level) +{ + qemu_irq *pci_irqs = opaque; + + trace_ppc440_pcix_set_irq(irq_num); + if (irq_num < 0) { + error_report("%s: PCI irq %d", __func__, irq_num); + return; + } + qemu_set_irq(pci_irqs[irq_num], level); +} + +static AddressSpace *ppc440_pcix_set_iommu(PCIBus *b, void *opaque, int devfn) +{ + PPC440PCIXState *s = opaque; + + return &s->bm_as; +} + +/* The default pci_host_data_{read,write} functions in pci/pci_host.c + * deny access to registers without bit 31 set but our clients want + * this to work so we have to override these here */ +static void pci_host_data_write(void *opaque, hwaddr addr, + uint64_t val, unsigned len) +{ + PCIHostState *s = opaque; + pci_data_write(s->bus, s->config_reg | (addr & 3), val, len); +} + +static uint64_t pci_host_data_read(void *opaque, + hwaddr addr, unsigned len) +{ + PCIHostState *s = opaque; + uint32_t val; + val = pci_data_read(s->bus, s->config_reg | (addr & 3), len); + return val; +} + +const MemoryRegionOps ppc440_pcix_host_data_ops = { + .read = pci_host_data_read, + .write = pci_host_data_write, + .endianness = DEVICE_LITTLE_ENDIAN, +}; + +static int ppc440_pcix_initfn(SysBusDevice *dev) +{ + PPC440PCIXState *s; + PCIHostState *h; + int i; + + h = PCI_HOST_BRIDGE(dev); + s = PPC440_PCIX_HOST_BRIDGE(dev); + + for (i = 0; i < ARRAY_SIZE(s->irq); i++) { + sysbus_init_irq(dev, &s->irq[i]); + } + + memory_region_init(&s->busmem, OBJECT(dev), "pci bus memory", UINT64_MAX); + h->bus = pci_register_root_bus(DEVICE(dev), NULL, ppc440_pcix_set_irq, + ppc440_pcix_map_irq, s->irq, &s->busmem, + get_system_io(), PCI_DEVFN(0, 0), 4, TYPE_PCI_BUS); + + s->dev = pci_create_simple(h->bus, PCI_DEVFN(0, 0), "ppc4xx-host-bridge"); + + memory_region_init(&s->bm, OBJECT(s), "bm-ppc440-pcix", UINT64_MAX); + memory_region_add_subregion(&s->bm, 0x0, &s->busmem); + address_space_init(&s->bm_as, &s->bm, "pci-bm"); + pci_setup_iommu(h->bus, ppc440_pcix_set_iommu, s); + + memory_region_init(&s->container, OBJECT(s), "pci-container", PCI_ALL_SIZE); + memory_region_init_io(&h->conf_mem, OBJECT(s), &pci_host_conf_le_ops, + h, "pci-conf-idx", 4); + memory_region_init_io(&h->data_mem, OBJECT(s), &ppc440_pcix_host_data_ops, + h, "pci-conf-data", 4); + memory_region_init_io(&s->iomem, OBJECT(s), &pci_reg_ops, s, + "pci.reg", PPC440_REG_SIZE); + memory_region_add_subregion(&s->container, PCIC0_CFGADDR, &h->conf_mem); + memory_region_add_subregion(&s->container, PCIC0_CFGDATA, &h->data_mem); + memory_region_add_subregion(&s->container, PPC440_REG_BASE, &s->iomem); + sysbus_init_mmio(dev, &s->container); + + return 0; +} + +static void ppc440_pcix_class_init(ObjectClass *klass, void *data) +{ + SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); + DeviceClass *dc = DEVICE_CLASS(klass); + + k->init = ppc440_pcix_initfn; + dc->reset = ppc440_pcix_reset; +} + +static const TypeInfo ppc440_pcix_info = { + .name = TYPE_PPC440_PCIX_HOST_BRIDGE, + .parent = TYPE_PCI_HOST_BRIDGE, + .instance_size = sizeof(PPC440PCIXState), + .class_init = ppc440_pcix_class_init, +}; + +static void ppc440_pcix_register_types(void) +{ + type_register_static(&ppc440_pcix_info); +} + +type_init(ppc440_pcix_register_types) diff --git a/hw/ppc/trace-events b/hw/ppc/trace-events index b7c3e64b5e..66ec7eda6e 100644 --- a/hw/ppc/trace-events +++ b/hw/ppc/trace-events @@ -99,3 +99,11 @@ mac99_uninorth_read(uint64_t addr, uint64_t value) "addr=0x%" PRIx64 " val=0x%"P # hw/ppc/ppc4xx_pci.c ppc4xx_pci_map_irq(int32_t devfn, int irq_num, int slot) "devfn 0x%x irq %d -> %d" ppc4xx_pci_set_irq(int irq_num) "PCI irq %d" + +# hw/ppc/ppc440_pcix.c +ppc440_pcix_map_irq(int32_t devfn, int irq_num, int slot) "devfn 0x%x irq %d -> %d" +ppc440_pcix_set_irq(int irq_num) "PCI irq %d" +ppc440_pcix_update_pim(int idx, uint64_t size, uint64_t la) "Added window %d of size=0x%" PRIx64 " to CPU=0x%" PRIx64 +ppc440_pcix_update_pom(int idx, uint32_t size, uint64_t la, uint64_t pcia) "Added window %d of size=0x%x from CPU=0x%" PRIx64 " to PCI=0x%" PRIx64 +ppc440_pcix_reg_read(uint64_t addr, uint32_t val) "addr 0x%" PRIx64 " = 0x%" PRIx32 +ppc440_pcix_reg_write(uint64_t addr, uint64_t val) "addr 0x%" PRIx64 " = 0x%" PRIx64 From b41a162c1bcd4b5d44191d465002dc790054db3f Mon Sep 17 00:00:00 2001 From: BALATON Zoltan Date: Fri, 2 Mar 2018 12:50:14 +0100 Subject: [PATCH 04/30] roms: Added git submodule for u-boot-sam460 (firmware for sam460ex) Signed-off-by: BALATON Zoltan Signed-off-by: David Gibson --- .gitmodules | 3 +++ roms/Makefile | 7 +++++++ roms/u-boot-sam460ex | 1 + 3 files changed, 11 insertions(+) create mode 160000 roms/u-boot-sam460ex diff --git a/.gitmodules b/.gitmodules index 7a8282df46..b76fb450a4 100644 --- a/.gitmodules +++ b/.gitmodules @@ -43,3 +43,6 @@ [submodule "roms/seabios-hppa"] path = roms/seabios-hppa url = git://github.com/hdeller/seabios-hppa.git +[submodule "roms/u-boot-sam460ex"] + path = roms/u-boot-sam460ex + url = git://github.com/zbalaton/u-boot-sam460ex diff --git a/roms/Makefile b/roms/Makefile index b5e5a69e91..02b69fbac8 100644 --- a/roms/Makefile +++ b/roms/Makefile @@ -65,6 +65,7 @@ default: @echo " slof -- update slof.bin" @echo " skiboot -- update skiboot.lid" @echo " u-boot.e500 -- update u-boot.e500" + @echo " u-boot.sam460 -- update u-boot.sam460" bios: build-seabios-config-seabios-128k build-seabios-config-seabios-256k cp seabios/builds/seabios-128k/bios.bin ../pc-bios/bios.bin @@ -147,6 +148,11 @@ u-boot.e500: $(powerpc_cross_prefix)strip u-boot/build.e500/u-boot -o \ ../pc-bios/u-boot.e500 +u-boot.sam460: + $(MAKE) -C u-boot-sam460ex Sam460ex_config + $(MAKE) -C u-boot-sam460ex CROSS_COMPILE=$(powerpc_cross_prefix) + cp u-boot-sam460ex/u-boot.bin ../pc-bios/u-boot-sam460-20100605.bin + skiboot: $(MAKE) -C skiboot CROSS=$(powerpc64_cross_prefix) cp skiboot/skiboot.lid ../pc-bios/skiboot.lid @@ -160,4 +166,5 @@ clean: $(MAKE) -C ipxe/src veryclean $(MAKE) -C SLOF clean rm -rf u-boot/build.e500 + $(MAKE) -C u-boot-sam460ex distclean $(MAKE) -C skiboot clean diff --git a/roms/u-boot-sam460ex b/roms/u-boot-sam460ex new file mode 160000 index 0000000000..119aa277f7 --- /dev/null +++ b/roms/u-boot-sam460ex @@ -0,0 +1 @@ +Subproject commit 119aa277f74a4a2d3f7ab6c9471292308eba14e4 From 82e65fe01eebf37c86b1f301dc8a7bfff1adbefc Mon Sep 17 00:00:00 2001 From: BALATON Zoltan Date: Fri, 2 Mar 2018 12:50:14 +0100 Subject: [PATCH 05/30] pc-bios: Added u-boot-sam460 firmware binary Signed-off-by: BALATON Zoltan Signed-off-by: David Gibson --- Makefile | 2 +- pc-bios/u-boot-sam460-20100605.bin | Bin 0 -> 524288 bytes 2 files changed, 1 insertion(+), 1 deletion(-) create mode 100755 pc-bios/u-boot-sam460-20100605.bin diff --git a/Makefile b/Makefile index 4df1f67fe4..352f3d5104 100644 --- a/Makefile +++ b/Makefile @@ -784,7 +784,7 @@ multiboot.bin linuxboot.bin linuxboot_dma.bin kvmvapic.bin \ s390-ccw.img s390-netboot.img \ spapr-rtas.bin slof.bin skiboot.lid \ palcode-clipper \ -u-boot.e500 \ +u-boot.e500 u-boot-sam460-20100605.bin \ qemu_vga.ndrv \ hppa-firmware.img else diff --git a/pc-bios/u-boot-sam460-20100605.bin b/pc-bios/u-boot-sam460-20100605.bin new file mode 100755 index 0000000000000000000000000000000000000000..99408f8e957b26e735e5befa98fa3d51a90d95f6 GIT binary patch literal 524288 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 CEz>vv literal 0 HcmV?d00001 From 4b387f9ee16358ab17ce74ff7266071bd2ae25ff Mon Sep 17 00:00:00 2001 From: BALATON Zoltan Date: Mon, 19 Feb 2018 11:34:25 +0100 Subject: [PATCH 06/30] ppc: Add aCube Sam460ex board MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add emulation of aCube Sam460ex board based on AMCC 460EX embedded SoC. This is not a complete implementation yet with a lot of components still missing but enough for the U-Boot firmware to start and to boot a Linux kernel or AROS. Signed-off-by: François Revol Signed-off-by: BALATON Zoltan Signed-off-by: David Gibson --- Makefile | 2 +- default-configs/ppc-softmmu.mak | 2 + default-configs/ppcemb-softmmu.mak | 1 + hw/ppc/Makefile.objs | 3 +- hw/ppc/sam460ex.c | 603 +++++++++++++++++++++++++++++ pc-bios/canyonlands.dtb | Bin 0 -> 9779 bytes pc-bios/canyonlands.dts | 566 +++++++++++++++++++++++++++ 7 files changed, 1175 insertions(+), 2 deletions(-) create mode 100644 hw/ppc/sam460ex.c create mode 100644 pc-bios/canyonlands.dtb create mode 100644 pc-bios/canyonlands.dts diff --git a/Makefile b/Makefile index 352f3d5104..9a75c48ae0 100644 --- a/Makefile +++ b/Makefile @@ -779,7 +779,7 @@ efi-e1000.rom efi-eepro100.rom efi-ne2k_pci.rom \ efi-pcnet.rom efi-rtl8139.rom efi-virtio.rom \ efi-e1000e.rom efi-vmxnet3.rom \ qemu-icon.bmp qemu_logo_no_text.svg \ -bamboo.dtb petalogix-s3adsp1800.dtb petalogix-ml605.dtb \ +bamboo.dtb canyonlands.dtb petalogix-s3adsp1800.dtb petalogix-ml605.dtb \ multiboot.bin linuxboot.bin linuxboot_dma.bin kvmvapic.bin \ s390-ccw.img s390-netboot.img \ spapr-rtas.bin slof.bin skiboot.lid \ diff --git a/default-configs/ppc-softmmu.mak b/default-configs/ppc-softmmu.mak index 76e29cfa14..4d7be45ac5 100644 --- a/default-configs/ppc-softmmu.mak +++ b/default-configs/ppc-softmmu.mak @@ -21,6 +21,8 @@ CONFIG_E500=y CONFIG_OPENPIC_KVM=$(call land,$(CONFIG_E500),$(CONFIG_KVM)) CONFIG_PLATFORM_BUS=y CONFIG_ETSEC=y +# For Sam460ex +CONFIG_USB_EHCI_SYSBUS=y CONFIG_SM501=y CONFIG_IDE_SII3112=y CONFIG_I2C=y diff --git a/default-configs/ppcemb-softmmu.mak b/default-configs/ppcemb-softmmu.mak index bc5e1b3ffe..67d18b2e0e 100644 --- a/default-configs/ppcemb-softmmu.mak +++ b/default-configs/ppcemb-softmmu.mak @@ -15,6 +15,7 @@ CONFIG_PTIMER=y CONFIG_I8259=y CONFIG_XILINX=y CONFIG_XILINX_ETHLITE=y +CONFIG_USB_EHCI_SYSBUS=y CONFIG_SM501=y CONFIG_IDE_SII3112=y CONFIG_I2C=y diff --git a/hw/ppc/Makefile.objs b/hw/ppc/Makefile.objs index bddc742bfb..86d82a6ec3 100644 --- a/hw/ppc/Makefile.objs +++ b/hw/ppc/Makefile.objs @@ -13,7 +13,8 @@ endif obj-$(CONFIG_PSERIES) += spapr_rtas_ddw.o # PowerPC 4xx boards obj-y += ppc4xx_devs.o ppc405_uc.o -obj-$(CONFIG_PPC4XX) += ppc4xx_pci.o ppc405_boards.o ppc440_bamboo.o ppc440_pcix.o +obj-$(CONFIG_PPC4XX) += ppc4xx_pci.o ppc405_boards.o +obj-$(CONFIG_PPC4XX) += ppc440_bamboo.o ppc440_pcix.o ppc440_uc.o sam460ex.o # PReP obj-$(CONFIG_PREP) += prep.o obj-$(CONFIG_PREP) += prep_systemio.o diff --git a/hw/ppc/sam460ex.c b/hw/ppc/sam460ex.c new file mode 100644 index 0000000000..70b8e76d9c --- /dev/null +++ b/hw/ppc/sam460ex.c @@ -0,0 +1,603 @@ +/* + * QEMU aCube Sam460ex board emulation + * + * Copyright (c) 2012 François Revol + * Copyright (c) 2016-2018 BALATON Zoltan + * + * This file is derived from hw/ppc440_bamboo.c, + * the copyright for that material belongs to the original owners. + * + * This work is licensed under the GNU GPL license version 2 or later. + * + */ + +#include "qemu/osdep.h" +#include "qemu-common.h" +#include "qemu/cutils.h" +#include "qemu/error-report.h" +#include "qapi/error.h" +#include "hw/hw.h" +#include "sysemu/blockdev.h" +#include "hw/boards.h" +#include "sysemu/kvm.h" +#include "kvm_ppc.h" +#include "sysemu/device_tree.h" +#include "sysemu/block-backend.h" +#include "hw/loader.h" +#include "elf.h" +#include "exec/address-spaces.h" +#include "exec/memory.h" +#include "hw/ppc/ppc440.h" +#include "hw/ppc/ppc405.h" +#include "hw/block/flash.h" +#include "sysemu/sysemu.h" +#include "sysemu/qtest.h" +#include "hw/sysbus.h" +#include "hw/char/serial.h" +#include "hw/i2c/ppc4xx_i2c.h" +#include "hw/i2c/smbus.h" +#include "hw/usb/hcd-ehci.h" + +#define BINARY_DEVICE_TREE_FILE "canyonlands.dtb" +#define UBOOT_FILENAME "u-boot-sam460-20100605.bin" +/* to extract the official U-Boot bin from the updater: */ +/* dd bs=1 skip=$(($(stat -c '%s' updater/updater-460) - 0x80000)) \ + if=updater/updater-460 of=u-boot-sam460-20100605.bin */ + +/* from Sam460 U-Boot include/configs/Sam460ex.h */ +#define FLASH_BASE 0xfff00000 +#define FLASH_BASE_H 0x4 +#define FLASH_SIZE (1 << 20) +#define UBOOT_LOAD_BASE 0xfff80000 +#define UBOOT_SIZE 0x00080000 +#define UBOOT_ENTRY 0xfffffffc + +/* from U-Boot */ +#define EPAPR_MAGIC (0x45504150) +#define KERNEL_ADDR 0x1000000 +#define FDT_ADDR 0x1800000 +#define RAMDISK_ADDR 0x1900000 + +/* Sam460ex IRQ MAP: + IRQ0 = ETH_INT + IRQ1 = FPGA_INT + IRQ2 = PCI_INT (PCIA, PCIB, PCIC, PCIB) + IRQ3 = FPGA_INT2 + IRQ11 = RTC_INT + IRQ12 = SM502_INT +*/ + +#define SDRAM_NR_BANKS 4 + +/* FIXME: See u-boot.git 8ac41e, also fix in ppc440_uc.c */ +static const unsigned int ppc460ex_sdram_bank_sizes[] = { + 1024 << 20, 512 << 20, 256 << 20, 128 << 20, 64 << 20, 32 << 20, 0 +}; + +struct boot_info { + uint32_t dt_base; + uint32_t dt_size; + uint32_t entry; +}; + +/*****************************************************************************/ +/* SPD eeprom content from mips_malta.c */ + +struct _eeprom24c0x_t { + uint8_t tick; + uint8_t address; + uint8_t command; + uint8_t ack; + uint8_t scl; + uint8_t sda; + uint8_t data; + uint8_t contents[256]; +}; + +typedef struct _eeprom24c0x_t eeprom24c0x_t; + +static eeprom24c0x_t spd_eeprom = { + .contents = { + /* 00000000: */ 0x80, 0x08, 0xFF, 0x0D, 0x0A, 0xFF, 0x40, 0x00, + /* 00000008: */ 0x04, 0x75, 0x54, 0x00, 0x82, 0x08, 0x00, 0x01, + /* 00000010: */ 0x8F, 0x04, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00, + /* 00000018: */ 0x00, 0x00, 0x00, 0x14, 0x0F, 0x14, 0x2D, 0xFF, + /* 00000020: */ 0x15, 0x08, 0x15, 0x08, 0x00, 0x00, 0x00, 0x00, + /* 00000028: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 00000030: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 00000038: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0xD0, + /* 00000040: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 00000048: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 00000050: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 00000058: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 00000060: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 00000068: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 00000070: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 00000078: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0xF4, + }, +}; + +static void generate_eeprom_spd(uint8_t *eeprom, ram_addr_t ram_size) +{ + enum { SDR = 0x4, DDR1 = 0x7, DDR2 = 0x8 } type; + uint8_t *spd = spd_eeprom.contents; + uint8_t nbanks = 0; + uint16_t density = 0; + int i; + + /* work in terms of MB */ + ram_size >>= 20; + + while ((ram_size >= 4) && (nbanks <= 2)) { + int sz_log2 = MIN(31 - clz32(ram_size), 14); + nbanks++; + density |= 1 << (sz_log2 - 2); + ram_size -= 1 << sz_log2; + } + + /* split to 2 banks if possible */ + if ((nbanks == 1) && (density > 1)) { + nbanks++; + density >>= 1; + } + + if (density & 0xff00) { + density = (density & 0xe0) | ((density >> 8) & 0x1f); + type = DDR2; + } else if (!(density & 0x1f)) { + type = DDR2; + } else { + type = SDR; + } + + if (ram_size) { + warn_report("SPD cannot represent final " RAM_ADDR_FMT "MB" + " of SDRAM", ram_size); + } + + /* fill in SPD memory information */ + spd[2] = type; + spd[5] = nbanks; + spd[31] = density; + + /* XXX: this is totally random */ + spd[9] = 0x10; /* CAS tcyc */ + spd[18] = 0x20; /* CAS bit */ + spd[23] = 0x10; /* CAS tcyc */ + spd[25] = 0x10; /* CAS tcyc */ + + /* checksum */ + spd[63] = 0; + for (i = 0; i < 63; i++) { + spd[63] += spd[i]; + } + + /* copy for SMBUS */ + memcpy(eeprom, spd, sizeof(spd_eeprom.contents)); +} + +static void generate_eeprom_serial(uint8_t *eeprom) +{ + int i, pos = 0; + uint8_t mac[6] = { 0x00 }; + uint8_t sn[5] = { 0x01, 0x23, 0x45, 0x67, 0x89 }; + + /* version */ + eeprom[pos++] = 0x01; + + /* count */ + eeprom[pos++] = 0x02; + + /* MAC address */ + eeprom[pos++] = 0x01; /* MAC */ + eeprom[pos++] = 0x06; /* length */ + memcpy(&eeprom[pos], mac, sizeof(mac)); + pos += sizeof(mac); + + /* serial number */ + eeprom[pos++] = 0x02; /* serial */ + eeprom[pos++] = 0x05; /* length */ + memcpy(&eeprom[pos], sn, sizeof(sn)); + pos += sizeof(sn); + + /* checksum */ + eeprom[pos] = 0; + for (i = 0; i < pos; i++) { + eeprom[pos] += eeprom[i]; + } +} + +/*****************************************************************************/ + +static int sam460ex_load_uboot(void) +{ + DriveInfo *dinfo; + BlockBackend *blk = NULL; + hwaddr base = FLASH_BASE | ((hwaddr)FLASH_BASE_H << 32); + long bios_size = FLASH_SIZE; + int fl_sectors; + + dinfo = drive_get(IF_PFLASH, 0, 0); + if (dinfo) { + blk = blk_by_legacy_dinfo(dinfo); + bios_size = blk_getlength(blk); + } + fl_sectors = (bios_size + 65535) >> 16; + + if (!pflash_cfi01_register(base, NULL, "sam460ex.flash", bios_size, + blk, (64 * 1024), fl_sectors, + 1, 0x89, 0x18, 0x0000, 0x0, 1)) { + error_report("qemu: Error registering flash memory."); + /* XXX: return an error instead? */ + exit(1); + } + + if (!blk) { + /*error_report("No flash image given with the 'pflash' parameter," + " using default u-boot image");*/ + base = UBOOT_LOAD_BASE | ((hwaddr)FLASH_BASE_H << 32); + rom_add_file_fixed(UBOOT_FILENAME, base, -1); + } + + return 0; +} + +static int sam460ex_load_device_tree(hwaddr addr, + uint32_t ramsize, + hwaddr initrd_base, + hwaddr initrd_size, + const char *kernel_cmdline) +{ + int ret = -1; + uint32_t mem_reg_property[] = { 0, 0, cpu_to_be32(ramsize) }; + char *filename; + int fdt_size; + void *fdt; + uint32_t tb_freq = 50000000; + uint32_t clock_freq = 50000000; + + filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, BINARY_DEVICE_TREE_FILE); + if (!filename) { + goto out; + } + fdt = load_device_tree(filename, &fdt_size); + g_free(filename); + if (fdt == NULL) { + goto out; + } + + /* Manipulate device tree in memory. */ + + ret = qemu_fdt_setprop(fdt, "/memory", "reg", mem_reg_property, + sizeof(mem_reg_property)); + if (ret < 0) { + error_report("couldn't set /memory/reg"); + } + + /* default FDT doesn't have a /chosen node... */ + qemu_fdt_add_subnode(fdt, "/chosen"); + + ret = qemu_fdt_setprop_cell(fdt, "/chosen", "linux,initrd-start", + initrd_base); + if (ret < 0) { + error_report("couldn't set /chosen/linux,initrd-start"); + } + + ret = qemu_fdt_setprop_cell(fdt, "/chosen", "linux,initrd-end", + (initrd_base + initrd_size)); + if (ret < 0) { + error_report("couldn't set /chosen/linux,initrd-end"); + } + + ret = qemu_fdt_setprop_string(fdt, "/chosen", "bootargs", + kernel_cmdline); + if (ret < 0) { + error_report("couldn't set /chosen/bootargs"); + } + + /* Copy data from the host device tree into the guest. Since the guest can + * directly access the timebase without host involvement, we must expose + * the correct frequencies. */ + if (kvm_enabled()) { + tb_freq = kvmppc_get_tbfreq(); + clock_freq = kvmppc_get_clockfreq(); + } + + qemu_fdt_setprop_cell(fdt, "/cpus/cpu@0", "clock-frequency", + clock_freq); + qemu_fdt_setprop_cell(fdt, "/cpus/cpu@0", "timebase-frequency", + tb_freq); + + rom_add_blob_fixed(BINARY_DEVICE_TREE_FILE, fdt, fdt_size, addr); + g_free(fdt); + ret = fdt_size; + +out: + + return ret; +} + +/* Create reset TLB entries for BookE, mapping only the flash memory. */ +static void mmubooke_create_initial_mapping_uboot(CPUPPCState *env) +{ + ppcemb_tlb_t *tlb = &env->tlb.tlbe[0]; + + /* on reset the flash is mapped by a shadow TLB, + * but since we don't implement them we need to use + * the same values U-Boot will use to avoid a fault. + */ + tlb->attr = 0; + tlb->prot = PAGE_VALID | ((PAGE_READ | PAGE_WRITE | PAGE_EXEC) << 4); + tlb->size = 0x10000000; /* up to 0xffffffff */ + tlb->EPN = 0xf0000000 & TARGET_PAGE_MASK; + tlb->RPN = (0xf0000000 & TARGET_PAGE_MASK) | 0x4; + tlb->PID = 0; +} + +/* Create reset TLB entries for BookE, spanning the 32bit addr space. */ +static void mmubooke_create_initial_mapping(CPUPPCState *env, + target_ulong va, + hwaddr pa) +{ + ppcemb_tlb_t *tlb = &env->tlb.tlbe[0]; + + tlb->attr = 0; + tlb->prot = PAGE_VALID | ((PAGE_READ | PAGE_WRITE | PAGE_EXEC) << 4); + tlb->size = 1 << 31; /* up to 0x80000000 */ + tlb->EPN = va & TARGET_PAGE_MASK; + tlb->RPN = pa & TARGET_PAGE_MASK; + tlb->PID = 0; +} + +static void main_cpu_reset(void *opaque) +{ + PowerPCCPU *cpu = opaque; + CPUPPCState *env = &cpu->env; + struct boot_info *bi = env->load_info; + + cpu_reset(CPU(cpu)); + + /* either we have a kernel to boot or we jump to U-Boot */ + if (bi->entry != UBOOT_ENTRY) { + env->gpr[1] = (16 << 20) - 8; + env->gpr[3] = FDT_ADDR; + env->nip = bi->entry; + + /* Create a mapping for the kernel. */ + mmubooke_create_initial_mapping(env, 0, 0); + env->gpr[6] = tswap32(EPAPR_MAGIC); + env->gpr[7] = (16 << 20) - 8; /*bi->ima_size;*/ + + } else { + env->nip = UBOOT_ENTRY; + mmubooke_create_initial_mapping_uboot(env); + } +} + +static void sam460ex_init(MachineState *machine) +{ + MemoryRegion *address_space_mem = get_system_memory(); + MemoryRegion *isa = g_new(MemoryRegion, 1); + MemoryRegion *ram_memories = g_new(MemoryRegion, SDRAM_NR_BANKS); + hwaddr ram_bases[SDRAM_NR_BANKS]; + hwaddr ram_sizes[SDRAM_NR_BANKS]; + MemoryRegion *l2cache_ram = g_new(MemoryRegion, 1); + qemu_irq *irqs, *uic[4]; + PCIBus *pci_bus; + PowerPCCPU *cpu; + CPUPPCState *env; + PPC4xxI2CState *i2c[2]; + hwaddr entry = UBOOT_ENTRY; + hwaddr loadaddr = 0; + target_long initrd_size = 0; + DeviceState *dev; + SysBusDevice *sbdev; + int success; + int i; + struct boot_info *boot_info; + const size_t smbus_eeprom_size = 8 * 256; + uint8_t *smbus_eeprom_buf = g_malloc0(smbus_eeprom_size); + + cpu = POWERPC_CPU(cpu_create(machine->cpu_type)); + env = &cpu->env; + if (env->mmu_model != POWERPC_MMU_BOOKE) { + error_report("Only MMU model BookE is supported by this machine."); + exit(1); + } + +#ifdef TARGET_PPCEMB + if (!qtest_enabled()) { + warn_report("qemu-system-ppcemb is deprecated, " + "please use qemu-system-ppc instead."); + } +#endif + + qemu_register_reset(main_cpu_reset, cpu); + boot_info = g_malloc0(sizeof(*boot_info)); + env->load_info = boot_info; + + ppc_booke_timers_init(cpu, 50000000, 0); + ppc_dcr_init(env, NULL, NULL); + + /* PLB arbitrer */ + ppc4xx_plb_init(env); + + /* interrupt controllers */ + irqs = g_malloc0(sizeof(*irqs) * PPCUIC_OUTPUT_NB); + irqs[PPCUIC_OUTPUT_INT] = ((qemu_irq *)env->irq_inputs)[PPC40x_INPUT_INT]; + irqs[PPCUIC_OUTPUT_CINT] = ((qemu_irq *)env->irq_inputs)[PPC40x_INPUT_CINT]; + uic[0] = ppcuic_init(env, irqs, 0xc0, 0, 1); + uic[1] = ppcuic_init(env, &uic[0][30], 0xd0, 0, 1); + uic[2] = ppcuic_init(env, &uic[0][10], 0xe0, 0, 1); + uic[3] = ppcuic_init(env, &uic[0][16], 0xf0, 0, 1); + + /* SDRAM controller */ + memset(ram_bases, 0, sizeof(ram_bases)); + memset(ram_sizes, 0, sizeof(ram_sizes)); + /* put all RAM on first bank because board has one slot + * and firmware only checks that */ + machine->ram_size = ppc4xx_sdram_adjust(machine->ram_size, 1, + ram_memories, ram_bases, ram_sizes, + ppc460ex_sdram_bank_sizes); + + /* FIXME: does 460EX have ECC interrupts? */ + ppc440_sdram_init(env, SDRAM_NR_BANKS, ram_memories, + ram_bases, ram_sizes, 1); + + /* generate SPD EEPROM data */ + for (i = 0; i < SDRAM_NR_BANKS; i++) { + generate_eeprom_spd(&smbus_eeprom_buf[i * 256], ram_sizes[i]); + } + generate_eeprom_serial(&smbus_eeprom_buf[4 * 256]); + generate_eeprom_serial(&smbus_eeprom_buf[6 * 256]); + + /* IIC controllers */ + dev = sysbus_create_simple(TYPE_PPC4xx_I2C, 0x4ef600700, uic[0][2]); + i2c[0] = PPC4xx_I2C(dev); + object_property_set_bool(OBJECT(dev), true, "realized", NULL); + smbus_eeprom_init(i2c[0]->bus, 8, smbus_eeprom_buf, smbus_eeprom_size); + g_free(smbus_eeprom_buf); + + dev = sysbus_create_simple(TYPE_PPC4xx_I2C, 0x4ef600800, uic[0][3]); + i2c[1] = PPC4xx_I2C(dev); + + /* External bus controller */ + ppc405_ebc_init(env); + + /* CPR */ + ppc4xx_cpr_init(env); + + /* PLB to AHB bridge */ + ppc4xx_ahb_init(env); + + /* System DCRs */ + ppc4xx_sdr_init(env); + + /* MAL */ + ppc4xx_mal_init(env, 4, 16, &uic[2][3]); + + /* 256K of L2 cache as memory */ + ppc4xx_l2sram_init(env); + /* FIXME: remove this after fixing l2sram mapping in ppc440_uc.c? */ + memory_region_init_ram(l2cache_ram, NULL, "ppc440.l2cache_ram", 256 << 10, + &error_abort); + memory_region_add_subregion(address_space_mem, 0x400000000LL, l2cache_ram); + + /* USB */ + sysbus_create_simple(TYPE_PPC4xx_EHCI, 0x4bffd0400, uic[2][29]); + dev = qdev_create(NULL, "sysbus-ohci"); + qdev_prop_set_string(dev, "masterbus", "usb-bus.0"); + qdev_prop_set_uint32(dev, "num-ports", 6); + qdev_init_nofail(dev); + sbdev = SYS_BUS_DEVICE(dev); + sysbus_mmio_map(sbdev, 0, 0x4bffd0000); + sysbus_connect_irq(sbdev, 0, uic[2][30]); + usb_create_simple(usb_bus_find(-1), "usb-kbd"); + usb_create_simple(usb_bus_find(-1), "usb-mouse"); + + /* PCI bus */ + ppc460ex_pcie_init(env); + /* FIXME: is this correct? */ + dev = sysbus_create_varargs("ppc440-pcix-host", 0xc0ec00000, + uic[1][0], uic[1][20], uic[1][21], uic[1][22], + NULL); + pci_bus = (PCIBus *)qdev_get_child_bus(dev, "pci.0"); + if (!pci_bus) { + error_report("couldn't create PCI controller!"); + exit(1); + } + memory_region_init_alias(isa, NULL, "isa_mmio", get_system_io(), + 0, 0x10000); + memory_region_add_subregion(get_system_memory(), 0xc08000000, isa); + + /* PCI devices */ + pci_create_simple(pci_bus, PCI_DEVFN(6, 0), "sm501"); + /* SoC has a single SATA port but we don't emulate that yet + * However, firmware and usual clients have driver for SiI311x + * so add one for convenience by default */ + if (defaults_enabled()) { + pci_create_simple(pci_bus, -1, "sii3112"); + } + + /* SoC has 4 UARTs + * but board has only one wired and two are present in fdt */ + if (serial_hds[0] != NULL) { + serial_mm_init(address_space_mem, 0x4ef600300, 0, uic[1][1], + PPC_SERIAL_MM_BAUDBASE, serial_hds[0], + DEVICE_BIG_ENDIAN); + } + if (serial_hds[1] != NULL) { + serial_mm_init(address_space_mem, 0x4ef600400, 0, uic[0][1], + PPC_SERIAL_MM_BAUDBASE, serial_hds[1], + DEVICE_BIG_ENDIAN); + } + + /* Load U-Boot image. */ + if (!machine->kernel_filename) { + success = sam460ex_load_uboot(); + if (success < 0) { + error_report("qemu: could not load firmware"); + exit(1); + } + } + + /* Load kernel. */ + if (machine->kernel_filename) { + success = load_uimage(machine->kernel_filename, &entry, &loadaddr, + NULL, NULL, NULL); + if (success < 0) { + uint64_t elf_entry, elf_lowaddr; + + success = load_elf(machine->kernel_filename, NULL, NULL, &elf_entry, + &elf_lowaddr, NULL, 1, PPC_ELF_MACHINE, 0, 0); + entry = elf_entry; + loadaddr = elf_lowaddr; + } + /* XXX try again as binary */ + if (success < 0) { + error_report("qemu: could not load kernel '%s'", + machine->kernel_filename); + exit(1); + } + } + + /* Load initrd. */ + if (machine->initrd_filename) { + initrd_size = load_image_targphys(machine->initrd_filename, + RAMDISK_ADDR, + machine->ram_size - RAMDISK_ADDR); + if (initrd_size < 0) { + error_report("qemu: could not load ram disk '%s' at %x", + machine->initrd_filename, RAMDISK_ADDR); + exit(1); + } + } + + /* If we're loading a kernel directly, we must load the device tree too. */ + if (machine->kernel_filename) { + int dt_size; + + dt_size = sam460ex_load_device_tree(FDT_ADDR, machine->ram_size, + RAMDISK_ADDR, initrd_size, + machine->kernel_cmdline); + if (dt_size < 0) { + error_report("couldn't load device tree"); + exit(1); + } + + boot_info->dt_base = FDT_ADDR; + boot_info->dt_size = dt_size; + } + + boot_info->entry = entry; +} + +static void sam460ex_machine_init(MachineClass *mc) +{ + mc->desc = "aCube Sam460ex"; + mc->init = sam460ex_init; + mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("460exb"); + mc->default_ram_size = 512 * M_BYTE; +} + +DEFINE_MACHINE("sam460ex", sam460ex_machine_init) diff --git a/pc-bios/canyonlands.dtb b/pc-bios/canyonlands.dtb new file mode 100644 index 0000000000000000000000000000000000000000..9dce3443ad9578a8a4bb92ba6970cb2ae54d1ec3 GIT binary patch literal 9779 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 literal 0 HcmV?d00001 diff --git a/pc-bios/canyonlands.dts b/pc-bios/canyonlands.dts new file mode 100644 index 0000000000..0d6ac92d0f --- /dev/null +++ b/pc-bios/canyonlands.dts @@ -0,0 +1,566 @@ +/* + * Device Tree Source for AMCC Canyonlands (460EX) + * + * Copyright 2008-2009 DENX Software Engineering, Stefan Roese + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without + * any warranty of any kind, whether express or implied. + */ + +/dts-v1/; + +/ { + #address-cells = <2>; + #size-cells = <1>; + model = "amcc,canyonlands"; + compatible = "amcc,canyonlands"; + dcr-parent = <&{/cpus/cpu@0}>; + + aliases { + ethernet0 = &EMAC0; + ethernet1 = &EMAC1; + serial0 = &UART0; + serial1 = &UART1; + }; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu@0 { + device_type = "cpu"; + model = "PowerPC,460EX"; + reg = <0x00000000>; + clock-frequency = <0>; /* Filled in by U-Boot */ + timebase-frequency = <0>; /* Filled in by U-Boot */ + i-cache-line-size = <32>; + d-cache-line-size = <32>; + i-cache-size = <32768>; + d-cache-size = <32768>; + dcr-controller; + dcr-access-method = "native"; + next-level-cache = <&L2C0>; + }; + }; + + memory { + device_type = "memory"; + reg = <0x00000000 0x00000000 0x00000000>; /* Filled in by U-Boot */ + }; + + UIC0: interrupt-controller0 { + compatible = "ibm,uic-460ex","ibm,uic"; + interrupt-controller; + cell-index = <0>; + dcr-reg = <0x0c0 0x009>; + #address-cells = <0>; + #size-cells = <0>; + #interrupt-cells = <2>; + }; + + UIC1: interrupt-controller1 { + compatible = "ibm,uic-460ex","ibm,uic"; + interrupt-controller; + cell-index = <1>; + dcr-reg = <0x0d0 0x009>; + #address-cells = <0>; + #size-cells = <0>; + #interrupt-cells = <2>; + interrupts = <0x1e 0x4 0x1f 0x4>; /* cascade */ + interrupt-parent = <&UIC0>; + }; + + UIC2: interrupt-controller2 { + compatible = "ibm,uic-460ex","ibm,uic"; + interrupt-controller; + cell-index = <2>; + dcr-reg = <0x0e0 0x009>; + #address-cells = <0>; + #size-cells = <0>; + #interrupt-cells = <2>; + interrupts = <0xa 0x4 0xb 0x4>; /* cascade */ + interrupt-parent = <&UIC0>; + }; + + UIC3: interrupt-controller3 { + compatible = "ibm,uic-460ex","ibm,uic"; + interrupt-controller; + cell-index = <3>; + dcr-reg = <0x0f0 0x009>; + #address-cells = <0>; + #size-cells = <0>; + #interrupt-cells = <2>; + interrupts = <0x10 0x4 0x11 0x4>; /* cascade */ + interrupt-parent = <&UIC0>; + }; + + SDR0: sdr { + compatible = "ibm,sdr-460ex"; + dcr-reg = <0x00e 0x002>; + }; + + CPR0: cpr { + compatible = "ibm,cpr-460ex"; + dcr-reg = <0x00c 0x002>; + }; + + CPM0: cpm { + compatible = "ibm,cpm"; + dcr-access-method = "native"; + dcr-reg = <0x160 0x003>; + unused-units = <0x00000100>; + idle-doze = <0x02000000>; + standby = <0xfeff791d>; + }; + + L2C0: l2c { + compatible = "ibm,l2-cache-460ex", "ibm,l2-cache"; + dcr-reg = <0x020 0x008 /* Internal SRAM DCR's */ + 0x030 0x008>; /* L2 cache DCR's */ + cache-line-size = <32>; /* 32 bytes */ + cache-size = <262144>; /* L2, 256K */ + interrupt-parent = <&UIC1>; + interrupts = <11 1>; + }; + + plb { + compatible = "ibm,plb-460ex", "ibm,plb4"; + #address-cells = <2>; + #size-cells = <1>; + ranges; + clock-frequency = <0>; /* Filled in by U-Boot */ + + SDRAM0: sdram { + compatible = "ibm,sdram-460ex", "ibm,sdram-405gp"; + dcr-reg = <0x010 0x002>; + }; + + CRYPTO: crypto@180000 { + compatible = "amcc,ppc460ex-crypto", "amcc,ppc4xx-crypto"; + reg = <4 0x00180000 0x80400>; + interrupt-parent = <&UIC0>; + interrupts = <0x1d 0x4>; + }; + + HWRNG: hwrng@110000 { + compatible = "amcc,ppc460ex-rng", "ppc4xx-rng"; + reg = <4 0x00110000 0x50>; + }; + + MAL0: mcmal { + compatible = "ibm,mcmal-460ex", "ibm,mcmal2"; + dcr-reg = <0x180 0x062>; + num-tx-chans = <2>; + num-rx-chans = <16>; + #address-cells = <0>; + #size-cells = <0>; + interrupt-parent = <&UIC2>; + interrupts = < /*TXEOB*/ 0x6 0x4 + /*RXEOB*/ 0x7 0x4 + /*SERR*/ 0x3 0x4 + /*TXDE*/ 0x4 0x4 + /*RXDE*/ 0x5 0x4>; + }; + + USB0: ehci@bffd0400 { + compatible = "ibm,usb-ehci-460ex", "usb-ehci"; + interrupt-parent = <&UIC2>; + interrupts = <0x1d 4>; + reg = <4 0xbffd0400 0x90 4 0xbffd0490 0x70>; + }; + + USB1: usb@bffd0000 { + compatible = "ohci-le"; + reg = <4 0xbffd0000 0x60>; + interrupt-parent = <&UIC2>; + interrupts = <0x1e 4>; + }; + + USBOTG0: usbotg@bff80000 { + compatible = "amcc,dwc-otg"; + reg = <0x4 0xbff80000 0x10000>; + interrupt-parent = <&USBOTG0>; + #interrupt-cells = <1>; + #address-cells = <0>; + #size-cells = <0>; + interrupts = <0x0 0x1 0x2>; + interrupt-map = ; + }; + + AHBDMA: dma@bffd0800 { + compatible = "snps,dma-spear1340"; + reg = <4 0xbffd0800 0x400>; + interrupt-parent = <&UIC3>; + interrupts = <0x5 0x4>; + #dma-cells = <3>; + }; + + SATA0: sata@bffd1000 { + compatible = "amcc,sata-460ex"; + reg = <4 0xbffd1000 0x800>; + interrupt-parent = <&UIC3>; + interrupts = <0x0 0x4>; + dmas = <&AHBDMA 0 1 0>; + dma-names = "sata-dma"; + }; + + POB0: opb { + compatible = "ibm,opb-460ex", "ibm,opb"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0xb0000000 0x00000004 0xb0000000 0x50000000>; + clock-frequency = <0>; /* Filled in by U-Boot */ + + EBC0: ebc { + compatible = "ibm,ebc-460ex", "ibm,ebc"; + dcr-reg = <0x012 0x002>; + #address-cells = <2>; + #size-cells = <1>; + clock-frequency = <0>; /* Filled in by U-Boot */ + /* ranges property is supplied by U-Boot */ + interrupts = <0x6 0x4>; + interrupt-parent = <&UIC1>; + + nor_flash@0,0 { + compatible = "amd,s29gl512n", "cfi-flash"; + bank-width = <2>; + reg = <0x00000000 0x00000000 0x04000000>; + #address-cells = <1>; + #size-cells = <1>; + partition@0 { + label = "kernel"; + reg = <0x00000000 0x001e0000>; + }; + partition@1e0000 { + label = "dtb"; + reg = <0x001e0000 0x00020000>; + }; + partition@200000 { + label = "ramdisk"; + reg = <0x00200000 0x01400000>; + }; + partition@1600000 { + label = "jffs2"; + reg = <0x01600000 0x00400000>; + }; + partition@1a00000 { + label = "user"; + reg = <0x01a00000 0x02560000>; + }; + partition@3f60000 { + label = "env"; + reg = <0x03f60000 0x00040000>; + }; + partition@3fa0000 { + label = "u-boot"; + reg = <0x03fa0000 0x00060000>; + }; + }; + + cpld@2,0 { + compatible = "amcc,ppc460ex-bcsr"; + reg = <2 0x0 0x9>; + }; + + ndfc@3,0 { + compatible = "ibm,ndfc"; + reg = <0x00000003 0x00000000 0x00002000>; + ccr = <0x00001000>; + bank-settings = <0x80002222>; + #address-cells = <1>; + #size-cells = <1>; + + nand { + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "u-boot"; + reg = <0x00000000 0x00100000>; + }; + partition@100000 { + label = "user"; + reg = <0x00000000 0x03f00000>; + }; + }; + }; + }; + + UART0: serial@ef600300 { + device_type = "serial"; + compatible = "ns16550"; + reg = <0xef600300 0x00000008>; + virtual-reg = <0xef600300>; + clock-frequency = <0>; /* Filled in by U-Boot */ + current-speed = <0>; /* Filled in by U-Boot */ + interrupt-parent = <&UIC1>; + interrupts = <0x1 0x4>; + }; + + UART1: serial@ef600400 { + device_type = "serial"; + compatible = "ns16550"; + reg = <0xef600400 0x00000008>; + virtual-reg = <0xef600400>; + clock-frequency = <0>; /* Filled in by U-Boot */ + current-speed = <0>; /* Filled in by U-Boot */ + interrupt-parent = <&UIC0>; + interrupts = <0x1 0x4>; + }; + + IIC0: i2c@ef600700 { + compatible = "ibm,iic-460ex", "ibm,iic"; + reg = <0xef600700 0x00000014>; + interrupt-parent = <&UIC0>; + interrupts = <0x2 0x4>; + #address-cells = <1>; + #size-cells = <0>; + rtc@68 { + compatible = "st,m41t80"; + reg = <0x68>; + interrupt-parent = <&UIC2>; + interrupts = <0x19 0x8>; + }; + sttm@48 { + compatible = "ad,ad7414"; + reg = <0x48>; + interrupt-parent = <&UIC1>; + interrupts = <0x14 0x8>; + }; + }; + + IIC1: i2c@ef600800 { + compatible = "ibm,iic-460ex", "ibm,iic"; + reg = <0xef600800 0x00000014>; + interrupt-parent = <&UIC0>; + interrupts = <0x3 0x4>; + }; + + GPIO0: gpio@ef600b00 { + compatible = "ibm,ppc4xx-gpio"; + reg = <0xef600b00 0x00000048>; + gpio-controller; + }; + + ZMII0: emac-zmii@ef600d00 { + compatible = "ibm,zmii-460ex", "ibm,zmii"; + reg = <0xef600d00 0x0000000c>; + }; + + RGMII0: emac-rgmii@ef601500 { + compatible = "ibm,rgmii-460ex", "ibm,rgmii"; + reg = <0xef601500 0x00000008>; + has-mdio; + }; + + TAH0: emac-tah@ef601350 { + compatible = "ibm,tah-460ex", "ibm,tah"; + reg = <0xef601350 0x00000030>; + }; + + TAH1: emac-tah@ef601450 { + compatible = "ibm,tah-460ex", "ibm,tah"; + reg = <0xef601450 0x00000030>; + }; + + EMAC0: ethernet@ef600e00 { + device_type = "network"; + compatible = "ibm,emac-460ex", "ibm,emac4sync"; + interrupt-parent = <&EMAC0>; + interrupts = <0x0 0x1>; + #interrupt-cells = <1>; + #address-cells = <0>; + #size-cells = <0>; + interrupt-map = ; + reg = <0xef600e00 0x000000c4>; + local-mac-address = [000000000000]; /* Filled in by U-Boot */ + mal-device = <&MAL0>; + mal-tx-channel = <0>; + mal-rx-channel = <0>; + cell-index = <0>; + max-frame-size = <9000>; + rx-fifo-size = <4096>; + tx-fifo-size = <2048>; + rx-fifo-size-gige = <16384>; + phy-mode = "rgmii"; + phy-map = <0x00000000>; + rgmii-device = <&RGMII0>; + rgmii-channel = <0>; + tah-device = <&TAH0>; + tah-channel = <0>; + has-inverted-stacr-oc; + has-new-stacr-staopc; + }; + + EMAC1: ethernet@ef600f00 { + device_type = "network"; + compatible = "ibm,emac-460ex", "ibm,emac4sync"; + interrupt-parent = <&EMAC1>; + interrupts = <0x0 0x1>; + #interrupt-cells = <1>; + #address-cells = <0>; + #size-cells = <0>; + interrupt-map = ; + reg = <0xef600f00 0x000000c4>; + local-mac-address = [000000000000]; /* Filled in by U-Boot */ + mal-device = <&MAL0>; + mal-tx-channel = <1>; + mal-rx-channel = <8>; + cell-index = <1>; + max-frame-size = <9000>; + rx-fifo-size = <4096>; + tx-fifo-size = <2048>; + rx-fifo-size-gige = <16384>; + phy-mode = "rgmii"; + phy-map = <0x00000000>; + rgmii-device = <&RGMII0>; + rgmii-channel = <1>; + tah-device = <&TAH1>; + tah-channel = <1>; + has-inverted-stacr-oc; + has-new-stacr-staopc; + mdio-device = <&EMAC0>; + }; + }; + + PCIX0: pci@c0ec00000 { + device_type = "pci"; + #interrupt-cells = <1>; + #size-cells = <2>; + #address-cells = <3>; + compatible = "ibm,plb-pcix-460ex", "ibm,plb-pcix"; + primary; + large-inbound-windows; + enable-msi-hole; + reg = <0x0000000c 0x0ec00000 0x00000008 /* Config space access */ + 0x00000000 0x00000000 0x00000000 /* no IACK cycles */ + 0x0000000c 0x0ed00000 0x00000004 /* Special cycles */ + 0x0000000c 0x0ec80000 0x00000100 /* Internal registers */ + 0x0000000c 0x0ec80100 0x000000fc>; /* Internal messaging registers */ + + /* Outbound ranges, one memory and one IO, + * later cannot be changed + */ + ranges = <0x02000000 0x00000000 0x80000000 0x0000000d 0x80000000 0x00000000 0x80000000 + 0x02000000 0x00000000 0x00000000 0x0000000c 0x0ee00000 0x00000000 0x00100000 + 0x01000000 0x00000000 0x00000000 0x0000000c 0x08000000 0x00000000 0x00010000>; + + /* Inbound 2GB range starting at 0 */ + dma-ranges = <0x42000000 0x0 0x0 0x0 0x0 0x0 0x80000000>; + + /* This drives busses 0 to 0x3f */ + bus-range = <0x0 0x3f>; + + /* All PCI interrupts are routed to ext IRQ 2 -> UIC1-0 */ + interrupt-map-mask = <0x0 0x0 0x0 0x0>; + interrupt-map = < 0x0 0x0 0x0 0x0 &UIC1 0x0 0x8 >; + }; + + PCIE0: pciex@d00000000 { + device_type = "pci"; + #interrupt-cells = <1>; + #size-cells = <2>; + #address-cells = <3>; + compatible = "ibm,plb-pciex-460ex", "ibm,plb-pciex"; + primary; + port = <0x0>; /* port number */ + reg = <0x0000000d 0x00000000 0x20000000 /* Config space access */ + 0x0000000c 0x08010000 0x00001000>; /* Registers */ + dcr-reg = <0x100 0x020>; + sdr-base = <0x300>; + + /* Outbound ranges, one memory and one IO, + * later cannot be changed + */ + ranges = <0x02000000 0x00000000 0x80000000 0x0000000e 0x00000000 0x00000000 0x80000000 + 0x02000000 0x00000000 0x00000000 0x0000000f 0x00000000 0x00000000 0x00100000 + 0x01000000 0x00000000 0x00000000 0x0000000f 0x80000000 0x00000000 0x00010000>; + + /* Inbound 2GB range starting at 0 */ + dma-ranges = <0x42000000 0x0 0x0 0x0 0x0 0x0 0x80000000>; + + /* This drives busses 40 to 0x7f */ + bus-range = <0x40 0x7f>; + + /* Legacy interrupts (note the weird polarity, the bridge seems + * to invert PCIe legacy interrupts). + * We are de-swizzling here because the numbers are actually for + * port of the root complex virtual P2P bridge. But I want + * to avoid putting a node for it in the tree, so the numbers + * below are basically de-swizzled numbers. + * The real slot is on idsel 0, so the swizzling is 1:1 + */ + interrupt-map-mask = <0x0 0x0 0x0 0x7>; + interrupt-map = < + 0x0 0x0 0x0 0x1 &UIC3 0xc 0x4 /* swizzled int A */ + 0x0 0x0 0x0 0x2 &UIC3 0xd 0x4 /* swizzled int B */ + 0x0 0x0 0x0 0x3 &UIC3 0xe 0x4 /* swizzled int C */ + 0x0 0x0 0x0 0x4 &UIC3 0xf 0x4 /* swizzled int D */>; + }; + + PCIE1: pciex@d20000000 { + device_type = "pci"; + #interrupt-cells = <1>; + #size-cells = <2>; + #address-cells = <3>; + compatible = "ibm,plb-pciex-460ex", "ibm,plb-pciex"; + primary; + port = <0x1>; /* port number */ + reg = <0x0000000d 0x20000000 0x20000000 /* Config space access */ + 0x0000000c 0x08011000 0x00001000>; /* Registers */ + dcr-reg = <0x120 0x020>; + sdr-base = <0x340>; + + /* Outbound ranges, one memory and one IO, + * later cannot be changed + */ + ranges = <0x02000000 0x00000000 0x80000000 0x0000000e 0x80000000 0x00000000 0x80000000 + 0x02000000 0x00000000 0x00000000 0x0000000f 0x00100000 0x00000000 0x00100000 + 0x01000000 0x00000000 0x00000000 0x0000000f 0x80010000 0x00000000 0x00010000>; + + /* Inbound 2GB range starting at 0 */ + dma-ranges = <0x42000000 0x0 0x0 0x0 0x0 0x0 0x80000000>; + + /* This drives busses 80 to 0xbf */ + bus-range = <0x80 0xbf>; + + /* Legacy interrupts (note the weird polarity, the bridge seems + * to invert PCIe legacy interrupts). + * We are de-swizzling here because the numbers are actually for + * port of the root complex virtual P2P bridge. But I want + * to avoid putting a node for it in the tree, so the numbers + * below are basically de-swizzled numbers. + * The real slot is on idsel 0, so the swizzling is 1:1 + */ + interrupt-map-mask = <0x0 0x0 0x0 0x7>; + interrupt-map = < + 0x0 0x0 0x0 0x1 &UIC3 0x10 0x4 /* swizzled int A */ + 0x0 0x0 0x0 0x2 &UIC3 0x11 0x4 /* swizzled int B */ + 0x0 0x0 0x0 0x3 &UIC3 0x12 0x4 /* swizzled int C */ + 0x0 0x0 0x0 0x4 &UIC3 0x13 0x4 /* swizzled int D */>; + }; + + MSI: ppc4xx-msi@C10000000 { + compatible = "amcc,ppc4xx-msi", "ppc4xx-msi"; + reg = < 0xC 0x10000000 0x100>; + sdr-base = <0x36C>; + msi-data = <0x00000000>; + msi-mask = <0x44440000>; + interrupt-count = <3>; + interrupts = <0 1 2 3>; + interrupt-parent = <&UIC3>; + #interrupt-cells = <1>; + #address-cells = <0>; + #size-cells = <0>; + interrupt-map = <0 &UIC3 0x18 1 + 1 &UIC3 0x19 1 + 2 &UIC3 0x1A 1 + 3 &UIC3 0x1B 1>; + }; + }; +}; From 72fdd4de8e5fdc1a6078e000835fb54592a3fe97 Mon Sep 17 00:00:00 2001 From: Greg Kurz Date: Tue, 27 Feb 2018 16:22:58 +0100 Subject: [PATCH 07/30] spapr: register dummy ICPs later Some older machine types create more ICPs than needed. We hence need to register up to xics_max_server_number() dummy ICPs to accomodate the migration of these machine types. Recent VSMT rework changed xics_max_server_number() to return DIV_ROUND_UP(max_cpus * spapr->vsmt, smp_threads) instead of DIV_ROUND_UP(max_cpus * kvmppc_smt_threads(), smp_threads); The change is okay but it requires spapr->vsmt to be set, which isn't the case with the current code. This causes the formula to return zero and we don't create dummy ICPs. This breaks migration of older guests as reported here: https://bugzilla.redhat.com/show_bug.cgi?id=1549087 The dummy ICP workaround doesn't really have a dependency on XICS itself. But it does depend on proper VCPU id numbering and it must be applied before creating vCPUs (ie, creating real ICPs). So this patch moves the workaround to spapr_init_cpus(), which already assumes VSMT to be set. Fixes: 72194664c8a1 ("spapr: use spapr->vsmt to compute VCPU ids") Reported-by: Lukas Doktor Signed-off-by: Greg Kurz Signed-off-by: David Gibson --- hw/ppc/spapr.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index d6fd0e666e..3f1c5c5133 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -183,7 +183,6 @@ static int xics_max_server_number(sPAPRMachineState *spapr) static void xics_system_init(MachineState *machine, int nr_irqs, Error **errp) { sPAPRMachineState *spapr = SPAPR_MACHINE(machine); - sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(machine); if (kvm_enabled()) { if (machine_kernel_irqchip_allowed(machine) && @@ -205,17 +204,6 @@ static void xics_system_init(MachineState *machine, int nr_irqs, Error **errp) return; } } - - if (smc->pre_2_10_has_unused_icps) { - int i; - - for (i = 0; i < xics_max_server_number(spapr); i++) { - /* Dummy entries get deregistered when real ICPState objects - * are registered during CPU core hotplug. - */ - pre_2_10_vmstate_register_dummy_icp(i); - } - } } static int spapr_fixup_cpu_smt_dt(void *fdt, int offset, PowerPCCPU *cpu, @@ -2236,6 +2224,7 @@ static void spapr_init_cpus(sPAPRMachineState *spapr) { MachineState *machine = MACHINE(spapr); MachineClass *mc = MACHINE_GET_CLASS(machine); + sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(machine); const char *type = spapr_get_cpu_core_type(machine->cpu_type); const CPUArchIdList *possible_cpus; int boot_cores_nr = smp_cpus / smp_threads; @@ -2261,6 +2250,17 @@ static void spapr_init_cpus(sPAPRMachineState *spapr) boot_cores_nr = possible_cpus->len; } + if (smc->pre_2_10_has_unused_icps) { + int i; + + for (i = 0; i < xics_max_server_number(spapr); i++) { + /* Dummy entries get deregistered when real ICPState objects + * are registered during CPU core hotplug. + */ + pre_2_10_vmstate_register_dummy_icp(i); + } + } + for (i = 0; i < possible_cpus->len; i++) { int core_id = i * smp_threads; From 1a5008fc17fe3d286baa6d07b5cce122553968e7 Mon Sep 17 00:00:00 2001 From: Greg Kurz Date: Tue, 27 Feb 2018 16:23:07 +0100 Subject: [PATCH 08/30] spapr: harden code that depends on VSMT VSMT must be set in order to compute VCPU ids. This means that the following functions must not be called before spapr_set_vsmt_mode() was called: - spapr_vcpu_id() - spapr_is_thread0_in_vcore() - xics_max_server_number() We had a recent regression where the latter would be called before VSMT was set, and broke migration of some old machine types. This patch adds assert() in the above functions to avoid problems in the future. Also, since VSMT is really a CPU related thing, spapr_set_vsmt_mode() is now called from spapr_init_cpus(), just before the first VSMT user. Signed-off-by: Greg Kurz Signed-off-by: David Gibson --- hw/ppc/spapr.c | 144 +++++++++++++++++++++++++------------------------ 1 file changed, 75 insertions(+), 69 deletions(-) diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index 3f1c5c5133..1c2703cb6b 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -105,12 +105,14 @@ */ static int spapr_vcpu_id(sPAPRMachineState *spapr, int cpu_index) { + assert(spapr->vsmt); return (cpu_index / smp_threads) * spapr->vsmt + cpu_index % smp_threads; } static bool spapr_is_thread0_in_vcore(sPAPRMachineState *spapr, PowerPCCPU *cpu) { + assert(spapr->vsmt); return spapr_get_vcpu_id(cpu) % spapr->vsmt == 0; } @@ -177,6 +179,7 @@ static void pre_2_10_vmstate_unregister_dummy_icp(int i) static int xics_max_server_number(sPAPRMachineState *spapr) { + assert(spapr->vsmt); return DIV_ROUND_UP(max_cpus * spapr->vsmt, smp_threads); } @@ -2220,73 +2223,6 @@ static CPUArchId *spapr_find_cpu_slot(MachineState *ms, uint32_t id, int *idx) return &ms->possible_cpus->cpus[index]; } -static void spapr_init_cpus(sPAPRMachineState *spapr) -{ - MachineState *machine = MACHINE(spapr); - MachineClass *mc = MACHINE_GET_CLASS(machine); - sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(machine); - const char *type = spapr_get_cpu_core_type(machine->cpu_type); - const CPUArchIdList *possible_cpus; - int boot_cores_nr = smp_cpus / smp_threads; - int i; - - possible_cpus = mc->possible_cpu_arch_ids(machine); - if (mc->has_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); - } - } else { - if (max_cpus != smp_cpus) { - error_report("This machine version does not support CPU hotplug"); - exit(1); - } - boot_cores_nr = possible_cpus->len; - } - - if (smc->pre_2_10_has_unused_icps) { - int i; - - for (i = 0; i < xics_max_server_number(spapr); i++) { - /* Dummy entries get deregistered when real ICPState objects - * are registered during CPU core hotplug. - */ - pre_2_10_vmstate_register_dummy_icp(i); - } - } - - for (i = 0; i < possible_cpus->len; i++) { - int core_id = i * smp_threads; - - if (mc->has_hotpluggable_cpus) { - spapr_dr_connector_new(OBJECT(spapr), TYPE_SPAPR_DRC_CPU, - spapr_vcpu_id(spapr, core_id)); - } - - if (i < boot_cores_nr) { - Object *core = object_new(type); - int nr_threads = smp_threads; - - /* Handle the partially filled core for older machine types */ - if ((i + 1) * smp_threads >= smp_cpus) { - nr_threads = smp_cpus - i * smp_threads; - } - - object_property_set_int(core, nr_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); - } - } -} - static void spapr_set_vsmt_mode(sPAPRMachineState *spapr, Error **errp) { Error *local_err = NULL; @@ -2359,6 +2295,78 @@ out: error_propagate(errp, local_err); } +static void spapr_init_cpus(sPAPRMachineState *spapr) +{ + MachineState *machine = MACHINE(spapr); + MachineClass *mc = MACHINE_GET_CLASS(machine); + sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(machine); + const char *type = spapr_get_cpu_core_type(machine->cpu_type); + const CPUArchIdList *possible_cpus; + int boot_cores_nr = smp_cpus / smp_threads; + int i; + + possible_cpus = mc->possible_cpu_arch_ids(machine); + if (mc->has_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); + } + } else { + if (max_cpus != smp_cpus) { + error_report("This machine version does not support CPU hotplug"); + exit(1); + } + boot_cores_nr = possible_cpus->len; + } + + /* VSMT must be set in order to be able to compute VCPU ids, ie to + * call xics_max_server_number() or spapr_vcpu_id(). + */ + spapr_set_vsmt_mode(spapr, &error_fatal); + + if (smc->pre_2_10_has_unused_icps) { + int i; + + for (i = 0; i < xics_max_server_number(spapr); i++) { + /* Dummy entries get deregistered when real ICPState objects + * are registered during CPU core hotplug. + */ + pre_2_10_vmstate_register_dummy_icp(i); + } + } + + for (i = 0; i < possible_cpus->len; i++) { + int core_id = i * smp_threads; + + if (mc->has_hotpluggable_cpus) { + spapr_dr_connector_new(OBJECT(spapr), TYPE_SPAPR_DRC_CPU, + spapr_vcpu_id(spapr, core_id)); + } + + if (i < boot_cores_nr) { + Object *core = object_new(type); + int nr_threads = smp_threads; + + /* Handle the partially filled core for older machine types */ + if ((i + 1) * smp_threads >= smp_cpus) { + nr_threads = smp_cpus - i * smp_threads; + } + + object_property_set_int(core, nr_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); + } + } +} + /* pSeries LPAR / sPAPR hardware init */ static void spapr_machine_init(MachineState *machine) { @@ -2486,8 +2494,6 @@ static void spapr_machine_init(MachineState *machine) } /* init CPUs */ - spapr_set_vsmt_mode(spapr, &error_fatal); - spapr_init_cpus(spapr); if (kvm_enabled()) { From a504b9b91a1a884ce7e5296f4692b9cac85beab5 Mon Sep 17 00:00:00 2001 From: Mark Cave-Ayland Date: Wed, 28 Feb 2018 20:32:32 +0000 Subject: [PATCH 09/30] macio: embed DBDMA device directly within macio The current recommendation is to embed subdevices directly within their container device, so do this for the DBDMA device. Signed-off-by: Mark Cave-Ayland Signed-off-by: David Gibson --- hw/misc/macio/macio.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/hw/misc/macio/macio.c b/hw/misc/macio/macio.c index 024f8557ab..7174135c8b 100644 --- a/hw/misc/macio/macio.c +++ b/hw/misc/macio/macio.c @@ -42,7 +42,7 @@ typedef struct MacIOState MemoryRegion bar; CUDAState cuda; - DBDMAState *dbdma; + DBDMAState dbdma; MemoryRegion *pic_mem; MemoryRegion *escc_mem; uint64_t frequency; @@ -129,12 +129,12 @@ static void macio_common_realize(PCIDevice *d, Error **errp) SysBusDevice *sysbus_dev; Error *err = NULL; - object_property_set_bool(OBJECT(s->dbdma), true, "realized", &err); + object_property_set_bool(OBJECT(&s->dbdma), true, "realized", &err); if (err) { error_propagate(errp, err); return; } - sysbus_dev = SYS_BUS_DEVICE(s->dbdma); + sysbus_dev = SYS_BUS_DEVICE(&s->dbdma); memory_region_add_subregion(&s->bar, 0x08000, sysbus_mmio_get_region(sysbus_dev, 0)); @@ -161,7 +161,7 @@ static void macio_realize_ide(MacIOState *s, MACIOIDEState *ide, sysbus_connect_irq(sysbus_dev, 0, irq0); sysbus_connect_irq(sysbus_dev, 1, irq1); qdev_prop_set_uint32(DEVICE(ide), "channel", dmaid); - object_property_set_link(OBJECT(ide), OBJECT(s->dbdma), "dbdma", errp); + object_property_set_link(OBJECT(ide), OBJECT(&s->dbdma), "dbdma", errp); macio_ide_register_dma(ide); object_property_set_bool(OBJECT(ide), true, "realized", errp); @@ -344,8 +344,9 @@ static void macio_instance_init(Object *obj) qdev_set_parent_bus(DEVICE(&s->cuda), sysbus_get_default()); object_property_add_child(obj, "cuda", OBJECT(&s->cuda), NULL); - s->dbdma = MAC_DBDMA(object_new(TYPE_MAC_DBDMA)); - object_property_add_child(obj, "dbdma", OBJECT(s->dbdma), NULL); + object_initialize(&s->dbdma, sizeof(s->dbdma), TYPE_MAC_DBDMA); + qdev_set_parent_bus(DEVICE(&s->dbdma), sysbus_get_default()); + object_property_add_child(obj, "dbdma", OBJECT(&s->dbdma), NULL); } static const VMStateDescription vmstate_macio_oldworld = { From 343bd85a40811f0522063e58d565c6965bd81e00 Mon Sep 17 00:00:00 2001 From: Mark Cave-Ayland Date: Wed, 28 Feb 2018 20:32:33 +0000 Subject: [PATCH 10/30] macio: move ESCC device within the macio device MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Now that the ESCC device is instantiated directly via qdev, move it to within the macio device and wire up the IRQs and memory regions using the sysbus API. This enables to remove the now-obsolete escc_mem parameter to the macio_init() function. (Note this patch also contains small touch-ups to the formatting in macio_escc_legacy_setup() and ppc_heathrow_init() in order to keep checkpatch happy) Signed-off-by: Mark Cave-Ayland Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: David Gibson --- hw/misc/macio/macio.c | 60 +++++++++++++++++++++++++++++++------------ hw/ppc/mac.h | 3 +-- hw/ppc/mac_newworld.c | 37 +++++++------------------- hw/ppc/mac_oldworld.c | 38 ++++++++------------------- 4 files changed, 63 insertions(+), 75 deletions(-) diff --git a/hw/misc/macio/macio.c b/hw/misc/macio/macio.c index 7174135c8b..1c10d8a1d7 100644 --- a/hw/misc/macio/macio.c +++ b/hw/misc/macio/macio.c @@ -43,8 +43,8 @@ typedef struct MacIOState MemoryRegion bar; CUDAState cuda; DBDMAState dbdma; + ESCCState escc; MemoryRegion *pic_mem; - MemoryRegion *escc_mem; uint64_t frequency; } MacIOState; @@ -56,7 +56,7 @@ typedef struct OldWorldMacIOState { MacIOState parent_obj; /*< public >*/ - qemu_irq irqs[5]; + qemu_irq irqs[7]; MacIONVRAMState nvram; MACIOIDEState ide[2]; @@ -69,7 +69,7 @@ typedef struct NewWorldMacIOState { /*< private >*/ MacIOState parent_obj; /*< public >*/ - qemu_irq irqs[5]; + qemu_irq irqs[7]; MACIOIDEState ide[2]; } NewWorldMacIOState; @@ -84,10 +84,12 @@ typedef struct NewWorldMacIOState { * * Reference: ftp://ftp.software.ibm.com/rs6000/technology/spec/chrp/inwork/CHRP_IORef_1.0.pdf */ -static void macio_escc_legacy_setup(MacIOState *macio_state) +static void macio_escc_legacy_setup(MacIOState *s) { + ESCCState *escc = ESCC(&s->escc); + SysBusDevice *sbd = SYS_BUS_DEVICE(escc); MemoryRegion *escc_legacy = g_new(MemoryRegion, 1); - MemoryRegion *bar = &macio_state->bar; + MemoryRegion *bar = &s->bar; int i; static const int maps[] = { 0x00, 0x00, /* Command B */ @@ -102,25 +104,26 @@ static void macio_escc_legacy_setup(MacIOState *macio_state) 0xb0, 0xb0, /* Detect AB */ }; - memory_region_init(escc_legacy, OBJECT(macio_state), "escc-legacy", 256); + memory_region_init(escc_legacy, OBJECT(s), "escc-legacy", 256); for (i = 0; i < ARRAY_SIZE(maps); i += 2) { MemoryRegion *port = g_new(MemoryRegion, 1); - memory_region_init_alias(port, OBJECT(macio_state), "escc-legacy-port", - macio_state->escc_mem, maps[i+1], 0x2); + memory_region_init_alias(port, OBJECT(s), "escc-legacy-port", + sysbus_mmio_get_region(sbd, 0), + maps[i + 1], 0x2); memory_region_add_subregion(escc_legacy, maps[i], port); } memory_region_add_subregion(bar, 0x12000, escc_legacy); } -static void macio_bar_setup(MacIOState *macio_state) +static void macio_bar_setup(MacIOState *s) { - MemoryRegion *bar = &macio_state->bar; + ESCCState *escc = ESCC(&s->escc); + SysBusDevice *sbd = SYS_BUS_DEVICE(escc); + MemoryRegion *bar = &s->bar; - if (macio_state->escc_mem) { - memory_region_add_subregion(bar, 0x13000, macio_state->escc_mem); - macio_escc_legacy_setup(macio_state); - } + memory_region_add_subregion(bar, 0x13000, sysbus_mmio_get_region(sbd, 0)); + macio_escc_legacy_setup(s); } static void macio_common_realize(PCIDevice *d, Error **errp) @@ -147,6 +150,12 @@ static void macio_common_realize(PCIDevice *d, Error **errp) memory_region_add_subregion(&s->bar, 0x16000, sysbus_mmio_get_region(sysbus_dev, 0)); + object_property_set_bool(OBJECT(&s->escc), true, "realized", &err); + if (err) { + error_propagate(errp, err); + return; + } + macio_bar_setup(s); pci_register_bar(d, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->bar); } @@ -185,6 +194,10 @@ static void macio_oldworld_realize(PCIDevice *d, Error **errp) sysbus_dev = SYS_BUS_DEVICE(&s->cuda); sysbus_connect_irq(sysbus_dev, 0, os->irqs[cur_irq++]); + sysbus_dev = SYS_BUS_DEVICE(&s->escc); + sysbus_connect_irq(sysbus_dev, 0, os->irqs[cur_irq++]); + sysbus_connect_irq(sysbus_dev, 1, os->irqs[cur_irq++]); + object_property_set_bool(OBJECT(&os->nvram), true, "realized", &err); if (err) { error_propagate(errp, err); @@ -297,6 +310,10 @@ static void macio_newworld_realize(PCIDevice *d, Error **errp) sysbus_dev = SYS_BUS_DEVICE(&s->cuda); sysbus_connect_irq(sysbus_dev, 0, ns->irqs[cur_irq++]); + sysbus_dev = SYS_BUS_DEVICE(&s->escc); + sysbus_connect_irq(sysbus_dev, 0, ns->irqs[cur_irq++]); + sysbus_connect_irq(sysbus_dev, 1, ns->irqs[cur_irq++]); + if (s->pic_mem) { /* OpenPIC */ memory_region_add_subregion(&s->bar, 0x40000, s->pic_mem); @@ -347,6 +364,17 @@ static void macio_instance_init(Object *obj) object_initialize(&s->dbdma, sizeof(s->dbdma), TYPE_MAC_DBDMA); qdev_set_parent_bus(DEVICE(&s->dbdma), sysbus_get_default()); object_property_add_child(obj, "dbdma", OBJECT(&s->dbdma), NULL); + + object_initialize(&s->escc, sizeof(s->escc), TYPE_ESCC); + qdev_prop_set_uint32(DEVICE(&s->escc), "disabled", 0); + qdev_prop_set_uint32(DEVICE(&s->escc), "frequency", ESCC_CLOCK); + qdev_prop_set_uint32(DEVICE(&s->escc), "it_shift", 4); + qdev_prop_set_chr(DEVICE(&s->escc), "chrA", serial_hds[0]); + qdev_prop_set_chr(DEVICE(&s->escc), "chrB", serial_hds[1]); + qdev_prop_set_uint32(DEVICE(&s->escc), "chnBtype", escc_serial); + qdev_prop_set_uint32(DEVICE(&s->escc), "chnAtype", escc_serial); + qdev_set_parent_bus(DEVICE(&s->escc), sysbus_get_default()); + object_property_add_child(obj, "escc", OBJECT(&s->escc), NULL); } static const VMStateDescription vmstate_macio_oldworld = { @@ -444,13 +472,11 @@ static void macio_register_types(void) type_init(macio_register_types) void macio_init(PCIDevice *d, - MemoryRegion *pic_mem, - MemoryRegion *escc_mem) + MemoryRegion *pic_mem) { MacIOState *macio_state = MACIO(d); macio_state->pic_mem = pic_mem; - macio_state->escc_mem = escc_mem; /* Note: this code is strongly inspirated from the corresponding code in PearPC */ qdev_prop_set_uint64(DEVICE(&macio_state->cuda), "timebase-frequency", diff --git a/hw/ppc/mac.h b/hw/ppc/mac.h index 4702194f3f..261b519aa5 100644 --- a/hw/ppc/mac.h +++ b/hw/ppc/mac.h @@ -76,8 +76,7 @@ void macio_ide_init_drives(MACIOIDEState *ide, DriveInfo **hd_table); void macio_ide_register_dma(MACIOIDEState *ide); void macio_init(PCIDevice *dev, - MemoryRegion *pic_mem, - MemoryRegion *escc_mem); + MemoryRegion *pic_mem); /* Heathrow PIC */ qemu_irq *heathrow_pic_init(MemoryRegion **pmem, diff --git a/hw/ppc/mac_newworld.c b/hw/ppc/mac_newworld.c index 4e1298ee50..5e82158759 100644 --- a/hw/ppc/mac_newworld.c +++ b/hw/ppc/mac_newworld.c @@ -159,8 +159,7 @@ static void ppc_core99_init(MachineState *machine) MacIONVRAMState *nvr; int bios_size, ndrv_size; uint8_t *ndrv_file; - MemoryRegion *pic_mem, *escc_mem; - MemoryRegion *escc_bar = g_new(MemoryRegion, 1); + MemoryRegion *pic_mem; int ppc_boot_device; DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS]; void *fw_cfg; @@ -368,36 +367,18 @@ static void ppc_core99_init(MachineState *machine) tbfreq = TBFREQ; } - /* init basic PC hardware */ - - dev = qdev_create(NULL, TYPE_ESCC); - qdev_prop_set_uint32(dev, "disabled", 0); - qdev_prop_set_uint32(dev, "frequency", ESCC_CLOCK); - qdev_prop_set_uint32(dev, "it_shift", 4); - qdev_prop_set_chr(dev, "chrA", serial_hds[0]); - qdev_prop_set_chr(dev, "chrB", serial_hds[1]); - qdev_prop_set_uint32(dev, "chnAtype", escc_serial); - qdev_prop_set_uint32(dev, "chnBtype", escc_serial); - qdev_init_nofail(dev); - - s = SYS_BUS_DEVICE(dev); - sysbus_connect_irq(s, 0, pic[0x24]); - sysbus_connect_irq(s, 1, pic[0x25]); - - escc_mem = &ESCC(s)->mmio; - - memory_region_init_alias(escc_bar, NULL, "escc-bar", - escc_mem, 0, memory_region_size(escc_mem)); - + /* MacIO */ macio = pci_create(pci_bus, -1, TYPE_NEWWORLD_MACIO); dev = DEVICE(macio); qdev_connect_gpio_out(dev, 0, pic[0x19]); /* CUDA */ - qdev_connect_gpio_out(dev, 1, pic[0x0d]); /* IDE */ - qdev_connect_gpio_out(dev, 2, pic[0x02]); /* IDE DMA */ - qdev_connect_gpio_out(dev, 3, pic[0x0e]); /* IDE */ - qdev_connect_gpio_out(dev, 4, pic[0x03]); /* IDE DMA */ + qdev_connect_gpio_out(dev, 1, pic[0x24]); /* ESCC-B */ + qdev_connect_gpio_out(dev, 2, pic[0x25]); /* ESCC-A */ + qdev_connect_gpio_out(dev, 3, pic[0x0d]); /* IDE */ + qdev_connect_gpio_out(dev, 4, pic[0x02]); /* IDE DMA */ + qdev_connect_gpio_out(dev, 5, pic[0x0e]); /* IDE */ + qdev_connect_gpio_out(dev, 6, pic[0x03]); /* IDE DMA */ qdev_prop_set_uint64(dev, "frequency", tbfreq); - macio_init(macio, pic_mem, escc_bar); + macio_init(macio, pic_mem); /* We only emulate 2 out of 3 IDE controllers for now */ ide_drive_get(hd, ARRAY_SIZE(hd)); diff --git a/hw/ppc/mac_oldworld.c b/hw/ppc/mac_oldworld.c index d0d21d2392..4401ce5af2 100644 --- a/hw/ppc/mac_oldworld.c +++ b/hw/ppc/mac_oldworld.c @@ -99,12 +99,10 @@ static void ppc_heathrow_init(MachineState *machine) int bios_size, ndrv_size; uint8_t *ndrv_file; MemoryRegion *pic_mem; - MemoryRegion *escc_mem, *escc_bar = g_new(MemoryRegion, 1); uint16_t ppc_boot_device; DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS]; void *fw_cfg; uint64_t tbfreq; - SysBusDevice *s; linux_boot = (kernel_filename != NULL); @@ -265,40 +263,24 @@ static void ppc_heathrow_init(MachineState *machine) get_system_io()); pci_vga_init(pci_bus); - dev = qdev_create(NULL, TYPE_ESCC); - qdev_prop_set_uint32(dev, "disabled", 0); - qdev_prop_set_uint32(dev, "frequency", ESCC_CLOCK); - qdev_prop_set_uint32(dev, "it_shift", 4); - qdev_prop_set_chr(dev, "chrA", serial_hds[0]); - qdev_prop_set_chr(dev, "chrB", serial_hds[1]); - qdev_prop_set_uint32(dev, "chnBtype", escc_serial); - qdev_prop_set_uint32(dev, "chnAtype", escc_serial); - qdev_init_nofail(dev); - - s = SYS_BUS_DEVICE(dev); - sysbus_connect_irq(s, 0, pic[0x10]); - sysbus_connect_irq(s, 1, pic[0x0f]); - - escc_mem = &ESCC(s)->mmio; - - memory_region_init_alias(escc_bar, NULL, "escc-bar", - escc_mem, 0, memory_region_size(escc_mem)); - - for(i = 0; i < nb_nics; i++) + for (i = 0; i < nb_nics; i++) { pci_nic_init_nofail(&nd_table[i], pci_bus, "ne2k_pci", NULL); - + } ide_drive_get(hd, ARRAY_SIZE(hd)); + /* MacIO */ macio = pci_create(pci_bus, -1, TYPE_OLDWORLD_MACIO); dev = DEVICE(macio); qdev_connect_gpio_out(dev, 0, pic[0x12]); /* CUDA */ - qdev_connect_gpio_out(dev, 1, pic[0x0D]); /* IDE-0 */ - qdev_connect_gpio_out(dev, 2, pic[0x02]); /* IDE-0 DMA */ - qdev_connect_gpio_out(dev, 3, pic[0x0E]); /* IDE-1 */ - qdev_connect_gpio_out(dev, 4, pic[0x03]); /* IDE-1 DMA */ + qdev_connect_gpio_out(dev, 1, pic[0x10]); /* ESCC-B */ + qdev_connect_gpio_out(dev, 2, pic[0x0F]); /* ESCC-A */ + qdev_connect_gpio_out(dev, 3, pic[0x0D]); /* IDE-0 */ + qdev_connect_gpio_out(dev, 4, pic[0x02]); /* IDE-0 DMA */ + qdev_connect_gpio_out(dev, 5, pic[0x0E]); /* IDE-1 */ + qdev_connect_gpio_out(dev, 6, pic[0x03]); /* IDE-1 DMA */ qdev_prop_set_uint64(dev, "frequency", tbfreq); - macio_init(macio, pic_mem, escc_bar); + macio_init(macio, pic_mem); macio_ide = MACIO_IDE(object_resolve_path_component(OBJECT(macio), "ide[0]")); From 086df4f30a8f33e7b696c79b6f5cd2c94afbf98f Mon Sep 17 00:00:00 2001 From: Mark Cave-Ayland Date: Wed, 28 Feb 2018 20:32:34 +0000 Subject: [PATCH 11/30] heathrow: QOMify heathrow PIC Signed-off-by: Mark Cave-Ayland Signed-off-by: David Gibson --- hw/intc/heathrow_pic.c | 128 ++++++++++++++++++--------------- include/hw/intc/heathrow_pic.h | 49 +++++++++++++ 2 files changed, 120 insertions(+), 57 deletions(-) create mode 100644 include/hw/intc/heathrow_pic.h diff --git a/hw/intc/heathrow_pic.c b/hw/intc/heathrow_pic.c index 171f5ed814..7bf44e0d86 100644 --- a/hw/intc/heathrow_pic.c +++ b/hw/intc/heathrow_pic.c @@ -25,6 +25,7 @@ #include "qemu/osdep.h" #include "hw/hw.h" #include "hw/ppc/mac.h" +#include "hw/intc/heathrow_pic.h" /* debug PIC */ //#define DEBUG_PIC @@ -36,39 +37,27 @@ #define PIC_DPRINTF(fmt, ...) #endif -typedef struct HeathrowPIC { - uint32_t events; - uint32_t mask; - uint32_t levels; - uint32_t level_triggered; -} HeathrowPIC; - -typedef struct HeathrowPICS { - MemoryRegion mem; - HeathrowPIC pics[2]; - qemu_irq *irqs; -} HeathrowPICS; - -static inline int check_irq(HeathrowPIC *pic) +static inline int heathrow_check_irq(HeathrowPICState *pic) { return (pic->events | (pic->levels & pic->level_triggered)) & pic->mask; } /* update the CPU irq state */ -static void heathrow_pic_update(HeathrowPICS *s) +static void heathrow_update_irq(HeathrowState *s) { - if (check_irq(&s->pics[0]) || check_irq(&s->pics[1])) { + if (heathrow_check_irq(&s->pics[0]) || + heathrow_check_irq(&s->pics[1])) { qemu_irq_raise(s->irqs[0]); } else { qemu_irq_lower(s->irqs[0]); } } -static void pic_write(void *opaque, hwaddr addr, - uint64_t value, unsigned size) +static void heathrow_write(void *opaque, hwaddr addr, + uint64_t value, unsigned size) { - HeathrowPICS *s = opaque; - HeathrowPIC *pic; + HeathrowState *s = opaque; + HeathrowPICState *pic; unsigned int n; n = ((addr & 0xfff) - 0x10) >> 4; @@ -79,24 +68,24 @@ static void pic_write(void *opaque, hwaddr addr, switch(addr & 0xf) { case 0x04: pic->mask = value; - heathrow_pic_update(s); + heathrow_update_irq(s); break; case 0x08: /* do not reset level triggered IRQs */ value &= ~pic->level_triggered; pic->events &= ~value; - heathrow_pic_update(s); + heathrow_update_irq(s); break; default: break; } } -static uint64_t pic_read(void *opaque, hwaddr addr, - unsigned size) +static uint64_t heathrow_read(void *opaque, hwaddr addr, + unsigned size) { - HeathrowPICS *s = opaque; - HeathrowPIC *pic; + HeathrowState *s = opaque; + HeathrowPICState *pic; unsigned int n; uint32_t value; @@ -124,16 +113,16 @@ static uint64_t pic_read(void *opaque, hwaddr addr, return value; } -static const MemoryRegionOps heathrow_pic_ops = { - .read = pic_read, - .write = pic_write, +static const MemoryRegionOps heathrow_ops = { + .read = heathrow_read, + .write = heathrow_write, .endianness = DEVICE_LITTLE_ENDIAN, }; -static void heathrow_pic_set_irq(void *opaque, int num, int level) +static void heathrow_set_irq(void *opaque, int num, int level) { - HeathrowPICS *s = opaque; - HeathrowPIC *pic; + HeathrowState *s = opaque; + HeathrowPICState *pic; unsigned int irq_bit; #if defined(DEBUG) @@ -153,7 +142,7 @@ static void heathrow_pic_set_irq(void *opaque, int num, int level) } else { pic->levels &= ~irq_bit; } - heathrow_pic_update(s); + heathrow_update_irq(s); } static const VMStateDescription vmstate_heathrow_pic_one = { @@ -161,54 +150,79 @@ static const VMStateDescription vmstate_heathrow_pic_one = { .version_id = 0, .minimum_version_id = 0, .fields = (VMStateField[]) { - VMSTATE_UINT32(events, HeathrowPIC), - VMSTATE_UINT32(mask, HeathrowPIC), - VMSTATE_UINT32(levels, HeathrowPIC), - VMSTATE_UINT32(level_triggered, HeathrowPIC), + VMSTATE_UINT32(events, HeathrowPICState), + VMSTATE_UINT32(mask, HeathrowPICState), + VMSTATE_UINT32(levels, HeathrowPICState), + VMSTATE_UINT32(level_triggered, HeathrowPICState), VMSTATE_END_OF_LIST() } }; -static const VMStateDescription vmstate_heathrow_pic = { +static const VMStateDescription vmstate_heathrow = { .name = "heathrow_pic", .version_id = 1, .minimum_version_id = 1, .fields = (VMStateField[]) { - VMSTATE_STRUCT_ARRAY(pics, HeathrowPICS, 2, 1, - vmstate_heathrow_pic_one, HeathrowPIC), + VMSTATE_STRUCT_ARRAY(pics, HeathrowState, 2, 1, + vmstate_heathrow_pic_one, HeathrowPICState), VMSTATE_END_OF_LIST() } }; -static void heathrow_pic_reset_one(HeathrowPIC *s) +static void heathrow_reset(DeviceState *d) { - memset(s, '\0', sizeof(HeathrowPIC)); -} - -static void heathrow_pic_reset(void *opaque) -{ - HeathrowPICS *s = opaque; - - heathrow_pic_reset_one(&s->pics[0]); - heathrow_pic_reset_one(&s->pics[1]); + HeathrowState *s = HEATHROW(d); s->pics[0].level_triggered = 0; s->pics[1].level_triggered = 0x1ff00000; } +static void heathrow_init(Object *obj) +{ + HeathrowState *s = HEATHROW(obj); + + memory_region_init_io(&s->mem, OBJECT(s), &heathrow_ops, s, + "heathrow-pic", 0x1000); +} + qemu_irq *heathrow_pic_init(MemoryRegion **pmem, int nb_cpus, qemu_irq **irqs) { - HeathrowPICS *s; + DeviceState *d; + HeathrowState *s; - s = g_malloc0(sizeof(HeathrowPICS)); + d = qdev_create(NULL, TYPE_HEATHROW); + qdev_init_nofail(d); + + s = HEATHROW(d); /* only 1 CPU */ s->irqs = irqs[0]; - memory_region_init_io(&s->mem, NULL, &heathrow_pic_ops, s, - "heathrow-pic", 0x1000); + *pmem = &s->mem; - vmstate_register(NULL, -1, &vmstate_heathrow_pic, s); - qemu_register_reset(heathrow_pic_reset, s); - return qemu_allocate_irqs(heathrow_pic_set_irq, s, 64); + return qemu_allocate_irqs(heathrow_set_irq, s, HEATHROW_NUM_IRQS); } + +static void heathrow_class_init(ObjectClass *oc, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(oc); + + dc->reset = heathrow_reset; + dc->vmsd = &vmstate_heathrow; + set_bit(DEVICE_CATEGORY_MISC, dc->categories); +} + +static const TypeInfo heathrow_type_info = { + .name = TYPE_HEATHROW, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(HeathrowState), + .instance_init = heathrow_init, + .class_init = heathrow_class_init, +}; + +static void heathrow_register_types(void) +{ + type_register_static(&heathrow_type_info); +} + +type_init(heathrow_register_types) diff --git a/include/hw/intc/heathrow_pic.h b/include/hw/intc/heathrow_pic.h new file mode 100644 index 0000000000..bc3ffaab87 --- /dev/null +++ b/include/hw/intc/heathrow_pic.h @@ -0,0 +1,49 @@ +/* + * Heathrow PIC support (OldWorld PowerMac) + * + * Copyright (c) 2005-2007 Fabrice Bellard + * Copyright (c) 2007 Jocelyn Mayer + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef HEATHROW_H +#define HEATHROW_H + +#define TYPE_HEATHROW "heathrow" +#define HEATHROW(obj) OBJECT_CHECK(HeathrowState, (obj), TYPE_HEATHROW) + +typedef struct HeathrowPICState { + uint32_t events; + uint32_t mask; + uint32_t levels; + uint32_t level_triggered; +} HeathrowPICState; + +typedef struct HeathrowState { + SysBusDevice parent_obj; + + MemoryRegion mem; + HeathrowPICState pics[2]; + qemu_irq *irqs; +} HeathrowState; + +#define HEATHROW_NUM_IRQS 64 + +#endif /* HEATHROW_H */ From ec7c2709d7f2ac04070ae7f10146f9ab733092c4 Mon Sep 17 00:00:00 2001 From: Mark Cave-Ayland Date: Wed, 28 Feb 2018 20:32:35 +0000 Subject: [PATCH 12/30] heathrow: convert to trace-events Signed-off-by: Mark Cave-Ayland Signed-off-by: David Gibson --- hw/intc/heathrow_pic.c | 32 +++++++++++--------------------- hw/intc/trace-events | 5 +++++ 2 files changed, 16 insertions(+), 21 deletions(-) diff --git a/hw/intc/heathrow_pic.c b/hw/intc/heathrow_pic.c index 7bf44e0d86..5fd2b33a12 100644 --- a/hw/intc/heathrow_pic.c +++ b/hw/intc/heathrow_pic.c @@ -26,16 +26,7 @@ #include "hw/hw.h" #include "hw/ppc/mac.h" #include "hw/intc/heathrow_pic.h" - -/* debug PIC */ -//#define DEBUG_PIC - -#ifdef DEBUG_PIC -#define PIC_DPRINTF(fmt, ...) \ - do { printf("PIC: " fmt , ## __VA_ARGS__); } while (0) -#else -#define PIC_DPRINTF(fmt, ...) -#endif +#include "trace.h" static inline int heathrow_check_irq(HeathrowPICState *pic) { @@ -61,7 +52,7 @@ static void heathrow_write(void *opaque, hwaddr addr, unsigned int n; n = ((addr & 0xfff) - 0x10) >> 4; - PIC_DPRINTF("writel: " TARGET_FMT_plx " %u: %08x\n", addr, n, value); + trace_heathrow_write(addr, n, value); if (n >= 2) return; pic = &s->pics[n]; @@ -109,7 +100,7 @@ static uint64_t heathrow_read(void *opaque, hwaddr addr, break; } } - PIC_DPRINTF("readl: " TARGET_FMT_plx " %u: %08x\n", addr, n, value); + trace_heathrow_read(addr, n, value); return value; } @@ -124,24 +115,23 @@ static void heathrow_set_irq(void *opaque, int num, int level) HeathrowState *s = opaque; HeathrowPICState *pic; unsigned int irq_bit; + int last_level; -#if defined(DEBUG) - { - static int last_level[64]; - if (last_level[num] != level) { - PIC_DPRINTF("set_irq: num=0x%02x level=%d\n", num, level); - last_level[num] = level; - } - } -#endif pic = &s->pics[1 - (num >> 5)]; irq_bit = 1 << (num & 0x1f); + last_level = (pic->levels & irq_bit) ? 1 : 0; + if (level) { pic->events |= irq_bit & ~pic->level_triggered; pic->levels |= irq_bit; } else { pic->levels &= ~irq_bit; } + + if (last_level != level) { + trace_heathrow_set_irq(num, level); + } + heathrow_update_irq(s); } diff --git a/hw/intc/trace-events b/hw/intc/trace-events index 4092d2825e..55e8c2570c 100644 --- a/hw/intc/trace-events +++ b/hw/intc/trace-events @@ -186,3 +186,8 @@ nvic_complete_irq(int irq, bool secure) "NVIC complete IRQ %d (secure %d)" nvic_set_irq_level(int irq, int level) "NVIC external irq %d level set to %d" nvic_sysreg_read(uint64_t addr, uint32_t value, unsigned size) "NVIC sysreg read addr 0x%" PRIx64 " data 0x%" PRIx32 " size %u" nvic_sysreg_write(uint64_t addr, uint32_t value, unsigned size) "NVIC sysreg write addr 0x%" PRIx64 " data 0x%" PRIx32 " size %u" + +# hw/intc/heathrow_pic.c +heathrow_write(uint64_t addr, unsigned int n, uint64_t value) "0x%"PRIx64" %u: 0x%"PRIx64 +heathrow_read(uint64_t addr, unsigned int n, uint64_t value) "0x%"PRIx64" %u: 0x%"PRIx64 +heathrow_set_irq(int num, int level) "set_irq: num=0x%02x level=%d" From c29646009a6a5428cf13600281f7d51eba9e8458 Mon Sep 17 00:00:00 2001 From: Mark Cave-Ayland Date: Wed, 28 Feb 2018 20:32:36 +0000 Subject: [PATCH 13/30] heathrow: change heathrow_pic_init() to return the heathrow device This enables the device to be made available during the setup of the Old World machine. In order to pass back the previous set of IRQs we temporarily introduce a new pic_irqs parameter until it can be removed. An additional benefit of this change is that it is also possible to remove the pic_mem pointer used for macio by accessing the memory region via sysbus. Signed-off-by: Mark Cave-Ayland Reviewed-by: David Gibson Signed-off-by: David Gibson --- hw/intc/heathrow_pic.c | 10 ++++++---- hw/ppc/mac.h | 4 ++-- hw/ppc/mac_oldworld.c | 9 +++++---- 3 files changed, 13 insertions(+), 10 deletions(-) diff --git a/hw/intc/heathrow_pic.c b/hw/intc/heathrow_pic.c index 5fd2b33a12..393fdd7326 100644 --- a/hw/intc/heathrow_pic.c +++ b/hw/intc/heathrow_pic.c @@ -170,13 +170,15 @@ static void heathrow_reset(DeviceState *d) static void heathrow_init(Object *obj) { HeathrowState *s = HEATHROW(obj); + SysBusDevice *sbd = SYS_BUS_DEVICE(obj); memory_region_init_io(&s->mem, OBJECT(s), &heathrow_ops, s, "heathrow-pic", 0x1000); + sysbus_init_mmio(sbd, &s->mem); } -qemu_irq *heathrow_pic_init(MemoryRegion **pmem, - int nb_cpus, qemu_irq **irqs) +DeviceState *heathrow_pic_init(int nb_cpus, qemu_irq **irqs, + qemu_irq **pic_irqs) { DeviceState *d; HeathrowState *s; @@ -188,9 +190,9 @@ qemu_irq *heathrow_pic_init(MemoryRegion **pmem, /* only 1 CPU */ s->irqs = irqs[0]; - *pmem = &s->mem; + *pic_irqs = qemu_allocate_irqs(heathrow_set_irq, s, HEATHROW_NUM_IRQS); - return qemu_allocate_irqs(heathrow_set_irq, s, HEATHROW_NUM_IRQS); + return d; } static void heathrow_class_init(ObjectClass *oc, void *data) diff --git a/hw/ppc/mac.h b/hw/ppc/mac.h index 261b519aa5..5b5fffdff3 100644 --- a/hw/ppc/mac.h +++ b/hw/ppc/mac.h @@ -79,8 +79,8 @@ void macio_init(PCIDevice *dev, MemoryRegion *pic_mem); /* Heathrow PIC */ -qemu_irq *heathrow_pic_init(MemoryRegion **pmem, - int nb_cpus, qemu_irq **irqs); +DeviceState *heathrow_pic_init(int nb_cpus, qemu_irq **irqs, + qemu_irq **pic_irqs); /* Grackle PCI */ #define TYPE_GRACKLE_PCI_HOST_BRIDGE "grackle-pcihost" diff --git a/hw/ppc/mac_oldworld.c b/hw/ppc/mac_oldworld.c index 4401ce5af2..06a61220cb 100644 --- a/hw/ppc/mac_oldworld.c +++ b/hw/ppc/mac_oldworld.c @@ -94,11 +94,11 @@ static void ppc_heathrow_init(MachineState *machine) PCIBus *pci_bus; PCIDevice *macio; MACIOIDEState *macio_ide; - DeviceState *dev; + DeviceState *dev, *pic_dev; + SysBusDevice *sbd; BusState *adb_bus; int bios_size, ndrv_size; uint8_t *ndrv_file; - MemoryRegion *pic_mem; uint16_t ppc_boot_device; DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS]; void *fw_cfg; @@ -257,7 +257,7 @@ static void ppc_heathrow_init(MachineState *machine) error_report("Only 6xx bus is supported on heathrow machine"); exit(1); } - pic = heathrow_pic_init(&pic_mem, 1, heathrow_irqs); + pic_dev = heathrow_pic_init(1, heathrow_irqs, &pic); pci_bus = pci_grackle_init(0xfec00000, pic, get_system_memory(), get_system_io()); @@ -280,7 +280,8 @@ static void ppc_heathrow_init(MachineState *machine) qdev_connect_gpio_out(dev, 5, pic[0x0E]); /* IDE-1 */ qdev_connect_gpio_out(dev, 6, pic[0x03]); /* IDE-1 DMA */ qdev_prop_set_uint64(dev, "frequency", tbfreq); - macio_init(macio, pic_mem); + sbd = SYS_BUS_DEVICE(pic_dev); + macio_init(macio, sysbus_mmio_get_region(sbd, 0)); macio_ide = MACIO_IDE(object_resolve_path_component(OBJECT(macio), "ide[0]")); From e1218e48128164d0971322f4577eb3ad5f2a17f5 Mon Sep 17 00:00:00 2001 From: Mark Cave-Ayland Date: Wed, 28 Feb 2018 20:32:37 +0000 Subject: [PATCH 14/30] macio: move macio related structures and defines into separate macio.h file MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Mark Cave-Ayland Reviewed-by: David Gibson Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: David Gibson --- hw/misc/macio/macio.c | 43 +------------------- hw/ppc/mac.h | 3 -- hw/ppc/mac_newworld.c | 1 + hw/ppc/mac_oldworld.c | 1 + include/hw/misc/macio/macio.h | 75 +++++++++++++++++++++++++++++++++++ 5 files changed, 78 insertions(+), 45 deletions(-) create mode 100644 include/hw/misc/macio/macio.h diff --git a/hw/misc/macio/macio.c b/hw/misc/macio/macio.c index 1c10d8a1d7..4e502ede2e 100644 --- a/hw/misc/macio/macio.c +++ b/hw/misc/macio/macio.c @@ -30,48 +30,7 @@ #include "hw/pci/pci.h" #include "hw/ppc/mac_dbdma.h" #include "hw/char/escc.h" - -#define TYPE_MACIO "macio" -#define MACIO(obj) OBJECT_CHECK(MacIOState, (obj), TYPE_MACIO) - -typedef struct MacIOState -{ - /*< private >*/ - PCIDevice parent; - /*< public >*/ - - MemoryRegion bar; - CUDAState cuda; - DBDMAState dbdma; - ESCCState escc; - MemoryRegion *pic_mem; - uint64_t frequency; -} MacIOState; - -#define OLDWORLD_MACIO(obj) \ - OBJECT_CHECK(OldWorldMacIOState, (obj), TYPE_OLDWORLD_MACIO) - -typedef struct OldWorldMacIOState { - /*< private >*/ - MacIOState parent_obj; - /*< public >*/ - - qemu_irq irqs[7]; - - MacIONVRAMState nvram; - MACIOIDEState ide[2]; -} OldWorldMacIOState; - -#define NEWWORLD_MACIO(obj) \ - OBJECT_CHECK(NewWorldMacIOState, (obj), TYPE_NEWWORLD_MACIO) - -typedef struct NewWorldMacIOState { - /*< private >*/ - MacIOState parent_obj; - /*< public >*/ - qemu_irq irqs[7]; - MACIOIDEState ide[2]; -} NewWorldMacIOState; +#include "hw/misc/macio/macio.h" /* * The mac-io has two interfaces to the ESCC. One is called "escc-legacy", diff --git a/hw/ppc/mac.h b/hw/ppc/mac.h index 5b5fffdff3..a02f797598 100644 --- a/hw/ppc/mac.h +++ b/hw/ppc/mac.h @@ -47,9 +47,6 @@ /* MacIO */ -#define TYPE_OLDWORLD_MACIO "macio-oldworld" -#define TYPE_NEWWORLD_MACIO "macio-newworld" - #define TYPE_MACIO_IDE "macio-ide" #define MACIO_IDE(obj) OBJECT_CHECK(MACIOIDEState, (obj), TYPE_MACIO_IDE) diff --git a/hw/ppc/mac_newworld.c b/hw/ppc/mac_newworld.c index 5e82158759..396216954e 100644 --- a/hw/ppc/mac_newworld.c +++ b/hw/ppc/mac_newworld.c @@ -60,6 +60,7 @@ #include "hw/boards.h" #include "hw/nvram/fw_cfg.h" #include "hw/char/escc.h" +#include "hw/misc/macio/macio.h" #include "hw/ppc/openpic.h" #include "hw/ide.h" #include "hw/loader.h" diff --git a/hw/ppc/mac_oldworld.c b/hw/ppc/mac_oldworld.c index 06a61220cb..5903ff47d3 100644 --- a/hw/ppc/mac_oldworld.c +++ b/hw/ppc/mac_oldworld.c @@ -37,6 +37,7 @@ #include "hw/boards.h" #include "hw/nvram/fw_cfg.h" #include "hw/char/escc.h" +#include "hw/misc/macio/macio.h" #include "hw/ide.h" #include "hw/loader.h" #include "elf.h" diff --git a/include/hw/misc/macio/macio.h b/include/hw/misc/macio/macio.h new file mode 100644 index 0000000000..e1e249f898 --- /dev/null +++ b/include/hw/misc/macio/macio.h @@ -0,0 +1,75 @@ +/* + * PowerMac MacIO device emulation + * + * Copyright (c) 2005-2007 Fabrice Bellard + * Copyright (c) 2007 Jocelyn Mayer + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef MACIO_H +#define MACIO_H + +#include "hw/misc/macio/cuda.h" +#include "hw/ppc/mac_dbdma.h" + +#define TYPE_MACIO "macio" +#define MACIO(obj) OBJECT_CHECK(MacIOState, (obj), TYPE_MACIO) + +typedef struct MacIOState { + /*< private >*/ + PCIDevice parent; + /*< public >*/ + + MemoryRegion bar; + CUDAState cuda; + DBDMAState dbdma; + ESCCState escc; + MemoryRegion *pic_mem; + uint64_t frequency; +} MacIOState; + +#define TYPE_OLDWORLD_MACIO "macio-oldworld" +#define OLDWORLD_MACIO(obj) \ + OBJECT_CHECK(OldWorldMacIOState, (obj), TYPE_OLDWORLD_MACIO) + +typedef struct OldWorldMacIOState { + /*< private >*/ + MacIOState parent_obj; + /*< public >*/ + + qemu_irq irqs[7]; + + MacIONVRAMState nvram; + MACIOIDEState ide[2]; +} OldWorldMacIOState; + +#define TYPE_NEWWORLD_MACIO "macio-newworld" +#define NEWWORLD_MACIO(obj) \ + OBJECT_CHECK(NewWorldMacIOState, (obj), TYPE_NEWWORLD_MACIO) + +typedef struct NewWorldMacIOState { + /*< private >*/ + MacIOState parent_obj; + /*< public >*/ + qemu_irq irqs[7]; + MACIOIDEState ide[2]; +} NewWorldMacIOState; + +#endif /* MACIO_H */ From 017812df5d97e587a6eef03ec5a9e94a471439f9 Mon Sep 17 00:00:00 2001 From: Mark Cave-Ayland Date: Wed, 28 Feb 2018 20:32:38 +0000 Subject: [PATCH 15/30] mac_oldworld: use object link to pass heathrow PIC object to macio Also switch macio_oldworld_realize() over to use it rather than using the pic_mem memory region directly. Signed-off-by: Mark Cave-Ayland Reviewed-by: David Gibson Signed-off-by: David Gibson --- hw/misc/macio/macio.c | 14 ++++++++++---- hw/ppc/mac_oldworld.c | 8 +++++--- include/hw/misc/macio/macio.h | 2 ++ 3 files changed, 17 insertions(+), 7 deletions(-) diff --git a/hw/misc/macio/macio.c b/hw/misc/macio/macio.c index 4e502ede2e..d4c1d190c4 100644 --- a/hw/misc/macio/macio.c +++ b/hw/misc/macio/macio.c @@ -31,6 +31,7 @@ #include "hw/ppc/mac_dbdma.h" #include "hw/char/escc.h" #include "hw/misc/macio/macio.h" +#include "hw/intc/heathrow_pic.h" /* * The mac-io has two interfaces to the ESCC. One is called "escc-legacy", @@ -167,10 +168,10 @@ static void macio_oldworld_realize(PCIDevice *d, Error **errp) sysbus_mmio_get_region(sysbus_dev, 0)); pmac_format_nvram_partition(&os->nvram, os->nvram.size); - if (s->pic_mem) { - /* Heathrow PIC */ - memory_region_add_subregion(&s->bar, 0x00000, s->pic_mem); - } + /* Heathrow PIC */ + sysbus_dev = SYS_BUS_DEVICE(os->pic); + memory_region_add_subregion(&s->bar, 0x0, + sysbus_mmio_get_region(sysbus_dev, 0)); /* IDE buses */ for (i = 0; i < ARRAY_SIZE(os->ide); i++) { @@ -208,6 +209,11 @@ static void macio_oldworld_init(Object *obj) qdev_init_gpio_out(DEVICE(obj), os->irqs, ARRAY_SIZE(os->irqs)); + object_property_add_link(obj, "pic", TYPE_HEATHROW, + (Object **) &os->pic, + qdev_prop_allow_set_link_before_realize, + 0, NULL); + object_initialize(&os->nvram, sizeof(os->nvram), TYPE_MACIO_NVRAM); dev = DEVICE(&os->nvram); qdev_prop_set_uint32(dev, "size", 0x2000); diff --git a/hw/ppc/mac_oldworld.c b/hw/ppc/mac_oldworld.c index 5903ff47d3..3ac5b19073 100644 --- a/hw/ppc/mac_oldworld.c +++ b/hw/ppc/mac_oldworld.c @@ -93,7 +93,7 @@ static void ppc_heathrow_init(MachineState *machine) uint32_t kernel_base, initrd_base, cmdline_base = 0; int32_t kernel_size, initrd_size; PCIBus *pci_bus; - PCIDevice *macio; + OldWorldMacIOState *macio; MACIOIDEState *macio_ide; DeviceState *dev, *pic_dev; SysBusDevice *sbd; @@ -271,7 +271,7 @@ static void ppc_heathrow_init(MachineState *machine) ide_drive_get(hd, ARRAY_SIZE(hd)); /* MacIO */ - macio = pci_create(pci_bus, -1, TYPE_OLDWORLD_MACIO); + macio = OLDWORLD_MACIO(pci_create(pci_bus, -1, TYPE_OLDWORLD_MACIO)); dev = DEVICE(macio); qdev_connect_gpio_out(dev, 0, pic[0x12]); /* CUDA */ qdev_connect_gpio_out(dev, 1, pic[0x10]); /* ESCC-B */ @@ -281,8 +281,10 @@ static void ppc_heathrow_init(MachineState *machine) qdev_connect_gpio_out(dev, 5, pic[0x0E]); /* IDE-1 */ qdev_connect_gpio_out(dev, 6, pic[0x03]); /* IDE-1 DMA */ qdev_prop_set_uint64(dev, "frequency", tbfreq); + object_property_set_link(OBJECT(macio), OBJECT(pic_dev), "pic", + &error_abort); sbd = SYS_BUS_DEVICE(pic_dev); - macio_init(macio, sysbus_mmio_get_region(sbd, 0)); + macio_init(PCI_DEVICE(macio), sysbus_mmio_get_region(sbd, 0)); macio_ide = MACIO_IDE(object_resolve_path_component(OBJECT(macio), "ide[0]")); diff --git a/include/hw/misc/macio/macio.h b/include/hw/misc/macio/macio.h index e1e249f898..843c114c07 100644 --- a/include/hw/misc/macio/macio.h +++ b/include/hw/misc/macio/macio.h @@ -26,6 +26,7 @@ #ifndef MACIO_H #define MACIO_H +#include "hw/intc/heathrow_pic.h" #include "hw/misc/macio/cuda.h" #include "hw/ppc/mac_dbdma.h" @@ -54,6 +55,7 @@ typedef struct OldWorldMacIOState { MacIOState parent_obj; /*< public >*/ + HeathrowState *pic; qemu_irq irqs[7]; MacIONVRAMState nvram; From 8d085cf03b4fe511089b540c10244ba53b414b57 Mon Sep 17 00:00:00 2001 From: Mark Cave-Ayland Date: Wed, 28 Feb 2018 20:32:39 +0000 Subject: [PATCH 16/30] openpic: move KVM-specific declarations into separate openpic_kvm.h file This is needed before the next patch because the target-dependent kvm stub uses the existing kvm_openpic_connect_vcpu() declaration, making it impossible to move the device-specific declarations into the same file without breaking ppc-linux-user compilation. Signed-off-by: Mark Cave-Ayland Signed-off-by: David Gibson --- hw/intc/openpic_kvm.c | 1 + hw/ppc/e500.c | 1 + include/hw/ppc/openpic.h | 3 --- include/hw/ppc/openpic_kvm.h | 7 +++++++ target/ppc/kvm-stub.c | 2 +- 5 files changed, 10 insertions(+), 4 deletions(-) create mode 100644 include/hw/ppc/openpic_kvm.h diff --git a/hw/intc/openpic_kvm.c b/hw/intc/openpic_kvm.c index fa83420254..f1a59e5a85 100644 --- a/hw/intc/openpic_kvm.c +++ b/hw/intc/openpic_kvm.c @@ -30,6 +30,7 @@ #include "exec/address-spaces.h" #include "hw/hw.h" #include "hw/ppc/openpic.h" +#include "hw/ppc/openpic_kvm.h" #include "hw/pci/msi.h" #include "hw/sysbus.h" #include "sysemu/kvm.h" diff --git a/hw/ppc/e500.c b/hw/ppc/e500.c index a40d3ec3e3..13a34f50b7 100644 --- a/hw/ppc/e500.c +++ b/hw/ppc/e500.c @@ -29,6 +29,7 @@ #include "kvm_ppc.h" #include "sysemu/device_tree.h" #include "hw/ppc/openpic.h" +#include "hw/ppc/openpic_kvm.h" #include "hw/ppc/ppc.h" #include "hw/loader.h" #include "elf.h" diff --git a/include/hw/ppc/openpic.h b/include/hw/ppc/openpic.h index e55ce546aa..693e981965 100644 --- a/include/hw/ppc/openpic.h +++ b/include/hw/ppc/openpic.h @@ -28,7 +28,4 @@ enum { #define OPENPIC_MAX_IRQ (OPENPIC_MAX_SRC + OPENPIC_MAX_IPI + \ OPENPIC_MAX_TMR) -#define TYPE_KVM_OPENPIC "kvm-openpic" -int kvm_openpic_connect_vcpu(DeviceState *d, CPUState *cs); - #endif /* OPENPIC_H */ diff --git a/include/hw/ppc/openpic_kvm.h b/include/hw/ppc/openpic_kvm.h new file mode 100644 index 0000000000..9ef4215257 --- /dev/null +++ b/include/hw/ppc/openpic_kvm.h @@ -0,0 +1,7 @@ +#ifndef OPENPIC_KVM_H +#define OPENPIC_KVM_H + +#define TYPE_KVM_OPENPIC "kvm-openpic" +int kvm_openpic_connect_vcpu(DeviceState *d, CPUState *cs); + +#endif /* OPENPIC_KVM_H */ diff --git a/target/ppc/kvm-stub.c b/target/ppc/kvm-stub.c index efeafca1df..b8aa97f2d4 100644 --- a/target/ppc/kvm-stub.c +++ b/target/ppc/kvm-stub.c @@ -12,7 +12,7 @@ #include "qemu/osdep.h" #include "qemu-common.h" #include "cpu.h" -#include "hw/ppc/openpic.h" +#include "hw/ppc/openpic_kvm.h" int kvm_openpic_connect_vcpu(DeviceState *d, CPUState *cs) { From f7bd7941d8c0478c123603fb4958bdbc25bdaf9a Mon Sep 17 00:00:00 2001 From: Mark Cave-Ayland Date: Wed, 28 Feb 2018 20:32:40 +0000 Subject: [PATCH 17/30] openpic: move OpenPIC state and related definitions to openpic.h This is to faciliate access to OpenPICState when wiring up the PIC to the macio controller. Signed-off-by: Mark Cave-Ayland Reviewed-by: David Gibson Signed-off-by: David Gibson --- hw/intc/openpic.c | 157 -------------------------------------- include/hw/ppc/openpic.h | 159 ++++++++++++++++++++++++++++++++++++++- 2 files changed, 158 insertions(+), 158 deletions(-) diff --git a/hw/intc/openpic.c b/hw/intc/openpic.c index 9159a06f07..811cee9b26 100644 --- a/hw/intc/openpic.c +++ b/hw/intc/openpic.c @@ -63,10 +63,6 @@ static int get_current_cpu(void); } \ } while (0) -#define MAX_CPU 32 -#define MAX_MSI 8 -#define VID 0x03 /* MPIC version ID */ - /* OpenPIC capability flags */ #define OPENPIC_FLAG_IDR_CRIT (1 << 0) #define OPENPIC_FLAG_ILR (2 << 0) @@ -85,35 +81,6 @@ static int get_current_cpu(void); #define OPENPIC_CPU_REG_START 0x20000 #define OPENPIC_CPU_REG_SIZE 0x100 + ((MAX_CPU - 1) * 0x1000) -/* Raven */ -#define RAVEN_MAX_CPU 2 -#define RAVEN_MAX_EXT 48 -#define RAVEN_MAX_IRQ 64 -#define RAVEN_MAX_TMR OPENPIC_MAX_TMR -#define RAVEN_MAX_IPI OPENPIC_MAX_IPI - -/* KeyLargo */ -#define KEYLARGO_MAX_CPU 4 -#define KEYLARGO_MAX_EXT 64 -#define KEYLARGO_MAX_IPI 4 -#define KEYLARGO_MAX_IRQ (64 + KEYLARGO_MAX_IPI) -#define KEYLARGO_MAX_TMR 0 -#define KEYLARGO_IPI_IRQ (KEYLARGO_MAX_EXT) /* First IPI IRQ */ -/* Timers don't exist but this makes the code happy... */ -#define KEYLARGO_TMR_IRQ (KEYLARGO_IPI_IRQ + KEYLARGO_MAX_IPI) - -/* Interrupt definitions */ -#define RAVEN_FE_IRQ (RAVEN_MAX_EXT) /* Internal functional IRQ */ -#define RAVEN_ERR_IRQ (RAVEN_MAX_EXT + 1) /* Error IRQ */ -#define RAVEN_TMR_IRQ (RAVEN_MAX_EXT + 2) /* First timer IRQ */ -#define RAVEN_IPI_IRQ (RAVEN_TMR_IRQ + RAVEN_MAX_TMR) /* First IPI IRQ */ -/* First doorbell IRQ */ -#define RAVEN_DBL_IRQ (RAVEN_IPI_IRQ + (RAVEN_MAX_CPU * RAVEN_MAX_IPI)) - -typedef struct FslMpicInfo { - int max_ext; -} FslMpicInfo; - static FslMpicInfo fsl_mpic_20 = { .max_ext = 12, }; @@ -211,55 +178,6 @@ static void openpic_cpu_write_internal(void *opaque, hwaddr addr, uint32_t val, int idx); static void openpic_reset(DeviceState *d); -typedef enum IRQType { - IRQ_TYPE_NORMAL = 0, - IRQ_TYPE_FSLINT, /* FSL internal interrupt -- level only */ - IRQ_TYPE_FSLSPECIAL, /* FSL timer/IPI interrupt, edge, no polarity */ -} IRQType; - -/* Round up to the nearest 64 IRQs so that the queue length - * won't change when moving between 32 and 64 bit hosts. - */ -#define IRQQUEUE_SIZE_BITS ((OPENPIC_MAX_IRQ + 63) & ~63) - -typedef struct IRQQueue { - unsigned long *queue; - int32_t queue_size; /* Only used for VMSTATE_BITMAP */ - int next; - int priority; -} IRQQueue; - -typedef struct IRQSource { - uint32_t ivpr; /* IRQ vector/priority register */ - uint32_t idr; /* IRQ destination register */ - uint32_t destmask; /* bitmap of CPU destinations */ - int last_cpu; - int output; /* IRQ level, e.g. OPENPIC_OUTPUT_INT */ - int pending; /* TRUE if IRQ is pending */ - IRQType type; - bool level:1; /* level-triggered */ - bool nomask:1; /* critical interrupts ignore mask on some FSL MPICs */ -} IRQSource; - -#define IVPR_MASK_SHIFT 31 -#define IVPR_MASK_MASK (1U << IVPR_MASK_SHIFT) -#define IVPR_ACTIVITY_SHIFT 30 -#define IVPR_ACTIVITY_MASK (1U << IVPR_ACTIVITY_SHIFT) -#define IVPR_MODE_SHIFT 29 -#define IVPR_MODE_MASK (1U << IVPR_MODE_SHIFT) -#define IVPR_POLARITY_SHIFT 23 -#define IVPR_POLARITY_MASK (1U << IVPR_POLARITY_SHIFT) -#define IVPR_SENSE_SHIFT 22 -#define IVPR_SENSE_MASK (1U << IVPR_SENSE_SHIFT) - -#define IVPR_PRIORITY_MASK (0xFU << 16) -#define IVPR_PRIORITY(_ivprr_) ((int)(((_ivprr_) & IVPR_PRIORITY_MASK) >> 16)) -#define IVPR_VECTOR(opp, _ivprr_) ((_ivprr_) & (opp)->vector_mask) - -/* IDR[EP/CI] are only for FSL MPIC prior to v4.0 */ -#define IDR_EP 0x80000000 /* external pin */ -#define IDR_CI 0x40000000 /* critical interrupt */ - /* Convert between openpic clock ticks and nanosecs. In the hardware the clock frequency is driven by board inputs to the PIC which the PIC would then divide by 4 or 8. For now hard code to 25MZ. @@ -275,81 +193,6 @@ static inline uint64_t ticks_to_ns(uint64_t ticks) return ticks * OPENPIC_TIMER_NS_PER_TICK; } -typedef struct OpenPICTimer { - uint32_t tccr; /* Global timer current count register */ - uint32_t tbcr; /* Global timer base count register */ - int n_IRQ; - bool qemu_timer_active; /* Is the qemu_timer is running? */ - struct QEMUTimer *qemu_timer; - struct OpenPICState *opp; /* Device timer is part of. */ - /* The QEMU_CLOCK_VIRTUAL time (in ns) corresponding to the last - current_count written or read, only defined if qemu_timer_active. */ - uint64_t origin_time; -} OpenPICTimer; - -typedef struct OpenPICMSI { - uint32_t msir; /* Shared Message Signaled Interrupt Register */ -} OpenPICMSI; - -typedef struct IRQDest { - int32_t ctpr; /* CPU current task priority */ - IRQQueue raised; - IRQQueue servicing; - qemu_irq *irqs; - - /* Count of IRQ sources asserting on non-INT outputs */ - uint32_t outputs_active[OPENPIC_OUTPUT_NB]; -} IRQDest; - -#define OPENPIC(obj) OBJECT_CHECK(OpenPICState, (obj), TYPE_OPENPIC) - -typedef struct OpenPICState { - /*< private >*/ - SysBusDevice parent_obj; - /*< public >*/ - - MemoryRegion mem; - - /* Behavior control */ - FslMpicInfo *fsl; - uint32_t model; - uint32_t flags; - uint32_t nb_irqs; - uint32_t vid; - uint32_t vir; /* Vendor identification register */ - uint32_t vector_mask; - uint32_t tfrr_reset; - uint32_t ivpr_reset; - uint32_t idr_reset; - uint32_t brr1; - uint32_t mpic_mode_mask; - - /* Sub-regions */ - MemoryRegion sub_io_mem[6]; - - /* Global registers */ - uint32_t frr; /* Feature reporting register */ - uint32_t gcr; /* Global configuration register */ - uint32_t pir; /* Processor initialization register */ - uint32_t spve; /* Spurious vector register */ - uint32_t tfrr; /* Timer frequency reporting register */ - /* Source registers */ - IRQSource src[OPENPIC_MAX_IRQ]; - /* Local registers per output pin */ - IRQDest dst[MAX_CPU]; - uint32_t nb_cpus; - /* Timer registers */ - OpenPICTimer timers[OPENPIC_MAX_TMR]; - uint32_t max_tmr; - - /* Shared MSI registers */ - OpenPICMSI msi[MAX_MSI]; - uint32_t max_irq; - uint32_t irq_ipi0; - uint32_t irq_tim0; - uint32_t irq_msi; -} OpenPICState; - static inline void IRQ_setbit(IRQQueue *q, int n_IRQ) { set_bit(n_IRQ, q->queue); diff --git a/include/hw/ppc/openpic.h b/include/hw/ppc/openpic.h index 693e981965..5eb982197d 100644 --- a/include/hw/ppc/openpic.h +++ b/include/hw/ppc/openpic.h @@ -2,10 +2,13 @@ #define OPENPIC_H #include "qemu-common.h" +#include "hw/sysbus.h" #include "hw/qdev-core.h" #include "qom/cpu.h" -#define TYPE_OPENPIC "openpic" +#define MAX_CPU 32 +#define MAX_MSI 8 +#define VID 0x03 /* MPIC version ID */ /* OpenPIC have 5 outputs per CPU connected and one IRQ out single output */ enum { @@ -28,4 +31,158 @@ enum { #define OPENPIC_MAX_IRQ (OPENPIC_MAX_SRC + OPENPIC_MAX_IPI + \ OPENPIC_MAX_TMR) +/* Raven */ +#define RAVEN_MAX_CPU 2 +#define RAVEN_MAX_EXT 48 +#define RAVEN_MAX_IRQ 64 +#define RAVEN_MAX_TMR OPENPIC_MAX_TMR +#define RAVEN_MAX_IPI OPENPIC_MAX_IPI + +/* KeyLargo */ +#define KEYLARGO_MAX_CPU 4 +#define KEYLARGO_MAX_EXT 64 +#define KEYLARGO_MAX_IPI 4 +#define KEYLARGO_MAX_IRQ (64 + KEYLARGO_MAX_IPI) +#define KEYLARGO_MAX_TMR 0 +#define KEYLARGO_IPI_IRQ (KEYLARGO_MAX_EXT) /* First IPI IRQ */ +/* Timers don't exist but this makes the code happy... */ +#define KEYLARGO_TMR_IRQ (KEYLARGO_IPI_IRQ + KEYLARGO_MAX_IPI) + +/* Interrupt definitions */ +#define RAVEN_FE_IRQ (RAVEN_MAX_EXT) /* Internal functional IRQ */ +#define RAVEN_ERR_IRQ (RAVEN_MAX_EXT + 1) /* Error IRQ */ +#define RAVEN_TMR_IRQ (RAVEN_MAX_EXT + 2) /* First timer IRQ */ +#define RAVEN_IPI_IRQ (RAVEN_TMR_IRQ + RAVEN_MAX_TMR) /* First IPI IRQ */ +/* First doorbell IRQ */ +#define RAVEN_DBL_IRQ (RAVEN_IPI_IRQ + (RAVEN_MAX_CPU * RAVEN_MAX_IPI)) + +typedef struct FslMpicInfo { + int max_ext; +} FslMpicInfo; + +typedef enum IRQType { + IRQ_TYPE_NORMAL = 0, + IRQ_TYPE_FSLINT, /* FSL internal interrupt -- level only */ + IRQ_TYPE_FSLSPECIAL, /* FSL timer/IPI interrupt, edge, no polarity */ +} IRQType; + +/* Round up to the nearest 64 IRQs so that the queue length + * won't change when moving between 32 and 64 bit hosts. + */ +#define IRQQUEUE_SIZE_BITS ((OPENPIC_MAX_IRQ + 63) & ~63) + +typedef struct IRQQueue { + unsigned long *queue; + int32_t queue_size; /* Only used for VMSTATE_BITMAP */ + int next; + int priority; +} IRQQueue; + +typedef struct IRQSource { + uint32_t ivpr; /* IRQ vector/priority register */ + uint32_t idr; /* IRQ destination register */ + uint32_t destmask; /* bitmap of CPU destinations */ + int last_cpu; + int output; /* IRQ level, e.g. OPENPIC_OUTPUT_INT */ + int pending; /* TRUE if IRQ is pending */ + IRQType type; + bool level:1; /* level-triggered */ + bool nomask:1; /* critical interrupts ignore mask on some FSL MPICs */ +} IRQSource; + +#define IVPR_MASK_SHIFT 31 +#define IVPR_MASK_MASK (1U << IVPR_MASK_SHIFT) +#define IVPR_ACTIVITY_SHIFT 30 +#define IVPR_ACTIVITY_MASK (1U << IVPR_ACTIVITY_SHIFT) +#define IVPR_MODE_SHIFT 29 +#define IVPR_MODE_MASK (1U << IVPR_MODE_SHIFT) +#define IVPR_POLARITY_SHIFT 23 +#define IVPR_POLARITY_MASK (1U << IVPR_POLARITY_SHIFT) +#define IVPR_SENSE_SHIFT 22 +#define IVPR_SENSE_MASK (1U << IVPR_SENSE_SHIFT) + +#define IVPR_PRIORITY_MASK (0xFU << 16) +#define IVPR_PRIORITY(_ivprr_) ((int)(((_ivprr_) & IVPR_PRIORITY_MASK) >> 16)) +#define IVPR_VECTOR(opp, _ivprr_) ((_ivprr_) & (opp)->vector_mask) + +/* IDR[EP/CI] are only for FSL MPIC prior to v4.0 */ +#define IDR_EP 0x80000000 /* external pin */ +#define IDR_CI 0x40000000 /* critical interrupt */ + +typedef struct OpenPICTimer { + uint32_t tccr; /* Global timer current count register */ + uint32_t tbcr; /* Global timer base count register */ + int n_IRQ; + bool qemu_timer_active; /* Is the qemu_timer is running? */ + struct QEMUTimer *qemu_timer; + struct OpenPICState *opp; /* Device timer is part of. */ + /* The QEMU_CLOCK_VIRTUAL time (in ns) corresponding to the last + current_count written or read, only defined if qemu_timer_active. */ + uint64_t origin_time; +} OpenPICTimer; + +typedef struct OpenPICMSI { + uint32_t msir; /* Shared Message Signaled Interrupt Register */ +} OpenPICMSI; + +typedef struct IRQDest { + int32_t ctpr; /* CPU current task priority */ + IRQQueue raised; + IRQQueue servicing; + qemu_irq *irqs; + + /* Count of IRQ sources asserting on non-INT outputs */ + uint32_t outputs_active[OPENPIC_OUTPUT_NB]; +} IRQDest; + +#define TYPE_OPENPIC "openpic" +#define OPENPIC(obj) OBJECT_CHECK(OpenPICState, (obj), TYPE_OPENPIC) + +typedef struct OpenPICState { + /*< private >*/ + SysBusDevice parent_obj; + /*< public >*/ + + MemoryRegion mem; + + /* Behavior control */ + FslMpicInfo *fsl; + uint32_t model; + uint32_t flags; + uint32_t nb_irqs; + uint32_t vid; + uint32_t vir; /* Vendor identification register */ + uint32_t vector_mask; + uint32_t tfrr_reset; + uint32_t ivpr_reset; + uint32_t idr_reset; + uint32_t brr1; + uint32_t mpic_mode_mask; + + /* Sub-regions */ + MemoryRegion sub_io_mem[6]; + + /* Global registers */ + uint32_t frr; /* Feature reporting register */ + uint32_t gcr; /* Global configuration register */ + uint32_t pir; /* Processor initialization register */ + uint32_t spve; /* Spurious vector register */ + uint32_t tfrr; /* Timer frequency reporting register */ + /* Source registers */ + IRQSource src[OPENPIC_MAX_IRQ]; + /* Local registers per output pin */ + IRQDest dst[MAX_CPU]; + uint32_t nb_cpus; + /* Timer registers */ + OpenPICTimer timers[OPENPIC_MAX_TMR]; + uint32_t max_tmr; + + /* Shared MSI registers */ + OpenPICMSI msi[MAX_MSI]; + uint32_t max_irq; + uint32_t irq_ipi0; + uint32_t irq_tim0; + uint32_t irq_msi; +} OpenPICState; + #endif /* OPENPIC_H */ From dda12e9a6f6ffcfac2642c11a1afb27af877e2c9 Mon Sep 17 00:00:00 2001 From: Mark Cave-Ayland Date: Wed, 28 Feb 2018 20:32:41 +0000 Subject: [PATCH 18/30] mac_newworld: use object link to pass OpenPIC object to macio Also switch macio_newworld_realize() over to use it rather than using the pic_mem memory region directly. Now that both Old World and New World macio devices no longer make use of the pic_mem memory region directly, we can remove it. Signed-off-by: Mark Cave-Ayland Reviewed-by: David Gibson Signed-off-by: David Gibson --- hw/misc/macio/macio.c | 14 +++++++++----- hw/ppc/mac_newworld.c | 20 +++++++++++--------- include/hw/misc/macio/macio.h | 4 +++- 3 files changed, 23 insertions(+), 15 deletions(-) diff --git a/hw/misc/macio/macio.c b/hw/misc/macio/macio.c index d4c1d190c4..e5288f1084 100644 --- a/hw/misc/macio/macio.c +++ b/hw/misc/macio/macio.c @@ -279,10 +279,10 @@ static void macio_newworld_realize(PCIDevice *d, Error **errp) sysbus_connect_irq(sysbus_dev, 0, ns->irqs[cur_irq++]); sysbus_connect_irq(sysbus_dev, 1, ns->irqs[cur_irq++]); - if (s->pic_mem) { - /* OpenPIC */ - memory_region_add_subregion(&s->bar, 0x40000, s->pic_mem); - } + /* OpenPIC */ + sysbus_dev = SYS_BUS_DEVICE(ns->pic); + memory_region_add_subregion(&s->bar, 0x40000, + sysbus_mmio_get_region(sysbus_dev, 0)); /* IDE buses */ for (i = 0; i < ARRAY_SIZE(ns->ide); i++) { @@ -311,6 +311,11 @@ static void macio_newworld_init(Object *obj) qdev_init_gpio_out(DEVICE(obj), ns->irqs, ARRAY_SIZE(ns->irqs)); + object_property_add_link(obj, "pic", TYPE_OPENPIC, + (Object **) &ns->pic, + qdev_prop_allow_set_link_before_realize, + 0, NULL); + for (i = 0; i < 2; i++) { macio_init_ide(s, &ns->ide[i], sizeof(ns->ide[i]), i); } @@ -441,7 +446,6 @@ void macio_init(PCIDevice *d, { MacIOState *macio_state = MACIO(d); - macio_state->pic_mem = pic_mem; /* Note: this code is strongly inspirated from the corresponding code in PearPC */ qdev_prop_set_uint64(DEVICE(&macio_state->cuda), "timebase-frequency", diff --git a/hw/ppc/mac_newworld.c b/hw/ppc/mac_newworld.c index 396216954e..c7960ab67a 100644 --- a/hw/ppc/mac_newworld.c +++ b/hw/ppc/mac_newworld.c @@ -154,7 +154,7 @@ static void ppc_core99_init(MachineState *machine) hwaddr kernel_base, initrd_base, cmdline_base = 0; long kernel_size, initrd_size; PCIBus *pci_bus; - PCIDevice *macio; + NewWorldMacIOState *macio; MACIOIDEState *macio_ide; BusState *adb_bus; MacIONVRAMState *nvr; @@ -166,7 +166,7 @@ static void ppc_core99_init(MachineState *machine) void *fw_cfg; int machine_arch; SysBusDevice *s; - DeviceState *dev; + DeviceState *dev, *pic_dev; int *token = g_new(int, 1); hwaddr nvram_addr = 0xFFF04000; uint64_t tbfreq; @@ -333,10 +333,10 @@ static void ppc_core99_init(MachineState *machine) pic = g_new0(qemu_irq, 64); - dev = qdev_create(NULL, TYPE_OPENPIC); - qdev_prop_set_uint32(dev, "model", OPENPIC_MODEL_KEYLARGO); - qdev_init_nofail(dev); - s = SYS_BUS_DEVICE(dev); + pic_dev = qdev_create(NULL, TYPE_OPENPIC); + qdev_prop_set_uint32(pic_dev, "model", OPENPIC_MODEL_KEYLARGO); + qdev_init_nofail(pic_dev); + s = SYS_BUS_DEVICE(pic_dev); pic_mem = s->mmio[0].memory; k = 0; for (i = 0; i < smp_cpus; i++) { @@ -346,7 +346,7 @@ static void ppc_core99_init(MachineState *machine) } for (i = 0; i < 64; i++) { - pic[i] = qdev_get_gpio_in(dev, i); + pic[i] = qdev_get_gpio_in(pic_dev, i); } if (PPC_INPUT(env) == PPC_FLAGS_INPUT_970) { @@ -369,7 +369,7 @@ static void ppc_core99_init(MachineState *machine) } /* MacIO */ - macio = pci_create(pci_bus, -1, TYPE_NEWWORLD_MACIO); + macio = NEWWORLD_MACIO(pci_create(pci_bus, -1, TYPE_NEWWORLD_MACIO)); dev = DEVICE(macio); qdev_connect_gpio_out(dev, 0, pic[0x19]); /* CUDA */ qdev_connect_gpio_out(dev, 1, pic[0x24]); /* ESCC-B */ @@ -379,7 +379,9 @@ static void ppc_core99_init(MachineState *machine) qdev_connect_gpio_out(dev, 5, pic[0x0e]); /* IDE */ qdev_connect_gpio_out(dev, 6, pic[0x03]); /* IDE DMA */ qdev_prop_set_uint64(dev, "frequency", tbfreq); - macio_init(macio, pic_mem); + object_property_set_link(OBJECT(macio), OBJECT(pic_dev), "pic", + &error_abort); + macio_init(PCI_DEVICE(macio), pic_mem); /* We only emulate 2 out of 3 IDE controllers for now */ ide_drive_get(hd, ARRAY_SIZE(hd)); diff --git a/include/hw/misc/macio/macio.h b/include/hw/misc/macio/macio.h index 843c114c07..4528282b36 100644 --- a/include/hw/misc/macio/macio.h +++ b/include/hw/misc/macio/macio.h @@ -29,6 +29,7 @@ #include "hw/intc/heathrow_pic.h" #include "hw/misc/macio/cuda.h" #include "hw/ppc/mac_dbdma.h" +#include "hw/ppc/openpic.h" #define TYPE_MACIO "macio" #define MACIO(obj) OBJECT_CHECK(MacIOState, (obj), TYPE_MACIO) @@ -42,7 +43,6 @@ typedef struct MacIOState { CUDAState cuda; DBDMAState dbdma; ESCCState escc; - MemoryRegion *pic_mem; uint64_t frequency; } MacIOState; @@ -70,6 +70,8 @@ typedef struct NewWorldMacIOState { /*< private >*/ MacIOState parent_obj; /*< public >*/ + + OpenPICState *pic; qemu_irq irqs[7]; MACIOIDEState ide[2]; } NewWorldMacIOState; From aa79b0860e795d879a06656a13bd8f987a36d199 Mon Sep 17 00:00:00 2001 From: Mark Cave-Ayland Date: Wed, 28 Feb 2018 20:32:42 +0000 Subject: [PATCH 19/30] macio: move setting of CUDA timebase frequency to macio_common_realize() This removes the last of the functionality from macio_init() in preparation for its subsequent removal. Signed-off-by: Mark Cave-Ayland Reviewed-by: David Gibson Signed-off-by: David Gibson --- hw/misc/macio/macio.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/hw/misc/macio/macio.c b/hw/misc/macio/macio.c index e5288f1084..f71ed61819 100644 --- a/hw/misc/macio/macio.c +++ b/hw/misc/macio/macio.c @@ -101,6 +101,8 @@ static void macio_common_realize(PCIDevice *d, Error **errp) memory_region_add_subregion(&s->bar, 0x08000, sysbus_mmio_get_region(sysbus_dev, 0)); + qdev_prop_set_uint64(DEVICE(&s->cuda), "timebase-frequency", + s->frequency); object_property_set_bool(OBJECT(&s->cuda), true, "realized", &err); if (err) { error_propagate(errp, err); @@ -444,12 +446,7 @@ type_init(macio_register_types) void macio_init(PCIDevice *d, MemoryRegion *pic_mem) { - MacIOState *macio_state = MACIO(d); - /* Note: this code is strongly inspirated from the corresponding code in PearPC */ - qdev_prop_set_uint64(DEVICE(&macio_state->cuda), "timebase-frequency", - macio_state->frequency); - qdev_init_nofail(DEVICE(d)); } From b6712ea39117c87de87b687ec4055e6ddbde9b37 Mon Sep 17 00:00:00 2001 From: Mark Cave-Ayland Date: Wed, 28 Feb 2018 20:32:43 +0000 Subject: [PATCH 20/30] macio: remove macio_init() function Move the remaining comment into macio.c for reference, then remove the macio_init() function and instantiate the macio devices for both Old World and New World machines via qdev_init_nofail() directly. Signed-off-by: Mark Cave-Ayland Signed-off-by: David Gibson --- hw/misc/macio/macio.c | 11 +++-------- hw/ppc/mac_newworld.c | 4 +--- hw/ppc/mac_oldworld.c | 4 +--- 3 files changed, 5 insertions(+), 14 deletions(-) diff --git a/hw/misc/macio/macio.c b/hw/misc/macio/macio.c index f71ed61819..af1bd46b4b 100644 --- a/hw/misc/macio/macio.c +++ b/hw/misc/macio/macio.c @@ -33,6 +33,9 @@ #include "hw/misc/macio/macio.h" #include "hw/intc/heathrow_pic.h" +/* Note: this code is strongly inspirated from the corresponding code + * in PearPC */ + /* * The mac-io has two interfaces to the ESCC. One is called "escc-legacy", * while the other one is the normal, current ESCC interface. @@ -442,11 +445,3 @@ static void macio_register_types(void) } type_init(macio_register_types) - -void macio_init(PCIDevice *d, - MemoryRegion *pic_mem) -{ - /* Note: this code is strongly inspirated from the corresponding code - in PearPC */ - qdev_init_nofail(DEVICE(d)); -} diff --git a/hw/ppc/mac_newworld.c b/hw/ppc/mac_newworld.c index c7960ab67a..a749e2565d 100644 --- a/hw/ppc/mac_newworld.c +++ b/hw/ppc/mac_newworld.c @@ -160,7 +160,6 @@ static void ppc_core99_init(MachineState *machine) MacIONVRAMState *nvr; int bios_size, ndrv_size; uint8_t *ndrv_file; - MemoryRegion *pic_mem; int ppc_boot_device; DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS]; void *fw_cfg; @@ -337,7 +336,6 @@ static void ppc_core99_init(MachineState *machine) qdev_prop_set_uint32(pic_dev, "model", OPENPIC_MODEL_KEYLARGO); qdev_init_nofail(pic_dev); s = SYS_BUS_DEVICE(pic_dev); - pic_mem = s->mmio[0].memory; k = 0; for (i = 0; i < smp_cpus; i++) { for (j = 0; j < OPENPIC_OUTPUT_NB; j++) { @@ -381,7 +379,7 @@ static void ppc_core99_init(MachineState *machine) qdev_prop_set_uint64(dev, "frequency", tbfreq); object_property_set_link(OBJECT(macio), OBJECT(pic_dev), "pic", &error_abort); - macio_init(PCI_DEVICE(macio), pic_mem); + qdev_init_nofail(dev); /* We only emulate 2 out of 3 IDE controllers for now */ ide_drive_get(hd, ARRAY_SIZE(hd)); diff --git a/hw/ppc/mac_oldworld.c b/hw/ppc/mac_oldworld.c index 3ac5b19073..935493c966 100644 --- a/hw/ppc/mac_oldworld.c +++ b/hw/ppc/mac_oldworld.c @@ -96,7 +96,6 @@ static void ppc_heathrow_init(MachineState *machine) OldWorldMacIOState *macio; MACIOIDEState *macio_ide; DeviceState *dev, *pic_dev; - SysBusDevice *sbd; BusState *adb_bus; int bios_size, ndrv_size; uint8_t *ndrv_file; @@ -283,8 +282,7 @@ static void ppc_heathrow_init(MachineState *machine) qdev_prop_set_uint64(dev, "frequency", tbfreq); object_property_set_link(OBJECT(macio), OBJECT(pic_dev), "pic", &error_abort); - sbd = SYS_BUS_DEVICE(pic_dev); - macio_init(PCI_DEVICE(macio), sysbus_mmio_get_region(sbd, 0)); + qdev_init_nofail(dev); macio_ide = MACIO_IDE(object_resolve_path_component(OBJECT(macio), "ide[0]")); From cb931c2108a59db0b4a22f0c439ee7362c4f95ab Mon Sep 17 00:00:00 2001 From: Suraj Jitindar Singh Date: Thu, 1 Mar 2018 17:37:58 +1100 Subject: [PATCH 21/30] target/ppc: Check mask when setting cap_ppc_safe_indirect_branch Check the character and character_mask field when setting cap_ppc_safe_indirect_branch based on the hypervisor response to KVM_PPC_GET_CPU_CHAR. Previously the mask field wasn't checked which was incorrect. Fixes: 8acc2ae5 (target/ppc/kvm: Add cap_ppc_safe_[cache/bounds_check/indirect_branch]) Signed-off-by: Suraj Jitindar Singh Signed-off-by: David Gibson --- target/ppc/kvm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target/ppc/kvm.c b/target/ppc/kvm.c index 9842b3bb12..2c183f61e2 100644 --- a/target/ppc/kvm.c +++ b/target/ppc/kvm.c @@ -2494,7 +2494,7 @@ static void kvmppc_get_cpu_characteristics(KVMState *s) cap_ppc_safe_bounds_check = 1; } /* Parse and set cap_ppc_safe_indirect_branch */ - if (c.character & H_CPU_CHAR_BCCTRL_SERIALISED) { + if (c.character & c.character_mask & H_CPU_CHAR_BCCTRL_SERIALISED) { cap_ppc_safe_indirect_branch = 2; } } From 87175d1bc5272fff5cffb05c410b39f839dfc948 Mon Sep 17 00:00:00 2001 From: Suraj Jitindar Singh Date: Thu, 1 Mar 2018 17:37:59 +1100 Subject: [PATCH 22/30] ppc/spapr-caps: Add support for custom spapr_capabilities There are currently 2 implemented types of spapr-caps, boolean and tristate. However there may be a need for caps which don't fit either of these options. Add a custom capability type for which a list of custom valid strings can be specified and implement the get/set functions for these. Also add a field for help text to describe the available options. Signed-off-by: Suraj Jitindar Singh [dwg: Change "help" option to "?" matching qemu conventions] [dwg: Add ATTRIBUTE_UNUSED to avoid breaking bisect] Signed-off-by: David Gibson --- hw/ppc/spapr_caps.c | 70 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) diff --git a/hw/ppc/spapr_caps.c b/hw/ppc/spapr_caps.c index 99a4b71d19..3d8b796df9 100644 --- a/hw/ppc/spapr_caps.c +++ b/hw/ppc/spapr_caps.c @@ -32,6 +32,20 @@ #include "hw/ppc/spapr.h" +typedef struct sPAPRCapPossible { + int num; /* size of vals array below */ + const char *help; /* help text for vals */ + /* + * Note: + * - because of the way compatibility is determined vals MUST be ordered + * such that later options are a superset of all preceding options. + * - the order of vals must be preserved, that is their index is important, + * however vals may be added to the end of the list so long as the above + * point is observed + */ + const char *vals[]; +} sPAPRCapPossible; + typedef struct sPAPRCapabilityInfo { const char *name; const char *description; @@ -41,6 +55,8 @@ typedef struct sPAPRCapabilityInfo { ObjectPropertyAccessor *get; ObjectPropertyAccessor *set; const char *type; + /* Possible values if this is a custom string type */ + sPAPRCapPossible *possible; /* Make sure the virtual hardware can support this capability */ void (*apply)(sPAPRMachineState *spapr, uint8_t val, Error **errp); } sPAPRCapabilityInfo; @@ -133,6 +149,60 @@ out: g_free(val); } +static void ATTRIBUTE_UNUSED spapr_cap_get_string(Object *obj, Visitor *v, + const char *name, + void *opaque, Error **errp) +{ + sPAPRCapabilityInfo *cap = opaque; + sPAPRMachineState *spapr = SPAPR_MACHINE(obj); + char *val = NULL; + uint8_t value = spapr_get_cap(spapr, cap->index); + + if (value >= cap->possible->num) { + error_setg(errp, "Invalid value (%d) for cap-%s", value, cap->name); + return; + } + + val = g_strdup(cap->possible->vals[value]); + + visit_type_str(v, name, &val, errp); + g_free(val); +} + +static void ATTRIBUTE_UNUSED spapr_cap_set_string(Object *obj, Visitor *v, + const char *name, + void *opaque, Error **errp) +{ + sPAPRCapabilityInfo *cap = opaque; + sPAPRMachineState *spapr = SPAPR_MACHINE(obj); + Error *local_err = NULL; + uint8_t i; + char *val; + + visit_type_str(v, name, &val, &local_err); + if (local_err) { + error_propagate(errp, local_err); + return; + } + + if (!strcmp(val, "?")) { + error_setg(errp, "%s", cap->possible->help); + goto out; + } + for (i = 0; i < cap->possible->num; i++) { + if (!strcasecmp(val, cap->possible->vals[i])) { + spapr->cmd_line_caps[cap->index] = true; + spapr->eff.caps[cap->index] = i; + goto out; + } + } + + error_setg(errp, "Invalid capability mode \"%s\" for cap-%s", val, + cap->name); +out: + g_free(val); +} + static void cap_htm_apply(sPAPRMachineState *spapr, uint8_t val, Error **errp) { if (!val) { From f27aa81e72b5a5e184a0f3aa3e77061f4fcfb265 Mon Sep 17 00:00:00 2001 From: Suraj Jitindar Singh Date: Thu, 1 Mar 2018 17:38:00 +1100 Subject: [PATCH 23/30] ppc/spapr-caps: Convert cap-cfpc to custom spapr-cap Convert cap-cfpc (cache flush on privilege change) to a custom spapr-cap type. Signed-off-by: Suraj Jitindar Singh [dwg: Don't explicitly list "?"/help option, trusting convention] [dwg: Strip no-longer-necessary ATTRIBUTE_UNUSED back off] [dwg: Fix some minor style problems] Signed-off-by: David Gibson --- hw/ppc/spapr_caps.c | 33 ++++++++++++++++++++++----------- 1 file changed, 22 insertions(+), 11 deletions(-) diff --git a/hw/ppc/spapr_caps.c b/hw/ppc/spapr_caps.c index 3d8b796df9..b5a991f97a 100644 --- a/hw/ppc/spapr_caps.c +++ b/hw/ppc/spapr_caps.c @@ -149,9 +149,8 @@ out: g_free(val); } -static void ATTRIBUTE_UNUSED spapr_cap_get_string(Object *obj, Visitor *v, - const char *name, - void *opaque, Error **errp) +static void spapr_cap_get_string(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) { sPAPRCapabilityInfo *cap = opaque; sPAPRMachineState *spapr = SPAPR_MACHINE(obj); @@ -169,9 +168,8 @@ static void ATTRIBUTE_UNUSED spapr_cap_get_string(Object *obj, Visitor *v, g_free(val); } -static void ATTRIBUTE_UNUSED spapr_cap_set_string(Object *obj, Visitor *v, - const char *name, - void *opaque, Error **errp) +static void spapr_cap_set_string(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) { sPAPRCapabilityInfo *cap = opaque; sPAPRMachineState *spapr = SPAPR_MACHINE(obj); @@ -250,14 +248,26 @@ static void cap_dfp_apply(sPAPRMachineState *spapr, uint8_t val, Error **errp) } } +sPAPRCapPossible cap_cfpc_possible = { + .num = 3, + .vals = {"broken", "workaround", "fixed"}, + .help = "broken - no protection, workaround - workaround available," + " fixed - fixed in hardware", +}; + static void cap_safe_cache_apply(sPAPRMachineState *spapr, uint8_t val, Error **errp) { + uint8_t kvm_val = kvmppc_get_cap_safe_cache(); + if (tcg_enabled() && val) { /* TODO - for now only allow broken for TCG */ - error_setg(errp, "Requested safe cache capability level not supported by tcg, try a different value for cap-cfpc"); - } else if (kvm_enabled() && (val > kvmppc_get_cap_safe_cache())) { - error_setg(errp, "Requested safe cache capability level not supported by kvm, try a different value for cap-cfpc"); + error_setg(errp, +"Requested safe cache capability level not supported by tcg, try a different value for cap-cfpc"); + } else if (kvm_enabled() && (val > kvm_val)) { + error_setg(errp, +"Requested safe cache capability level not supported by kvm, try cap-cfpc=%s", + cap_cfpc_possible.vals[kvm_val]); } } @@ -319,9 +329,10 @@ sPAPRCapabilityInfo capability_table[SPAPR_CAP_NUM] = { .name = "cfpc", .description = "Cache Flush on Privilege Change" VALUE_DESC_TRISTATE, .index = SPAPR_CAP_CFPC, - .get = spapr_cap_get_tristate, - .set = spapr_cap_set_tristate, + .get = spapr_cap_get_string, + .set = spapr_cap_set_string, .type = "string", + .possible = &cap_cfpc_possible, .apply = cap_safe_cache_apply, }, [SPAPR_CAP_SBBC] = { From aaf265ffde352c4100a8e2adc554ec11aa6abe08 Mon Sep 17 00:00:00 2001 From: Suraj Jitindar Singh Date: Thu, 1 Mar 2018 17:38:01 +1100 Subject: [PATCH 24/30] ppc/spapr-caps: Convert cap-sbbc to custom spapr-cap Convert cap-sbbc (speculation barrier bounds checking) to a custom spapr-cap type. Signed-off-by: Suraj Jitindar Singh [dwg: Removed trailing whitespace] [dwg: Don't explicitly list "?"/help option, trust convention] [dwg: Fix some minor style problems] Signed-off-by: David Gibson --- hw/ppc/spapr_caps.c | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/hw/ppc/spapr_caps.c b/hw/ppc/spapr_caps.c index b5a991f97a..8748692425 100644 --- a/hw/ppc/spapr_caps.c +++ b/hw/ppc/spapr_caps.c @@ -271,14 +271,26 @@ static void cap_safe_cache_apply(sPAPRMachineState *spapr, uint8_t val, } } +sPAPRCapPossible cap_sbbc_possible = { + .num = 3, + .vals = {"broken", "workaround", "fixed"}, + .help = "broken - no protection, workaround - workaround available," + " fixed - fixed in hardware", +}; + static void cap_safe_bounds_check_apply(sPAPRMachineState *spapr, uint8_t val, Error **errp) { + uint8_t kvm_val = kvmppc_get_cap_safe_bounds_check(); + if (tcg_enabled() && val) { /* TODO - for now only allow broken for TCG */ - error_setg(errp, "Requested safe bounds check capability level not supported by tcg, try a different value for cap-sbbc"); - } else if (kvm_enabled() && (val > kvmppc_get_cap_safe_bounds_check())) { - error_setg(errp, "Requested safe bounds check capability level not supported by kvm, try a different value for cap-sbbc"); + error_setg(errp, +"Requested safe bounds check capability level not supported by tcg, try a different value for cap-sbbc"); + } else if (kvm_enabled() && (val > kvm_val)) { + error_setg(errp, +"Requested safe bounds check capability level not supported by kvm, try cap-sbbc=%s", + cap_sbbc_possible.vals[kvm_val]); } } @@ -339,9 +351,10 @@ sPAPRCapabilityInfo capability_table[SPAPR_CAP_NUM] = { .name = "sbbc", .description = "Speculation Barrier Bounds Checking" VALUE_DESC_TRISTATE, .index = SPAPR_CAP_SBBC, - .get = spapr_cap_get_tristate, - .set = spapr_cap_set_tristate, + .get = spapr_cap_get_string, + .set = spapr_cap_set_string, .type = "string", + .possible = &cap_sbbc_possible, .apply = cap_safe_bounds_check_apply, }, [SPAPR_CAP_IBS] = { From c76c0d3090136773219baad486c836c67ba9ea6d Mon Sep 17 00:00:00 2001 From: Suraj Jitindar Singh Date: Thu, 1 Mar 2018 17:38:02 +1100 Subject: [PATCH 25/30] ppc/spapr-caps: Convert cap-ibs to custom spapr-cap Convert cap-ibs (indirect branch speculation) to a custom spapr-cap type. All tristate caps have now been converted to custom spapr-caps, so remove the remaining support for them. Signed-off-by: Suraj Jitindar Singh [dwg: Don't explicitly list "?"/help option, trust convention] [dwg: Fold tristate removal into here, to not break bisect] [dwg: Fix minor style problems] Signed-off-by: David Gibson --- hw/ppc/spapr_caps.c | 90 +++++++++++------------------------------- hw/ppc/spapr_hcall.c | 5 ++- include/hw/ppc/spapr.h | 5 ++- target/ppc/kvm.c | 6 ++- 4 files changed, 36 insertions(+), 70 deletions(-) diff --git a/hw/ppc/spapr_caps.c b/hw/ppc/spapr_caps.c index 8748692425..da1f519e13 100644 --- a/hw/ppc/spapr_caps.c +++ b/hw/ppc/spapr_caps.c @@ -89,65 +89,6 @@ static void spapr_cap_set_bool(Object *obj, Visitor *v, const char *name, spapr->eff.caps[cap->index] = value ? SPAPR_CAP_ON : SPAPR_CAP_OFF; } -static void spapr_cap_get_tristate(Object *obj, Visitor *v, const char *name, - void *opaque, Error **errp) -{ - sPAPRCapabilityInfo *cap = opaque; - sPAPRMachineState *spapr = SPAPR_MACHINE(obj); - char *val = NULL; - uint8_t value = spapr_get_cap(spapr, cap->index); - - switch (value) { - case SPAPR_CAP_BROKEN: - val = g_strdup("broken"); - break; - case SPAPR_CAP_WORKAROUND: - val = g_strdup("workaround"); - break; - case SPAPR_CAP_FIXED: - val = g_strdup("fixed"); - break; - default: - error_setg(errp, "Invalid value (%d) for cap-%s", value, cap->name); - return; - } - - visit_type_str(v, name, &val, errp); - g_free(val); -} - -static void spapr_cap_set_tristate(Object *obj, Visitor *v, const char *name, - void *opaque, Error **errp) -{ - sPAPRCapabilityInfo *cap = opaque; - sPAPRMachineState *spapr = SPAPR_MACHINE(obj); - char *val; - Error *local_err = NULL; - uint8_t value; - - visit_type_str(v, name, &val, &local_err); - if (local_err) { - error_propagate(errp, local_err); - return; - } - - if (!strcasecmp(val, "broken")) { - value = SPAPR_CAP_BROKEN; - } else if (!strcasecmp(val, "workaround")) { - value = SPAPR_CAP_WORKAROUND; - } else if (!strcasecmp(val, "fixed")) { - value = SPAPR_CAP_FIXED; - } else { - error_setg(errp, "Invalid capability mode \"%s\" for cap-%s", val, - cap->name); - goto out; - } - - spapr->cmd_line_caps[cap->index] = true; - spapr->eff.caps[cap->index] = value; -out: - g_free(val); -} static void spapr_cap_get_string(Object *obj, Visitor *v, const char *name, void *opaque, Error **errp) @@ -294,16 +235,31 @@ static void cap_safe_bounds_check_apply(sPAPRMachineState *spapr, uint8_t val, } } +sPAPRCapPossible cap_ibs_possible = { + .num = 4, + /* Note workaround only maintained for compatibility */ + .vals = {"broken", "workaround", "fixed-ibs", "fixed-ccd"}, + .help = "broken - no protection, fixed-ibs - indirect branch serialisation," + " fixed-ccd - cache count disabled", +}; + static void cap_safe_indirect_branch_apply(sPAPRMachineState *spapr, uint8_t val, Error **errp) { + uint8_t kvm_val = kvmppc_get_cap_safe_indirect_branch(); + if (val == SPAPR_CAP_WORKAROUND) { /* Can only be Broken or Fixed */ - error_setg(errp, "Requested safe indirect branch capability level \"workaround\" not valid, try cap-ibs=fixed"); + error_setg(errp, +"Requested safe indirect branch capability level \"workaround\" not valid, try cap-ibs=%s", + cap_ibs_possible.vals[kvm_val]); } else if (tcg_enabled() && val) { /* TODO - for now only allow broken for TCG */ - error_setg(errp, "Requested safe indirect branch capability level not supported by tcg, try a different value for cap-ibs"); - } else if (kvm_enabled() && (val > kvmppc_get_cap_safe_indirect_branch())) { - error_setg(errp, "Requested safe indirect branch capability level not supported by kvm, try a different value for cap-ibs"); + error_setg(errp, +"Requested safe indirect branch capability level not supported by tcg, try a different value for cap-ibs"); + } else if (kvm_enabled() && val && (val != kvm_val)) { + error_setg(errp, +"Requested safe indirect branch capability level not supported by kvm, try cap-ibs=%s", + cap_ibs_possible.vals[kvm_val]); } } @@ -359,11 +315,13 @@ sPAPRCapabilityInfo capability_table[SPAPR_CAP_NUM] = { }, [SPAPR_CAP_IBS] = { .name = "ibs", - .description = "Indirect Branch Serialisation (broken, fixed)", + .description = + "Indirect Branch Speculation (broken, fixed-ibs, fixed-ccd)", .index = SPAPR_CAP_IBS, - .get = spapr_cap_get_tristate, - .set = spapr_cap_set_tristate, + .get = spapr_cap_get_string, + .set = spapr_cap_set_string, .type = "string", + .possible = &cap_ibs_possible, .apply = cap_safe_indirect_branch_apply, }, }; diff --git a/hw/ppc/spapr_hcall.c b/hw/ppc/spapr_hcall.c index 1986560480..16bccdd5c0 100644 --- a/hw/ppc/spapr_hcall.c +++ b/hw/ppc/spapr_hcall.c @@ -1705,7 +1705,10 @@ static target_ulong h_get_cpu_characteristics(PowerPCCPU *cpu, } switch (safe_indirect_branch) { - case SPAPR_CAP_FIXED: + case SPAPR_CAP_FIXED_CCD: + characteristics |= H_CPU_CHAR_CACHE_COUNT_DIS; + break; + case SPAPR_CAP_FIXED_IBS: characteristics |= H_CPU_CHAR_BCCTRL_SERIALISED; break; default: /* broken */ diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h index 36942b378d..d60b7c6d7a 100644 --- a/include/hw/ppc/spapr.h +++ b/include/hw/ppc/spapr.h @@ -75,10 +75,12 @@ typedef enum { /* Bool Caps */ #define SPAPR_CAP_OFF 0x00 #define SPAPR_CAP_ON 0x01 -/* Broken | Workaround | Fixed Caps */ +/* Custom Caps */ #define SPAPR_CAP_BROKEN 0x00 #define SPAPR_CAP_WORKAROUND 0x01 #define SPAPR_CAP_FIXED 0x02 +#define SPAPR_CAP_FIXED_IBS 0x02 +#define SPAPR_CAP_FIXED_CCD 0x03 typedef struct sPAPRCapabilities sPAPRCapabilities; struct sPAPRCapabilities { @@ -313,6 +315,7 @@ struct sPAPRMachineState { #define H_CPU_CHAR_L1D_THREAD_PRIV PPC_BIT(4) #define H_CPU_CHAR_HON_BRANCH_HINTS PPC_BIT(5) #define H_CPU_CHAR_THR_RECONF_TRIG PPC_BIT(6) +#define H_CPU_CHAR_CACHE_COUNT_DIS PPC_BIT(7) #define H_CPU_BEHAV_FAVOUR_SECURITY PPC_BIT(0) #define H_CPU_BEHAV_L1D_FLUSH_PR PPC_BIT(1) #define H_CPU_BEHAV_BNDS_CHK_SPEC_BAR PPC_BIT(2) diff --git a/target/ppc/kvm.c b/target/ppc/kvm.c index 2c183f61e2..79a436a384 100644 --- a/target/ppc/kvm.c +++ b/target/ppc/kvm.c @@ -2494,8 +2494,10 @@ static void kvmppc_get_cpu_characteristics(KVMState *s) cap_ppc_safe_bounds_check = 1; } /* Parse and set cap_ppc_safe_indirect_branch */ - if (c.character & c.character_mask & H_CPU_CHAR_BCCTRL_SERIALISED) { - cap_ppc_safe_indirect_branch = 2; + if (c.character & c.character_mask & H_CPU_CHAR_CACHE_COUNT_DIS) { + cap_ppc_safe_indirect_branch = SPAPR_CAP_FIXED_CCD; + } else if (c.character & c.character_mask & H_CPU_CHAR_BCCTRL_SERIALISED) { + cap_ppc_safe_indirect_branch = SPAPR_CAP_FIXED_IBS; } } From 813f3cf655c6f3afe6e2ef04281ba7cd5ea24357 Mon Sep 17 00:00:00 2001 From: Suraj Jitindar Singh Date: Thu, 1 Mar 2018 17:38:04 +1100 Subject: [PATCH 26/30] ppc/spapr-caps: Define the pseries-2.12-sxxm machine type The sxxm (speculative execution exploit mitigation) machine type is a variant of the 2.12 machine type with workarounds for speculative execution vulnerabilities enabled by default. Signed-off-by: Suraj Jitindar Singh Signed-off-by: David Gibson --- hw/ppc/spapr.c | 17 +++++++++++++++++ hw/ppc/spapr_caps.c | 11 +++++++++++ 2 files changed, 28 insertions(+) diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index 1c2703cb6b..1b6ddd827e 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -3983,6 +3983,23 @@ static void spapr_machine_2_12_class_options(MachineClass *mc) DEFINE_SPAPR_MACHINE(2_12, "2.12", true); +static void spapr_machine_2_12_sxxm_instance_options(MachineState *machine) +{ + spapr_machine_2_12_instance_options(machine); +} + +static void spapr_machine_2_12_sxxm_class_options(MachineClass *mc) +{ + sPAPRMachineClass *smc = SPAPR_MACHINE_CLASS(mc); + + spapr_machine_2_12_class_options(mc); + smc->default_caps.caps[SPAPR_CAP_CFPC] = SPAPR_CAP_WORKAROUND; + smc->default_caps.caps[SPAPR_CAP_SBBC] = SPAPR_CAP_WORKAROUND; + smc->default_caps.caps[SPAPR_CAP_IBS] = SPAPR_CAP_FIXED_CCD; +} + +DEFINE_SPAPR_MACHINE(2_12_sxxm, "2.12-sxxm", false); + /* * pseries-2.11 */ diff --git a/hw/ppc/spapr_caps.c b/hw/ppc/spapr_caps.c index da1f519e13..531e145114 100644 --- a/hw/ppc/spapr_caps.c +++ b/hw/ppc/spapr_caps.c @@ -335,15 +335,26 @@ static sPAPRCapabilities default_caps_with_cpu(sPAPRMachineState *spapr, caps = smc->default_caps; + if (!ppc_check_compat(cpu, CPU_POWERPC_LOGICAL_3_00, + 0, spapr->max_compat_pvr)) { + caps.caps[SPAPR_CAP_CFPC] = SPAPR_CAP_BROKEN; + } + if (!ppc_check_compat(cpu, CPU_POWERPC_LOGICAL_2_07, 0, spapr->max_compat_pvr)) { caps.caps[SPAPR_CAP_HTM] = SPAPR_CAP_OFF; } + if (!ppc_check_compat(cpu, CPU_POWERPC_LOGICAL_2_06_PLUS, + 0, spapr->max_compat_pvr)) { + caps.caps[SPAPR_CAP_SBBC] = SPAPR_CAP_BROKEN; + } + if (!ppc_check_compat(cpu, CPU_POWERPC_LOGICAL_2_06, 0, spapr->max_compat_pvr)) { caps.caps[SPAPR_CAP_VSX] = SPAPR_CAP_OFF; caps.caps[SPAPR_CAP_DFP] = SPAPR_CAP_OFF; + caps.caps[SPAPR_CAP_IBS] = SPAPR_CAP_BROKEN; } return caps; From 90ee4e01a1cddcb56bd65f10dd80aad7f86b5829 Mon Sep 17 00:00:00 2001 From: Nikunj A Dadhania Date: Thu, 1 Mar 2018 11:35:50 +0530 Subject: [PATCH 27/30] hw/ppc/spapr,e500: Use new property "stdout-path" for boot console Linux kernel commit 2a9d832cc9aae21ea827520fef635b6c49a06c6d (of: Add bindings for chosen node, stdout-path) deprecated chosen property "linux,stdout-path" and "stdout". Introduce the new property "stdout-path" and continue supporting the older property to remain compatible with existing/older firmware. This older property can be deprecated after 5 years. Signed-off-by: Nikunj A Dadhania Signed-off-by: David Gibson --- hw/ppc/e500.c | 7 +++++++ hw/ppc/spapr.c | 7 +++++++ 2 files changed, 14 insertions(+) diff --git a/hw/ppc/e500.c b/hw/ppc/e500.c index 13a34f50b7..ef541a00be 100644 --- a/hw/ppc/e500.c +++ b/hw/ppc/e500.c @@ -120,7 +120,14 @@ static void dt_serial_create(void *fdt, unsigned long long offset, qemu_fdt_setprop_string(fdt, "/aliases", alias, ser); if (defcon) { + /* + * "linux,stdout-path" and "stdout" properties are deprecated by linux + * kernel. New platforms should only use the "stdout-path" property. Set + * the new property and continue using older property to remain + * compatible with the existing firmware. + */ qemu_fdt_setprop_string(fdt, "/chosen", "linux,stdout-path", ser); + qemu_fdt_setprop_string(fdt, "/chosen", "stdout-path", ser); } } diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index 1b6ddd827e..7e1c858566 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -1053,7 +1053,14 @@ static void spapr_dt_chosen(sPAPRMachineState *spapr, void *fdt) } if (!spapr->has_graphics && stdout_path) { + /* + * "linux,stdout-path" and "stdout" properties are deprecated by linux + * kernel. New platforms should only use the "stdout-path" property. Set + * the new property and continue using older property to remain + * compatible with the existing firmware. + */ _FDT(fdt_setprop_string(fdt, chosen, "linux,stdout-path", stdout_path)); + _FDT(fdt_setprop_string(fdt, chosen, "stdout-path", stdout_path)); } spapr_dt_ov5_platform_support(fdt, chosen); From 8d622594201286ddbb9e2dbf32a9e65c060ed4ed Mon Sep 17 00:00:00 2001 From: David Engraf Date: Fri, 2 Mar 2018 12:20:13 +0100 Subject: [PATCH 28/30] PPC: e500: Fix duplicate kernel load and device tree overlap This patch fixes an incorrect behavior when the -kernel argument has been specified without -bios. In this case the kernel was loaded twice. At address 32M as a raw image and afterwards by load_elf/load_uimage at the corresponding load address. In this case the region for the device tree and the raw kernel image may overlap. The patch fixes the behavior by loading the kernel image once with load_elf/load_uimage and skips loading the raw image. When here do not use bios_name/size for the kernel and use a more generic name called payload_name/size. New in v3: dtb must be stored between kernel and initrd because Linux can handle the dtb only within the first 64MB. Add a comment to clarify the behavior. Signed-off-by: David Engraf Reviewed-by: David Gibson Signed-off-by: David Gibson --- hw/ppc/e500.c | 116 ++++++++++++++++++++++++++++++-------------------- 1 file changed, 70 insertions(+), 46 deletions(-) diff --git a/hw/ppc/e500.c b/hw/ppc/e500.c index ef541a00be..43c15d18c4 100644 --- a/hw/ppc/e500.c +++ b/hw/ppc/e500.c @@ -792,8 +792,10 @@ void ppce500_init(MachineState *machine, PPCE500Params *params) int initrd_size = 0; hwaddr cur_base = 0; char *filename; + const char *payload_name; + bool kernel_as_payload; hwaddr bios_entry = 0; - target_long bios_size; + target_long payload_size; struct boot_info *boot_info; int dt_size; int i; @@ -921,11 +923,6 @@ void ppce500_init(MachineState *machine, PPCE500Params *params) /* Register spinning region */ sysbus_create_simple("e500-spin", params->spin_base, NULL); - if (cur_base < (32 * 1024 * 1024)) { - /* u-boot occupies memory up to 32MB, so load blobs above */ - cur_base = (32 * 1024 * 1024); - } - if (params->has_mpc8xxx_gpio) { qemu_irq poweroff_irq; @@ -960,8 +957,61 @@ void ppce500_init(MachineState *machine, PPCE500Params *params) sysbus_mmio_get_region(s, 0)); } - /* Load kernel. */ - if (machine->kernel_filename) { + /* + * Smart firmware defaults ahead! + * + * We follow the following table to select which payload we execute. + * + * -kernel | -bios | payload + * ---------+-------+--------- + * N | Y | u-boot + * N | N | u-boot + * Y | Y | u-boot + * Y | N | kernel + * + * This ensures backwards compatibility with how we used to expose + * -kernel to users but allows them to run through u-boot as well. + */ + kernel_as_payload = false; + if (bios_name == NULL) { + if (machine->kernel_filename) { + payload_name = machine->kernel_filename; + kernel_as_payload = true; + } else { + payload_name = "u-boot.e500"; + } + } else { + payload_name = bios_name; + } + + filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, payload_name); + + payload_size = load_elf(filename, NULL, NULL, &bios_entry, &loadaddr, NULL, + 1, PPC_ELF_MACHINE, 0, 0); + if (payload_size < 0) { + /* + * Hrm. No ELF image? Try a uImage, maybe someone is giving us an + * ePAPR compliant kernel + */ + payload_size = load_uimage(filename, &bios_entry, &loadaddr, NULL, + NULL, NULL); + if (payload_size < 0) { + error_report("qemu: could not load firmware '%s'", filename); + exit(1); + } + } + + g_free(filename); + + if (kernel_as_payload) { + kernel_base = loadaddr; + kernel_size = payload_size; + } + + cur_base = loadaddr + payload_size; + + /* Load bare kernel only if no bios/u-boot has been provided */ + if (machine->kernel_filename && !kernel_as_payload) { kernel_base = cur_base; kernel_size = load_image_targphys(machine->kernel_filename, cur_base, @@ -975,6 +1025,11 @@ void ppce500_init(MachineState *machine, PPCE500Params *params) cur_base += kernel_size; } + if (cur_base < (32 * 1024 * 1024)) { + /* u-boot occupies memory up to 32MB, so load blobs above */ + cur_base = (32 * 1024 * 1024); + } + /* Load initrd. */ if (machine->initrd_filename) { initrd_base = (cur_base + INITRD_LOAD_PAD) & ~INITRD_PAD_MASK; @@ -991,47 +1046,16 @@ void ppce500_init(MachineState *machine, PPCE500Params *params) } /* - * Smart firmware defaults ahead! - * - * We follow the following table to select which payload we execute. - * - * -kernel | -bios | payload - * ---------+-------+--------- - * N | Y | u-boot - * N | N | u-boot - * Y | Y | u-boot - * Y | N | kernel - * - * This ensures backwards compatibility with how we used to expose - * -kernel to users but allows them to run through u-boot as well. + * Reserve space for dtb behind the kernel image because Linux has a bug + * where it can only handle the dtb if it's within the first 64MB of where + * starts. dtb cannot not reach initrd_base because INITRD_LOAD_PAD + * ensures enough space between kernel and initrd. */ - if (bios_name == NULL) { - if (machine->kernel_filename) { - bios_name = machine->kernel_filename; - } else { - bios_name = "u-boot.e500"; - } - } - filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); - - bios_size = load_elf(filename, NULL, NULL, &bios_entry, &loadaddr, NULL, - 1, PPC_ELF_MACHINE, 0, 0); - if (bios_size < 0) { - /* - * Hrm. No ELF image? Try a uImage, maybe someone is giving us an - * ePAPR compliant kernel - */ - kernel_size = load_uimage(filename, &bios_entry, &loadaddr, NULL, - NULL, NULL); - if (kernel_size < 0) { - error_report("could not load firmware '%s'", filename); + dt_base = (loadaddr + payload_size + DTC_LOAD_PAD) & ~DTC_PAD_MASK; + if (dt_base + DTB_MAX_SIZE > ram_size) { + error_report("qemu: not enough memory for device tree"); exit(1); - } } - g_free(filename); - - /* Reserve space for dtb */ - dt_base = (loadaddr + bios_size + DTC_LOAD_PAD) & ~DTC_PAD_MASK; dt_size = ppce500_prep_device_tree(machine, params, dt_base, initrd_base, initrd_size, From 9d9769c2082bc0bdb88d0f138c5aae562b0c1826 Mon Sep 17 00:00:00 2001 From: Mark Cave-Ayland Date: Mon, 5 Mar 2018 21:51:13 +0000 Subject: [PATCH 29/30] adb: add trace-events for monitoring keyboard/mouse during bus enumeration This is useful to help diagnose problems related to address clashes during MacOS 9 boot. Signed-off-by: Mark Cave-Ayland Signed-off-by: David Gibson --- hw/input/adb-kbd.c | 4 ++++ hw/input/adb-mouse.c | 5 +++++ hw/input/trace-events | 5 +++++ 3 files changed, 14 insertions(+) diff --git a/hw/input/adb-kbd.c b/hw/input/adb-kbd.c index 266aed1b7b..50b62712c8 100644 --- a/hw/input/adb-kbd.c +++ b/hw/input/adb-kbd.c @@ -258,6 +258,7 @@ static int adb_kbd_request(ADBDevice *d, uint8_t *obuf, case ADB_CMD_CHANGE_ID_AND_ACT: case ADB_CMD_CHANGE_ID_AND_ENABLE: d->devaddr = buf[1] & 0xf; + trace_adb_kbd_request_change_addr(d->devaddr); break; default: d->devaddr = buf[1] & 0xf; @@ -269,6 +270,9 @@ static int adb_kbd_request(ADBDevice *d, uint8_t *obuf, if (buf[2] == 1 || buf[2] == 2 || buf[2] == 3) { d->handler = buf[2]; } + + trace_adb_kbd_request_change_addr_and_handler(d->devaddr, + d->handler); break; } } diff --git a/hw/input/adb-mouse.c b/hw/input/adb-mouse.c index 47e88faf25..3ba6027d33 100644 --- a/hw/input/adb-mouse.c +++ b/hw/input/adb-mouse.c @@ -118,6 +118,7 @@ static int adb_mouse_request(ADBDevice *d, uint8_t *obuf, s->dx = 0; s->dy = 0; s->dz = 0; + trace_adb_mouse_flush(); return 0; } @@ -138,6 +139,7 @@ static int adb_mouse_request(ADBDevice *d, uint8_t *obuf, case ADB_CMD_CHANGE_ID_AND_ACT: case ADB_CMD_CHANGE_ID_AND_ENABLE: d->devaddr = buf[1] & 0xf; + trace_adb_mouse_request_change_addr(d->devaddr); break; default: d->devaddr = buf[1] & 0xf; @@ -155,6 +157,9 @@ static int adb_mouse_request(ADBDevice *d, uint8_t *obuf, if (buf[2] == 1 || buf[2] == 2) { d->handler = buf[2]; } + + trace_adb_mouse_request_change_addr_and_handler(d->devaddr, + d->handler); break; } } diff --git a/hw/input/trace-events b/hw/input/trace-events index 5affabc81d..db72484a25 100644 --- a/hw/input/trace-events +++ b/hw/input/trace-events @@ -4,10 +4,15 @@ adb_kbd_no_key(void) "Ignoring NO_KEY" adb_kbd_writereg(int reg, uint8_t val) "reg %d val 0x%2.2x" adb_kbd_readreg(int reg, uint8_t val0, uint8_t val1) "reg %d obuf[0] 0x%2.2x obuf[1] 0x%2.2x" +adb_kbd_request_change_addr(int devaddr) "change addr to 0x%x" +adb_kbd_request_change_addr_and_handler(int devaddr, int handler) "change addr and handler to 0x%x, 0x%x" # hw/input/adb-mouse.c +adb_mouse_flush(void) "flush" adb_mouse_writereg(int reg, uint8_t val) "reg %d val 0x%2.2x" adb_mouse_readreg(int reg, uint8_t val0, uint8_t val1) "reg %d obuf[0] 0x%2.2x obuf[1] 0x%2.2x" +adb_mouse_request_change_addr(int devaddr) "change addr to 0x%x" +adb_mouse_request_change_addr_and_handler(int devaddr, int handler) "change addr and handler to 0x%x, 0x%x" # hw/input/ps2.c ps2_put_keycode(void *opaque, int keycode) "%p keycode 0x%02x" From 21b786f607b11d888f90bbb8c3414500515d11e7 Mon Sep 17 00:00:00 2001 From: Simon Guo Date: Mon, 5 Mar 2018 18:53:48 +0800 Subject: [PATCH 30/30] PowerPC: Add TS bits into msr_mask During migration, after MSR bits is synced, cpu_post_load() will use msr_mask to determine which PPC MSR bits will be applied into the target side. Hardware Transaction Memory(HTM) has been supported since Power8, but TS0/TS1 bit was not in msr_mask yet. That will prevent target KVM from loading TM checkpointed values. This patch adds TS bits into msr_mask for Power8, so that transactional application can be migrated across qemu. Signed-off-by: Simon Guo Signed-off-by: David Gibson --- target/ppc/translate_init.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/target/ppc/translate_init.c b/target/ppc/translate_init.c index 17a87df654..391b94b97d 100644 --- a/target/ppc/translate_init.c +++ b/target/ppc/translate_init.c @@ -8692,6 +8692,8 @@ POWERPC_FAMILY(POWER8)(ObjectClass *oc, void *data) (1ull << MSR_DR) | (1ull << MSR_PMM) | (1ull << MSR_RI) | + (1ull << MSR_TS0) | + (1ull << MSR_TS1) | (1ull << MSR_LE); pcc->mmu_model = POWERPC_MMU_2_07; #if defined(CONFIG_SOFTMMU)