Message ID | 1304334247-6005-3-git-send-email-agraf@suse.de |
---|---|
State | New |
Headers | show |
On Mon, May 02, 2011 at 01:04:04PM +0200, Alexander Graf 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. Just a few inline questions... > > Signed-off-by: Alexander Graf <agraf@suse.de> > --- > hw/ppce500_mpc8544ds.c | 56 +++++++++++++++++++++++++++++++++++++++-------- > 1 files changed, 46 insertions(+), 10 deletions(-) > > diff --git a/hw/ppce500_mpc8544ds.c b/hw/ppce500_mpc8544ds.c > index 1b8a1c4..b5dd937 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" > @@ -82,7 +83,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 +104,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 +150,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 +168,21 @@ out: > return ret; > } > > +/* Create reset TLB entries for BookE, spanning the 32bit addr space. */ > +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; Is this code really mapping the entire 32bit addr space as the comment says? > + tlb->EPN = va & TARGET_PAGE_MASK; > + tlb->RPN = pa & TARGET_PAGE_MASK; > + tlb->PID = 0; > +} > + > static void mpc8544ds_init(ram_addr_t ram_size, > const char *boot_device, > const char *kernel_filename, > @@ -188,6 +215,10 @@ 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); > + > /* Fixup Memory size on a alignment boundary */ > ram_size &= ~(RAM_SIZES_ALIGN - 1); > > @@ -265,6 +296,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,11 +306,13 @@ static void mpc8544ds_init(ram_addr_t ram_size, > exit(1); > } > > + cpu_reset(env); > + > /* 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. */ > + mmubooke_create_initial_mapping(env, 0, 0); > } > Should the cpu_reset & friends maybe be done from a qemu_register_reset registerd callback? Cheers
On 02.05.2011, at 14:05, Edgar E. Iglesias wrote: > On Mon, May 02, 2011 at 01:04:04PM +0200, Alexander Graf 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. > > > Just a few inline questions... > > >> >> Signed-off-by: Alexander Graf <agraf@suse.de> >> --- >> hw/ppce500_mpc8544ds.c | 56 +++++++++++++++++++++++++++++++++++++++-------- >> 1 files changed, 46 insertions(+), 10 deletions(-) >> >> diff --git a/hw/ppce500_mpc8544ds.c b/hw/ppce500_mpc8544ds.c >> index 1b8a1c4..b5dd937 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" >> @@ -82,7 +83,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 +104,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 +150,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 +168,21 @@ out: >> return ret; >> } >> >> +/* Create reset TLB entries for BookE, spanning the 32bit addr space. */ >> +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; > > > Is this code really mapping the entire 32bit addr space as the comment says? You're right - the comment is wrong :). > > >> + tlb->EPN = va & TARGET_PAGE_MASK; >> + tlb->RPN = pa & TARGET_PAGE_MASK; >> + tlb->PID = 0; >> +} >> + >> static void mpc8544ds_init(ram_addr_t ram_size, >> const char *boot_device, >> const char *kernel_filename, >> @@ -188,6 +215,10 @@ 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); >> + >> /* Fixup Memory size on a alignment boundary */ >> ram_size &= ~(RAM_SIZES_ALIGN - 1); >> >> @@ -265,6 +296,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,11 +306,13 @@ static void mpc8544ds_init(ram_addr_t ram_size, >> exit(1); >> } >> >> + cpu_reset(env); >> + >> /* 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. */ >> + mmubooke_create_initial_mapping(env, 0, 0); >> } >> > > Should the cpu_reset & friends maybe be done from a qemu_register_reset > registerd callback? That would definitely be better, yes! Will fix and send out v3. Alex
diff --git a/hw/ppce500_mpc8544ds.c b/hw/ppce500_mpc8544ds.c index 1b8a1c4..b5dd937 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" @@ -82,7 +83,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 +104,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 +150,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 +168,21 @@ out: return ret; } +/* Create reset TLB entries for BookE, spanning the 32bit addr space. */ +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_init(ram_addr_t ram_size, const char *boot_device, const char *kernel_filename, @@ -188,6 +215,10 @@ 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); + /* Fixup Memory size on a alignment boundary */ ram_size &= ~(RAM_SIZES_ALIGN - 1); @@ -265,6 +296,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,11 +306,13 @@ static void mpc8544ds_init(ram_addr_t ram_size, exit(1); } + cpu_reset(env); + /* 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. */ + mmubooke_create_initial_mapping(env, 0, 0); } if (kvm_enabled())
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 <agraf@suse.de> --- hw/ppce500_mpc8544ds.c | 56 +++++++++++++++++++++++++++++++++++++++-------- 1 files changed, 46 insertions(+), 10 deletions(-)