Statistics
| Branch: | Revision:

root / hw / ppc440_bamboo.c @ 18ebcc86

History | View | Annotate | Download (6.4 kB)

1 2c9fade2 aurel32
/*
2 2c9fade2 aurel32
 * Qemu PowerPC 440 Bamboo board emulation
3 2c9fade2 aurel32
 *
4 2c9fade2 aurel32
 * Copyright 2007 IBM Corporation.
5 2c9fade2 aurel32
 * Authors:
6 2c9fade2 aurel32
 *         Jerone Young <jyoung5@us.ibm.com>
7 2c9fade2 aurel32
 *         Christian Ehrhardt <ehrhardt@linux.vnet.ibm.com>
8 2c9fade2 aurel32
 *         Hollis Blanchard <hollisb@us.ibm.com>
9 2c9fade2 aurel32
 *
10 2c9fade2 aurel32
 * This work is licensed under the GNU GPL license version 2 or later.
11 2c9fade2 aurel32
 *
12 2c9fade2 aurel32
 */
13 2c9fade2 aurel32
14 2c9fade2 aurel32
#include "config.h"
15 2c9fade2 aurel32
#include "qemu-common.h"
16 2c9fade2 aurel32
#include "net.h"
17 2c9fade2 aurel32
#include "hw.h"
18 2c9fade2 aurel32
#include "pci.h"
19 2c9fade2 aurel32
#include "boards.h"
20 2c9fade2 aurel32
#include "ppc440.h"
21 2c9fade2 aurel32
#include "kvm.h"
22 2c9fade2 aurel32
#include "kvm_ppc.h"
23 2c9fade2 aurel32
#include "device_tree.h"
24 ca20cf32 Blue Swirl
#include "loader.h"
25 ca20cf32 Blue Swirl
#include "elf.h"
26 3e9f0113 Richard Henderson
#include "exec-memory.h"
27 2c9fade2 aurel32
28 2c9fade2 aurel32
#define BINARY_DEVICE_TREE_FILE "bamboo.dtb"
29 2c9fade2 aurel32
30 ceee6da6 Hollis Blanchard
/* from u-boot */
31 ceee6da6 Hollis Blanchard
#define KERNEL_ADDR  0x1000000
32 ceee6da6 Hollis Blanchard
#define FDT_ADDR     0x1800000
33 ceee6da6 Hollis Blanchard
#define RAMDISK_ADDR 0x1900000
34 ceee6da6 Hollis Blanchard
35 04088adb Liu Yu
static int bamboo_load_device_tree(target_phys_addr_t addr,
36 2c9fade2 aurel32
                                     uint32_t ramsize,
37 c227f099 Anthony Liguori
                                     target_phys_addr_t initrd_base,
38 c227f099 Anthony Liguori
                                     target_phys_addr_t initrd_size,
39 2c9fade2 aurel32
                                     const char *kernel_cmdline)
40 2c9fade2 aurel32
{
41 dbf916d8 Aurelien Jarno
    int ret = -1;
42 3f0855b1 Juan Quintela
#ifdef CONFIG_FDT
43 2c9fade2 aurel32
    uint32_t mem_reg_property[] = { 0, 0, ramsize };
44 5cea8590 Paul Brook
    char *filename;
45 7ec632b4 pbrook
    int fdt_size;
46 dbf916d8 Aurelien Jarno
    void *fdt;
47 7dadd40c Alexander Graf
    uint32_t tb_freq = 400000000;
48 7dadd40c Alexander Graf
    uint32_t clock_freq = 400000000;
49 2c9fade2 aurel32
50 5cea8590 Paul Brook
    filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, BINARY_DEVICE_TREE_FILE);
51 5cea8590 Paul Brook
    if (!filename) {
52 5cea8590 Paul Brook
        goto out;
53 5cea8590 Paul Brook
    }
54 5cea8590 Paul Brook
    fdt = load_device_tree(filename, &fdt_size);
55 7267c094 Anthony Liguori
    g_free(filename);
56 5cea8590 Paul Brook
    if (fdt == NULL) {
57 2c9fade2 aurel32
        goto out;
58 5cea8590 Paul Brook
    }
59 2c9fade2 aurel32
60 2c9fade2 aurel32
    /* Manipulate device tree in memory. */
61 2c9fade2 aurel32
62 2c9fade2 aurel32
    ret = qemu_devtree_setprop(fdt, "/memory", "reg", mem_reg_property,
63 2c9fade2 aurel32
                               sizeof(mem_reg_property));
64 2c9fade2 aurel32
    if (ret < 0)
65 2c9fade2 aurel32
        fprintf(stderr, "couldn't set /memory/reg\n");
66 2c9fade2 aurel32
67 2c9fade2 aurel32
    ret = qemu_devtree_setprop_cell(fdt, "/chosen", "linux,initrd-start",
68 2c9fade2 aurel32
                                    initrd_base);
69 2c9fade2 aurel32
    if (ret < 0)
70 2c9fade2 aurel32
        fprintf(stderr, "couldn't set /chosen/linux,initrd-start\n");
71 2c9fade2 aurel32
72 2c9fade2 aurel32
    ret = qemu_devtree_setprop_cell(fdt, "/chosen", "linux,initrd-end",
73 2c9fade2 aurel32
                                    (initrd_base + initrd_size));
74 2c9fade2 aurel32
    if (ret < 0)
75 2c9fade2 aurel32
        fprintf(stderr, "couldn't set /chosen/linux,initrd-end\n");
76 2c9fade2 aurel32
77 2c9fade2 aurel32
    ret = qemu_devtree_setprop_string(fdt, "/chosen", "bootargs",
78 2c9fade2 aurel32
                                      kernel_cmdline);
79 2c9fade2 aurel32
    if (ret < 0)
80 2c9fade2 aurel32
        fprintf(stderr, "couldn't set /chosen/bootargs\n");
81 2c9fade2 aurel32
82 7dadd40c Alexander Graf
    /* Copy data from the host device tree into the guest. Since the guest can
83 7dadd40c Alexander Graf
     * directly access the timebase without host involvement, we must expose
84 7dadd40c Alexander Graf
     * the correct frequencies. */
85 a489f7f7 Alexander Graf
    if (kvm_enabled()) {
86 7dadd40c Alexander Graf
        tb_freq = kvmppc_get_tbfreq();
87 7dadd40c Alexander Graf
        clock_freq = kvmppc_get_clockfreq();
88 a489f7f7 Alexander Graf
    }
89 2c9fade2 aurel32
90 7dadd40c Alexander Graf
    qemu_devtree_setprop_cell(fdt, "/cpus/cpu@0", "clock-frequency",
91 7dadd40c Alexander Graf
                              clock_freq);
92 7dadd40c Alexander Graf
    qemu_devtree_setprop_cell(fdt, "/cpus/cpu@0", "timebase-frequency",
93 7dadd40c Alexander Graf
                              tb_freq);
94 2c9fade2 aurel32
95 04088adb Liu Yu
    ret = rom_add_blob_fixed(BINARY_DEVICE_TREE_FILE, fdt, fdt_size, addr);
96 7267c094 Anthony Liguori
    g_free(fdt);
97 7ec632b4 pbrook
98 2c9fade2 aurel32
out:
99 2c9fade2 aurel32
#endif
100 2c9fade2 aurel32
101 04088adb Liu Yu
    return ret;
102 2c9fade2 aurel32
}
103 2c9fade2 aurel32
104 c227f099 Anthony Liguori
static void bamboo_init(ram_addr_t ram_size,
105 a147d62b blueswir1
                        const char *boot_device,
106 2c9fade2 aurel32
                        const char *kernel_filename,
107 2c9fade2 aurel32
                        const char *kernel_cmdline,
108 2c9fade2 aurel32
                        const char *initrd_filename,
109 2c9fade2 aurel32
                        const char *cpu_model)
110 2c9fade2 aurel32
{
111 2c9fade2 aurel32
    unsigned int pci_irq_nrs[4] = { 28, 27, 26, 25 };
112 3e9f0113 Richard Henderson
    MemoryRegion *address_space_mem = get_system_memory();
113 2c9fade2 aurel32
    PCIBus *pcibus;
114 2c9fade2 aurel32
    CPUState *env;
115 2c9fade2 aurel32
    uint64_t elf_entry;
116 2c9fade2 aurel32
    uint64_t elf_lowaddr;
117 c227f099 Anthony Liguori
    target_phys_addr_t entry = 0;
118 c227f099 Anthony Liguori
    target_phys_addr_t loadaddr = 0;
119 2c9fade2 aurel32
    target_long initrd_size = 0;
120 ceee6da6 Hollis Blanchard
    int success;
121 2c9fade2 aurel32
    int i;
122 2c9fade2 aurel32
123 2c9fade2 aurel32
    /* Setup CPU. */
124 3e9f0113 Richard Henderson
    env = ppc440ep_init(address_space_mem, &ram_size, &pcibus,
125 3e9f0113 Richard Henderson
                        pci_irq_nrs, 1, cpu_model);
126 2c9fade2 aurel32
127 2c9fade2 aurel32
    if (pcibus) {
128 2c9fade2 aurel32
        /* Register network interfaces. */
129 2c9fade2 aurel32
        for (i = 0; i < nb_nics; i++) {
130 cb457d76 aliguori
            /* There are no PCI NICs on the Bamboo board, but there are
131 cb457d76 aliguori
             * PCI slots, so we can pick whatever default model we want. */
132 07caea31 Markus Armbruster
            pci_nic_init_nofail(&nd_table[i], "e1000", NULL);
133 2c9fade2 aurel32
        }
134 2c9fade2 aurel32
    }
135 2c9fade2 aurel32
136 2c9fade2 aurel32
    /* Load kernel. */
137 2c9fade2 aurel32
    if (kernel_filename) {
138 ceee6da6 Hollis Blanchard
        success = load_uimage(kernel_filename, &entry, &loadaddr, NULL);
139 ceee6da6 Hollis Blanchard
        if (success < 0) {
140 ceee6da6 Hollis Blanchard
            success = load_elf(kernel_filename, NULL, NULL, &elf_entry,
141 ceee6da6 Hollis Blanchard
                               &elf_lowaddr, NULL, 1, ELF_MACHINE, 0);
142 2c9fade2 aurel32
            entry = elf_entry;
143 2c9fade2 aurel32
            loadaddr = elf_lowaddr;
144 2c9fade2 aurel32
        }
145 2c9fade2 aurel32
        /* XXX try again as binary */
146 ceee6da6 Hollis Blanchard
        if (success < 0) {
147 2c9fade2 aurel32
            fprintf(stderr, "qemu: could not load kernel '%s'\n",
148 2c9fade2 aurel32
                    kernel_filename);
149 2c9fade2 aurel32
            exit(1);
150 2c9fade2 aurel32
        }
151 2c9fade2 aurel32
    }
152 2c9fade2 aurel32
153 2c9fade2 aurel32
    /* Load initrd. */
154 2c9fade2 aurel32
    if (initrd_filename) {
155 ceee6da6 Hollis Blanchard
        initrd_size = load_image_targphys(initrd_filename, RAMDISK_ADDR,
156 ceee6da6 Hollis Blanchard
                                          ram_size - RAMDISK_ADDR);
157 2c9fade2 aurel32
158 2c9fade2 aurel32
        if (initrd_size < 0) {
159 ceee6da6 Hollis Blanchard
            fprintf(stderr, "qemu: could not load ram disk '%s' at %x\n",
160 ceee6da6 Hollis Blanchard
                    initrd_filename, RAMDISK_ADDR);
161 2c9fade2 aurel32
            exit(1);
162 2c9fade2 aurel32
        }
163 2c9fade2 aurel32
    }
164 2c9fade2 aurel32
165 2c9fade2 aurel32
    /* If we're loading a kernel directly, we must load the device tree too. */
166 2c9fade2 aurel32
    if (kernel_filename) {
167 ceee6da6 Hollis Blanchard
        if (bamboo_load_device_tree(FDT_ADDR, ram_size, RAMDISK_ADDR,
168 ceee6da6 Hollis Blanchard
                                    initrd_size, kernel_cmdline) < 0) {
169 2c9fade2 aurel32
            fprintf(stderr, "couldn't load device tree\n");
170 2c9fade2 aurel32
            exit(1);
171 2c9fade2 aurel32
        }
172 2c9fade2 aurel32
173 2c9fade2 aurel32
        /* Set initial guest state. */
174 2c9fade2 aurel32
        env->gpr[1] = (16<<20) - 8;
175 ceee6da6 Hollis Blanchard
        env->gpr[3] = FDT_ADDR;
176 2c9fade2 aurel32
        env->nip = entry;
177 2c9fade2 aurel32
        /* XXX we currently depend on KVM to create some initial TLB entries. */
178 2c9fade2 aurel32
    }
179 2c9fade2 aurel32
180 2c9fade2 aurel32
    if (kvm_enabled())
181 2c9fade2 aurel32
        kvmppc_init();
182 2c9fade2 aurel32
}
183 2c9fade2 aurel32
184 f80f9ec9 Anthony Liguori
static QEMUMachine bamboo_machine = {
185 977b6b91 Amit Shah
    .name = "bamboo-0.13",
186 977b6b91 Amit Shah
    .alias = "bamboo",
187 977b6b91 Amit Shah
    .desc = "bamboo",
188 977b6b91 Amit Shah
    .init = bamboo_init,
189 977b6b91 Amit Shah
};
190 977b6b91 Amit Shah
191 977b6b91 Amit Shah
static QEMUMachine bamboo_machine_v0_12 = {
192 977b6b91 Amit Shah
    .name = "bamboo-0.12",
193 2c9fade2 aurel32
    .desc = "bamboo",
194 2c9fade2 aurel32
    .init = bamboo_init,
195 21be440c Amit Shah
    .compat_props = (GlobalProperty[]) {
196 21be440c Amit Shah
        {
197 21be440c Amit Shah
            .driver   = "virtio-serial-pci",
198 1e29a009 Amit Shah
            .property = "max_ports",
199 21be440c Amit Shah
            .value    = stringify(1),
200 21be440c Amit Shah
        },{
201 21be440c Amit Shah
            .driver   = "virtio-serial-pci",
202 21be440c Amit Shah
            .property = "vectors",
203 21be440c Amit Shah
            .value    = stringify(0),
204 21be440c Amit Shah
        },
205 21be440c Amit Shah
        { /* end of list */ }
206 21be440c Amit Shah
    },
207 2c9fade2 aurel32
};
208 f80f9ec9 Anthony Liguori
209 f80f9ec9 Anthony Liguori
static void bamboo_machine_init(void)
210 f80f9ec9 Anthony Liguori
{
211 f80f9ec9 Anthony Liguori
    qemu_register_machine(&bamboo_machine);
212 977b6b91 Amit Shah
    qemu_register_machine(&bamboo_machine_v0_12);
213 f80f9ec9 Anthony Liguori
}
214 f80f9ec9 Anthony Liguori
215 f80f9ec9 Anthony Liguori
machine_init(bamboo_machine_init);