Commit 1db09b847e910952e4ad77560963762fb490dafc

Authored by aurel32
1 parent 9fdc60bf

kvm/powerpc: Add MPC8544DS board support

This patch add an emulation of MPC8544DS board.
It can work on All E500 platforms.

Signed-off-by: Liu Yu <yu.liu@freescale.com>
Acked-by: Hollis Blanchard <hollisb@us.ibm.com>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>

git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@6663 c046a42c-6fe2-441c-8c8c-71466251a162
Makefile.target
... ... @@ -603,7 +603,7 @@ OBJS+= unin_pci.o ppc_newworld.o
603 603 OBJS+= pflash_cfi02.o ppc4xx_devs.o ppc4xx_pci.o ppc405_uc.o ppc405_boards.o
604 604 OBJS+= ppc440.o ppc440_bamboo.o
605 605 # PowerPC E500 boards
606   -OBJS+= ppce500_pci.o
  606 +OBJS+= ppce500_pci.o ppce500_mpc8544ds.o
607 607 ifdef FDT_LIBS
608 608 OBJS+= device_tree.o
609 609 LIBS+= $(FDT_LIBS)
... ...
hw/boards.h
... ... @@ -42,6 +42,7 @@ extern QEMUMachine heathrow_machine;
42 42 extern QEMUMachine ref405ep_machine;
43 43 extern QEMUMachine taihu_machine;
44 44 extern QEMUMachine bamboo_machine;
  45 +extern QEMUMachine mpc8544ds_machine;
45 46  
46 47 /* mips_r4k.c */
47 48 extern QEMUMachine mips_machine;
... ...
hw/ppce500.h 0 → 100644
  1 +/*
  2 + * QEMU PowerPC E500 emulation shared definitions
  3 + *
  4 + * Copyright (C) 2009 Freescale Semiconductor, Inc. All rights reserved.
  5 + *
  6 + * Author: Yu Liu, <yu.liu@freescale.com>
  7 + *
  8 + * This file is derived from hw/ppc440.h
  9 + * the copyright for that material belongs to the original owners.
  10 + *
  11 + * This is free software; you can redistribute it and/or modify
  12 + * it under the terms of the GNU General Public License as published by
  13 + * the Free Software Foundation; either version 2 of the License, or
  14 + * (at your option) any later version.
  15 + */
  16 +
  17 +#if !defined(PPC_E500_H)
  18 +#define PPC_E500_H
  19 +
  20 +PCIBus *ppce500_pci_init(qemu_irq *pic, target_phys_addr_t registers);
  21 +
  22 +#endif /* !defined(PPC_E500_H) */
... ...
hw/ppce500_mpc8544ds.c 0 → 100644
  1 +/*
  2 + * Qemu PowerPC MPC8544DS board emualtion
  3 + *
  4 + * Copyright (C) 2009 Freescale Semiconductor, Inc. All rights reserved.
  5 + *
  6 + * Author: Yu Liu, <yu.liu@freescale.com>
  7 + *
  8 + * This file is derived from hw/ppc440_bamboo.c,
  9 + * the copyright for that material belongs to the original owners.
  10 + *
  11 + * This is free software; you can redistribute it and/or modify
  12 + * it under the terms of the GNU General Public License as published by
  13 + * the Free Software Foundation; either version 2 of the License, or
  14 + * (at your option) any later version.
  15 + */
  16 +
  17 +#include <dirent.h>
  18 +
  19 +#include "config.h"
  20 +#include "qemu-common.h"
  21 +#include "net.h"
  22 +#include "hw.h"
  23 +#include "pc.h"
  24 +#include "pci.h"
  25 +#include "virtio-blk.h"
  26 +#include "boards.h"
  27 +#include "sysemu.h"
  28 +#include "kvm.h"
  29 +#include "kvm_ppc.h"
  30 +#include "device_tree.h"
  31 +#include "openpic.h"
  32 +#include "ppce500.h"
  33 +
  34 +#define BINARY_DEVICE_TREE_FILE "mpc8544ds.dtb"
  35 +#define UIMAGE_LOAD_BASE 0
  36 +#define DTB_LOAD_BASE 0x600000
  37 +#define INITRD_LOAD_BASE 0x2000000
  38 +
  39 +#define RAM_SIZES_ALIGN (64UL << 20)
  40 +
  41 +#define MPC8544_CCSRBAR_BASE 0xE0000000
  42 +#define MPC8544_MPIC_REGS_BASE (MPC8544_CCSRBAR_BASE + 0x40000)
  43 +#define MPC8544_SERIAL0_REGS_BASE (MPC8544_CCSRBAR_BASE + 0x4500)
  44 +#define MPC8544_SERIAL1_REGS_BASE (MPC8544_CCSRBAR_BASE + 0x4600)
  45 +#define MPC8544_PCI_REGS_BASE (MPC8544_CCSRBAR_BASE + 0x8000)
  46 +#define MPC8544_PCI_REGS_SIZE 0x1000
  47 +#define MPC8544_PCI_IO 0xE1000000
  48 +#define MPC8544_PCI_IOLEN 0x10000
  49 +
  50 +static int mpc8544_copy_soc_cell(void *fdt, const char *node, const char *prop)
  51 +{
  52 + uint32_t cell;
  53 + int ret;
  54 +
  55 + ret = kvmppc_read_host_property(node, prop, &cell, sizeof(cell));
  56 + if (ret < 0) {
  57 + fprintf(stderr, "couldn't read host %s/%s\n", node, prop);
  58 + goto out;
  59 + }
  60 +
  61 + ret = qemu_devtree_setprop_cell(fdt, "/cpus/PowerPC,8544@0",
  62 + prop, cell);
  63 + if (ret < 0) {
  64 + fprintf(stderr, "couldn't set guest /cpus/PowerPC,8544@0/%s\n", prop);
  65 + goto out;
  66 + }
  67 +
  68 +out:
  69 + return ret;
  70 +}
  71 +
  72 +static void *mpc8544_load_device_tree(void *addr,
  73 + uint32_t ramsize,
  74 + target_phys_addr_t initrd_base,
  75 + target_phys_addr_t initrd_size,
  76 + const char *kernel_cmdline)
  77 +{
  78 + void *fdt = NULL;
  79 +#ifdef HAVE_FDT
  80 + uint32_t mem_reg_property[] = {0, ramsize};
  81 + char *path;
  82 + int pathlen;
  83 + int ret;
  84 +
  85 + pathlen = snprintf(NULL, 0, "%s/%s", bios_dir, BINARY_DEVICE_TREE_FILE) + 1;
  86 + path = qemu_malloc(pathlen);
  87 +
  88 + snprintf(path, pathlen, "%s/%s", bios_dir, BINARY_DEVICE_TREE_FILE);
  89 +
  90 + fdt = load_device_tree(path, addr);
  91 + qemu_free(path);
  92 + if (fdt == NULL)
  93 + goto out;
  94 +
  95 + /* Manipulate device tree in memory. */
  96 + ret = qemu_devtree_setprop(fdt, "/memory", "reg", mem_reg_property,
  97 + sizeof(mem_reg_property));
  98 + if (ret < 0)
  99 + fprintf(stderr, "couldn't set /memory/reg\n");
  100 +
  101 + ret = qemu_devtree_setprop_cell(fdt, "/chosen", "linux,initrd-start",
  102 + initrd_base);
  103 + if (ret < 0)
  104 + fprintf(stderr, "couldn't set /chosen/linux,initrd-start\n");
  105 +
  106 + ret = qemu_devtree_setprop_cell(fdt, "/chosen", "linux,initrd-end",
  107 + (initrd_base + initrd_size));
  108 + if (ret < 0)
  109 + fprintf(stderr, "couldn't set /chosen/linux,initrd-end\n");
  110 +
  111 + ret = qemu_devtree_setprop_string(fdt, "/chosen", "bootargs",
  112 + kernel_cmdline);
  113 + if (ret < 0)
  114 + fprintf(stderr, "couldn't set /chosen/bootargs\n");
  115 +
  116 + if (kvm_enabled()) {
  117 + struct dirent *dirp;
  118 + DIR *dp;
  119 + char buf[128];
  120 +
  121 + if ((dp = opendir("/proc/device-tree/cpus/")) == NULL) {
  122 + printf("Can't open directory /proc/device-tree/cpus/\n");
  123 + goto out;
  124 + }
  125 +
  126 + buf[0] = '\0';
  127 + while ((dirp = readdir(dp)) != NULL) {
  128 + if (strncmp(dirp->d_name, "PowerPC", 7) == 0) {
  129 + snprintf(buf, 128, "/cpus/%s", dirp->d_name);
  130 + break;
  131 + }
  132 + }
  133 + closedir(dp);
  134 + if (buf[0] == '\0') {
  135 + printf("Unknow host!\n");
  136 + goto out;
  137 + }
  138 +
  139 + mpc8544_copy_soc_cell(fdt, buf, "clock-frequency");
  140 + mpc8544_copy_soc_cell(fdt, buf, "timebase-frequency");
  141 + }
  142 +
  143 +out:
  144 +#endif
  145 +
  146 + return fdt;
  147 +}
  148 +
  149 +static void mpc8544ds_init(ram_addr_t ram_size, int vga_ram_size,
  150 + const char *boot_device,
  151 + const char *kernel_filename,
  152 + const char *kernel_cmdline,
  153 + const char *initrd_filename,
  154 + const char *cpu_model)
  155 +{
  156 + PCIBus *pci_bus;
  157 + CPUState *env;
  158 + uint64_t elf_entry;
  159 + uint64_t elf_lowaddr;
  160 + target_ulong entry=0;
  161 + target_ulong loadaddr=UIMAGE_LOAD_BASE;
  162 + target_long kernel_size=0;
  163 + target_ulong dt_base=DTB_LOAD_BASE;
  164 + target_ulong initrd_base=INITRD_LOAD_BASE;
  165 + target_long initrd_size=0;
  166 + void *fdt;
  167 + int i=0;
  168 + unsigned int pci_irq_nrs[4] = {1, 2, 3, 4};
  169 + qemu_irq *irqs, *mpic, *pci_irqs;
  170 + SerialState * serial[2];
  171 +
  172 + /* Setup CPU */
  173 + env = cpu_ppc_init("e500v2_v30");
  174 + if (!env) {
  175 + fprintf(stderr, "Unable to initialize CPU!\n");
  176 + exit(1);
  177 + }
  178 +
  179 + /* Fixup Memory size on a alignment boundary */
  180 + ram_size &= ~(RAM_SIZES_ALIGN - 1);
  181 +
  182 + /* Register Memory */
  183 + cpu_register_physical_memory(0, ram_size, 0);
  184 +
  185 + /* MPIC */
  186 + irqs = qemu_mallocz(sizeof(qemu_irq) * OPENPIC_OUTPUT_NB);
  187 + irqs[OPENPIC_OUTPUT_INT] = ((qemu_irq *)env->irq_inputs)[PPCE500_INPUT_INT];
  188 + irqs[OPENPIC_OUTPUT_CINT] = ((qemu_irq *)env->irq_inputs)[PPCE500_INPUT_CINT];
  189 + mpic = mpic_init(MPC8544_MPIC_REGS_BASE, 1, &irqs, NULL);
  190 +
  191 + /* Serial */
  192 + if (serial_hds[0])
  193 + serial[0] = serial_mm_init(MPC8544_SERIAL0_REGS_BASE,
  194 + 0, mpic[12+26], 399193,
  195 + serial_hds[0], 1);
  196 +
  197 + if (serial_hds[1])
  198 + serial[0] = serial_mm_init(MPC8544_SERIAL1_REGS_BASE,
  199 + 0, mpic[12+26], 399193,
  200 + serial_hds[0], 1);
  201 +
  202 + /* PCI */
  203 + pci_irqs = qemu_malloc(sizeof(qemu_irq) * 4);
  204 + pci_irqs[0] = mpic[pci_irq_nrs[0]];
  205 + pci_irqs[1] = mpic[pci_irq_nrs[1]];
  206 + pci_irqs[2] = mpic[pci_irq_nrs[2]];
  207 + pci_irqs[3] = mpic[pci_irq_nrs[3]];
  208 + pci_bus = ppce500_pci_init(pci_irqs, MPC8544_PCI_REGS_BASE);
  209 + if (!pci_bus)
  210 + printf("couldn't create PCI controller!\n");
  211 +
  212 + isa_mmio_init(MPC8544_PCI_IO, MPC8544_PCI_IOLEN);
  213 +
  214 + if (pci_bus) {
  215 + int unit_id = 0;
  216 +
  217 + /* Add virtio block devices. */
  218 + while ((i = drive_get_index(IF_VIRTIO, 0, unit_id)) != -1) {
  219 + virtio_blk_init(pci_bus, drives_table[i].bdrv);
  220 + unit_id++;
  221 + }
  222 +
  223 + /* Register network interfaces. */
  224 + for (i = 0; i < nb_nics; i++) {
  225 + pci_nic_init(pci_bus, &nd_table[i], -1, "virtio");
  226 + }
  227 + }
  228 +
  229 + /* Load kernel. */
  230 + if (kernel_filename) {
  231 + kernel_size = load_uimage(kernel_filename, &entry, &loadaddr, NULL);
  232 + if (kernel_size < 0) {
  233 + kernel_size = load_elf(kernel_filename, 0, &elf_entry, &elf_lowaddr,
  234 + NULL);
  235 + entry = elf_entry;
  236 + loadaddr = elf_lowaddr;
  237 + }
  238 + /* XXX try again as binary */
  239 + if (kernel_size < 0) {
  240 + fprintf(stderr, "qemu: could not load kernel '%s'\n",
  241 + kernel_filename);
  242 + exit(1);
  243 + }
  244 + }
  245 +
  246 + /* Load initrd. */
  247 + if (initrd_filename) {
  248 + initrd_size = load_image(initrd_filename, phys_ram_base + initrd_base);
  249 +
  250 + if (initrd_size < 0) {
  251 + fprintf(stderr, "qemu: could not load initial ram disk '%s'\n",
  252 + initrd_filename);
  253 + exit(1);
  254 + }
  255 + }
  256 +
  257 + /* If we're loading a kernel directly, we must load the device tree too. */
  258 + if (kernel_filename) {
  259 + fdt = mpc8544_load_device_tree(phys_ram_base + dt_base, ram_size,
  260 + initrd_base, initrd_size, kernel_cmdline);
  261 + if (fdt == NULL) {
  262 + fprintf(stderr, "couldn't load device tree\n");
  263 + exit(1);
  264 + }
  265 +
  266 + /* Set initial guest state. */
  267 + env->gpr[1] = (16<<20) - 8;
  268 + env->gpr[3] = dt_base;
  269 + env->nip = entry;
  270 + /* XXX we currently depend on KVM to create some initial TLB entries. */
  271 + }
  272 +
  273 + if (kvm_enabled())
  274 + kvmppc_init();
  275 +
  276 + return;
  277 +}
  278 +
  279 +QEMUMachine mpc8544ds_machine = {
  280 + .name = "mpc8544ds",
  281 + .desc = "mpc8544ds",
  282 + .init = mpc8544ds_init,
  283 + .ram_require = RAM_SIZES_ALIGN | RAMSIZE_FIXED,
  284 +};
... ...
target-ppc/machine.c
... ... @@ -9,6 +9,7 @@ void register_machines(void)
9 9 qemu_register_machine(&ref405ep_machine);
10 10 qemu_register_machine(&taihu_machine);
11 11 qemu_register_machine(&bamboo_machine);
  12 + qemu_register_machine(&mpc8544ds_machine);
12 13 }
13 14  
14 15 void cpu_save(QEMUFile *f, void *opaque)
... ...