From 231903bf27c18ba6d4d905601eab368f324159eb Mon Sep 17 00:00:00 2001 From: Alexey Kardashevskiy Date: Wed, 13 Jun 2012 18:38:50 +0000 Subject: [PATCH 01/24] pseries pci: removed redundant busdev The PCIHostState struct already contains SysBusDevice so the one in sPAPRPHBState has to go. Signed-off-by: Alexey Kardashevskiy Signed-off-by: Alexander Graf --- hw/spapr_pci.c | 4 ++-- hw/spapr_pci.h | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/hw/spapr_pci.c b/hw/spapr_pci.c index b2e4f785e..5bee18098 100644 --- a/hw/spapr_pci.c +++ b/hw/spapr_pci.c @@ -276,7 +276,7 @@ static DMAContext *spapr_pci_dma_context_fn(PCIBus *bus, void *opaque, static int spapr_phb_init(SysBusDevice *s) { - sPAPRPHBState *phb = FROM_SYSBUS(sPAPRPHBState, s); + sPAPRPHBState *phb = DO_UPCAST(sPAPRPHBState, host_state.busdev, s); char *namebuf; int i; PCIBus *bus; @@ -314,7 +314,7 @@ static int spapr_phb_init(SysBusDevice *s) memory_region_add_subregion(get_system_memory(), phb->io_win_addr, &phb->iowindow); - bus = pci_register_bus(&phb->busdev.qdev, + bus = pci_register_bus(&phb->host_state.busdev.qdev, phb->busname ? phb->busname : phb->dtbusname, pci_spapr_set_irq, pci_spapr_map_irq, phb, &phb->memspace, &phb->iospace, diff --git a/hw/spapr_pci.h b/hw/spapr_pci.h index d9e46e22e..a141764a6 100644 --- a/hw/spapr_pci.h +++ b/hw/spapr_pci.h @@ -28,7 +28,6 @@ #include "hw/xics.h" typedef struct sPAPRPHBState { - SysBusDevice busdev; PCIHostState host_state; uint64_t buid; From e0fdbd7c1b45c1af034d4070a65067f6635f77b0 Mon Sep 17 00:00:00 2001 From: Alexey Kardashevskiy Date: Wed, 13 Jun 2012 18:40:06 +0000 Subject: [PATCH 02/24] pseries pci: spapr_populate_pci_devices renamed to spapr_populate_pci_dt spapr_populate_pci_devices() populates the device tree only with bus properties and has nothing to do with the devices on it as PCI BAR allocation is done by the system firmware (SLOF). New name - spapr_populate_pci_dt() - describes the functionality better. Signed-off-by: Alexey Kardashevskiy Signed-off-by: Alexander Graf --- hw/spapr.c | 2 +- hw/spapr_pci.c | 6 +++--- hw/spapr_pci.h | 6 +++--- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/hw/spapr.c b/hw/spapr.c index 81c9343ca..ab5a0c2ed 100644 --- a/hw/spapr.c +++ b/hw/spapr.c @@ -481,7 +481,7 @@ static void spapr_finalize_fdt(sPAPREnvironment *spapr, } QLIST_FOREACH(phb, &spapr->phbs, list) { - ret = spapr_populate_pci_devices(phb, PHANDLE_XICP, fdt); + ret = spapr_populate_pci_dt(phb, PHANDLE_XICP, fdt); } if (ret < 0) { diff --git a/hw/spapr_pci.c b/hw/spapr_pci.c index 5bee18098..291354094 100644 --- a/hw/spapr_pci.c +++ b/hw/spapr_pci.c @@ -406,9 +406,9 @@ void spapr_create_phb(sPAPREnvironment *spapr, #define b_fff(x) b_x((x), 8, 3) /* function number */ #define b_rrrrrrrr(x) b_x((x), 0, 8) /* register number */ -int spapr_populate_pci_devices(sPAPRPHBState *phb, - uint32_t xics_phandle, - void *fdt) +int spapr_populate_pci_dt(sPAPRPHBState *phb, + uint32_t xics_phandle, + void *fdt) { int bus_off, i, j; char nodename[256]; diff --git a/hw/spapr_pci.h b/hw/spapr_pci.h index a141764a6..dd66f4b38 100644 --- a/hw/spapr_pci.h +++ b/hw/spapr_pci.h @@ -55,8 +55,8 @@ void spapr_create_phb(sPAPREnvironment *spapr, uint64_t mem_win_addr, uint64_t mem_win_size, uint64_t io_win_addr); -int spapr_populate_pci_devices(sPAPRPHBState *phb, - uint32_t xics_phandle, - void *fdt); +int spapr_populate_pci_dt(sPAPRPHBState *phb, + uint32_t xics_phandle, + void *fdt); #endif /* __HW_SPAPR_PCI_H__ */ From 4a18e7c92a3c23ee742eda1e4442299b56198517 Mon Sep 17 00:00:00 2001 From: Scott Wood Date: Mon, 2 Jul 2012 13:03:18 +0000 Subject: [PATCH 03/24] PPC: e500: rename mpc8544ds into generic file MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rename the file (with no changes other than fixing up the header paths) in preparation for refactoring into a generic e500 platform. Also move it into the newly created ppc/ directory. Signed-off-by: Scott Wood Reviewed-by: Andreas Färber [agraf: conditionalize on CONFIG_FDT] Signed-off-by: Alexander Graf --- hw/ppc/Makefile.objs | 4 +++- hw/{ppce500_mpc8544ds.c => ppc/e500.c} | 16 ++++++++-------- 2 files changed, 11 insertions(+), 9 deletions(-) rename hw/{ppce500_mpc8544ds.c => ppc/e500.c} (99%) diff --git a/hw/ppc/Makefile.objs b/hw/ppc/Makefile.objs index aa4bbeb66..e86c5244b 100644 --- a/hw/ppc/Makefile.objs +++ b/hw/ppc/Makefile.objs @@ -15,7 +15,7 @@ obj-$(CONFIG_PSERIES) += spapr_pci.o pci-hotplug.o spapr_iommu.o obj-y += ppc4xx_devs.o ppc4xx_pci.o ppc405_uc.o ppc405_boards.o obj-y += ppc440_bamboo.o # PowerPC E500 boards -obj-$(CONFIG_FDT) += ppce500_mpc8544ds.o mpc8544_guts.o ppce500_spin.o +obj-$(CONFIG_FDT) += mpc8544_guts.o ppce500_spin.o # PowerPC 440 Xilinx ML507 reference board. obj-y += virtex_ml507.o # PowerPC OpenPIC @@ -26,3 +26,5 @@ obj-$(CONFIG_FDT) += ../device_tree.o obj-y += xilinx_ethlite.o obj-y := $(addprefix ../,$(obj-y)) + +obj-$(CONFIG_FDT) += e500.o diff --git a/hw/ppce500_mpc8544ds.c b/hw/ppc/e500.c similarity index 99% rename from hw/ppce500_mpc8544ds.c rename to hw/ppc/e500.c index 8b9fd83ce..0b383e628 100644 --- a/hw/ppce500_mpc8544ds.c +++ b/hw/ppc/e500.c @@ -17,19 +17,19 @@ #include "config.h" #include "qemu-common.h" #include "net.h" -#include "hw.h" -#include "pc.h" -#include "pci.h" -#include "boards.h" +#include "hw/hw.h" +#include "hw/pc.h" +#include "hw/pci.h" +#include "hw/boards.h" #include "sysemu.h" #include "kvm.h" #include "kvm_ppc.h" #include "device_tree.h" -#include "openpic.h" -#include "ppc.h" -#include "loader.h" +#include "hw/openpic.h" +#include "hw/ppc.h" +#include "hw/loader.h" #include "elf.h" -#include "sysbus.h" +#include "hw/sysbus.h" #include "exec-memory.h" #include "host-utils.h" From b330598137cad915f65562a524b30e32498e44be Mon Sep 17 00:00:00 2001 From: Scott Wood Date: Mon, 2 Jul 2012 13:03:19 +0000 Subject: [PATCH 04/24] PPC: e500: change internal references away from mpc8544ds No functional changes -- machine is still outwardly mpc8544ds. The references that are not changed contain mpc8544 hardware details that need to be parameterized if/when a different e500 platform wants to change them. Signed-off-by: Scott Wood Signed-off-by: Alexander Graf --- hw/ppc/e500.c | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/hw/ppc/e500.c b/hw/ppc/e500.c index 0b383e628..db5ca6e69 100644 --- a/hw/ppc/e500.c +++ b/hw/ppc/e500.c @@ -1,5 +1,5 @@ /* - * QEMU PowerPC MPC8544DS board emulation + * QEMU PowerPC e500-based platforms * * Copyright (C) 2009 Freescale Semiconductor, Inc. All rights reserved. * @@ -42,6 +42,7 @@ #define RAM_SIZES_ALIGN (64UL << 20) +/* TODO: parameterize */ #define MPC8544_CCSRBAR_BASE 0xE0000000ULL #define MPC8544_CCSRBAR_SIZE 0x00100000ULL #define MPC8544_MPIC_REGS_BASE (MPC8544_CCSRBAR_BASE + 0x40000ULL) @@ -104,7 +105,7 @@ static void dt_serial_create(void *fdt, unsigned long long offset, } } -static int mpc8544_load_device_tree(CPUPPCState *env, +static int ppce500_load_device_tree(CPUPPCState *env, target_phys_addr_t addr, target_phys_addr_t ramsize, target_phys_addr_t initrd_base, @@ -388,7 +389,7 @@ static void mmubooke_create_initial_mapping(CPUPPCState *env) env->tlb_dirty = true; } -static void mpc8544ds_cpu_reset_sec(void *opaque) +static void ppce500_cpu_reset_sec(void *opaque) { PowerPCCPU *cpu = opaque; CPUPPCState *env = &cpu->env; @@ -401,7 +402,7 @@ static void mpc8544ds_cpu_reset_sec(void *opaque) env->exception_index = EXCP_HLT; } -static void mpc8544ds_cpu_reset(void *opaque) +static void ppce500_cpu_reset(void *opaque) { PowerPCCPU *cpu = opaque; CPUPPCState *env = &cpu->env; @@ -417,7 +418,7 @@ static void mpc8544ds_cpu_reset(void *opaque) mmubooke_create_initial_mapping(env); } -static void mpc8544ds_init(ram_addr_t ram_size, +static void ppce500_init(ram_addr_t ram_size, const char *boot_device, const char *kernel_filename, const char *kernel_cmdline, @@ -478,11 +479,11 @@ static void mpc8544ds_init(ram_addr_t ram_size, /* Primary CPU */ struct boot_info *boot_info; boot_info = g_malloc0(sizeof(struct boot_info)); - qemu_register_reset(mpc8544ds_cpu_reset, cpu); + qemu_register_reset(ppce500_cpu_reset, cpu); env->load_info = boot_info; } else { /* Secondary CPUs */ - qemu_register_reset(mpc8544ds_cpu_reset_sec, cpu); + qemu_register_reset(ppce500_cpu_reset_sec, cpu); } } @@ -577,7 +578,7 @@ static void mpc8544ds_init(ram_addr_t ram_size, int dt_size; dt_base = (loadaddr + kernel_size + DTC_LOAD_PAD) & ~DTC_PAD_MASK; - dt_size = mpc8544_load_device_tree(env, dt_base, ram_size, initrd_base, + dt_size = ppce500_load_device_tree(env, dt_base, ram_size, initrd_base, initrd_size, kernel_cmdline); if (dt_size < 0) { fprintf(stderr, "couldn't load device tree\n"); @@ -595,16 +596,16 @@ static void mpc8544ds_init(ram_addr_t ram_size, } } -static QEMUMachine mpc8544ds_machine = { +static QEMUMachine ppce500_machine = { .name = "mpc8544ds", .desc = "mpc8544ds", - .init = mpc8544ds_init, + .init = ppce500_init, .max_cpus = 15, }; -static void mpc8544ds_machine_init(void) +static void ppce500_machine_init(void) { - qemu_register_machine(&mpc8544ds_machine); + qemu_register_machine(&ppce500_machine); } -machine_init(mpc8544ds_machine_init); +machine_init(ppce500_machine_init); From e6eaabeb8dfb026da51d178974bddf56f1f06ffe Mon Sep 17 00:00:00 2001 From: Scott Wood Date: Mon, 2 Jul 2012 13:03:20 +0000 Subject: [PATCH 05/24] PPC: e500: split mpc8544ds machine from generic e500 code Currently the only mpc8544ds-ism that is factored out is toplevel compatible and model. In the future the generic e500 code is expected to become more generic. Signed-off-by: Scott Wood [agraf: conditionalize on CONFIG_FDT] Signed-off-by: Alexander Graf --- hw/ppc/Makefile.objs | 2 +- hw/ppc/e500.c | 81 +++++++++++++++++--------------------------- hw/ppc/e500.h | 21 ++++++++++++ hw/ppc/mpc8544ds.c | 61 +++++++++++++++++++++++++++++++++ 4 files changed, 114 insertions(+), 51 deletions(-) create mode 100644 hw/ppc/e500.h create mode 100644 hw/ppc/mpc8544ds.c diff --git a/hw/ppc/Makefile.objs b/hw/ppc/Makefile.objs index e86c5244b..99fe83712 100644 --- a/hw/ppc/Makefile.objs +++ b/hw/ppc/Makefile.objs @@ -27,4 +27,4 @@ obj-y += xilinx_ethlite.o obj-y := $(addprefix ../,$(obj-y)) -obj-$(CONFIG_FDT) += e500.o +obj-$(CONFIG_FDT) += e500.o mpc8544ds.o diff --git a/hw/ppc/e500.c b/hw/ppc/e500.c index db5ca6e69..f07be08f6 100644 --- a/hw/ppc/e500.c +++ b/hw/ppc/e500.c @@ -16,6 +16,7 @@ #include "config.h" #include "qemu-common.h" +#include "e500.h" #include "net.h" #include "hw/hw.h" #include "hw/pc.h" @@ -106,24 +107,21 @@ static void dt_serial_create(void *fdt, unsigned long long offset, } static int ppce500_load_device_tree(CPUPPCState *env, + PPCE500Params *params, target_phys_addr_t addr, - target_phys_addr_t ramsize, target_phys_addr_t initrd_base, - target_phys_addr_t initrd_size, - const char *kernel_cmdline) + target_phys_addr_t initrd_size) { int ret = -1; - uint64_t mem_reg_property[] = { 0, cpu_to_be64(ramsize) }; + uint64_t mem_reg_property[] = { 0, cpu_to_be64(params->ram_size) }; int fdt_size; void *fdt; uint8_t hypercall[16]; uint32_t clock_freq = 400000000; uint32_t tb_freq = 400000000; int i; - const char *compatible = "MPC8544DS\0MPC85xxDS"; - int compatible_len = sizeof("MPC8544DS\0MPC85xxDS"); + const char *toplevel_compat = NULL; /* user override */ char compatible_sb[] = "fsl,mpc8544-immr\0simple-bus"; - char model[] = "MPC8544DS"; char soc[128]; char mpic[128]; uint32_t mpic_ph; @@ -146,14 +144,9 @@ static int ppce500_load_device_tree(CPUPPCState *env, machine_opts = qemu_opts_find(qemu_find_opts("machine"), 0); if (machine_opts) { - const char *tmp; dumpdtb = qemu_opt_get(machine_opts, "dumpdtb"); dtb_file = qemu_opt_get(machine_opts, "dtb"); - tmp = qemu_opt_get(machine_opts, "dt_compatible"); - if (tmp) { - compatible = tmp; - compatible_len = strlen(compatible) + 1; - } + toplevel_compat = qemu_opt_get(machine_opts, "dt_compatible"); } if (dtb_file) { @@ -176,8 +169,6 @@ static int ppce500_load_device_tree(CPUPPCState *env, } /* Manipulate device tree in memory. */ - qemu_devtree_setprop_string(fdt, "/", "model", model); - qemu_devtree_setprop(fdt, "/", "compatible", compatible, compatible_len); qemu_devtree_setprop_cell(fdt, "/", "#address-cells", 2); qemu_devtree_setprop_cell(fdt, "/", "#size-cells", 2); @@ -202,7 +193,7 @@ static int ppce500_load_device_tree(CPUPPCState *env, } ret = qemu_devtree_setprop_string(fdt, "/chosen", "bootargs", - kernel_cmdline); + params->kernel_cmdline); if (ret < 0) fprintf(stderr, "couldn't set /chosen/bootargs\n"); @@ -338,6 +329,13 @@ static int ppce500_load_device_tree(CPUPPCState *env, qemu_devtree_setprop_cell(fdt, pci, "#address-cells", 3); qemu_devtree_setprop_string(fdt, "/aliases", "pci0", pci); + params->fixup_devtree(params, fdt); + + if (toplevel_compat) { + qemu_devtree_setprop(fdt, "/", "compatible", toplevel_compat, + strlen(toplevel_compat) + 1); + } + done: if (dumpdtb) { /* Dump the dtb to a file and quit */ @@ -418,12 +416,7 @@ static void ppce500_cpu_reset(void *opaque) mmubooke_create_initial_mapping(env); } -static void ppce500_init(ram_addr_t ram_size, - const char *boot_device, - const char *kernel_filename, - const char *kernel_cmdline, - const char *initrd_filename, - const char *cpu_model) +void ppce500_init(PPCE500Params *params) { MemoryRegion *address_space_mem = get_system_memory(); MemoryRegion *ram = g_new(MemoryRegion, 1); @@ -444,8 +437,8 @@ static void ppce500_init(ram_addr_t ram_size, CPUPPCState *firstenv = NULL; /* Setup CPUs */ - if (cpu_model == NULL) { - cpu_model = "e500v2_v30"; + if (params->cpu_model == NULL) { + params->cpu_model = "e500v2_v30"; } irqs = g_malloc0(smp_cpus * sizeof(qemu_irq *)); @@ -454,7 +447,7 @@ static void ppce500_init(ram_addr_t ram_size, PowerPCCPU *cpu; qemu_irq *input; - cpu = cpu_ppc_init(cpu_model); + cpu = cpu_ppc_init(params->cpu_model); if (cpu == NULL) { fprintf(stderr, "Unable to initialize CPU!\n"); exit(1); @@ -543,43 +536,45 @@ static void ppce500_init(ram_addr_t ram_size, sysbus_create_simple("e500-spin", MPC8544_SPIN_BASE, NULL); /* Load kernel. */ - if (kernel_filename) { - kernel_size = load_uimage(kernel_filename, &entry, &loadaddr, NULL); + if (params->kernel_filename) { + kernel_size = load_uimage(params->kernel_filename, &entry, + &loadaddr, NULL); if (kernel_size < 0) { - kernel_size = load_elf(kernel_filename, NULL, NULL, &elf_entry, - &elf_lowaddr, NULL, 1, ELF_MACHINE, 0); + kernel_size = load_elf(params->kernel_filename, NULL, NULL, + &elf_entry, &elf_lowaddr, NULL, 1, + ELF_MACHINE, 0); entry = elf_entry; loadaddr = elf_lowaddr; } /* XXX try again as binary */ if (kernel_size < 0) { fprintf(stderr, "qemu: could not load kernel '%s'\n", - kernel_filename); + params->kernel_filename); exit(1); } } /* Load initrd. */ - if (initrd_filename) { + if (params->initrd_filename) { initrd_base = (kernel_size + INITRD_LOAD_PAD) & ~INITRD_PAD_MASK; - initrd_size = load_image_targphys(initrd_filename, initrd_base, + initrd_size = load_image_targphys(params->initrd_filename, initrd_base, ram_size - initrd_base); if (initrd_size < 0) { fprintf(stderr, "qemu: could not load initial ram disk '%s'\n", - initrd_filename); + params->initrd_filename); exit(1); } } /* If we're loading a kernel directly, we must load the device tree too. */ - if (kernel_filename) { + if (params->kernel_filename) { struct boot_info *boot_info; int dt_size; dt_base = (loadaddr + kernel_size + DTC_LOAD_PAD) & ~DTC_PAD_MASK; - dt_size = ppce500_load_device_tree(env, dt_base, ram_size, initrd_base, - initrd_size, kernel_cmdline); + dt_size = ppce500_load_device_tree(env, params, dt_base, initrd_base, + initrd_size); if (dt_size < 0) { fprintf(stderr, "couldn't load device tree\n"); exit(1); @@ -595,17 +590,3 @@ static void ppce500_init(ram_addr_t ram_size, kvmppc_init(); } } - -static QEMUMachine ppce500_machine = { - .name = "mpc8544ds", - .desc = "mpc8544ds", - .init = ppce500_init, - .max_cpus = 15, -}; - -static void ppce500_machine_init(void) -{ - qemu_register_machine(&ppce500_machine); -} - -machine_init(ppce500_machine_init); diff --git a/hw/ppc/e500.h b/hw/ppc/e500.h new file mode 100644 index 000000000..7ae87f4e2 --- /dev/null +++ b/hw/ppc/e500.h @@ -0,0 +1,21 @@ +#ifndef PPCE500_H +#define PPCE500_H + +typedef struct PPCE500Params { + /* Standard QEMU machine init params */ + ram_addr_t ram_size; + const char *boot_device; + const char *kernel_filename; + const char *kernel_cmdline; + const char *initrd_filename; + const char *cpu_model; + + /* e500-specific params */ + + /* required -- must at least add toplevel board compatible */ + void (*fixup_devtree)(struct PPCE500Params *params, void *fdt); +} PPCE500Params; + +void ppce500_init(PPCE500Params *params); + +#endif diff --git a/hw/ppc/mpc8544ds.c b/hw/ppc/mpc8544ds.c new file mode 100644 index 000000000..984d21cbf --- /dev/null +++ b/hw/ppc/mpc8544ds.c @@ -0,0 +1,61 @@ +/* + * Support for the PPC e500-based mpc8544ds board + * + * Copyright 2012 Freescale Semiconductor, Inc. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include "config.h" +#include "qemu-common.h" +#include "e500.h" +#include "../boards.h" +#include "device_tree.h" + +static void mpc8544ds_fixup_devtree(PPCE500Params *params, void *fdt) +{ + const char model[] = "MPC8544DS"; + const char compatible[] = "MPC8544DS\0MPC85xxDS"; + + qemu_devtree_setprop(fdt, "/", "model", model, sizeof(model)); + qemu_devtree_setprop(fdt, "/", "compatible", compatible, + sizeof(compatible)); +} + +static void mpc8544ds_init(ram_addr_t ram_size, + const char *boot_device, + const char *kernel_filename, + const char *kernel_cmdline, + const char *initrd_filename, + const char *cpu_model) +{ + PPCE500Params params = { + .ram_size = ram_size, + .boot_device = boot_device, + .kernel_filename = kernel_filename, + .kernel_cmdline = kernel_cmdline, + .initrd_filename = initrd_filename, + .cpu_model = cpu_model, + .fixup_devtree = mpc8544ds_fixup_devtree, + }; + + ppce500_init(¶ms); +} + + +static QEMUMachine ppce500_machine = { + .name = "mpc8544ds", + .desc = "mpc8544ds", + .init = mpc8544ds_init, + .max_cpus = 15, +}; + +static void ppce500_machine_init(void) +{ + qemu_register_machine(&ppce500_machine); +} + +machine_init(ppce500_machine_init); From 4d5c29ca455ed6adb1fb9f8394e4d7badfd0c532 Mon Sep 17 00:00:00 2001 From: Scott Wood Date: Mon, 2 Jul 2012 13:03:21 +0000 Subject: [PATCH 06/24] PPC: e500: add generic e500 platform This gives the kernel a paravirtualized machine to target, without requiring both sides to pretend to be targeting a specific board that likely has little to do with the host in KVM scenarios. This avoids the need to add new boards to QEMU, just to be able to run KVM on new CPUs. Signed-off-by: Scott Wood [agraf: conditionalize on CONFIG_FDT] Signed-off-by: Alexander Graf --- hw/ppc/Makefile.objs | 2 +- hw/ppc/e500plat.c | 60 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 61 insertions(+), 1 deletion(-) create mode 100644 hw/ppc/e500plat.c diff --git a/hw/ppc/Makefile.objs b/hw/ppc/Makefile.objs index 99fe83712..951e407f1 100644 --- a/hw/ppc/Makefile.objs +++ b/hw/ppc/Makefile.objs @@ -27,4 +27,4 @@ obj-y += xilinx_ethlite.o obj-y := $(addprefix ../,$(obj-y)) -obj-$(CONFIG_FDT) += e500.o mpc8544ds.o +obj-$(CONFIG_FDT) += e500.o mpc8544ds.o e500plat.o diff --git a/hw/ppc/e500plat.c b/hw/ppc/e500plat.c new file mode 100644 index 000000000..60a5cb3bd --- /dev/null +++ b/hw/ppc/e500plat.c @@ -0,0 +1,60 @@ +/* + * Generic device-tree-driven paravirt PPC e500 platform + * + * Copyright 2012 Freescale Semiconductor, Inc. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include "config.h" +#include "qemu-common.h" +#include "e500.h" +#include "../boards.h" +#include "device_tree.h" + +static void e500plat_fixup_devtree(PPCE500Params *params, void *fdt) +{ + const char model[] = "QEMU ppce500"; + const char compatible[] = "fsl,qemu-e500"; + + qemu_devtree_setprop(fdt, "/", "model", model, sizeof(model)); + qemu_devtree_setprop(fdt, "/", "compatible", compatible, + sizeof(compatible)); +} + +static void e500plat_init(ram_addr_t ram_size, + const char *boot_device, + const char *kernel_filename, + const char *kernel_cmdline, + const char *initrd_filename, + const char *cpu_model) +{ + PPCE500Params params = { + .ram_size = ram_size, + .boot_device = boot_device, + .kernel_filename = kernel_filename, + .kernel_cmdline = kernel_cmdline, + .initrd_filename = initrd_filename, + .cpu_model = cpu_model, + .fixup_devtree = e500plat_fixup_devtree, + }; + + ppce500_init(¶ms); +} + +static QEMUMachine e500plat_machine = { + .name = "ppce500", + .desc = "generic paravirt e500 platform", + .init = e500plat_init, + .max_cpus = 15, +}; + +static void e500plat_machine_init(void) +{ + qemu_register_machine(&e500plat_machine); +} + +machine_init(e500plat_machine_init); From 78e8fde26c032931ca2ae13bfc7c59e38afd17ee Mon Sep 17 00:00:00 2001 From: David Gibson Date: Mon, 6 Aug 2012 18:44:45 +0000 Subject: [PATCH 07/24] ppc: Fix bug in handling of PAPR hypercall exits Currently for powerpc, kvm_arch_handle_exit() always returns 1, meaning that its caller - kvm_cpu_exec() - will always exit immediately afterwards to the loop in qemu_kvm_cpu_thread_fn(). There's no need to do this. Once we've handled the hypercall there's no reason we can't go straight around and KVM_RUN again, which is what ret = 0 will signal. The only exception might be for hypercalls which affect the state of cpu_can_run(), however the only one that might do this is H_CEDE and for kvm that is always handled in the kernel, not qemu. Furtherm setting ret = 0 means that when exit_requested is set from a hypercall, we will enter KVM_RUN once more with a signal which lets the the kernel do its internal logic to complete the hypercall with out actually executing any more guest code. This is important if our hypercall also triggered a reset, which previously would re-initialize everything without completing the hypercall. This caused the kernel to get confused because it thought the guest was still in the middle of a hypercall when it has actually been reset. This patch therefore changes to ret = 0, which is both a bugfix and a small optimization. Signed-off-by: David Gibson Signed-off-by: Alexander Graf --- 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 829e180f8..a31d278a5 100644 --- a/target-ppc/kvm.c +++ b/target-ppc/kvm.c @@ -766,7 +766,7 @@ int kvm_arch_handle_exit(CPUPPCState *env, struct kvm_run *run) dprintf("handle PAPR hypercall\n"); run->papr_hcall.ret = spapr_hypercall(env, run->papr_hcall.nr, run->papr_hcall.args); - ret = 1; + ret = 0; break; #endif default: From 7e99826c350f21cb7d162e802efaa5d1b8689ad0 Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Thu, 9 Aug 2012 22:57:14 +0200 Subject: [PATCH 08/24] Revert "PPC: e500: Use new MPIC dt format" This reverts commit 518c7fb44f2182cde943dc64f88cb2fd4e4ff6b5. It breaks new Linux guests with SMP, because IPIs get mapped to large vectors which our MPIC emulation does not implement. Conflicts: hw/ppc/e500.c --- hw/ppc/e500.c | 31 ++++++++++++++----------------- 1 file changed, 14 insertions(+), 17 deletions(-) diff --git a/hw/ppc/e500.c b/hw/ppc/e500.c index f07be08f6..6f0de6d95 100644 --- a/hw/ppc/e500.c +++ b/hw/ppc/e500.c @@ -68,18 +68,18 @@ static void pci_map_create(void *fdt, uint32_t *pci_map, uint32_t mpic) int i; const uint32_t tmp[] = { /* IDSEL 0x11 J17 Slot 1 */ - 0x8800, 0x0, 0x0, 0x1, mpic, 0x2, 0x1, 0x0, 0x0, - 0x8800, 0x0, 0x0, 0x2, mpic, 0x3, 0x1, 0x0, 0x0, - 0x8800, 0x0, 0x0, 0x3, mpic, 0x4, 0x1, 0x0, 0x0, - 0x8800, 0x0, 0x0, 0x4, mpic, 0x1, 0x1, 0x0, 0x0, + 0x8800, 0x0, 0x0, 0x1, mpic, 0x2, 0x1, + 0x8800, 0x0, 0x0, 0x2, mpic, 0x3, 0x1, + 0x8800, 0x0, 0x0, 0x3, mpic, 0x4, 0x1, + 0x8800, 0x0, 0x0, 0x4, mpic, 0x1, 0x1, /* IDSEL 0x12 J16 Slot 2 */ - 0x9000, 0x0, 0x0, 0x1, mpic, 0x3, 0x1, 0x0, 0x0, - 0x9000, 0x0, 0x0, 0x2, mpic, 0x4, 0x1, 0x0, 0x0, - 0x9000, 0x0, 0x0, 0x3, mpic, 0x2, 0x1, 0x0, 0x0, - 0x9000, 0x0, 0x0, 0x4, mpic, 0x1, 0x1, 0x0, 0x0, + 0x9000, 0x0, 0x0, 0x1, mpic, 0x3, 0x1, + 0x9000, 0x0, 0x0, 0x2, mpic, 0x4, 0x1, + 0x9000, 0x0, 0x0, 0x3, mpic, 0x2, 0x1, + 0x9000, 0x0, 0x0, 0x4, mpic, 0x1, 0x1, }; - for (i = 0; i < ARRAY_SIZE(tmp); i++) { + for (i = 0; i < (7 * 8); i++) { pci_map[i] = cpu_to_be32(tmp[i]); } } @@ -97,7 +97,7 @@ static void dt_serial_create(void *fdt, unsigned long long offset, qemu_devtree_setprop_cells(fdt, ser, "reg", offset, 0x100); qemu_devtree_setprop_cell(fdt, ser, "cell-index", idx); qemu_devtree_setprop_cell(fdt, ser, "clock-frequency", 0); - qemu_devtree_setprop_cells(fdt, ser, "interrupts", 42, 2, 0, 0); + qemu_devtree_setprop_cells(fdt, ser, "interrupts", 42, 2); qemu_devtree_setprop_phandle(fdt, ser, "interrupt-parent", mpic); qemu_devtree_setprop_string(fdt, "/aliases", alias, ser); @@ -127,7 +127,7 @@ static int ppce500_load_device_tree(CPUPPCState *env, uint32_t mpic_ph; char gutil[128]; char pci[128]; - uint32_t pci_map[9 * 8]; + uint32_t pci_map[7 * 8]; uint32_t pci_ranges[14] = { 0x2000000, 0x0, 0xc0000000, @@ -274,18 +274,15 @@ static int ppce500_load_device_tree(CPUPPCState *env, MPC8544_MPIC_REGS_BASE - MPC8544_CCSRBAR_BASE); qemu_devtree_add_subnode(fdt, mpic); qemu_devtree_setprop_string(fdt, mpic, "device_type", "open-pic"); - qemu_devtree_setprop_string(fdt, mpic, "compatible", "fsl,mpic"); + qemu_devtree_setprop_string(fdt, mpic, "compatible", "chrp,open-pic"); qemu_devtree_setprop_cells(fdt, mpic, "reg", MPC8544_MPIC_REGS_BASE - MPC8544_CCSRBAR_BASE, 0x40000); qemu_devtree_setprop_cell(fdt, mpic, "#address-cells", 0); - qemu_devtree_setprop_cell(fdt, mpic, "#interrupt-cells", 4); + qemu_devtree_setprop_cell(fdt, mpic, "#interrupt-cells", 2); mpic_ph = qemu_devtree_alloc_phandle(fdt); qemu_devtree_setprop_cell(fdt, mpic, "phandle", mpic_ph); qemu_devtree_setprop_cell(fdt, mpic, "linux,phandle", mpic_ph); qemu_devtree_setprop(fdt, mpic, "interrupt-controller", NULL, 0); - qemu_devtree_setprop(fdt, mpic, "big-endian", NULL, 0); - qemu_devtree_setprop(fdt, mpic, "single-cpu-affinity", NULL, 0); - qemu_devtree_setprop_cell(fdt, mpic, "last-interrupt-source", 255); /* * We have to generate ser1 first, because Linux takes the first @@ -315,7 +312,7 @@ static int ppce500_load_device_tree(CPUPPCState *env, pci_map_create(fdt, pci_map, qemu_devtree_get_phandle(fdt, mpic)); qemu_devtree_setprop(fdt, pci, "interrupt-map", pci_map, sizeof(pci_map)); qemu_devtree_setprop_phandle(fdt, pci, "interrupt-parent", mpic); - qemu_devtree_setprop_cells(fdt, pci, "interrupts", 24, 2, 0, 0); + qemu_devtree_setprop_cells(fdt, pci, "interrupts", 24, 2); qemu_devtree_setprop_cells(fdt, pci, "bus-range", 0, 255); for (i = 0; i < 14; i++) { pci_ranges[i] = cpu_to_be32(pci_ranges[i]); From c1195d1677a41f42be712620674d42b39d83bdfe Mon Sep 17 00:00:00 2001 From: "zhlcindy@gmail.com" Date: Mon, 6 Aug 2012 16:41:59 +0000 Subject: [PATCH 09/24] Add one new file vga-pci.h and cleanup on all platforms Functions pci_vga_init() and pci_cirrus_vga_init() are declared in pc.h. That prevents other platforms (e.g. sPAPR) to use them. This patch is to create one new file vga-pci.h and move the declarations to vga-pci.h, so that they can be shared by all platforms. This patch also cleans up on all platforms. Signed-off-by: Li Zhang Signed-off-by: Alexander Graf --- hw/alpha_pci.c | 1 + hw/cirrus_vga.c | 2 +- hw/mips_malta.c | 1 + hw/pc.c | 1 + hw/pc.h | 4 ---- hw/ppc_newworld.c | 2 +- hw/ppc_oldworld.c | 2 +- hw/ppc_prep.c | 1 + hw/sun4u.c | 1 + hw/vga-pci.c | 2 +- hw/vga-pci.h | 12 ++++++++++++ 11 files changed, 21 insertions(+), 8 deletions(-) create mode 100644 hw/vga-pci.h diff --git a/hw/alpha_pci.c b/hw/alpha_pci.c index 673557781..ea546f83f 100644 --- a/hw/alpha_pci.c +++ b/hw/alpha_pci.c @@ -11,6 +11,7 @@ #include "qemu-log.h" #include "sysemu.h" #include "vmware_vga.h" +#include "vga-pci.h" /* PCI IO reads/writes, to byte-word addressable memory. */ diff --git a/hw/cirrus_vga.c b/hw/cirrus_vga.c index 623dd688d..e8dcc6b88 100644 --- a/hw/cirrus_vga.c +++ b/hw/cirrus_vga.c @@ -27,8 +27,8 @@ * available at http://home.worldonline.dk/~finth/ */ #include "hw.h" -#include "pc.h" #include "pci.h" +#include "vga-pci.h" #include "console.h" #include "vga_int.h" #include "loader.h" diff --git a/hw/mips_malta.c b/hw/mips_malta.c index 351c88ebc..ad23f26e5 100644 --- a/hw/mips_malta.c +++ b/hw/mips_malta.c @@ -48,6 +48,7 @@ #include "blockdev.h" #include "exec-memory.h" #include "sysbus.h" /* SysBusDevice */ +#include "vga-pci.h" //#define DEBUG_BOARD_INIT diff --git a/hw/pc.c b/hw/pc.c index e8bcfc0b4..3ed1a3caa 100644 --- a/hw/pc.c +++ b/hw/pc.c @@ -51,6 +51,7 @@ #include "exec-memory.h" #include "arch_init.h" #include "bitmap.h" +#include "vga-pci.h" /* output Bochs bios info messages */ //#define DEBUG_BIOS diff --git a/hw/pc.h b/hw/pc.h index 31ccb6f49..e4db0715b 100644 --- a/hw/pc.h +++ b/hw/pc.h @@ -189,14 +189,10 @@ static inline DeviceState *isa_vga_init(ISABus *bus) return &dev->qdev; } -DeviceState *pci_vga_init(PCIBus *bus); int isa_vga_mm_init(target_phys_addr_t vram_base, target_phys_addr_t ctrl_base, int it_shift, MemoryRegion *address_space); -/* cirrus_vga.c */ -DeviceState *pci_cirrus_vga_init(PCIBus *bus); - /* ne2000.c */ static inline bool isa_ne2000_init(ISABus *bus, int base, int irq, NICInfo *nd) { diff --git a/hw/ppc_newworld.c b/hw/ppc_newworld.c index 4e2a6e691..e95cfe831 100644 --- a/hw/ppc_newworld.c +++ b/hw/ppc_newworld.c @@ -52,7 +52,6 @@ #include "adb.h" #include "mac_dbdma.h" #include "nvram.h" -#include "pc.h" #include "pci.h" #include "net.h" #include "sysemu.h" @@ -68,6 +67,7 @@ #include "hw/usb.h" #include "blockdev.h" #include "exec-memory.h" +#include "vga-pci.h" #define MAX_IDE_BUS 2 #define CFG_ADDR 0xf0000510 diff --git a/hw/ppc_oldworld.c b/hw/ppc_oldworld.c index f2c690853..1dcd8a6c3 100644 --- a/hw/ppc_oldworld.c +++ b/hw/ppc_oldworld.c @@ -29,7 +29,6 @@ #include "adb.h" #include "mac_dbdma.h" #include "nvram.h" -#include "pc.h" #include "sysemu.h" #include "net.h" #include "isa.h" @@ -44,6 +43,7 @@ #include "kvm_ppc.h" #include "blockdev.h" #include "exec-memory.h" +#include "vga-pci.h" #define MAX_IDE_BUS 2 #define CFG_ADDR 0xf0000510 diff --git a/hw/ppc_prep.c b/hw/ppc_prep.c index be2b26830..7a876164c 100644 --- a/hw/ppc_prep.c +++ b/hw/ppc_prep.c @@ -39,6 +39,7 @@ #include "blockdev.h" #include "arch_init.h" #include "exec-memory.h" +#include "vga-pci.h" //#define HARD_DEBUG_PPC_IO //#define DEBUG_PPC_IO diff --git a/hw/sun4u.c b/hw/sun4u.c index 137a7c666..07cd04273 100644 --- a/hw/sun4u.c +++ b/hw/sun4u.c @@ -39,6 +39,7 @@ #include "elf.h" #include "blockdev.h" #include "exec-memory.h" +#include "vga-pci.h" //#define DEBUG_IRQ //#define DEBUG_EBUS diff --git a/hw/vga-pci.c b/hw/vga-pci.c index 37dc019a6..9abbada8f 100644 --- a/hw/vga-pci.c +++ b/hw/vga-pci.c @@ -23,8 +23,8 @@ */ #include "hw.h" #include "console.h" -#include "pc.h" #include "pci.h" +#include "vga-pci.h" #include "vga_int.h" #include "pixel_ops.h" #include "qemu-timer.h" diff --git a/hw/vga-pci.h b/hw/vga-pci.h new file mode 100644 index 000000000..49abf1309 --- /dev/null +++ b/hw/vga-pci.h @@ -0,0 +1,12 @@ +#ifndef VGA_PCI_H +#define VGA_PCI_H + +#include "qemu-common.h" + +/* vga-pci.c */ +DeviceState *pci_vga_init(PCIBus *bus); + +/* cirrus_vga.c */ +DeviceState *pci_cirrus_vga_init(PCIBus *bus); + +#endif From f28359d8e8fc64192450a72164b89d06cc3f781d Mon Sep 17 00:00:00 2001 From: "zhlcindy@gmail.com" Date: Mon, 6 Aug 2012 16:42:00 +0000 Subject: [PATCH 10/24] spapr: Add support for -vga option Also instanciate the USB keyboard and mouse when that option is used (you can still use -device to create individual devices without all the defaults) Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Li Zhang [agraf: remove USB bits] Signed-off-by: Alexander Graf --- hw/spapr.c | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/hw/spapr.c b/hw/spapr.c index ab5a0c2ed..494c412db 100644 --- a/hw/spapr.c +++ b/hw/spapr.c @@ -45,6 +45,7 @@ #include "kvm.h" #include "kvm_ppc.h" #include "pci.h" +#include "vga-pci.h" #include "exec-memory.h" @@ -82,6 +83,7 @@ #define PHANDLE_XICP 0x00001111 sPAPREnvironment *spapr; +bool spapr_has_graphics; qemu_irq spapr_allocate_irq(uint32_t hint, uint32_t *irq_num, enum xics_irq_type type) @@ -257,6 +259,9 @@ static void *spapr_create_fdt_skel(const char *cpu_model, _FDT((fdt_property(fdt, "qemu,boot-kernel", &kprop, sizeof(kprop)))); } _FDT((fdt_property_string(fdt, "qemu,boot-device", boot_device))); + _FDT((fdt_property_cell(fdt, "qemu,graphic-width", graphic_width))); + _FDT((fdt_property_cell(fdt, "qemu,graphic-height", graphic_height))); + _FDT((fdt_property_cell(fdt, "qemu,graphic-depth", graphic_depth))); _FDT((fdt_end_node(fdt))); @@ -503,7 +508,9 @@ static void spapr_finalize_fdt(sPAPREnvironment *spapr, } } - spapr_populate_chosen_stdout(fdt, spapr->vio_bus); + if (!spapr_has_graphics) { + spapr_populate_chosen_stdout(fdt, spapr->vio_bus); + } _FDT((fdt_pack(fdt))); @@ -556,6 +563,18 @@ static void spapr_cpu_reset(void *opaque) cpu_reset(CPU(cpu)); } +static int spapr_vga_init(PCIBus *pci_bus) +{ + if (std_vga_enabled) { + pci_vga_init(pci_bus); + } else { + fprintf(stderr, "This vga model is not supported," + "currently it only supports -vga std\n"); + return 0; + } + return 1; +} + /* pSeries LPAR / sPAPR hardware init */ static void ppc_spapr_init(ram_addr_t ram_size, const char *boot_device, @@ -710,6 +729,11 @@ static void ppc_spapr_init(ram_addr_t ram_size, spapr_vscsi_create(spapr->vio_bus); } + /* Graphics */ + if (spapr_vga_init(QLIST_FIRST(&spapr->phbs)->host_state.bus)) { + spapr_has_graphics = true; + } + if (rma_size < (MIN_RMA_SLOF << 20)) { fprintf(stderr, "qemu: pSeries SLOF firmware requires >= " "%ldM guest RMA (Real Mode Area memory)\n", MIN_RMA_SLOF); From a5b71725c7067f6805eb30ff8e03dce3b6bf7a53 Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Tue, 14 Aug 2012 12:53:18 +0200 Subject: [PATCH 11/24] xbzrle: fix compilation on ppc32 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When compiling the xbzrle code on my ppc32 user space, I hit the following gcc compiler warning (treated as an error): cc1: warnings being treated as errors savevm.c: In function ‘xbzrle_encode_buffer’: savevm.c:2476: error: overflow in implicit constant conversion Fix this by making the cast explicit, rather than implicit. Signed-off-by: Alexander Graf --- savevm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/savevm.c b/savevm.c index 0ea10c9b6..9ab4d83da 100644 --- a/savevm.c +++ b/savevm.c @@ -2473,7 +2473,7 @@ int xbzrle_encode_buffer(uint8_t *old_buf, uint8_t *new_buf, int slen, /* word at a time for speed, use of 32-bit long okay */ if (!res) { /* truncation to 32-bit long okay */ - long mask = 0x0101010101010101ULL; + long mask = (long)0x0101010101010101ULL; while (i < slen) { xor = *(long *)(old_buf + i) ^ *(long *)(new_buf + i); if ((xor - mask) & ~xor & (mask << 7)) { From 8c57b867b5d18b0d916797dfbac465b8aaa5bf5a Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Tue, 14 Aug 2012 13:11:49 +0200 Subject: [PATCH 12/24] PPC: spapr: Rework VGA select logic When selecting our VGA adapter, we want to: * fail completely when we can't satisfy the user's request * support -nographic where no VGA adapter should be spawned This patch reworks the logic so we fulfill the two conditions above. Signed-off-by: Alexander Graf --- hw/spapr.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/hw/spapr.c b/hw/spapr.c index 494c412db..709673e76 100644 --- a/hw/spapr.c +++ b/hw/spapr.c @@ -563,16 +563,21 @@ static void spapr_cpu_reset(void *opaque) cpu_reset(CPU(cpu)); } +/* Returns whether we want to use VGA or not */ static int spapr_vga_init(PCIBus *pci_bus) { - if (std_vga_enabled) { + switch (vga_interface_type) { + case VGA_STD: pci_vga_init(pci_bus); - } else { + return 1; + case VGA_NONE: + return 0; + default: fprintf(stderr, "This vga model is not supported," "currently it only supports -vga std\n"); - return 0; + exit(0); + break; } - return 1; } /* pSeries LPAR / sPAPR hardware init */ From 3fc5acdeedfcea7c7d86040fa427ae785920b399 Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Tue, 14 Aug 2012 13:22:13 +0200 Subject: [PATCH 13/24] PPC: spapr: Remove global variable Global variables are bad. Let's move spapr_has_graphics into the machine state struct. Signed-off-by: Alexander Graf --- hw/spapr.c | 5 ++--- hw/spapr.h | 1 + 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/hw/spapr.c b/hw/spapr.c index 709673e76..aa39d2d2c 100644 --- a/hw/spapr.c +++ b/hw/spapr.c @@ -83,7 +83,6 @@ #define PHANDLE_XICP 0x00001111 sPAPREnvironment *spapr; -bool spapr_has_graphics; qemu_irq spapr_allocate_irq(uint32_t hint, uint32_t *irq_num, enum xics_irq_type type) @@ -508,7 +507,7 @@ static void spapr_finalize_fdt(sPAPREnvironment *spapr, } } - if (!spapr_has_graphics) { + if (!spapr->has_graphics) { spapr_populate_chosen_stdout(fdt, spapr->vio_bus); } @@ -736,7 +735,7 @@ static void ppc_spapr_init(ram_addr_t ram_size, /* Graphics */ if (spapr_vga_init(QLIST_FIRST(&spapr->phbs)->host_state.bus)) { - spapr_has_graphics = true; + spapr->has_graphics = true; } if (rma_size < (MIN_RMA_SLOF << 20)) { diff --git a/hw/spapr.h b/hw/spapr.h index 9153f29a6..fe40e7d00 100644 --- a/hw/spapr.h +++ b/hw/spapr.h @@ -23,6 +23,7 @@ typedef struct sPAPREnvironment { int next_irq; int rtc_offset; char *cpu_model; + bool has_graphics; } sPAPREnvironment; #define H_SUCCESS 0 From 03332579b81ef7f2b0fcb41e45f7764a5bfc1ea4 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Mon, 30 Jul 2012 20:09:01 +0000 Subject: [PATCH 14/24] pseries: Update SLOF This patch updates the SLOF version, introducing a number of fixes: * add proper graphics support * fix bugs with graphical terminal under grub2 * fix bugs in handling of 64-bit unit addresses * fix VSCSI representation to be closer to PowerVM * fix bugs which caused grub2 to crash Signed-off-by: Benjamin Herrenschmidt Signed-off-by: David Gibson Signed-off-by: Alexander Graf --- pc-bios/README | 2 +- pc-bios/slof.bin | Bin 880496 -> 878088 bytes roms/SLOF | 2 +- 3 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pc-bios/README b/pc-bios/README index e56e9e5f0..e71bcd0f3 100644 --- a/pc-bios/README +++ b/pc-bios/README @@ -17,7 +17,7 @@ - SLOF (Slimline Open Firmware) is a free IEEE 1275 Open Firmware implementation for certain IBM POWER hardware. The sources are at https://github.com/dgibson/SLOF, and the image currently in qemu is - built from git tag qemu-slof-20120217. + built from git tag qemu-slof-20120719. - sgabios (the Serial Graphics Adapter option ROM) provides a means for legacy x86 software to communicate with an attached serial console as diff --git a/pc-bios/slof.bin b/pc-bios/slof.bin index 449a7bb2afaf604f6c089612e99086df0800d7dc..320b8f001cf9962318812a5b9109242e210fe499 100644 GIT binary patch delta 149136 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
uB7(Tl{Z_zPG%GKwI);XZL=yYnr`vG4{ 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

UmOEx7=;6L^YR1nVIk6 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 delta 156060 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 diff --git a/roms/SLOF b/roms/SLOF index d15336425..7279655af 160000 --- a/roms/SLOF +++ b/roms/SLOF @@ -1 +1 @@ -Subproject commit d153364253548d6cd91403711f84996e6a7dab31 +Subproject commit 7279655af2eba855bd2df61303d25abd1eeb2300 From c9f709d2e7d9dcc6e6ecbee8d499b4b14b11320b Mon Sep 17 00:00:00 2001 From: David Gibson Date: Tue, 7 Aug 2012 16:10:31 +0000 Subject: [PATCH 15/24] pseries: Remove extraneous prints The pseries machine prints several messages to stderr whenever it starts up and another whenever the vm is reset. It's not normal for qemu machines to do this though, so this patch removes them. We can put them back conditional on a DEBUG symbol if we really need them in future. Signed-off-by: David Gibson Signed-off-by: Alexander Graf --- hw/spapr.c | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/hw/spapr.c b/hw/spapr.c index aa39d2d2c..032d259e8 100644 --- a/hw/spapr.c +++ b/hw/spapr.c @@ -538,8 +538,6 @@ static void spapr_reset(void *opaque) { sPAPREnvironment *spapr = (sPAPREnvironment *)opaque; - fprintf(stderr, "sPAPR reset\n"); - /* flush out the hash table */ memset(spapr->htab, 0, spapr->htab_size); @@ -744,14 +742,6 @@ static void ppc_spapr_init(ram_addr_t ram_size, exit(1); } - fprintf(stderr, "sPAPR memory map:\n"); - fprintf(stderr, "RTAS : 0x%08lx..%08lx\n", - (unsigned long)spapr->rtas_addr, - (unsigned long)(spapr->rtas_addr + spapr->rtas_size - 1)); - fprintf(stderr, "FDT : 0x%08lx..%08lx\n", - (unsigned long)spapr->fdt_addr, - (unsigned long)(spapr->fdt_addr + FDT_MAX_SIZE - 1)); - if (kernel_filename) { uint64_t lowaddr = 0; @@ -767,8 +757,6 @@ static void ppc_spapr_init(ram_addr_t ram_size, kernel_filename); exit(1); } - fprintf(stderr, "Kernel : 0x%08x..%08lx\n", - KERNEL_LOAD_ADDR, KERNEL_LOAD_ADDR + kernel_size - 1); /* load initrd */ if (initrd_filename) { @@ -783,8 +771,6 @@ static void ppc_spapr_init(ram_addr_t ram_size, initrd_filename); exit(1); } - fprintf(stderr, "Ramdisk : 0x%08lx..%08lx\n", - (long)initrd_base, (long)(initrd_base + initrd_size - 1)); } else { initrd_base = 0; initrd_size = 0; @@ -798,10 +784,6 @@ static void ppc_spapr_init(ram_addr_t ram_size, exit(1); } g_free(filename); - fprintf(stderr, "Firmware load : 0x%08x..%08lx\n", - 0, fw_size); - fprintf(stderr, "Firmware runtime : 0x%08lx..%08lx\n", - load_limit, (unsigned long)spapr->fdt_addr); spapr->entry_point = 0x100; From a307d59434ba78b97544b42b8cfd24a1b62e39a6 Mon Sep 17 00:00:00 2001 From: Alexey Kardashevskiy Date: Tue, 7 Aug 2012 16:10:32 +0000 Subject: [PATCH 16/24] pseries: Rework irq assignment to avoid carrying qemu_irqs around Currently, the interfaces in the pseries machine code for assignment and setup of interrupts pass around qemu_irq objects. That was done in an attempt not to be too closely linked to the specific XICS interrupt controller. However interactions with the device tree setup made that attempt rather futile, and XICS is part of the PAPR spec anyway, so this really just meant we had to carry both the qemu_irq pointers and the XICS irq numbers around. This mess will just get worse when we add upcoming PCI MSI support, since that will require tracking a bunch more interrupt. Therefore, this patch reworks the spapr code to just use XICS irq numbers (roughly equivalent to GSIs on x86) and only retrieve the qemu_irq pointers from the XICS code when we need them (a trivial lookup). This is a reworked and generalized version of an earlier spapr_pci specific patch from Alexey Kardashevskiy. Signed-off-by: Alexey Kardashevskiy Signed-off-by: David Gibson [agraf: fix checkpath warning] Signed-off-by: Alexander Graf --- hw/spapr.c | 18 +++++++----------- hw/spapr.h | 11 +++++------ hw/spapr_llan.c | 2 +- hw/spapr_pci.c | 14 ++++++-------- hw/spapr_pci.h | 8 ++++++-- hw/spapr_vio.c | 12 ++++++------ hw/spapr_vio.h | 8 ++++++-- hw/spapr_vty.c | 2 +- hw/xics.c | 12 +++++++++--- hw/xics.h | 5 +++-- 10 files changed, 50 insertions(+), 42 deletions(-) diff --git a/hw/spapr.c b/hw/spapr.c index 032d259e8..40bb6d300 100644 --- a/hw/spapr.c +++ b/hw/spapr.c @@ -84,11 +84,9 @@ sPAPREnvironment *spapr; -qemu_irq spapr_allocate_irq(uint32_t hint, uint32_t *irq_num, - enum xics_irq_type type) +int spapr_allocate_irq(int hint, enum xics_irq_type type) { - uint32_t irq; - qemu_irq qirq; + int irq; if (hint) { irq = hint; @@ -97,16 +95,14 @@ qemu_irq spapr_allocate_irq(uint32_t hint, uint32_t *irq_num, irq = spapr->next_irq++; } - qirq = xics_assign_irq(spapr->icp, irq, type); - if (!qirq) { - return NULL; + /* Configure irq type */ + if (!xics_get_qirq(spapr->icp, irq)) { + return 0; } - if (irq_num) { - *irq_num = irq; - } + xics_set_irq_type(spapr->icp, irq, type); - return qirq; + return irq; } static int spapr_set_associativity(void *fdt, sPAPREnvironment *spapr) diff --git a/hw/spapr.h b/hw/spapr.h index fe40e7d00..b5cf6afca 100644 --- a/hw/spapr.h +++ b/hw/spapr.h @@ -289,17 +289,16 @@ void spapr_register_hypercall(target_ulong opcode, spapr_hcall_fn fn); target_ulong spapr_hypercall(CPUPPCState *env, target_ulong opcode, target_ulong *args); -qemu_irq spapr_allocate_irq(uint32_t hint, uint32_t *irq_num, - enum xics_irq_type type); +int spapr_allocate_irq(int hint, enum xics_irq_type type); -static inline qemu_irq spapr_allocate_msi(uint32_t hint, uint32_t *irq_num) +static inline int spapr_allocate_msi(int hint) { - return spapr_allocate_irq(hint, irq_num, XICS_MSI); + return spapr_allocate_irq(hint, XICS_MSI); } -static inline qemu_irq spapr_allocate_lsi(uint32_t hint, uint32_t *irq_num) +static inline int spapr_allocate_lsi(int hint) { - return spapr_allocate_irq(hint, irq_num, XICS_LSI); + return spapr_allocate_irq(hint, XICS_LSI); } static inline uint32_t rtas_ld(target_ulong phys, int n) diff --git a/hw/spapr_llan.c b/hw/spapr_llan.c index 01e54f367..bd3f131d7 100644 --- a/hw/spapr_llan.c +++ b/hw/spapr_llan.c @@ -169,7 +169,7 @@ static ssize_t spapr_vlan_receive(NetClientState *nc, const uint8_t *buf, } if (sdev->signal_state & 1) { - qemu_irq_pulse(sdev->qirq); + qemu_irq_pulse(spapr_vio_qirq(sdev)); } return size; diff --git a/hw/spapr_pci.c b/hw/spapr_pci.c index 291354094..65ae8c480 100644 --- a/hw/spapr_pci.c +++ b/hw/spapr_pci.c @@ -223,7 +223,7 @@ static void pci_spapr_set_irq(void *opaque, int irq_num, int level) */ sPAPRPHBState *phb = opaque; - qemu_set_irq(phb->lsi_table[irq_num].qirq, level); + qemu_set_irq(spapr_phb_lsi_qirq(phb, irq_num), level); } static uint64_t spapr_io_read(void *opaque, target_phys_addr_t addr, @@ -329,16 +329,14 @@ static int spapr_phb_init(SysBusDevice *s) /* Initialize the LSI table */ for (i = 0; i < PCI_NUM_PINS; i++) { - qemu_irq qirq; - uint32_t num; + uint32_t irq; - qirq = spapr_allocate_lsi(0, &num); - if (!qirq) { + irq = spapr_allocate_lsi(0); + if (!irq) { return -1; } - phb->lsi_table[i].dt_irq = num; - phb->lsi_table[i].qirq = qirq; + phb->lsi_table[i].irq = irq; } return 0; @@ -477,7 +475,7 @@ int spapr_populate_pci_dt(sPAPRPHBState *phb, irqmap[2] = 0; irqmap[3] = cpu_to_be32(j+1); irqmap[4] = cpu_to_be32(xics_phandle); - irqmap[5] = cpu_to_be32(phb->lsi_table[lsi_num].dt_irq); + irqmap[5] = cpu_to_be32(phb->lsi_table[lsi_num].irq); irqmap[6] = cpu_to_be32(0x8); } } diff --git a/hw/spapr_pci.h b/hw/spapr_pci.h index dd66f4b38..6bba88560 100644 --- a/hw/spapr_pci.h +++ b/hw/spapr_pci.h @@ -40,13 +40,17 @@ typedef struct sPAPRPHBState { DMAContext *dma; struct { - uint32_t dt_irq; - qemu_irq qirq; + uint32_t irq; } lsi_table[PCI_NUM_PINS]; QLIST_ENTRY(sPAPRPHBState) list; } sPAPRPHBState; +static inline qemu_irq spapr_phb_lsi_qirq(struct sPAPRPHBState *phb, int pin) +{ + return xics_get_qirq(spapr->icp, phb->lsi_table[pin].irq); +} + #define SPAPR_PCI_MEM_WIN_BUS_OFFSET 0x80000000ULL #define SPAPR_PCI_IO_WIN_SIZE 0x10000 diff --git a/hw/spapr_vio.c b/hw/spapr_vio.c index 05b55032a..3abe853f3 100644 --- a/hw/spapr_vio.c +++ b/hw/spapr_vio.c @@ -49,7 +49,7 @@ #endif static Property spapr_vio_props[] = { - DEFINE_PROP_UINT32("irq", VIOsPAPRDevice, vio_irq_num, 0), \ + DEFINE_PROP_UINT32("irq", VIOsPAPRDevice, irq, 0), \ DEFINE_PROP_END_OF_LIST(), }; @@ -132,8 +132,8 @@ static int vio_make_devnode(VIOsPAPRDevice *dev, } } - if (dev->qirq) { - uint32_t ints_prop[] = {cpu_to_be32(dev->vio_irq_num), 0}; + if (dev->irq) { + uint32_t ints_prop[] = {cpu_to_be32(dev->irq), 0}; ret = fdt_setprop(fdt, node_off, "interrupts", ints_prop, sizeof(ints_prop)); @@ -306,7 +306,7 @@ int spapr_vio_send_crq(VIOsPAPRDevice *dev, uint8_t *crq) dev->crq.qnext = (dev->crq.qnext + 16) % dev->crq.qsize; if (dev->signal_state & 1) { - qemu_irq_pulse(dev->qirq); + qemu_irq_pulse(spapr_vio_qirq(dev)); } return 0; @@ -459,8 +459,8 @@ static int spapr_vio_busdev_init(DeviceState *qdev) dev->qdev.id = id; } - dev->qirq = spapr_allocate_msi(dev->vio_irq_num, &dev->vio_irq_num); - if (!dev->qirq) { + dev->irq = spapr_allocate_msi(dev->irq); + if (!dev->irq) { return -1; } diff --git a/hw/spapr_vio.h b/hw/spapr_vio.h index 6f9a498cc..ea6aa43e2 100644 --- a/hw/spapr_vio.h +++ b/hw/spapr_vio.h @@ -61,8 +61,7 @@ struct VIOsPAPRDevice { DeviceState qdev; uint32_t reg; uint32_t flags; - qemu_irq qirq; - uint32_t vio_irq_num; + uint32_t irq; target_ulong signal_state; VIOsPAPR_CRQ crq; DMAContext *dma; @@ -85,6 +84,11 @@ extern int spapr_populate_chosen_stdout(void *fdt, VIOsPAPRBus *bus); extern int spapr_vio_signal(VIOsPAPRDevice *dev, target_ulong mode); +static inline qemu_irq spapr_vio_qirq(VIOsPAPRDevice *dev) +{ + return xics_get_qirq(spapr->icp, dev->irq); +} + static inline bool spapr_vio_dma_valid(VIOsPAPRDevice *dev, uint64_t taddr, uint32_t size, DMADirection dir) { diff --git a/hw/spapr_vty.c b/hw/spapr_vty.c index 99e52cc6b..5da17a3ff 100644 --- a/hw/spapr_vty.c +++ b/hw/spapr_vty.c @@ -26,7 +26,7 @@ static void vty_receive(void *opaque, const uint8_t *buf, int size) if ((dev->in == dev->out) && size) { /* toggle line to simulate edge interrupt */ - qemu_irq_pulse(dev->sdev.qirq); + qemu_irq_pulse(spapr_vio_qirq(&dev->sdev)); } for (i = 0; i < size; i++) { assert((dev->in - dev->out) < VTERM_BUFSIZE); diff --git a/hw/xics.c b/hw/xics.c index 668a0d648..b674771dc 100644 --- a/hw/xics.c +++ b/hw/xics.c @@ -315,18 +315,24 @@ static void ics_eoi(struct ics_state *ics, int nr) * Exported functions */ -qemu_irq xics_assign_irq(struct icp_state *icp, int irq, - enum xics_irq_type type) +qemu_irq xics_get_qirq(struct icp_state *icp, int irq) { if ((irq < icp->ics->offset) || (irq >= (icp->ics->offset + icp->ics->nr_irqs))) { return NULL; } + return icp->ics->qirqs[irq - icp->ics->offset]; +} + +void xics_set_irq_type(struct icp_state *icp, int irq, + enum xics_irq_type type) +{ + assert((irq >= icp->ics->offset) + && (irq < (icp->ics->offset + icp->ics->nr_irqs))); assert((type == XICS_MSI) || (type == XICS_LSI)); icp->ics->irqs[irq - icp->ics->offset].type = type; - return icp->ics->qirqs[irq - icp->ics->offset]; } static target_ulong h_cppr(CPUPPCState *env, sPAPREnvironment *spapr, diff --git a/hw/xics.h b/hw/xics.h index 208015939..99b96ac85 100644 --- a/hw/xics.h +++ b/hw/xics.h @@ -36,8 +36,9 @@ enum xics_irq_type { XICS_LSI, /* Level-signalled interrupt */ }; -qemu_irq xics_assign_irq(struct icp_state *icp, int irq, - enum xics_irq_type type); +qemu_irq xics_get_qirq(struct icp_state *icp, int irq); +void xics_set_irq_type(struct icp_state *icp, int irq, + enum xics_irq_type type); struct icp_state *xics_system_init(int nr_irqs); From fa28f71b4a88cdb796f1e0a308205c6be604d3f3 Mon Sep 17 00:00:00 2001 From: Alexey Kardashevskiy Date: Tue, 7 Aug 2012 16:10:33 +0000 Subject: [PATCH 17/24] pseries: Separate PCI RTAS setup from common from emulation specific PCI setup Currently the RTAS functions for handling PCI are registered from the class init code for the PCI host bridge. That sort of makes sense now, but will break in the future when vfio gives us multiple types of host bridge for pseries (emulated and pass-through, at least). The RTAS functions will be common across all host bridge types (and will call out to different places internally depending on the type). So, this patch moves the RTAS registration into its own function called direct from the machine setup code. Signed-off-by: Alexey Kardashevskiy Signed-off-by: David Gibson Signed-off-by: Alexander Graf --- hw/spapr.c | 2 ++ hw/spapr_pci.c | 13 ++++++++----- hw/spapr_pci.h | 2 ++ 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/hw/spapr.c b/hw/spapr.c index 40bb6d300..8153c0563 100644 --- a/hw/spapr.c +++ b/hw/spapr.c @@ -704,6 +704,8 @@ static void ppc_spapr_init(ram_addr_t ram_size, } /* Set up PCI */ + spapr_pci_rtas_init(); + spapr_create_phb(spapr, "pci", SPAPR_PCI_BUID, SPAPR_PCI_MEM_WIN_ADDR, SPAPR_PCI_MEM_WIN_SIZE, diff --git a/hw/spapr_pci.c b/hw/spapr_pci.c index 65ae8c480..fcc358e4c 100644 --- a/hw/spapr_pci.c +++ b/hw/spapr_pci.c @@ -359,11 +359,6 @@ static void spapr_phb_class_init(ObjectClass *klass, void *data) sdc->init = spapr_phb_init; dc->props = spapr_phb_properties; - - spapr_rtas_register("read-pci-config", rtas_read_pci_config); - spapr_rtas_register("write-pci-config", rtas_write_pci_config); - spapr_rtas_register("ibm,read-pci-config", rtas_ibm_read_pci_config); - spapr_rtas_register("ibm,write-pci-config", rtas_ibm_write_pci_config); } static TypeInfo spapr_phb_info = { @@ -488,6 +483,14 @@ int spapr_populate_pci_dt(sPAPRPHBState *phb, return 0; } +void spapr_pci_rtas_init(void) +{ + spapr_rtas_register("read-pci-config", rtas_read_pci_config); + spapr_rtas_register("write-pci-config", rtas_write_pci_config); + spapr_rtas_register("ibm,read-pci-config", rtas_ibm_read_pci_config); + spapr_rtas_register("ibm,write-pci-config", rtas_ibm_write_pci_config); +} + static void register_types(void) { type_register_static(&spapr_phb_info); diff --git a/hw/spapr_pci.h b/hw/spapr_pci.h index 6bba88560..2aee67fd4 100644 --- a/hw/spapr_pci.h +++ b/hw/spapr_pci.h @@ -63,4 +63,6 @@ int spapr_populate_pci_dt(sPAPRPHBState *phb, uint32_t xics_phandle, void *fdt); +void spapr_pci_rtas_init(void); + #endif /* __HW_SPAPR_PCI_H__ */ From f4b9523ba6388f6f951933de3f9a76e2e9ea2ede Mon Sep 17 00:00:00 2001 From: Alexey Kardashevskiy Date: Tue, 7 Aug 2012 16:10:34 +0000 Subject: [PATCH 18/24] pseries: added allocator for a block of IRQs The patch adds a simple helper which allocates a consecutive sequence of IRQs calling spapr_allocate_irq for each and checks that allocated IRQs go consequently. The patch is required for upcoming support of MSI/MSIX on POWER. Signed-off-by: Alexey Kardashevskiy Signed-off-by: David Gibson Signed-off-by: Alexander Graf --- hw/spapr.c | 26 ++++++++++++++++++++++++++ hw/spapr.h | 1 + 2 files changed, 27 insertions(+) diff --git a/hw/spapr.c b/hw/spapr.c index 8153c0563..afbdbc586 100644 --- a/hw/spapr.c +++ b/hw/spapr.c @@ -105,6 +105,32 @@ int spapr_allocate_irq(int hint, enum xics_irq_type type) return irq; } +/* Allocate block of consequtive IRQs, returns a number of the first */ +int spapr_allocate_irq_block(int num, enum xics_irq_type type) +{ + int first = -1; + int i; + + for (i = 0; i < num; ++i) { + int irq; + + irq = spapr_allocate_irq(0, type); + if (!irq) { + return -1; + } + + if (0 == i) { + first = irq; + } + + /* If the above doesn't create a consecutive block then that's + * an internal bug */ + assert(irq == (first + i)); + } + + return first; +} + static int spapr_set_associativity(void *fdt, sPAPREnvironment *spapr) { int ret = 0, offset; diff --git a/hw/spapr.h b/hw/spapr.h index b5cf6afca..6229769ce 100644 --- a/hw/spapr.h +++ b/hw/spapr.h @@ -290,6 +290,7 @@ target_ulong spapr_hypercall(CPUPPCState *env, target_ulong opcode, target_ulong *args); int spapr_allocate_irq(int hint, enum xics_irq_type type); +int spapr_allocate_irq_block(int num, enum xics_irq_type type); static inline int spapr_allocate_msi(int hint) { From 9894c5d4b467d24e281c22f2f5e24822c9b55fb3 Mon Sep 17 00:00:00 2001 From: Alexey Kardashevskiy Date: Tue, 7 Aug 2012 16:10:35 +0000 Subject: [PATCH 19/24] pseries: Export find_phb() utility function for PCI code The pseries PCI code makes use of an internal find_dev() function which locates a PCIDevice * given a (platform specific) bus ID and device address. Internally this needs to first locate the host bridge on which the device resides based on the bus ID. This patch exposes that host bridge lookup as a separate function, which we will need later in the MSI and VFIO code. Signed-off-by: Alexey Kardashevskiy Signed-off-by: David Gibson [agraf: drop trace.h inclusion] Signed-off-by: Alexander Graf --- hw/spapr_pci.c | 31 +++++++++++++++++++++---------- 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/hw/spapr_pci.c b/hw/spapr_pci.c index fcc358e4c..2e38fee01 100644 --- a/hw/spapr_pci.c +++ b/hw/spapr_pci.c @@ -32,24 +32,35 @@ #include "hw/pci_internals.h" -static PCIDevice *find_dev(sPAPREnvironment *spapr, - uint64_t buid, uint32_t config_addr) +static sPAPRPHBState *find_phb(sPAPREnvironment *spapr, uint64_t buid) { - int devfn = (config_addr >> 8) & 0xFF; sPAPRPHBState *phb; QLIST_FOREACH(phb, &spapr->phbs, list) { - BusChild *kid; - if (phb->buid != buid) { continue; } + return phb; + } - QTAILQ_FOREACH(kid, &phb->host_state.bus->qbus.children, sibling) { - PCIDevice *dev = (PCIDevice *)kid->child; - if (dev->devfn == devfn) { - return dev; - } + return NULL; +} + +static PCIDevice *find_dev(sPAPREnvironment *spapr, uint64_t buid, + uint32_t config_addr) +{ + sPAPRPHBState *phb = find_phb(spapr, buid); + BusChild *kid; + int devfn = (config_addr >> 8) & 0xFF; + + if (!phb) { + return NULL; + } + + QTAILQ_FOREACH(kid, &phb->host_state.bus->qbus.children, sibling) { + PCIDevice *dev = (PCIDevice *)kid->child; + if (dev->devfn == devfn) { + return dev; } } From a2950fb6e795e3e10fed35d347a7aa28a44be2ff Mon Sep 17 00:00:00 2001 From: Alexey Kardashevskiy Date: Tue, 7 Aug 2012 16:10:36 +0000 Subject: [PATCH 20/24] pseries: Add trace event for PCI irqs This adds a trace event in the pseries PCI specific set_irq() function to assist in debugging. Signed-off-by: Alexey Kardashevskiy Signed-off-by: David Gibson [agraf: add trace.h include] Signed-off-by: Alexander Graf --- hw/spapr_pci.c | 2 ++ trace-events | 3 +++ 2 files changed, 5 insertions(+) diff --git a/hw/spapr_pci.c b/hw/spapr_pci.c index 2e38fee01..1eb1a7edc 100644 --- a/hw/spapr_pci.c +++ b/hw/spapr_pci.c @@ -29,6 +29,7 @@ #include "hw/spapr_pci.h" #include "exec-memory.h" #include +#include "trace.h" #include "hw/pci_internals.h" @@ -234,6 +235,7 @@ static void pci_spapr_set_irq(void *opaque, int irq_num, int level) */ sPAPRPHBState *phb = opaque; + trace_spapr_pci_lsi_set(phb->busname, irq_num, phb->lsi_table[irq_num].irq); qemu_set_irq(spapr_phb_lsi_qirq(phb, irq_num), level); } diff --git a/trace-events b/trace-events index 6b12f83de..191b39ebd 100644 --- a/trace-events +++ b/trace-events @@ -970,3 +970,6 @@ qxl_render_blit_guest_primary_initialized(void) "" qxl_render_blit(int32_t stride, int32_t left, int32_t right, int32_t top, int32_t bottom) "stride=%d [%d, %d, %d, %d]" qxl_render_guest_primary_resized(int32_t width, int32_t height, int32_t stride, int32_t bytes_pp, int32_t bits_pp) "%dx%d, stride %d, bpp %d, depth %d" qxl_render_update_area_done(void *cookie) "%p" + +# hw/spapr_pci.c +spapr_pci_lsi_set(const char *busname, int pin, uint32_t irq) "%s PIN%d IRQ %u" From 0ee2c058a3fe485b8901186179102e251a33d082 Mon Sep 17 00:00:00 2001 From: Alexey Kardashevskiy Date: Tue, 7 Aug 2012 16:10:37 +0000 Subject: [PATCH 21/24] pseries: Add PCI MSI/MSI-X support This patch implements MSI and MSI-X support for the pseries PCI host bridge. To do this it adds: * A "config_space_address to msi_table" map, since the MSI RTAS calls take a PCI config space address as an identifier. * A MSIX memory region to catch msi_notify()/msix_notiry() from virtio-pci and pass them to the guest via qemu_irq_pulse(). * RTAS call "ibm,change-msi" which sets up MSI vectors for a device. Note that this call may configure and return lesser number of vectors than requested. * RTAS call "ibm,query-interrupt-source-number" which translates MSI vector to interrupt controller (XICS) IRQ number. Signed-off-by: Alexey Kardashevskiy Signed-off-by: David Gibson [agraf: fix error case ndev < 0] Signed-off-by: Alexander Graf --- hw/spapr.c | 7 +- hw/spapr_pci.c | 245 ++++++++++++++++++++++++++++++++++++++++++++++++- hw/spapr_pci.h | 15 ++- trace-events | 5 + 4 files changed, 268 insertions(+), 4 deletions(-) diff --git a/hw/spapr.c b/hw/spapr.c index afbdbc586..5178721d4 100644 --- a/hw/spapr.c +++ b/hw/spapr.c @@ -41,6 +41,7 @@ #include "hw/spapr_vio.h" #include "hw/spapr_pci.h" #include "hw/xics.h" +#include "hw/msi.h" #include "kvm.h" #include "kvm_ppc.h" @@ -79,6 +80,7 @@ #define SPAPR_PCI_MEM_WIN_ADDR (0x10000000000ULL + 0xA0000000) #define SPAPR_PCI_MEM_WIN_SIZE 0x20000000 #define SPAPR_PCI_IO_WIN_ADDR (0x10000000000ULL + 0x80000000) +#define SPAPR_PCI_MSI_WIN_ADDR (0x10000000000ULL + 0x90000000) #define PHANDLE_XICP 0x00001111 @@ -619,6 +621,8 @@ static void ppc_spapr_init(ram_addr_t ram_size, long pteg_shift = 17; char *filename; + msi_supported = true; + spapr = g_malloc0(sizeof(*spapr)); QLIST_INIT(&spapr->phbs); @@ -735,7 +739,8 @@ static void ppc_spapr_init(ram_addr_t ram_size, spapr_create_phb(spapr, "pci", SPAPR_PCI_BUID, SPAPR_PCI_MEM_WIN_ADDR, SPAPR_PCI_MEM_WIN_SIZE, - SPAPR_PCI_IO_WIN_ADDR); + SPAPR_PCI_IO_WIN_ADDR, + SPAPR_PCI_MSI_WIN_ADDR); for (i = 0; i < nb_nics; i++) { NICInfo *nd = &nd_table[i]; diff --git a/hw/spapr_pci.c b/hw/spapr_pci.c index 1eb1a7edc..780a4d6f1 100644 --- a/hw/spapr_pci.c +++ b/hw/spapr_pci.c @@ -24,6 +24,8 @@ */ #include "hw.h" #include "pci.h" +#include "msi.h" +#include "msix.h" #include "pci_host.h" #include "hw/spapr.h" #include "hw/spapr_pci.h" @@ -33,6 +35,17 @@ #include "hw/pci_internals.h" +/* Copied from the kernel arch/powerpc/platforms/pseries/msi.c */ +#define RTAS_QUERY_FN 0 +#define RTAS_CHANGE_FN 1 +#define RTAS_RESET_FN 2 +#define RTAS_CHANGE_MSI_FN 3 +#define RTAS_CHANGE_MSIX_FN 4 + +/* Interrupt types to return on RTAS_CHANGE_* */ +#define RTAS_TYPE_MSI 1 +#define RTAS_TYPE_MSIX 2 + static sPAPRPHBState *find_phb(sPAPREnvironment *spapr, uint64_t buid) { sPAPRPHBState *phb; @@ -211,6 +224,191 @@ static void rtas_write_pci_config(sPAPREnvironment *spapr, finish_write_pci_config(spapr, 0, addr, size, val, rets); } +/* + * Find an entry with config_addr or returns the empty one if not found AND + * alloc_new is set. + * At the moment the msi_table entries are never released so there is + * no point to look till the end of the list if we need to find the free entry. + */ +static int spapr_msicfg_find(sPAPRPHBState *phb, uint32_t config_addr, + bool alloc_new) +{ + int i; + + for (i = 0; i < SPAPR_MSIX_MAX_DEVS; ++i) { + if (!phb->msi_table[i].nvec) { + break; + } + if (phb->msi_table[i].config_addr == config_addr) { + return i; + } + } + if ((i < SPAPR_MSIX_MAX_DEVS) && alloc_new) { + trace_spapr_pci_msi("Allocating new MSI config", i, config_addr); + return i; + } + + return -1; +} + +/* + * Set MSI/MSIX message data. + * This is required for msi_notify()/msix_notify() which + * will write at the addresses via spapr_msi_write(). + */ +static void spapr_msi_setmsg(PCIDevice *pdev, target_phys_addr_t addr, + bool msix, unsigned req_num) +{ + unsigned i; + MSIMessage msg = { .address = addr, .data = 0 }; + + if (!msix) { + msi_set_message(pdev, msg); + trace_spapr_pci_msi_setup(pdev->name, 0, msg.address); + return; + } + + for (i = 0; i < req_num; ++i) { + msg.address = addr | (i << 2); + msix_set_message(pdev, i, msg); + trace_spapr_pci_msi_setup(pdev->name, i, msg.address); + } +} + +static void rtas_ibm_change_msi(sPAPREnvironment *spapr, + uint32_t token, uint32_t nargs, + target_ulong args, uint32_t nret, + target_ulong rets) +{ + uint32_t config_addr = rtas_ld(args, 0); + uint64_t buid = ((uint64_t)rtas_ld(args, 1) << 32) | rtas_ld(args, 2); + unsigned int func = rtas_ld(args, 3); + unsigned int req_num = rtas_ld(args, 4); /* 0 == remove all */ + unsigned int seq_num = rtas_ld(args, 5); + unsigned int ret_intr_type; + int ndev, irq; + sPAPRPHBState *phb = NULL; + PCIDevice *pdev = NULL; + + switch (func) { + case RTAS_CHANGE_MSI_FN: + case RTAS_CHANGE_FN: + ret_intr_type = RTAS_TYPE_MSI; + break; + case RTAS_CHANGE_MSIX_FN: + ret_intr_type = RTAS_TYPE_MSIX; + break; + default: + fprintf(stderr, "rtas_ibm_change_msi(%u) is not implemented\n", func); + rtas_st(rets, 0, -3); /* Parameter error */ + return; + } + + /* Fins sPAPRPHBState */ + phb = find_phb(spapr, buid); + if (phb) { + pdev = find_dev(spapr, buid, config_addr); + } + if (!phb || !pdev) { + rtas_st(rets, 0, -3); /* Parameter error */ + return; + } + + /* Releasing MSIs */ + if (!req_num) { + ndev = spapr_msicfg_find(phb, config_addr, false); + if (ndev < 0) { + trace_spapr_pci_msi("MSI has not been enabled", -1, config_addr); + rtas_st(rets, 0, -1); /* Hardware error */ + return; + } + trace_spapr_pci_msi("Released MSIs", ndev, config_addr); + rtas_st(rets, 0, 0); + rtas_st(rets, 1, 0); + return; + } + + /* Enabling MSI */ + + /* Find a device number in the map to add or reuse the existing one */ + ndev = spapr_msicfg_find(phb, config_addr, true); + if (ndev >= SPAPR_MSIX_MAX_DEVS || ndev < 0) { + fprintf(stderr, "No free entry for a new MSI device\n"); + rtas_st(rets, 0, -1); /* Hardware error */ + return; + } + trace_spapr_pci_msi("Configuring MSI", ndev, config_addr); + + /* Check if there is an old config and MSI number has not changed */ + if (phb->msi_table[ndev].nvec && (req_num != phb->msi_table[ndev].nvec)) { + /* Unexpected behaviour */ + fprintf(stderr, "Cannot reuse MSI config for device#%d", ndev); + rtas_st(rets, 0, -1); /* Hardware error */ + return; + } + + /* There is no cached config, allocate MSIs */ + if (!phb->msi_table[ndev].nvec) { + irq = spapr_allocate_irq_block(req_num, XICS_MSI); + if (irq < 0) { + fprintf(stderr, "Cannot allocate MSIs for device#%d", ndev); + rtas_st(rets, 0, -1); /* Hardware error */ + return; + } + phb->msi_table[ndev].irq = irq; + phb->msi_table[ndev].nvec = req_num; + phb->msi_table[ndev].config_addr = config_addr; + } + + /* Setup MSI/MSIX vectors in the device (via cfgspace or MSIX BAR) */ + spapr_msi_setmsg(pdev, phb->msi_win_addr | (ndev << 16), + ret_intr_type == RTAS_TYPE_MSIX, req_num); + + rtas_st(rets, 0, 0); + rtas_st(rets, 1, req_num); + rtas_st(rets, 2, ++seq_num); + rtas_st(rets, 3, ret_intr_type); + + trace_spapr_pci_rtas_ibm_change_msi(func, req_num); +} + +static void rtas_ibm_query_interrupt_source_number(sPAPREnvironment *spapr, + uint32_t token, + uint32_t nargs, + target_ulong args, + uint32_t nret, + target_ulong rets) +{ + uint32_t config_addr = rtas_ld(args, 0); + uint64_t buid = ((uint64_t)rtas_ld(args, 1) << 32) | rtas_ld(args, 2); + unsigned int intr_src_num = -1, ioa_intr_num = rtas_ld(args, 3); + int ndev; + sPAPRPHBState *phb = NULL; + + /* Fins sPAPRPHBState */ + phb = find_phb(spapr, buid); + if (!phb) { + rtas_st(rets, 0, -3); /* Parameter error */ + return; + } + + /* Find device descriptor and start IRQ */ + ndev = spapr_msicfg_find(phb, config_addr, false); + if (ndev < 0) { + trace_spapr_pci_msi("MSI has not been enabled", -1, config_addr); + rtas_st(rets, 0, -1); /* Hardware error */ + return; + } + + intr_src_num = phb->msi_table[ndev].irq + ioa_intr_num; + trace_spapr_pci_rtas_ibm_query_interrupt_source_number(ioa_intr_num, + intr_src_num); + + rtas_st(rets, 0, 0); + rtas_st(rets, 1, intr_src_num); + rtas_st(rets, 2, 1);/* 0 == level; 1 == edge */ +} + static int pci_spapr_swizzle(int slot, int pin) { return (slot + pin) % PCI_NUM_PINS; @@ -276,6 +474,33 @@ static const MemoryRegionOps spapr_io_ops = { .write = spapr_io_write }; +/* + * MSI/MSIX memory region implementation. + * The handler handles both MSI and MSIX. + * For MSI-X, the vector number is encoded as a part of the address, + * data is set to 0. + * For MSI, the vector number is encoded in least bits in data. + */ +static void spapr_msi_write(void *opaque, target_phys_addr_t addr, + uint64_t data, unsigned size) +{ + sPAPRPHBState *phb = opaque; + int ndev = addr >> 16; + int vec = ((addr & 0xFFFF) >> 2) | data; + uint32_t irq = phb->msi_table[ndev].irq + vec; + + trace_spapr_pci_msi_write(addr, data, irq); + + qemu_irq_pulse(xics_get_qirq(spapr->icp, irq)); +} + +static const MemoryRegionOps spapr_msi_ops = { + /* There is no .read as the read result is undefined by PCI spec */ + .read = NULL, + .write = spapr_msi_write, + .endianness = DEVICE_LITTLE_ENDIAN +}; + /* * PHB PCI device */ @@ -327,6 +552,17 @@ static int spapr_phb_init(SysBusDevice *s) memory_region_add_subregion(get_system_memory(), phb->io_win_addr, &phb->iowindow); + /* As MSI/MSIX interrupts trigger by writing at MSI/MSIX vectors, + * we need to allocate some memory to catch those writes coming + * from msi_notify()/msix_notify() */ + if (msi_supported) { + sprintf(namebuf, "%s.msi", phb->dtbusname); + memory_region_init_io(&phb->msiwindow, &spapr_msi_ops, phb, + namebuf, SPAPR_MSIX_MAX_DEVS * 0x10000); + memory_region_add_subregion(get_system_memory(), phb->msi_win_addr, + &phb->msiwindow); + } + bus = pci_register_bus(&phb->host_state.busdev.qdev, phb->busname ? phb->busname : phb->dtbusname, pci_spapr_set_irq, pci_spapr_map_irq, phb, @@ -362,6 +598,7 @@ static Property spapr_phb_properties[] = { DEFINE_PROP_HEX64("mem_win_size", sPAPRPHBState, mem_win_size, 0x20000000), DEFINE_PROP_HEX64("io_win_addr", sPAPRPHBState, io_win_addr, 0), DEFINE_PROP_HEX64("io_win_size", sPAPRPHBState, io_win_size, 0x10000), + DEFINE_PROP_HEX64("msi_win_addr", sPAPRPHBState, msi_win_addr, 0), DEFINE_PROP_END_OF_LIST(), }; @@ -384,7 +621,7 @@ static TypeInfo spapr_phb_info = { void spapr_create_phb(sPAPREnvironment *spapr, const char *busname, uint64_t buid, uint64_t mem_win_addr, uint64_t mem_win_size, - uint64_t io_win_addr) + uint64_t io_win_addr, uint64_t msi_win_addr) { DeviceState *dev; @@ -397,6 +634,7 @@ void spapr_create_phb(sPAPREnvironment *spapr, qdev_prop_set_uint64(dev, "mem_win_addr", mem_win_addr); qdev_prop_set_uint64(dev, "mem_win_size", mem_win_size); qdev_prop_set_uint64(dev, "io_win_addr", io_win_addr); + qdev_prop_set_uint64(dev, "msi_win_addr", msi_win_addr); qdev_init_nofail(dev); } @@ -502,6 +740,11 @@ void spapr_pci_rtas_init(void) spapr_rtas_register("write-pci-config", rtas_write_pci_config); spapr_rtas_register("ibm,read-pci-config", rtas_ibm_read_pci_config); spapr_rtas_register("ibm,write-pci-config", rtas_ibm_write_pci_config); + if (msi_supported) { + spapr_rtas_register("ibm,query-interrupt-source-number", + rtas_ibm_query_interrupt_source_number); + spapr_rtas_register("ibm,change-msi", rtas_ibm_change_msi); + } } static void register_types(void) diff --git a/hw/spapr_pci.h b/hw/spapr_pci.h index 2aee67fd4..6892e4fae 100644 --- a/hw/spapr_pci.h +++ b/hw/spapr_pci.h @@ -27,6 +27,8 @@ #include "hw/pci_host.h" #include "hw/xics.h" +#define SPAPR_MSIX_MAX_DEVS 32 + typedef struct sPAPRPHBState { PCIHostState host_state; @@ -36,13 +38,22 @@ typedef struct sPAPRPHBState { MemoryRegion memspace, iospace; target_phys_addr_t mem_win_addr, mem_win_size, io_win_addr, io_win_size; - MemoryRegion memwindow, iowindow; + target_phys_addr_t msi_win_addr; + MemoryRegion memwindow, iowindow, msiwindow; + + DMAContext *dma; struct { uint32_t irq; } lsi_table[PCI_NUM_PINS]; + struct { + uint32_t config_addr; + uint32_t irq; + int nvec; + } msi_table[SPAPR_MSIX_MAX_DEVS]; + QLIST_ENTRY(sPAPRPHBState) list; } sPAPRPHBState; @@ -57,7 +68,7 @@ static inline qemu_irq spapr_phb_lsi_qirq(struct sPAPRPHBState *phb, int pin) void spapr_create_phb(sPAPREnvironment *spapr, const char *busname, uint64_t buid, uint64_t mem_win_addr, uint64_t mem_win_size, - uint64_t io_win_addr); + uint64_t io_win_addr, uint64_t msi_win_addr); int spapr_populate_pci_dt(sPAPRPHBState *phb, uint32_t xics_phandle, diff --git a/trace-events b/trace-events index 191b39ebd..04b072392 100644 --- a/trace-events +++ b/trace-events @@ -972,4 +972,9 @@ qxl_render_guest_primary_resized(int32_t width, int32_t height, int32_t stride, qxl_render_update_area_done(void *cookie) "%p" # hw/spapr_pci.c +spapr_pci_msi(const char *msg, uint32_t n, uint32_t ca) "%s (device#%d, cfg=%x)" +spapr_pci_msi_setup(const char *name, unsigned vector, uint64_t addr) "dev\"%s\" vector %u, addr=%"PRIx64 +spapr_pci_rtas_ibm_change_msi(unsigned func, unsigned req) "func %u, requested %u" +spapr_pci_rtas_ibm_query_interrupt_source_number(unsigned ioa, unsigned intr) "queries for #%u, IRQ%u" +spapr_pci_msi_write(uint64_t addr, uint64_t data, uint32_t dt_irq) "@%"PRIx64"<=%"PRIx64" IRQ %u" spapr_pci_lsi_set(const char *busname, int pin, uint32_t irq) "%s PIN%d IRQ %u" From 5c4cbcf26ca9465a36fc0661b4103d55897e1a19 Mon Sep 17 00:00:00 2001 From: Alexey Kardashevskiy Date: Tue, 7 Aug 2012 16:10:38 +0000 Subject: [PATCH 22/24] pseries dma: DMA window params added to PHB and DT population changed Previously the only PCI bus supported was the emulated PCI bus with fixed DMA window with start at 0 and size 1GB. As we are going to support PCI pass through which DMA window properties are set by the host kernel, we have to support DMA windows with parameters other than default. This patch adds: 1. DMA window properties to sPAPRPHBState: LIOBN (bus id), start, size of the window. 2. An additional function spapr_dma_dt() to populate DMA window properties in the device tree which simply accepts all the parameters and does not try to guess what kind of IOMMU is given to it. The original spapr_dma_dt() is renamed to spapr_tcet_dma_dt(). Signed-off-by: Alexey Kardashevskiy Signed-off-by: David Gibson Signed-off-by: Alexander Graf --- hw/spapr.h | 4 +++- hw/spapr_iommu.c | 56 +++++++++++++++++++++++++++++++----------------- hw/spapr_pci.c | 11 ++++++---- hw/spapr_pci.h | 4 +++- hw/spapr_vio.c | 2 +- 5 files changed, 50 insertions(+), 27 deletions(-) diff --git a/hw/spapr.h b/hw/spapr.h index 6229769ce..ac34a171e 100644 --- a/hw/spapr.h +++ b/hw/spapr.h @@ -337,6 +337,8 @@ void spapr_iommu_init(void); DMAContext *spapr_tce_new_dma_context(uint32_t liobn, size_t window_size); void spapr_tce_free(DMAContext *dma); int spapr_dma_dt(void *fdt, int node_off, const char *propname, - DMAContext *dma); + uint32_t liobn, uint64_t window, uint32_t size); +int spapr_tcet_dma_dt(void *fdt, int node_off, const char *propname, + DMAContext *dma); #endif /* !defined (__HW_SPAPR_H__) */ diff --git a/hw/spapr_iommu.c b/hw/spapr_iommu.c index 388ffa4b2..53b731773 100644 --- a/hw/spapr_iommu.c +++ b/hw/spapr_iommu.c @@ -216,31 +216,47 @@ void spapr_iommu_init(void) } int spapr_dma_dt(void *fdt, int node_off, const char *propname, - DMAContext *dma) + uint32_t liobn, uint64_t window, uint32_t size) { - if (dma) { - sPAPRTCETable *tcet = DO_UPCAST(sPAPRTCETable, dma, dma); - uint32_t dma_prop[] = {cpu_to_be32(tcet->liobn), - 0, 0, - 0, cpu_to_be32(tcet->window_size)}; - int ret; + uint32_t dma_prop[5]; + int ret; - ret = fdt_setprop_cell(fdt, node_off, "ibm,#dma-address-cells", 2); - if (ret < 0) { - return ret; - } + dma_prop[0] = cpu_to_be32(liobn); + dma_prop[1] = cpu_to_be32(window >> 32); + dma_prop[2] = cpu_to_be32(window & 0xFFFFFFFF); + dma_prop[3] = 0; /* window size is 32 bits */ + dma_prop[4] = cpu_to_be32(size); - ret = fdt_setprop_cell(fdt, node_off, "ibm,#dma-size-cells", 2); - if (ret < 0) { - return ret; - } + ret = fdt_setprop_cell(fdt, node_off, "ibm,#dma-address-cells", 2); + if (ret < 0) { + return ret; + } - ret = fdt_setprop(fdt, node_off, propname, dma_prop, - sizeof(dma_prop)); - if (ret < 0) { - return ret; - } + ret = fdt_setprop_cell(fdt, node_off, "ibm,#dma-size-cells", 2); + if (ret < 0) { + return ret; + } + + ret = fdt_setprop(fdt, node_off, propname, dma_prop, sizeof(dma_prop)); + if (ret < 0) { + return ret; } return 0; } + +int spapr_tcet_dma_dt(void *fdt, int node_off, const char *propname, + DMAContext *iommu) +{ + if (!iommu) { + return 0; + } + + if (iommu->translate == spapr_tce_translate) { + sPAPRTCETable *tcet = DO_UPCAST(sPAPRTCETable, dma, iommu); + return spapr_dma_dt(fdt, node_off, propname, + tcet->liobn, 0, tcet->window_size); + } + + return -1; +} diff --git a/hw/spapr_pci.c b/hw/spapr_pci.c index 780a4d6f1..b92583a99 100644 --- a/hw/spapr_pci.c +++ b/hw/spapr_pci.c @@ -518,7 +518,6 @@ static int spapr_phb_init(SysBusDevice *s) char *namebuf; int i; PCIBus *bus; - uint32_t liobn; phb->dtbusname = g_strdup_printf("pci@%" PRIx64, phb->buid); namebuf = alloca(strlen(phb->dtbusname) + 32); @@ -570,8 +569,10 @@ static int spapr_phb_init(SysBusDevice *s) PCI_DEVFN(0, 0), PCI_NUM_PINS); phb->host_state.bus = bus; - liobn = SPAPR_PCI_BASE_LIOBN | (pci_find_domain(bus) << 16); - phb->dma = spapr_tce_new_dma_context(liobn, 0x40000000); + phb->dma_liobn = SPAPR_PCI_BASE_LIOBN | (pci_find_domain(bus) << 16); + phb->dma_window_start = 0; + phb->dma_window_size = 0x40000000; + phb->dma = spapr_tce_new_dma_context(phb->dma_liobn, phb->dma_window_size); pci_setup_iommu(bus, spapr_pci_dma_context_fn, phb); QLIST_INSERT_HEAD(&spapr->phbs, phb, list); @@ -729,7 +730,9 @@ int spapr_populate_pci_dt(sPAPRPHBState *phb, _FDT(fdt_setprop(fdt, bus_off, "interrupt-map", &interrupt_map, sizeof(interrupt_map))); - spapr_dma_dt(fdt, bus_off, "ibm,dma-window", phb->dma); + spapr_dma_dt(fdt, bus_off, "ibm,dma-window", + phb->dma_liobn, phb->dma_window_start, + phb->dma_window_size); return 0; } diff --git a/hw/spapr_pci.h b/hw/spapr_pci.h index 6892e4fae..7518899b8 100644 --- a/hw/spapr_pci.h +++ b/hw/spapr_pci.h @@ -41,7 +41,9 @@ typedef struct sPAPRPHBState { target_phys_addr_t msi_win_addr; MemoryRegion memwindow, iowindow, msiwindow; - + uint32_t dma_liobn; + uint64_t dma_window_start; + uint64_t dma_window_size; DMAContext *dma; struct { diff --git a/hw/spapr_vio.c b/hw/spapr_vio.c index 3abe853f3..7ca445216 100644 --- a/hw/spapr_vio.c +++ b/hw/spapr_vio.c @@ -142,7 +142,7 @@ static int vio_make_devnode(VIOsPAPRDevice *dev, } } - ret = spapr_dma_dt(fdt, node_off, "ibm,my-dma-window", dev->dma); + ret = spapr_tcet_dma_dt(fdt, node_off, "ibm,my-dma-window", dev->dma); if (ret < 0) { return ret; } From 4504068723bcf9a3b37f6683d87711b6c5e4c0c3 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Tue, 7 Aug 2012 16:10:39 +0000 Subject: [PATCH 23/24] pseries: Update SLOF firmware image This updates SLOF to handle the necessary device tree properties for MSI and MSI-X. Signed-off-by: David Gibson Signed-off-by: Alexander Graf --- pc-bios/README | 2 +- pc-bios/slof.bin | Bin 878088 -> 878640 bytes roms/SLOF | 2 +- 3 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pc-bios/README b/pc-bios/README index e71bcd0f3..f4b37d66d 100644 --- a/pc-bios/README +++ b/pc-bios/README @@ -17,7 +17,7 @@ - SLOF (Slimline Open Firmware) is a free IEEE 1275 Open Firmware implementation for certain IBM POWER hardware. The sources are at https://github.com/dgibson/SLOF, and the image currently in qemu is - built from git tag qemu-slof-20120719. + built from git tag qemu-slof-20120731. - sgabios (the Serial Graphics Adapter option ROM) provides a means for legacy x86 software to communicate with an attached serial console as diff --git a/pc-bios/slof.bin b/pc-bios/slof.bin index 320b8f001cf9962318812a5b9109242e210fe499..84ba6b83f3c7fe523cb0b0e73ae8522872d1feef 100644 GIT binary patch delta 970 zcmb7?&rj1}7{}MHWur`EB4Q#5J^>FyEv#cd%oLfCAtXX(Fu02e-P%GE=tfsyBt|@F zSYk|ANO(yQ4szk32}Vh8WXBzdfeU&tWdDHH$iSQUc5D-a9()HPU+b3bFB=G=@<4Cs8-k&`RR8>J6<_>do|MQf3osJONJN z1wjRtg=WSJiI~jB_yjA-iU5^x0zNCsnwbt^JOMpjjQa|x8lPliaYd4c*vTMPJHfQY zCz=``!G0X5$zfU2zz=-c??^LU5(U}<92T0MKDc4}a*&+l6EJdAXnIbFF)gkpo3Kt) zVsSxaWkrKVkfWnlRdK8d|FaRyUPM)!VnTQOLrhB}^e7Yjh%7*Fe^1!~l=0E1sN&L= zX^5%J{q9iT(c?N3D7KERQYW!++~2wU7nam9E`G@={U%bvTm(~51vpp0g*!&K=IFDX ze^Mx4!M|v*sbf4UO`;c{sTTC%BW1f-zWgG0^U5oIGXmy_h%eMR{qiG5eX56edMZQO z2T}Gr{g|u{qu?H1@3>IbTq8jgEYMwKID!VZ?e%D-K-ZHG*HE@V`xqlm!wFG(YXf=jkK(pZ>@EZK0{aaQAGaMtLNCCBR= JwSK90?HATCK#BkW delta 440 zcmdmR!L;Ly=>#*TG>(ZDrp(G>1``WJSlV;HR7_ux!Yekpp4VaHy+!r{=0@h0W~Qcz zX-26@i58}&nYUZfNSOo1`uGISup(uGov5VJB{fYER1GMZx(D%U}3yBkLzs$NS;sRZNhes#fd1jNkS<@8x9)=r;&k41HQ*Bus~_V@Q#w!go}`dyTX&0_kCFRXP; z>>ATEz5;1ij_EHzbeP2SjBl)NOnwH_H+*9?V~XyW{sKsIyM&)^S0$$#er1)Ke(F1`4Aa{k(_egNwPX5}F1XurV3w*3MV`?NVyZv%kVumZ6f o*t+H`6(Abu>w@-%`RqW<0mPg@%mu{U+Z*QdtU1B*d19Rx0DW1U^8f$< diff --git a/roms/SLOF b/roms/SLOF index 7279655af..f21f7a3f4 160000 --- a/roms/SLOF +++ b/roms/SLOF @@ -1 +1 @@ -Subproject commit 7279655af2eba855bd2df61303d25abd1eeb2300 +Subproject commit f21f7a3f46b557eb5923f899ce8b4401b3cc6d91 From 3e77223293bcb9277f7b760b88f694f097f29c33 Mon Sep 17 00:00:00 2001 From: Bharat Bhushan Date: Tue, 14 Aug 2012 04:30:55 +0000 Subject: [PATCH 24/24] openpic: Added BRR1 register Linux mpic driver uses (changes may be in pipeline to get upstreamed soon) BRR1. This patch adds the support to emulate readonly FSL BRR1 register. Currently QEMU does not fully emulate any version on MPIC, so the MPIC Major number and Minor number are set to 0. Signed-off-by: Bharat Bhushan Signed-off-by: Alexander Graf --- hw/openpic.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/hw/openpic.c b/hw/openpic.c index 58ef871f6..b9d856830 100644 --- a/hw/openpic.c +++ b/hw/openpic.c @@ -130,6 +130,17 @@ enum { #define MPIC_CPU_REG_START 0x20000 #define MPIC_CPU_REG_SIZE 0x100 + ((MAX_CPU - 1) * 0x1000) +/* + * Block Revision Register1 (BRR1): QEMU does not fully emulate + * any version on MPIC. So to start with, set the IP version to 0. + * + * NOTE: This is Freescale MPIC specific register. Keep it here till + * this code is refactored for different variants of OPENPIC and MPIC. + */ +#define FSL_BRR1_IPID (0x0040 << 16) /* 16 bit IP-block ID */ +#define FSL_BRR1_IPMJ (0x00 << 8) /* 8 bit IP major number */ +#define FSL_BRR1_IPMN 0x00 /* 8 bit IP minor number */ + enum mpic_ide_bits { IDR_EP = 31, IDR_CI0 = 30, @@ -595,6 +606,8 @@ static void openpic_gbl_write (void *opaque, target_phys_addr_t addr, uint32_t v if (addr & 0xF) return; switch (addr) { + case 0x00: /* Block Revision Register1 (BRR1) is Readonly */ + break; case 0x40: case 0x50: case 0x60: @@ -671,6 +684,7 @@ static uint32_t openpic_gbl_read (void *opaque, target_phys_addr_t addr) case 0x1090: /* PINT */ retval = 0x00000000; break; + case 0x00: /* Block Revision Register1 (BRR1) */ case 0x40: case 0x50: case 0x60: @@ -893,6 +907,9 @@ static uint32_t openpic_cpu_read_internal(void *opaque, target_phys_addr_t addr, dst = &opp->dst[idx]; addr &= 0xFF0; switch (addr) { + case 0x00: /* Block Revision Register1 (BRR1) */ + retval = FSL_BRR1_IPID | FSL_BRR1_IPMJ | FSL_BRR1_IPMN; + break; case 0x80: /* PCTP */ retval = dst->pctp; break;