[Qemu-devel] [PATCH 2/7] PPC: Make MPC8544DS emulation work w/o KVM
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 --- 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 0xE100 #define MPC8544_PCI_IOLEN 0x1 +static struct boot_info +{ +uint32_t dt_base; +uint32_t entry; +} boot_info; + #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 = 4; + +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, 4, 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 sup
[Qemu-devel] [PATCH 2/7] PPC: Make MPC8544DS emulation work w/o KVM
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 --- 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 0xE100 #define MPC8544_PCI_IOLEN 0x1 +static struct boot_info +{ +uint32_t dt_base; +uint32_t entry; +} boot_info; + #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 = 4; + +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, 4, 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 sup
[Qemu-devel] [PATCH 2/7] PPC: Make MPC8544DS emulation work w/o KVM
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 --- v2 -> v3: - fix mpc initial tlb size comment - enable cpu reset v5 -> v6: - use dynamically allocated boot_info struct --- hw/ppce500_mpc8544ds.c | 91 +++- 1 files changed, 74 insertions(+), 17 deletions(-) diff --git a/hw/ppce500_mpc8544ds.c b/hw/ppce500_mpc8544ds.c index 1b8a1c4..25c14c1 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 0xE100 #define MPC8544_PCI_IOLEN 0x1 +struct boot_info +{ +uint32_t dt_base; +uint32_t entry; +}; + #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 = 4; + +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, @@ -176,6 +223,7 @@ static void mpc8544ds_init(ram_addr_t ram_size, int i=0; unsigned int pci_irq_nrs[4] = {1, 2, 3, 4}; qemu_irq *irqs, *mpic, *pci_irqs; +struct boot_info *boot_info; /* Setup CPU */ if (cpu_model == NULL) { @@ -188,6 +236,13 @@ static void mpc8544ds_init(ram_addr_t ram_size, exit(1); } +/* XXX register timer? */ +ppc_emb_timers_init(env, 4, 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 bou
Re: [Qemu-devel] [PATCH 2/7] PPC: Make MPC8544DS emulation work w/o KVM
On Sun, May 8, 2011 at 2:00 AM, 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. > > Signed-off-by: Alexander Graf > > --- > > 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 0xE100 > #define MPC8544_PCI_IOLEN 0x1 > > +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 = 4; > + > + 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, 4, PPC_INTERRUPT_DECR); > + ppc_dcr_init(env, NULL, NULL); > + > + /* Register reset handler */ > + qemu_register_reset(mpc8544ds_cpu_
Re: [Qemu-devel] [PATCH 2/7] PPC: Make MPC8544DS emulation work w/o KVM
Am 08.05.2011 um 12:08 schrieb Blue Swirl : > On Sun, May 8, 2011 at 2:00 AM, 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. >> >> Signed-off-by: Alexander Graf >> >> --- >> >> 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 0xE100 >> #define MPC8544_PCI_IOLEN 0x1 >> >> +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. I just modeled it the same as Edgar's code :) > Alex