Re: [PATCH 4/5] qemu/kvm: Add MPC85xx support

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Fri, 2009-01-09 at 15:56 +0800, Liu Yu wrote:
> As E500 exists in various boards such as MPC8544ds, MPC8572ds, MPC8560ads, etc..
> So I would like to implement a general virtual board MPC85xx to simplify the case.
> 
> When 'cat /proc/cpuinfo' in guest, it will show:
> processor       : 0
> cpu             : e500v2
> clock           : 1499.985015MHz
> revision        : 3.0 (pvr 8021 0030)
> bogomips        : 285.69
> timebase        : 74999250
> platform        : MPC8572 DS     <---- Host platform
> model           : KVM MPC85xx
> 
> The current method is that change guest dts /compatible="host model",
> this seems somewhat dirty. It works for 8544, 8572 but not sure for others.
> I'll change it to search a table next time.
> 
> Signed-off-by: Liu Yu <yu.liu@xxxxxxxxxxxxx>
> ---
>  Makefile.target             |    2 +
>  hw/boards.h                 |    1 +
>  hw/ppc.c                    |   89 +++++++++++
>  hw/ppc.h                    |    1 +
>  hw/ppce500_mpc85xx.c        |  284 ++++++++++++++++++++++++++++++++++
>  pc-bios/mpc85xx.dtb         |  Bin 0 -> 12288 bytes
>  pc-bios/mpc85xx.dts         |  361 +++++++++++++++++++++++++++++++++++++++++++
>  target-ppc/cpu.h            |   12 ++
>  target-ppc/machine.c        |    1 +
>  target-ppc/translate_init.c |    6 +-
>  10 files changed, 755 insertions(+), 2 deletions(-)
>  create mode 100644 hw/ppce500_mpc85xx.c
>  create mode 100644 pc-bios/mpc85xx.dtb
>  create mode 100644 pc-bios/mpc85xx.dts
> 
> diff --git a/Makefile.target b/Makefile.target
> index b66b699..abf0d59 100644
> --- a/Makefile.target
> +++ b/Makefile.target
> @@ -657,6 +657,8 @@ OBJS+= unin_pci.o ppc_chrp.o
>  # PowerPC 4xx boards
>  OBJS+= pflash_cfi02.o ppc4xx_devs.o ppc4xx_pci.o ppc405_uc.o ppc405_boards.o
>  OBJS+= ppc440.o ppc440_bamboo.o
> +# PowerPC E500 boards
> +OBJS+= ppce500.o ppce500_mpc85xx.o ppce500_pci.o mpic.o
>  ifdef FDT_LIBS
>  OBJS+= device_tree.o
>  LIBS+= $(FDT_LIBS)
> diff --git a/hw/boards.h b/hw/boards.h
> index bff1cf0..35bd5ae 100644
> --- a/hw/boards.h
> +++ b/hw/boards.h
> @@ -39,6 +39,7 @@ extern QEMUMachine heathrow_machine;
>  extern QEMUMachine ref405ep_machine;
>  extern QEMUMachine taihu_machine;
>  extern QEMUMachine bamboo_machine;
> +extern QEMUMachine mpc85xx_machine;
> 
>  /* mips_r4k.c */
>  extern QEMUMachine mips_machine;
> diff --git a/hw/ppc.c b/hw/ppc.c
> index 60d6e86..fbce211 100644
> --- a/hw/ppc.c
> +++ b/hw/ppc.c
> @@ -421,6 +421,95 @@ void ppc40x_irq_init (CPUState *env)
>                                                    env, PPC40x_INPUT_NB);
>  }
> 
> +/* PowerPC E500 internal IRQ controller */
> +static void ppce500_set_irq (void *opaque, int pin, int level)
> +{
> +    CPUState *env = opaque;
> +    int cur_level;
> +
> +#if defined(PPC_DEBUG_IRQ)
> +    if (loglevel & CPU_LOG_INT) {
> +        fprintf(logfile, "%s: env %p pin %d level %d\n", __func__,
> +                env, pin, level);
> +    }
> +#endif
> +    cur_level = (env->irq_input_state >> pin) & 1;
> +    /* Don't generate spurious events */
> +    if ((cur_level == 1 && level == 0) || (cur_level == 0 && level != 0)) {
> +        switch (pin) {
> +        case PPCE500_INPUT_MCK:
> +            if (level) {
> +#if defined(PPC_DEBUG_IRQ)
> +                if (loglevel & CPU_LOG_INT) {
> +                    fprintf(logfile, "%s: reset the PowerPC system\n",
> +                            __func__);
> +                }
> +#endif
> +		fprintf(stderr,"PowerPC E500 reset core\n");
> +		qemu_system_reset_request();
> +            }
> +            break;
> +        case PPCE500_INPUT_RESET_CORE:
> +            if (level) {
> +#if defined(PPC_DEBUG_IRQ)
> +                if (loglevel & CPU_LOG_INT) {
> +                    fprintf(logfile, "%s: reset the PowerPC core\n", __func__);
> +                }
> +#endif
> +		ppc_set_irq(env, PPC_INTERRUPT_MCK, level);
> +            }
> +            break;
> +        case PPCE500_INPUT_CINT:
> +            /* Level sensitive - active high */
> +#if defined(PPC_DEBUG_IRQ)
> +            if (loglevel & CPU_LOG_INT) {
> +                fprintf(logfile, "%s: set the critical IRQ state to %d\n",
> +                        __func__, level);
> +            }
> +#endif
> +            ppc_set_irq(env, PPC_INTERRUPT_CEXT, level);
> +            break;
> +        case PPCE500_INPUT_INT:
> +            /* Level sensitive - active high */
> +#if defined(PPC_DEBUG_IRQ)
> +            if (loglevel & CPU_LOG_INT) {
> +                fprintf(logfile, "%s: set the core IRQ state to %d\n",
> +                        __func__, level);
> +            }
> +#endif
> +            ppc_set_irq(env, PPC_INTERRUPT_EXT, level);
> +            break;
> +        case PPCE500_INPUT_DEBUG:
> +            /* Level sensitive - active high */
> +#if defined(PPC_DEBUG_IRQ)
> +            if (loglevel & CPU_LOG_INT) {
> +                fprintf(logfile, "%s: set the debug pin state to %d\n",
> +                        __func__, level);
> +            }
> +#endif
> +            ppc_set_irq(env, PPC_INTERRUPT_DEBUG, level);
> +            break;
> +        default:
> +            /* Unknown pin - do nothing */
> +#if defined(PPC_DEBUG_IRQ)
> +            if (loglevel & CPU_LOG_INT) {
> +                fprintf(logfile, "%s: unknown IRQ pin %d\n", __func__, pin);
> +            }
> +#endif
> +            return;
> +        }
> +        if (level)
> +            env->irq_input_state |= 1 << pin;
> +        else
> +            env->irq_input_state &= ~(1 << pin);
> +    }
> +}
> +
> +void ppce500_irq_init (CPUState *env)
> +{
> +    env->irq_inputs = (void **)qemu_allocate_irqs(&ppce500_set_irq,
> +					env, PPCE500_INPUT_NB);
> +}
>  /*****************************************************************************/
>  /* PowerPC time base and decrementer emulation */
>  struct ppc_tb_t {
> diff --git a/hw/ppc.h b/hw/ppc.h
> index 297f550..c0c602d 100644
> --- a/hw/ppc.h
> +++ b/hw/ppc.h
> @@ -31,5 +31,6 @@ extern CPUReadMemoryFunc *PPC_io_read[];
>  void PPC_debug_write (void *opaque, uint32_t addr, uint32_t val);
> 
>  void ppc40x_irq_init (CPUState *env);
> +void ppce500_irq_init (CPUState *env);
>  void ppc6xx_irq_init (CPUState *env);
>  void ppc970_irq_init (CPUState *env);
> diff --git a/hw/ppce500_mpc85xx.c b/hw/ppce500_mpc85xx.c
> new file mode 100644
> index 0000000..a17131d
> --- /dev/null
> +++ b/hw/ppce500_mpc85xx.c
> @@ -0,0 +1,284 @@
> +/*
> + * Qemu PowerPC MPC85xx board emualtion
> + *
> + * Copyright (C) 2009 Freescale Semiconductor, Inc. All rights reserved.
> + *
> + * Author: Yu Liu,     <yu.liu@xxxxxxxxxxxxx>
> + *
> + * This file is derived from hw/ppc440_bamboo.c,
> + * the copyright for that material belongs to the original owners.
> + *
> + * 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 <dirent.h>
> +
> +#include "config.h"
> +#include "qemu-common.h"
> +#include "net.h"
> +#include "hw.h"
> +#include "pci.h"
> +#include "virtio-blk.h"
> +#include "boards.h"
> +#include "sysemu.h"
> +#include "ppce500.h"
> +#include "kvm.h"
> +#include "kvm_ppc.h"
> +#include "device_tree.h"
> +
> +#define BINARY_DEVICE_TREE_FILE  "mpc85xx.dtb"
> +#define UIMAGE_LOAD_BASE         0
> +#define DTB_LOAD_BASE            0x600000
> +#define INITRD_LOAD_BASE         0x2000000
> +
> +#define PPCE500_CCSRBAR_BASE     0xE0000000
> +#define PPCE500_PCI_REGS_BASE    (PPCE500_CCSRBAR_BASE + 0x8000)
> +#define PPCE500_PCI_REGS_SIZE    0x1000
> +#define PPCE500_PCI_IO           0xE1000000
> +#define PPCE500_PCI_IOLEN	 0x10000
> +
> +static int mpc85xx_copy_host_cell(void *fdt, const char *node, const char *prop)
> +{
> +    uint32_t cell;
> +    int ret;
> +
> +    ret = kvmppc_read_host_property(node, prop, &cell, sizeof(cell));
> +    if (ret < 0) {
> +	fprintf(stderr, "couldn't read host %s/%s\n", node, prop);
> +	goto out;
> +    }
> +
> +    ret = qemu_devtree_setprop_cell(fdt, "/cpus/PowerPC,85xx@0",
> +				prop, cell);
> +    if (ret < 0) {
> +	fprintf(stderr, "couldn't set guest /cpus/PowerPC,85xx@0/%s\n", prop);
> +	goto out;
> +    }
> +
> +out:
> +    return ret;
> +}

The function name sounds generic, but apparently it only works with cpu
nodes?

> +static void *mpc85xx_load_device_tree(void *addr,
> +                                     uint32_t ramsize,
> +                                     target_phys_addr_t initrd_base,
> +                                     target_phys_addr_t initrd_size,
> +                                     const char *kernel_cmdline)
> +{
> +    void *fdt = NULL;
> +#ifdef HAVE_FDT
> +    uint32_t mem_reg_property[] = {0, ramsize};
> +    char *path;
> +    int pathlen;
> +    int ret;
> +
> +    pathlen = snprintf(NULL, 0, "%s/%s", bios_dir, BINARY_DEVICE_TREE_FILE) + 1;
> +    path = qemu_malloc(pathlen);
> +    if (path == NULL)
> +	goto out;
> +
> +    snprintf(path, pathlen, "%s/%s", bios_dir, BINARY_DEVICE_TREE_FILE);
> +
> +    fdt = load_device_tree(path, addr);
> +    free(path);
> +    if (fdt == NULL)
> +	goto out;
> +
> +    /* Manipulate device tree in memory. */
> +
> +    ret = qemu_devtree_setprop(fdt, "/memory", "reg", mem_reg_property,
> +                               sizeof(mem_reg_property));
> +    if (ret < 0)
> +	fprintf(stderr, "couldn't set /memory/reg\n");
> +
> +    ret = qemu_devtree_setprop_cell(fdt, "/chosen", "linux,initrd-start",
> +                                    initrd_base);
> +    if (ret < 0)
> +	fprintf(stderr, "couldn't set /chosen/linux,initrd-start\n");
> +
> +    ret = qemu_devtree_setprop_cell(fdt, "/chosen", "linux,initrd-end",
> +                                    (initrd_base + initrd_size));
> +    if (ret < 0)
> +	fprintf(stderr, "couldn't set /chosen/linux,initrd-end\n");
> +
> +    ret = qemu_devtree_setprop_string(fdt, "/chosen", "bootargs",
> +                                      kernel_cmdline);
> +    if (ret < 0)
> +	fprintf(stderr, "couldn't set /chosen/bootargs\n");
> +
> +    if (kvm_enabled()) {
> +	FILE *fp;
> +	char *model = NULL;
> +	struct dirent *dirp;
> +	DIR *dp;
> +	char buf[128];
> +
> +	if ((fp = fopen("/proc/cpuinfo", "r")) == NULL) {
> +	    printf("Can't open file /proc/cpuinfo\n");
> +	    goto out;
> +	}
> +	while (fgets(buf, 128, fp) != NULL) {
> +	    if (strncmp(buf, "model", 5) == 0) {
> +		model = buf + 9;
> +		break;
> +	    }
> +	}
> +	fclose(fp);
> +	
> +	if (model == NULL) {
> +	    printf("unknow host\n");
> +	    goto out;
> +	}
> +	
> +	ret = qemu_devtree_setprop_string(fdt, "/", "compatible", model);
> +	if (ret < 0)
> +	    fprintf(stderr, "couldn't set /compatible = %s\n", model);

I don't like this. For 440, we just picked a platform to emulate, so
whether we ran on Bamboo or Sequoia (or something else), the guest
always thought it was a Bamboo. I think you should do the same: pick a
platform and emulate it.

> +	if ((dp = opendir("/proc/device-tree/cpus/")) == NULL) {
> +	    printf("Can't open directory /proc/device-tree/cpus/\n");
> +	    goto out;
> +	}
> +
> +	buf[0] = '\0';
> +	while ((dirp = readdir(dp)) != NULL) {
> +	    if (strncmp(dirp->d_name, "PowerPC", 7) == 0) {
> +		sprintf(buf, "/proc/device-tree/cpus/%s", dirp->d_name);
> +		break;
> +	    }
> +	}
> +	closedir(dp);
> +	if (buf[0] == '\0') {
> +	    printf("unknow host\n");
> +	    goto out;
> +	}
> +	path = buf + 17;
> +	
> +	mpc85xx_copy_host_cell(fdt, path, "clock-frequency");
> +	mpc85xx_copy_host_cell(fdt, path, "timebase-frequency");

Can't you use kvmppc_fdt_update() here? Ugh, that sucks that the CPU
nodes are named differently... can you abstract kvmppc_fdt_update() to
work?

> +    }
> +
> +out:
> +#endif
> +
> +    return fdt;
> +}
> +
> +static void mpc85xx_init(ram_addr_t ram_size, int vga_ram_size,
> +    		const char *boot_device, DisplayState *ds,
> +    		const char *kernel_filename,
> +    		const char *kernel_cmdline,
> +    		const char *initrd_filename,
> +    		const char *cpu_model)
> +{
> +    NICInfo *nd;
> +    PCIBus *pci_bus;
> +    CPUState *env;
> +    uint64_t elf_entry;
> +    uint64_t elf_lowaddr;
> +    target_ulong entry=0;
> +    target_ulong loadaddr=UIMAGE_LOAD_BASE;
> +    target_long kernel_size=0;
> +    target_ulong dt_base=DTB_LOAD_BASE;
> +    target_ulong initrd_base=INITRD_LOAD_BASE;
> +    target_long initrd_size=0;
> +    void *fdt;
> +    int i=0;
> +    unsigned int pci_irq_nrs[4] = {1, 2, 3, 4};
> +    qemu_irq *mpic, *pci_irqs;
> +
> +    /* Setup CPU */
> +    env = ppce500_init(&ram_size, &mpic, PPCE500_CCSRBAR_BASE);
> +
> +    /* PCI */
> +    pci_irqs = qemu_malloc(sizeof(qemu_irq) * 4);
> +    pci_irqs[0] = mpic[pci_irq_nrs[0]];
> +    pci_irqs[1] = mpic[pci_irq_nrs[1]];
> +    pci_irqs[2] = mpic[pci_irq_nrs[2]];
> +    pci_irqs[3] = mpic[pci_irq_nrs[3]];
> +    pci_bus = ppce500_pci_init(pci_irqs, PPCE500_PCI_REGS_BASE);
> +    if (!pci_bus)
> +	printf("couldn't create PCI controller!\n");
> +
> +    isa_mmio_init(PPCE500_PCI_IO, PPCE500_PCI_IOLEN);
> +
> +    /* Register mem */
> +    cpu_register_physical_memory(0, ram_size, 0);
> +
> +    if (pci_bus) {
> +    	int unit_id = 0;
> +
> +    	/* Add virtio block devices. */
> +    	while ((i = drive_get_index(IF_VIRTIO, 0, unit_id)) != -1) {
> +    		virtio_blk_init(pci_bus, drives_table[i].bdrv);
> +    		unit_id++;
> +    	}
> +
> +    	/* Register network interfaces. */
> +    	for (i = 0; i < nb_nics; i++) {
> +    		nd = &nd_table[i];
> +    		if (!nd->model)
> +    			nd->model = "virtio";
> +    		pci_nic_init(pci_bus, nd, -1);
> +    	}
> +    }
> +
> +    /* Load kernel. */
> +    if (kernel_filename) {
> +        kernel_size = load_uimage(kernel_filename, &entry, &loadaddr, NULL);
> +        if (kernel_size < 0) {
> +            kernel_size = load_elf(kernel_filename, 0, &elf_entry, &elf_lowaddr,
> +                                   NULL);
> +            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);
> +            exit(1);
> +        }
> +    }
> +
> +    /* Load initrd. */
> +    if (initrd_filename) {
> +        initrd_size = load_image(initrd_filename, phys_ram_base + initrd_base);
> +
> +        if (initrd_size < 0) {
> +            fprintf(stderr, "qemu: could not load initial ram disk '%s'\n",
> +                    initrd_filename);
> +            exit(1);
> +        }
> +    }
> +
> +    /* If we're loading a kernel directly, we must load the device tree too. */
> +    if (kernel_filename) {
> +        fdt = mpc85xx_load_device_tree(phys_ram_base + dt_base, ram_size,
> +                                      initrd_base, initrd_size, kernel_cmdline);
> +        if (fdt == NULL) {
> +            fprintf(stderr, "couldn't load device tree\n");
> +            exit(1);
> +        }
> +
> +        /* Set initial guest state. */
> +        env->gpr[1] = (16<<20) - 8;
> +        env->gpr[3] = dt_base;
> +        env->nip = entry;
> +        /* XXX we currently depend on KVM to create some initial TLB entries. */
> +    }
> +
> +    if (kvm_enabled())
> +	kvmppc_init();
> +
> +    return;
> +}
> +
> +QEMUMachine mpc85xx_machine = {
> +    .name = "mpc85xx",
> +    .desc = "mpc85xx",
> +    .init = mpc85xx_init,
> +    .ram_require = 256<<20 | RAMSIZE_FIXED,
> +};
> diff --git a/pc-bios/mpc85xx.dtb b/pc-bios/mpc85xx.dtb
> new file mode 100644
> index 0000000000000000000000000000000000000000..a10e29d5bd0d65add2faed921434ff3ac2d16cdd
> GIT binary patch
> literal 12288
> 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
> 
> literal 0
> HcmV?d00001
> 
> diff --git a/pc-bios/mpc85xx.dts b/pc-bios/mpc85xx.dts
> new file mode 100644
> index 0000000..45a9c3d
> --- /dev/null
> +++ b/pc-bios/mpc85xx.dts
> @@ -0,0 +1,361 @@
> +/*
> + * MPC85xx DS Device Tree Source
> + *
> + * Copyright 2007-2009 Freescale Semiconductor Inc.
> + *
> + * This program is free software; you can redistribute  it and/or modify it
> + * under  the terms of  the GNU General  Public License as published by the
> + * Free Software Foundation;  either version 2 of the  License, or (at your
> + * option) any later version.
> + */
> +
> +/dts-v1/;
> +/ {
> +	model = "KVM MPC85xx";
> +	compatible = "MPC8544DS", "MPC85xxDS";
> +	#address-cells = <1>;
> +	#size-cells = <1>;
> +
> +	aliases {
> +		serial0 = &serial0;
> +		serial1 = &serial1;
> +		pci0 = &pci0;
> +		pci1 = &pci1;
> +		pci2 = &pci2;
> +		pci3 = &pci3;
> +	};
> +
> +	cpus {
> +		#address-cells = <1>;
> +		#size-cells = <0>;
> +
> +		PowerPC,85xx@0 {
> +			device_type = "cpu";
> +			reg = <0x0>;
> +			d-cache-line-size = <32>;	// 32 bytes
> +			i-cache-line-size = <32>;	// 32 bytes
> +			d-cache-size = <0x8000>;		// L1, 32K
> +			i-cache-size = <0x8000>;		// L1, 32K
> +			timebase-frequency = <0>;
> +			bus-frequency = <0>;
> +			clock-frequency = <0>;
> +			next-level-cache = <&L2>;
> +		};
> +	};
> +
> +	memory {
> +		device_type = "memory";
> +		reg = <0x0 0x0>;	// Filled by U-Boot
> +	};
> +
> +	soc85xx@e0000000 {
> +		#address-cells = <1>;
> +		#size-cells = <1>;
> +		device_type = "soc";
> +		compatible = "simple-bus";
> +
> +		ranges = <0x0 0xe0000000 0x100000>;
> +		reg = <0xe0000000 0x1000>;	// CCSRBAR 1M
> +		bus-frequency = <0>;		// Filled out by uboot.
> +
> +		memory-controller@2000 {
> +			compatible = "fsl,8544-memory-controller";
> +			reg = <0x2000 0x1000>;
> +			interrupt-parent = <&mpic>;
> +			interrupts = <18 2>;
> +		};
> +
> +		L2: l2-cache-controller@20000 {
> +			compatible = "fsl,8544-l2-cache-controller";
> +			reg = <0x20000 0x1000>;
> +			cache-line-size = <32>;	// 32 bytes
> +			cache-size = <0x40000>;	// L2, 256K
> +			interrupt-parent = <&mpic>;
> +			interrupts = <16 2>;
> +		};
> +
> +		serial0: serial@4500 {
> +			cell-index = <0>;
> +			device_type = "serial";
> +			compatible = "ns16550";
> +			reg = <0x4500 0x100>;
> +			clock-frequency = <0>;
> +			interrupts = <42 2>;
> +			interrupt-parent = <&mpic>;
> +		};
> +
> +		serial1: serial@4600 {
> +			cell-index = <1>;
> +			device_type = "serial";
> +			compatible = "ns16550";
> +			reg = <0x4600 0x100>;
> +			clock-frequency = <0>;
> +			interrupts = <42 2>;
> +			interrupt-parent = <&mpic>;
> +		};
> +
> +		global-utilities@e0000 {	//global utilities block
> +			compatible = "fsl,mpc8548-guts";
> +			reg = <0xe0000 0x1000>;
> +			fsl,has-rstcr;
> +		};
> +
> +		crypto@30000 {
> +			compatible = "fsl,sec2.1", "fsl,sec2.0";
> +			reg = <0x30000 0x10000>;
> +			interrupts = <45 2>;
> +			interrupt-parent = <&mpic>;
> +			fsl,num-channels = <4>;
> +			fsl,channel-fifo-len = <24>;
> +			fsl,exec-units-mask = <0xfe>;
> +			fsl,descriptor-types-mask = <0x12b0ebf>;
> +		};

Since I'm pretty sure you don't emulate the crypto engine, you should
not advertise one in the device tree. Same is true for everything in the
tree that qemu doesn't actually emulate: just remove it.

> +		mpic: pic@40000 {
> +			interrupt-controller;
> +			#address-cells = <0>;
> +			#interrupt-cells = <2>;
> +			reg = <0x40000 0x40000>;
> +			compatible = "chrp,open-pic";
> +			device_type = "open-pic";
> +		};
> +
> +		msi@41600 {
> +			compatible = "fsl,mpc8544-msi", "fsl,mpic-msi";
> +			reg = <0x41600 0x80>;
> +			msi-available-ranges = <0 0x100>;
> +			interrupts = <
> +				0xe0 0
> +				0xe1 0
> +				0xe2 0
> +				0xe3 0
> +				0xe4 0
> +				0xe5 0
> +				0xe6 0
> +				0xe7 0>;
> +			interrupt-parent = <&mpic>;
> +		};
> +	};
> +
> +	pci0: pci@e0008000 {
> +		cell-index = <0>;
> +		compatible = "fsl,mpc8540-pci";
> +		device_type = "pci";
> +		interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
> +		interrupt-map = <
> +
> +			/* IDSEL 0x11 J17 Slot 1 */
> +			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
> +			0x9000 0x0 0x0 0x2 &mpic 0x4 0x1
> +			0x9000 0x0 0x0 0x3 &mpic 0x2 0x1
> +			0x9000 0x0 0x0 0x4 &mpic 0x1 0x1>;
> +
> +		interrupt-parent = <&mpic>;
> +		interrupts = <24 2>;
> +		bus-range = <0 255>;
> +		ranges = <0x2000000 0x0 0xc0000000 0xc0000000 0x0 0x20000000
> +			  0x1000000 0x0 0x0 0xe1000000 0x0 0x10000>;
> +		clock-frequency = <66666666>;
> +		#interrupt-cells = <1>;
> +		#size-cells = <2>;
> +		#address-cells = <3>;
> +		reg = <0xe0008000 0x1000>;
> +	};
> +
> +	pci1: pcie@e0009000 {

I think you only actually created 1 emulated PCI controller, so you
should remove all the others.
...
> +	chosen {
> +		linux,stdout-path = "/soc85xx@e0000000/serial@4500";
> +	};
> +};
> diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h
> index f7600c4..d64f882 100644
> --- a/target-ppc/cpu.h
> +++ b/target-ppc/cpu.h
> @@ -1345,6 +1345,18 @@ enum {
>  };
> 
>  enum {
> +    /* PowerPC E500 input pins */
> +    PPCE500_INPUT_RESET_CORE = 0,
> +    PPCE500_INPUT_MCK        = 1,
> +    PPCE500_INPUT_RESET_SYS  = 2,      // in order same with 440
> +    PPCE500_INPUT_CINT       = 3,
> +    PPCE500_INPUT_INT        = 4,
> +    PPCE500_INPUT_HALT       = 5,      // in order same with 440
> +    PPCE500_INPUT_DEBUG      = 6,
> +    PPCE500_INPUT_NB,
> +};
> +
> +enum {
>      /* PowerPC 40x input pins */
>      PPC40x_INPUT_RESET_CORE = 0,
>      PPC40x_INPUT_RESET_CHIP = 1,
> diff --git a/target-ppc/machine.c b/target-ppc/machine.c
> index ea2257b..97a7ee8 100644
> --- a/target-ppc/machine.c
> +++ b/target-ppc/machine.c
> @@ -9,6 +9,7 @@ void register_machines(void)
>      qemu_register_machine(&ref405ep_machine);
>      qemu_register_machine(&taihu_machine);
>      qemu_register_machine(&bamboo_machine);
> +    qemu_register_machine(&mpc85xx_machine);
>  }
> 
>  void cpu_save(QEMUFile *f, void *opaque)
> diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
> index 3f01e66..f20e857 100644
> --- a/target-ppc/translate_init.c
> +++ b/target-ppc/translate_init.c
> @@ -4154,7 +4154,8 @@ static void init_proc_e300 (CPUPPCState *env)
>                                POWERPC_FLAG_BUS_CLK)
>  #define check_pow_e500       check_pow_hid0
> 
> -__attribute__ (( unused ))
> +extern void ppce500_irq_init (CPUState *env);
> +
>  static void init_proc_e500 (CPUPPCState *env)
>  {
>      /* Time base */
> @@ -4256,7 +4257,8 @@ static void init_proc_e500 (CPUPPCState *env)
>      init_excp_e200(env);
>      env->dcache_line_size = 32;
>      env->icache_line_size = 32;
> -    /* XXX: TODO: allocate internal IRQ controller */
> +    /* Allocate hardware IRQ controller */
> +    ppce500_irq_init(env);
>  }
> 
>  /* Non-embedded PowerPC                                                      */

-- 
Hollis Blanchard
IBM Linux Technology Center

--
To unsubscribe from this list: send the line "unsubscribe kvm-ppc" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [KVM Development]     [KVM ARM]     [KVM ia64]     [Linux Virtualization]     [Linux USB Devel]     [Linux Video]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Big List of Linux Books]

  Powered by Linux