On Sun, May 8, 2011 at 2:00 AM, Alexander Graf <ag...@suse.de> wrote: > The MPC8544DS board emulation was only used with KVM so far, so some > parts of the code didn't provide proper values for non-KVM execution. > > This patch makes the machine work without KVM enabled. To actually use > this, you also need proper e500v2 MMU emulation. > > Signed-off-by: Alexander Graf <ag...@suse.de> > > --- > > v2 -> v3: > > - fix mpc initial tlb size comment > - enable cpu reset > --- > hw/ppce500_mpc8544ds.c | 86 +++++++++++++++++++++++++++++++++++++++-------- > 1 files changed, 71 insertions(+), 15 deletions(-) > > diff --git a/hw/ppce500_mpc8544ds.c b/hw/ppce500_mpc8544ds.c > index 1b8a1c4..44d6440 100644 > --- a/hw/ppce500_mpc8544ds.c > +++ b/hw/ppce500_mpc8544ds.c > @@ -28,6 +28,7 @@ > #include "kvm_ppc.h" > #include "device_tree.h" > #include "openpic.h" > +#include "ppc.h" > #include "ppce500.h" > #include "loader.h" > #include "elf.h" > @@ -50,6 +51,12 @@ > #define MPC8544_PCI_IO 0xE1000000 > #define MPC8544_PCI_IOLEN 0x10000 > > +static struct boot_info > +{ > + uint32_t dt_base; > + uint32_t entry; > +} boot_info;
I don't think there is a need to use static state here. > + > #ifdef CONFIG_FDT > static int mpc8544_copy_soc_cell(void *fdt, const char *node, const char > *prop) > { > @@ -82,7 +89,7 @@ static int mpc8544_load_device_tree(target_phys_addr_t addr, > { > int ret = -1; > #ifdef CONFIG_FDT > - uint32_t mem_reg_property[] = {0, ramsize}; > + uint32_t mem_reg_property[] = {0, cpu_to_be32(ramsize)}; > char *filename; > int fdt_size; > void *fdt; > @@ -103,15 +110,19 @@ static int mpc8544_load_device_tree(target_phys_addr_t > addr, > 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"); > + if (initrd_size) { > + 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_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); > @@ -145,6 +156,13 @@ static int mpc8544_load_device_tree(target_phys_addr_t > addr, > > mpc8544_copy_soc_cell(fdt, buf, "clock-frequency"); > mpc8544_copy_soc_cell(fdt, buf, "timebase-frequency"); > + } else { > + const uint32_t freq = 400000000; > + > + qemu_devtree_setprop_cell(fdt, "/cpus/PowerPC,8544@0", > + "clock-frequency", freq); > + qemu_devtree_setprop_cell(fdt, "/cpus/PowerPC,8544@0", > + "timebase-frequency", freq); > } > > ret = rom_add_blob_fixed(BINARY_DEVICE_TREE_FILE, fdt, fdt_size, addr); > @@ -156,6 +174,35 @@ out: > return ret; > } > > +/* Create -kernel TLB entries for BookE, linearly spanning 256MB. */ > +static void mmubooke_create_initial_mapping(CPUState *env, > + target_ulong va, > + target_phys_addr_t pa) > +{ > + ppcemb_tlb_t *tlb = &env->tlb[512].tlbe; > + > + tlb->attr = 0; > + tlb->prot = PAGE_VALID | ((PAGE_READ | PAGE_WRITE | PAGE_EXEC) << 4); > + tlb->size = 256 * 1024 * 1024; > + tlb->EPN = va & TARGET_PAGE_MASK; > + tlb->RPN = pa & TARGET_PAGE_MASK; > + tlb->PID = 0; > +} > + > +static void mpc8544ds_cpu_reset(void *opaque) > +{ > + CPUState *env = opaque; > + struct boot_info *bi = env->load_info; > + > + cpu_reset(env); > + > + /* Set initial guest state. */ > + env->gpr[1] = (16<<20) - 8; > + env->gpr[3] = bi->dt_base; > + env->nip = bi->entry; > + mmubooke_create_initial_mapping(env, 0, 0); > +} > + > static void mpc8544ds_init(ram_addr_t ram_size, > const char *boot_device, > const char *kernel_filename, > @@ -188,6 +235,13 @@ static void mpc8544ds_init(ram_addr_t ram_size, > exit(1); > } > > + /* XXX register timer? */ > + ppc_emb_timers_init(env, 400000000, PPC_INTERRUPT_DECR); > + ppc_dcr_init(env, NULL, NULL); > + > + /* Register reset handler */ > + qemu_register_reset(mpc8544ds_cpu_reset, env); > + > /* Fixup Memory size on a alignment boundary */ > ram_size &= ~(RAM_SIZES_ALIGN - 1); > > @@ -265,6 +319,9 @@ static void mpc8544ds_init(ram_addr_t ram_size, > > /* If we're loading a kernel directly, we must load the device tree too. > */ > if (kernel_filename) { > +#ifndef CONFIG_FDT > + cpu_abort(env, "Compiled without FDT support - can't load kernel\n"); > +#endif > dt_base = (kernel_size + DTC_LOAD_PAD) & ~DTC_PAD_MASK; > if (mpc8544_load_device_tree(dt_base, ram_size, > initrd_base, initrd_size, kernel_cmdline) < 0) { > @@ -272,15 +329,14 @@ static void mpc8544ds_init(ram_addr_t ram_size, > 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. */ > + boot_info.entry = entry; > + boot_info.dt_base = dt_base; > } > + env->load_info = &boot_info; > > - if (kvm_enabled()) > + if (kvm_enabled()) { > kvmppc_init(); > + } > > return; > } > -- > 1.6.0.2 > > >