qemu/hw/ppc440_bamboo.c
<<
>>
Prefs
   1/*
   2 * Qemu PowerPC 440 Bamboo board emulation
   3 *
   4 * Copyright 2007 IBM Corporation.
   5 * Authors:
   6 *      Jerone Young <jyoung5@us.ibm.com>
   7 *      Christian Ehrhardt <ehrhardt@linux.vnet.ibm.com>
   8 *      Hollis Blanchard <hollisb@us.ibm.com>
   9 *
  10 * This work is licensed under the GNU GPL license version 2 or later.
  11 *
  12 */
  13
  14#include "config.h"
  15#include "qemu-common.h"
  16#include "net.h"
  17#include "hw.h"
  18#include "pci.h"
  19#include "boards.h"
  20#include "sysemu.h"
  21#include "ppc440.h"
  22#include "kvm.h"
  23#include "kvm_ppc.h"
  24#include "device_tree.h"
  25#include "loader.h"
  26#include "elf.h"
  27
  28#define BINARY_DEVICE_TREE_FILE "bamboo.dtb"
  29
  30static void *bamboo_load_device_tree(target_phys_addr_t addr,
  31                                     uint32_t ramsize,
  32                                     target_phys_addr_t initrd_base,
  33                                     target_phys_addr_t initrd_size,
  34                                     const char *kernel_cmdline)
  35{
  36    void *fdt = NULL;
  37#ifdef CONFIG_FDT
  38    uint32_t mem_reg_property[] = { 0, 0, ramsize };
  39    char *filename;
  40    int fdt_size;
  41    int ret;
  42
  43    filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, BINARY_DEVICE_TREE_FILE);
  44    if (!filename) {
  45        goto out;
  46    }
  47    fdt = load_device_tree(filename, &fdt_size);
  48    qemu_free(filename);
  49    if (fdt == NULL) {
  50        goto out;
  51    }
  52
  53    /* Manipulate device tree in memory. */
  54
  55    ret = qemu_devtree_setprop(fdt, "/memory", "reg", mem_reg_property,
  56                               sizeof(mem_reg_property));
  57    if (ret < 0)
  58        fprintf(stderr, "couldn't set /memory/reg\n");
  59
  60    ret = qemu_devtree_setprop_cell(fdt, "/chosen", "linux,initrd-start",
  61                                    initrd_base);
  62    if (ret < 0)
  63        fprintf(stderr, "couldn't set /chosen/linux,initrd-start\n");
  64
  65    ret = qemu_devtree_setprop_cell(fdt, "/chosen", "linux,initrd-end",
  66                                    (initrd_base + initrd_size));
  67    if (ret < 0)
  68        fprintf(stderr, "couldn't set /chosen/linux,initrd-end\n");
  69
  70    ret = qemu_devtree_setprop_string(fdt, "/chosen", "bootargs",
  71                                      kernel_cmdline);
  72    if (ret < 0)
  73        fprintf(stderr, "couldn't set /chosen/bootargs\n");
  74
  75    if (kvm_enabled())
  76        kvmppc_fdt_update(fdt);
  77
  78    cpu_physical_memory_write (addr, (void *)fdt, fdt_size);
  79
  80out:
  81#endif
  82
  83    return fdt;
  84}
  85
  86static void bamboo_init(ram_addr_t ram_size,
  87                        const char *boot_device,
  88                        const char *kernel_filename,
  89                        const char *kernel_cmdline,
  90                        const char *initrd_filename,
  91                        const char *cpu_model)
  92{
  93    unsigned int pci_irq_nrs[4] = { 28, 27, 26, 25 };
  94    PCIBus *pcibus;
  95    CPUState *env;
  96    uint64_t elf_entry;
  97    uint64_t elf_lowaddr;
  98    target_phys_addr_t entry = 0;
  99    target_phys_addr_t loadaddr = 0;
 100    target_long kernel_size = 0;
 101    target_ulong initrd_base = 0;
 102    target_long initrd_size = 0;
 103    target_ulong dt_base = 0;
 104    void *fdt;
 105    int i;
 106
 107    /* Setup CPU. */
 108    env = ppc440ep_init(&ram_size, &pcibus, pci_irq_nrs, 1, cpu_model);
 109
 110    if (pcibus) {
 111        /* Add virtio console devices */
 112        for(i = 0; i < MAX_VIRTIO_CONSOLES; i++) {
 113            if (virtcon_hds[i]) {
 114                pci_create_simple(pcibus, -1, "virtio-console-pci");
 115            }
 116        }
 117
 118        /* Register network interfaces. */
 119        for (i = 0; i < nb_nics; i++) {
 120            /* There are no PCI NICs on the Bamboo board, but there are
 121             * PCI slots, so we can pick whatever default model we want. */
 122            pci_nic_init_nofail(&nd_table[i], "e1000", NULL);
 123        }
 124    }
 125
 126    /* Load kernel. */
 127    if (kernel_filename) {
 128        kernel_size = load_uimage(kernel_filename, &entry, &loadaddr, NULL);
 129        if (kernel_size < 0) {
 130            kernel_size = load_elf(kernel_filename, 0, &elf_entry, &elf_lowaddr,
 131                                   NULL, 1, ELF_MACHINE, 0);
 132            entry = elf_entry;
 133            loadaddr = elf_lowaddr;
 134        }
 135        /* XXX try again as binary */
 136        if (kernel_size < 0) {
 137            fprintf(stderr, "qemu: could not load kernel '%s'\n",
 138                    kernel_filename);
 139            exit(1);
 140        }
 141    }
 142
 143    /* Load initrd. */
 144    if (initrd_filename) {
 145        initrd_base = kernel_size + loadaddr;
 146        initrd_size = load_image_targphys(initrd_filename, initrd_base,
 147                                          ram_size - initrd_base);
 148
 149        if (initrd_size < 0) {
 150            fprintf(stderr, "qemu: could not load initial ram disk '%s'\n",
 151                    initrd_filename);
 152            exit(1);
 153        }
 154    }
 155
 156    /* If we're loading a kernel directly, we must load the device tree too. */
 157    if (kernel_filename) {
 158        if (initrd_base)
 159            dt_base = initrd_base + initrd_size;
 160        else
 161            dt_base = kernel_size + loadaddr;
 162
 163        fdt = bamboo_load_device_tree(dt_base, ram_size,
 164                                      initrd_base, initrd_size, kernel_cmdline);
 165        if (fdt == NULL) {
 166            fprintf(stderr, "couldn't load device tree\n");
 167            exit(1);
 168        }
 169
 170        /* Set initial guest state. */
 171        env->gpr[1] = (16<<20) - 8;
 172        env->gpr[3] = dt_base;
 173        env->nip = entry;
 174        /* XXX we currently depend on KVM to create some initial TLB entries. */
 175    }
 176
 177    if (kvm_enabled())
 178        kvmppc_init();
 179}
 180
 181static QEMUMachine bamboo_machine = {
 182    .name = "bamboo",
 183    .desc = "bamboo",
 184    .init = bamboo_init,
 185};
 186
 187static void bamboo_machine_init(void)
 188{
 189    qemu_register_machine(&bamboo_machine);
 190}
 191
 192machine_init(bamboo_machine_init);
 193