[PATCH 7 of 7] Add Powerpc 440 board model "bamboo" to take advantage of Powerpc KVM

Jerone Young
2008-01-28T03:16:30Z

# User Jerone Young <jyoung5-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
# Date 1201490062 21600
# Node ID 39f4363836421bc1f78f83c69ad10d76c58a678a
# Parent bf22e220977099e60b57be9e16d7d96487defdc1
Add Powerpc 440 board model "bamboo" to take advantage of Powerpc KVM.

This patch adds the bamboo board model to Qemu. The Bamboo is a PowerPC 440 SOC (System-on-chip) reference platform. This code takes advantage of PowerPC KVM capabilities.

Signed-off-by: Jerone Young <jyoung5-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>

diff --git a/qemu/hw/boards.h b/qemu/hw/boards.h
--- a/qemu/hw/boards.h
+++ b/qemu/hw/boards.h
@@ -32,6 +32,7 @@ extern QEMUMachine heathrow_machine;
extern QEMUMachine heathrow_machine;
extern QEMUMachine ref405ep_machine;
extern QEMUMachine taihu_machine;
+extern QEMUMachine bamboo_machine;

/* mips_r4k.c */
extern QEMUMachine mips_machine;
diff --git a/qemu/hw/ppc440.c b/qemu/hw/ppc440.c
new file mode 100644
--- /dev/null
+++ b/qemu/hw/ppc440.c
@@ -0,0 +1,56 @@
+/*
+ * Qemu PowerPC 440 board emualtion
+ *
+ * Copyright 2007 IBM Corporation.
+ * Authors: Jerone Young <jyoung5-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
+ *
+ * This work is licensed under the GNU LGPL license, version 2.
+ *
+ */
+
+#include "ppc440.h"
+
+void ppc440_init(CPUState *env,
+ target_phys_addr_t ram_bases[2],
+ target_phys_addr_t ram_sizes[2],
+ qemu_irq **picp,
+ int do_init)
+{
+ ppc4xx_mmio_t *mmio;
+ qemu_irq *pic, *irqs;
+ ram_addr_t offset;
+ int i;
+
+ ppc_dcr_init(env, NULL, NULL);
+
+ /* mmio */
+ printf("setup mmio\n");
+ mmio = ppc4xx_mmio_init(env, 0xEF600000);
+
+ /* universal controller */
+ printf("setup universal controller\n");
+ irqs = qemu_mallocz(sizeof(qemu_irq) * PPCUIC_OUTPUT_NB);
+ irqs[PPCUIC_OUTPUT_INT] =
+ ((qemu_irq *)env->irq_inputs)[PPC40x_INPUT_INT];
+ irqs[PPCUIC_OUTPUT_CINT] =
+ ((qemu_irq *)env->irq_inputs)[PPC40x_INPUT_CINT];
+ pic = ppcuic_init(env, irqs, 0x0C0, 0, 1);
+ *picp = pic;
+
+ /* SDRAM controller */
+ printf("trying to setup sdram controller\n");
+ ppc405_sdram_init(env, pic[14], 2, ram_bases, ram_sizes, do_init);
+ offset = 0;
+ for (i = 0; i < 2; i++)
+ offset += ram_sizes[i];
+
+ /* serial ports on page 126 of 440EP user manual */
+ if (serial_hds[0]) {
+ printf("Initializing first serial port\n");
+ ppc405_serial_init(env, mmio,0x300, pic[31], serial_hds[0]);
+ }
+ if (serial_hds[1]) {
+ printf("Initializing 2nd serial port\n");
+ ppc405_serial_init(env, mmio,0x400, pic[30], serial_hds[1]);
+ }
+}
diff --git a/qemu/hw/ppc440.h b/qemu/hw/ppc440.h
new file mode 100644
--- /dev/null
+++ b/qemu/hw/ppc440.h
@@ -0,0 +1,29 @@
+/*
+ * Qemu PowerPC 440 board emualtion
+ *
+ * Copyright 2007 IBM Corporation.
+ * Authors: Jerone Young <jyoung5-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
+ *
+ * This work is licensed under the GNU LGPL license, version 2.
+ *
+ */
+
+#ifndef QEMU_PPC440_H
+#define QEMU_PPC440_H
+
+#include "hw.h"
+#include "ppc.h"
+#include "ppc405.h"
+#include "pc.h"
+#include "qemu-timer.h"
+#include "sysemu.h"
+#include "exec-all.h"
+#include "boards.h"
+
+void ppc440_init(CPUState *env,
+ target_phys_addr_t ram_bases[2],
+ target_phys_addr_t ram_sizes[2],
+ qemu_irq **picp,
+ int do_init);
+
+#endif
diff --git a/qemu/hw/ppc440_bamboo.c b/qemu/hw/ppc440_bamboo.c
new file mode 100644
--- /dev/null
+++ b/qemu/hw/ppc440_bamboo.c
@@ -0,0 +1,124 @@
+/*
+ * Qemu PowerPC 440 board emualtion
+ *
+ * Copyright 2007 IBM Corporation.
+ * Authors: Jerone Young <jyoung5-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
+ *
+ * This work is licensed under the GNU LGPL license, version 2.
+ *
+ */
+
+#include "ppc440.h"
+
+#define KERNEL_LOAD_ADDR 0x400000 /* uboot loader puts kernel at 4MB */
+
+#if USE_KVM
+#include "qemu-kvm.h"
+#endif
+
+/* PPC 440 refrence demo board
+ *
+ * 440 PowerPC CPU
+ */
+
+void bamboo_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)
+{
+ target_phys_addr_t ram_bases[2], ram_sizes[2];
+ qemu_irq *pic;
+ CPUState *env;
+ target_ulong ep;
+ int is_linux=1; /* Will assume allways is Linux for now */
+ long kernel_size=0;
+ target_ulong initrd_base=0;
+ target_ulong initrd_size=0;
+
+ printf("%s: START\n", __func__);
+
+ /* Setup Memory */
+ if (ram_size) {
+ printf("Ram size specified on command line is %i bytes\n",
+ (int)ram_size);
+ printf("WARNING: RAM is hard coded to 144MB\n");
+ }
+ else {
+ printf("Using defualt ram size of %iMB\n",
+ ((int)ram_size/1024)/1024);
+ }
+
+ /* Each bank can only have memory in configurations of
+ * 16MB, 32MB, 64MB, 128MB, or 256MB
+ */
+ ram_bases[0] = 0x0;
+ ram_sizes[0] = 0x08000000;
+ ram_bases[1] = 0x0;
+ ram_sizes[1] = 0x01000000;
+
+ printf("Ram size of domain is %d bytes\n", (int)ram_size);
+
+ /* Setup CPU */
+ /* XXX We cheat for now and use 405 */
+ env = cpu_ppc_init("405");
+ if (!env) {
+ fprintf(stderr, "Unable to initilize CPU!\n");
+ exit(1);
+ }
+
+ /* call init */
+ printf("Calling function ppc440_init\n");
+ ppc440_init(env, ram_bases, ram_sizes, &pic,1);
+ printf("Done calling ppc440_init\n");
+
+ /* Register mem */
+ cpu_register_physical_memory(0, ram_size, 0);
+#if USE_KVM
+ kvm_cpu_register_physical_memory(0, ram_size, 0);
+#endif
+ /* load kernel with uboot loader */
+ printf("%s: load kernel\n", __func__);
+ kernel_size = load_uboot(kernel_filename, &ep, &is_linux);
+ if (kernel_size < 0) {
+ fprintf(stderr, "qemu: could not load kernel '%s'\n",
+ kernel_filename);
+ exit(1);
+ }
+
+ /* load initrd */
+ if (initrd_filename) {
+ initrd_base = kernel_size + KERNEL_LOAD_ADDR;
+ 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 USE_KVM
+ /* XXX insert TLB entries */
+ env->gpr[1] = (16<<20) - 8;
+ env->gpr[4] = initrd_base;
+ env->gpr[5] = initrd_size;
+
+ env->nip = ep;
+
+ env->cpu_index = 0;
+ printf("%s: loading kvm registers\n", __func__);
+ kvm_load_registers(env);
+#endif
+
+ printf("%s: DONE\n", __func__);
+}
+
+QEMUMachine bamboo_machine = {
+ "bamboo",
+ "bamboo",
+ bamboo_init,
+};
diff --git a/qemu/vl.c b/qemu/vl.c
--- a/qemu/vl.c
+++ b/qemu/vl.c
@@ -8318,6 +8318,7 @@ static void register_machines(void)
qemu_register_machine(&prep_machine);
qemu_register_machine(&ref405ep_machine);
qemu_register_machine(&taihu_machine);
+ qemu_register_machine(&bamboo_machine);
#elif defined(TARGET_MIPS)
qemu_register_machine(&mips_machine);
qemu_register_machine(&mips_malta_machine);