* [Qemu-devel] [PATCH 0/4] powerpc: Add the Virtex5 ML507 refdesign board
@ 2010-09-11 14:09 Edgar E. Iglesias
2010-09-11 14:09 ` [Qemu-devel] [PATCH 1/4] powerpc: Improve emulation of the BookE MMU Edgar E. Iglesias
` (4 more replies)
0 siblings, 5 replies; 15+ messages in thread
From: Edgar E. Iglesias @ 2010-09-11 14:09 UTC (permalink / raw)
To: qemu-devel; +Cc: Edgar E. Iglesias, Alexander Graf
Hi,
This series adds support for emulating virtex5 ml507 PPC-440 boards.
I've tested this by booting linux into userspace and running a bunch
of cryptographic testsuites on top of the guest.
One thing to note is that QEMU lacks a model for the Xilinx LL-TEMAC
and linux will hang if the device-tree says there is one but there is
no model backing it. So either you'll have to disable the driver or
remove it from the device tree, I've been doing the latter. In the
near future I beleive we will contribute a model of the LL-TEMAC and
SDMA.
I can provide device-trees and kernel configs/images to anybody who
might be interested in testing further.
As I said before, this does not add full 440/BookE emulation, instead
I've only done the bare minimum to get linux to boot the virtex5.
The MMU and timer patches could definitely be cleaner, any hints on howto
improve things are welcome.
I'll be happy to fix any issues that people may find.
Cheers
Edgar E. Iglesias (4):
powerpc: Improve emulation of the BookE MMU
powerpc: Make the decr interrupt type overridable
powerpc: Add a ppc-440x5 Xilinx model
powerpc: Add a virtex5 ml507 refdesign board
Makefile.target | 8 +
default-configs/ppc-softmmu.mak | 2 +
default-configs/ppc64-softmmu.mak | 2 +
default-configs/ppcemb-softmmu.mak | 2 +
hw/ppc.c | 22 +++-
hw/ppc.h | 2 +
hw/virtex_ml507.c | 283 ++++++++++++++++++++++++++++++++++++
target-ppc/helper.c | 46 +++++-
target-ppc/translate_init.c | 6 +-
9 files changed, 363 insertions(+), 10 deletions(-)
create mode 100644 hw/virtex_ml507.c
^ permalink raw reply [flat|nested] 15+ messages in thread
* [Qemu-devel] [PATCH 1/4] powerpc: Improve emulation of the BookE MMU
2010-09-11 14:09 [Qemu-devel] [PATCH 0/4] powerpc: Add the Virtex5 ML507 refdesign board Edgar E. Iglesias
@ 2010-09-11 14:09 ` Edgar E. Iglesias
2010-09-11 14:42 ` Andreas Färber
2010-09-20 10:35 ` [Qemu-devel] " Alexander Graf
2010-09-11 14:09 ` [Qemu-devel] [PATCH 2/4] powerpc: Make the decr interrupt type overridable Edgar E. Iglesias
` (3 subsequent siblings)
4 siblings, 2 replies; 15+ messages in thread
From: Edgar E. Iglesias @ 2010-09-11 14:09 UTC (permalink / raw)
To: qemu-devel; +Cc: Edgar E. Iglesias, Alexander Graf
Improve the emulation of the BookE MMU to be able to boot linux
on virtex5 boards.
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@gmail.com>
---
target-ppc/helper.c | 46 ++++++++++++++++++++++++++++++++++++++++------
1 files changed, 40 insertions(+), 6 deletions(-)
diff --git a/target-ppc/helper.c b/target-ppc/helper.c
index a7ec1f4..4c810d1 100644
--- a/target-ppc/helper.c
+++ b/target-ppc/helper.c
@@ -1325,8 +1325,15 @@ int get_physical_address (CPUState *env, mmu_ctx_t *ctx, target_ulong eaddr,
#endif
if ((access_type == ACCESS_CODE && msr_ir == 0) ||
(access_type != ACCESS_CODE && msr_dr == 0)) {
- /* No address translation */
- ret = check_physical(env, ctx, eaddr, rw);
+ if (env->mmu_model == POWERPC_MMU_BOOKE) {
+ /* The BookE MMU always performs address translation. The
+ IS and DS bits only affect the address space. */
+ ret = mmubooke_get_physical_address(env, ctx, eaddr,
+ rw, access_type);
+ } else {
+ /* No address translation. */
+ ret = check_physical(env, ctx, eaddr, rw);
+ }
} else {
ret = -1;
switch (env->mmu_model) {
@@ -1445,7 +1452,10 @@ int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
break;
case POWERPC_MMU_BOOKE:
/* XXX: TODO */
- cpu_abort(env, "BookE MMU model is not implemented\n");
+ env->exception_index = POWERPC_EXCP_ITLB;
+ env->error_code = 0;
+ env->spr[SPR_BOOKE_DEAR] = address;
+ env->spr[SPR_BOOKE_ESR] = 0x00000000;
return -1;
case POWERPC_MMU_BOOKE_FSL:
/* XXX: TODO */
@@ -1471,6 +1481,10 @@ int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
break;
case -3:
/* No execute protection violation */
+ if (env->mmu_model == POWERPC_MMU_BOOKE) {
+ env->spr[SPR_BOOKE_DEAR] = address;
+ env->spr[SPR_BOOKE_ESR] = 0x00000000;
+ }
env->exception_index = POWERPC_EXCP_ISI;
env->error_code = 0x10000000;
break;
@@ -1557,7 +1571,14 @@ int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
break;
case POWERPC_MMU_BOOKE:
/* XXX: TODO */
- cpu_abort(env, "BookE MMU model is not implemented\n");
+ env->exception_index = POWERPC_EXCP_DTLB;
+ env->error_code = 0;
+ env->spr[SPR_BOOKE_DEAR] = address;
+ if (rw) {
+ env->spr[SPR_BOOKE_ESR] = 0x00800000;
+ } else {
+ env->spr[SPR_BOOKE_ESR] = 0x00000000;
+ }
return -1;
case POWERPC_MMU_BOOKE_FSL:
/* XXX: TODO */
@@ -1582,6 +1603,13 @@ int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
if (rw) {
env->spr[SPR_40x_ESR] |= 0x00800000;
}
+ } else if (env->mmu_model == POWERPC_MMU_BOOKE) {
+ env->spr[SPR_BOOKE_DEAR] = address;
+ if (rw) {
+ env->spr[SPR_BOOKE_ESR] = 0x00800000;
+ } else {
+ env->spr[SPR_BOOKE_ESR] = 0x00000000;
+ }
} else {
env->spr[SPR_DAR] = address;
if (rw == 1) {
@@ -1848,8 +1876,7 @@ void ppc_tlb_invalidate_all (CPUPPCState *env)
cpu_abort(env, "MPC8xx MMU model is not implemented\n");
break;
case POWERPC_MMU_BOOKE:
- /* XXX: TODO */
- cpu_abort(env, "BookE MMU model is not implemented\n");
+ tlb_flush(env, 1);
break;
case POWERPC_MMU_BOOKE_FSL:
/* XXX: TODO */
@@ -2629,6 +2656,13 @@ static inline void powerpc_excp(CPUState *env, int excp_model, int excp)
/* Reset exception state */
env->exception_index = POWERPC_EXCP_NONE;
env->error_code = 0;
+
+ if (env->mmu_model == POWERPC_MMU_BOOKE) {
+ /* XXX: The BookE changes address space when switching modes,
+ we should probably implement that as different MMU indexes,
+ but for the moment we do it the slow way and flush all. */
+ tlb_flush(env, 1);
+ }
}
void do_interrupt (CPUState *env)
--
1.7.1
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [Qemu-devel] [PATCH 2/4] powerpc: Make the decr interrupt type overridable
2010-09-11 14:09 [Qemu-devel] [PATCH 0/4] powerpc: Add the Virtex5 ML507 refdesign board Edgar E. Iglesias
2010-09-11 14:09 ` [Qemu-devel] [PATCH 1/4] powerpc: Improve emulation of the BookE MMU Edgar E. Iglesias
@ 2010-09-11 14:09 ` Edgar E. Iglesias
2010-09-20 10:42 ` [Qemu-devel] " Alexander Graf
2010-09-11 14:09 ` [Qemu-devel] [PATCH 3/4] powerpc: Add a ppc-440x5 Xilinx model Edgar E. Iglesias
` (2 subsequent siblings)
4 siblings, 1 reply; 15+ messages in thread
From: Edgar E. Iglesias @ 2010-09-11 14:09 UTC (permalink / raw)
To: qemu-devel; +Cc: Edgar E. Iglesias, Alexander Graf
Make it possible for boards to override the kind of interrupt
to be signaled when the decr timer hits. The 405's signal PIT
interrupts while the 440's signal DECR.
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@gmail.com>
---
hw/ppc.c | 22 ++++++++++++++++++++--
hw/ppc.h | 2 ++
2 files changed, 22 insertions(+), 2 deletions(-)
diff --git a/hw/ppc.c b/hw/ppc.c
index 55e3808..3df7801 100644
--- a/hw/ppc.c
+++ b/hw/ppc.c
@@ -769,6 +769,9 @@ struct ppcemb_timer_t {
struct QEMUTimer *fit_timer;
uint64_t wdt_next; /* Tick for next WDT interrupt */
struct QEMUTimer *wdt_timer;
+
+ /* 405 have the PIT, 440 have a DECR. */
+ unsigned int decr_excp;
};
/* Fixed interval timer */
@@ -851,7 +854,7 @@ static void cpu_4xx_pit_cb (void *opaque)
ppcemb_timer = tb_env->opaque;
env->spr[SPR_40x_TSR] |= 1 << 27;
if ((env->spr[SPR_40x_TCR] >> 26) & 0x1)
- ppc_set_irq(env, PPC_INTERRUPT_PIT, 1);
+ ppc_set_irq(env, ppcemb_timer->decr_excp, 1);
start_stop_pit(env, tb_env, 1);
LOG_TB("%s: ar %d ir %d TCR " TARGET_FMT_lx " TSR " TARGET_FMT_lx " "
"%016" PRIx64 "\n", __func__,
@@ -948,10 +951,15 @@ target_ulong load_40x_pit (CPUState *env)
void store_booke_tsr (CPUState *env, target_ulong val)
{
+ ppc_tb_t *tb_env = env->tb_env;
+ ppcemb_timer_t *ppcemb_timer;
+
+ ppcemb_timer = tb_env->opaque;
+
LOG_TB("%s: val " TARGET_FMT_lx "\n", __func__, val);
env->spr[SPR_40x_TSR] &= ~(val & 0xFC000000);
if (val & 0x80000000)
- ppc_set_irq(env, PPC_INTERRUPT_PIT, 0);
+ ppc_set_irq(env, ppcemb_timer->decr_excp, 0);
}
void store_booke_tcr (CPUState *env, target_ulong val)
@@ -977,6 +985,15 @@ static void ppc_emb_set_tb_clk (void *opaque, uint32_t freq)
/* XXX: we should also update all timers */
}
+void ppc_emb_timers_set_decr_excp(CPUState *env, unsigned int excp)
+{
+ ppc_tb_t *tb_env = env->tb_env;
+ ppcemb_timer_t *ppcemb_timer;
+
+ ppcemb_timer = tb_env->opaque;
+ ppcemb_timer->decr_excp = excp;
+}
+
clk_setup_cb ppc_emb_timers_init (CPUState *env, uint32_t freq)
{
ppc_tb_t *tb_env;
@@ -996,6 +1013,7 @@ clk_setup_cb ppc_emb_timers_init (CPUState *env, uint32_t freq)
qemu_new_timer(vm_clock, &cpu_4xx_fit_cb, env);
ppcemb_timer->wdt_timer =
qemu_new_timer(vm_clock, &cpu_4xx_wdt_cb, env);
+ ppcemb_timer->decr_excp = PPC_INTERRUPT_PIT;
}
return &ppc_emb_set_tb_clk;
diff --git a/hw/ppc.h b/hw/ppc.h
index 1251932..a0fc651 100644
--- a/hw/ppc.h
+++ b/hw/ppc.h
@@ -20,6 +20,8 @@ int ppc_dcr_init (CPUState *env, int (*dcr_read_error)(int dcrn),
int ppc_dcr_register (CPUState *env, int dcrn, void *opaque,
dcr_read_cb drc_read, dcr_write_cb dcr_write);
clk_setup_cb ppc_emb_timers_init (CPUState *env, uint32_t freq);
+void ppc_emb_timers_set_decr_excp(CPUState *env, unsigned int excp);
+
/* Embedded PowerPC reset */
void ppc40x_core_reset (CPUState *env);
void ppc40x_chip_reset (CPUState *env);
--
1.7.1
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [Qemu-devel] [PATCH 3/4] powerpc: Add a ppc-440x5 Xilinx model
2010-09-11 14:09 [Qemu-devel] [PATCH 0/4] powerpc: Add the Virtex5 ML507 refdesign board Edgar E. Iglesias
2010-09-11 14:09 ` [Qemu-devel] [PATCH 1/4] powerpc: Improve emulation of the BookE MMU Edgar E. Iglesias
2010-09-11 14:09 ` [Qemu-devel] [PATCH 2/4] powerpc: Make the decr interrupt type overridable Edgar E. Iglesias
@ 2010-09-11 14:09 ` Edgar E. Iglesias
2010-09-11 14:09 ` [Qemu-devel] [PATCH 4/4] powerpc: Add a virtex5 ml507 refdesign board Edgar E. Iglesias
2010-09-11 15:32 ` [Qemu-devel] Re: [PATCH 0/4] powerpc: Add the Virtex5 ML507 " Alexander Graf
4 siblings, 0 replies; 15+ messages in thread
From: Edgar E. Iglesias @ 2010-09-11 14:09 UTC (permalink / raw)
To: qemu-devel; +Cc: Edgar E. Iglesias, Alexander Graf
Add a powerpc 440x5 with the model ID on the Xilinx virtex5.
Connect the 440x5 to the 40x interrupt logic.
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@gmail.com>
---
target-ppc/translate_init.c | 6 ++++--
1 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index 2bd8b00..05ffe95 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -3596,7 +3596,6 @@ static void init_proc_440x4 (CPUPPCState *env)
POWERPC_FLAG_DE | POWERPC_FLAG_BUS_CLK)
#define check_pow_440x5 check_pow_nocheck
-__attribute__ (( unused ))
static void init_proc_440x5 (CPUPPCState *env)
{
/* Time base */
@@ -3656,7 +3655,7 @@ static void init_proc_440x5 (CPUPPCState *env)
init_excp_BookE(env);
env->dcache_line_size = 32;
env->icache_line_size = 32;
- /* XXX: TODO: allocate internal IRQ controller */
+ ppc40x_irq_init(env);
}
/* PowerPC 460 (guessed) */
@@ -6536,6 +6535,7 @@ enum {
#if 0
CPU_POWERPC_440A4 = xxx,
#endif
+ CPU_POWERPC_440_XILINX = 0x7ff21910,
#if 0
CPU_POWERPC_440A5 = xxx,
#endif
@@ -7464,6 +7464,8 @@ static const ppc_def_t ppc_defs[] = {
/* PowerPC 440 A4 */
POWERPC_DEF("440A4", CPU_POWERPC_440A4, 440x4),
#endif
+ /* PowerPC 440 Xilinx 5 */
+ POWERPC_DEF("440-Xilinx", CPU_POWERPC_440_XILINX, 440x5),
#if defined (TODO)
/* PowerPC 440 A5 */
POWERPC_DEF("440A5", CPU_POWERPC_440A5, 440x5),
--
1.7.1
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [Qemu-devel] [PATCH 4/4] powerpc: Add a virtex5 ml507 refdesign board
2010-09-11 14:09 [Qemu-devel] [PATCH 0/4] powerpc: Add the Virtex5 ML507 refdesign board Edgar E. Iglesias
` (2 preceding siblings ...)
2010-09-11 14:09 ` [Qemu-devel] [PATCH 3/4] powerpc: Add a ppc-440x5 Xilinx model Edgar E. Iglesias
@ 2010-09-11 14:09 ` Edgar E. Iglesias
2010-09-20 10:53 ` [Qemu-devel] " Alexander Graf
2010-09-11 15:32 ` [Qemu-devel] Re: [PATCH 0/4] powerpc: Add the Virtex5 ML507 " Alexander Graf
4 siblings, 1 reply; 15+ messages in thread
From: Edgar E. Iglesias @ 2010-09-11 14:09 UTC (permalink / raw)
To: qemu-devel; +Cc: Edgar E. Iglesias, Alexander Graf
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@gmail.com>
---
Makefile.target | 8 +
default-configs/ppc-softmmu.mak | 2 +
default-configs/ppc64-softmmu.mak | 2 +
default-configs/ppcemb-softmmu.mak | 2 +
hw/virtex_ml507.c | 283 ++++++++++++++++++++++++++++++++++++
5 files changed, 297 insertions(+), 0 deletions(-)
create mode 100644 hw/virtex_ml507.c
diff --git a/Makefile.target b/Makefile.target
index a4e80b1..91d0381 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -217,9 +217,17 @@ obj-ppc-y += ppc4xx_devs.o ppc4xx_pci.o ppc405_uc.o ppc405_boards.o
obj-ppc-y += ppc440.o ppc440_bamboo.o
# PowerPC E500 boards
obj-ppc-y += ppce500_mpc8544ds.o
+# PowerPC 440 Xilinx ML507 reference board.
+obj-ppc-y += virtex_ml507.o
obj-ppc-$(CONFIG_KVM) += kvm_ppc.o
obj-ppc-$(CONFIG_FDT) += device_tree.o
+# Xilinx PPC peripherals
+obj-ppc-y += xilinx_intc.o
+obj-ppc-y += xilinx_timer.o
+obj-ppc-y += xilinx_uartlite.o
+obj-ppc-y += xilinx_ethlite.o
+
obj-mips-y = mips_r4k.o mips_jazz.o mips_malta.o mips_mipssim.o
obj-mips-y += mips_addr.o mips_timer.o mips_int.o
obj-mips-y += vga.o i8259.o
diff --git a/default-configs/ppc-softmmu.mak b/default-configs/ppc-softmmu.mak
index c026bbb..940f4bf 100644
--- a/default-configs/ppc-softmmu.mak
+++ b/default-configs/ppc-softmmu.mak
@@ -32,4 +32,6 @@ CONFIG_IDE_MACIO=y
CONFIG_NE2000_ISA=y
CONFIG_SOUND=y
CONFIG_VIRTIO_PCI=y
+CONFIG_PFLASH_CFI01=y
CONFIG_PFLASH_CFI02=y
+CONFIG_PTIMER=y
diff --git a/default-configs/ppc64-softmmu.mak b/default-configs/ppc64-softmmu.mak
index 0101a28..e1bc6b8 100644
--- a/default-configs/ppc64-softmmu.mak
+++ b/default-configs/ppc64-softmmu.mak
@@ -32,4 +32,6 @@ CONFIG_IDE_MACIO=y
CONFIG_NE2000_ISA=y
CONFIG_SOUND=y
CONFIG_VIRTIO_PCI=y
+CONFIG_PFLASH_CFI01=y
CONFIG_PFLASH_CFI02=y
+CONFIG_PTIMER=y
diff --git a/default-configs/ppcemb-softmmu.mak b/default-configs/ppcemb-softmmu.mak
index 8ba9ac1..8f1cc09 100644
--- a/default-configs/ppcemb-softmmu.mak
+++ b/default-configs/ppcemb-softmmu.mak
@@ -32,4 +32,6 @@ CONFIG_IDE_MACIO=y
CONFIG_NE2000_ISA=y
CONFIG_SOUND=y
CONFIG_VIRTIO_PCI=y
+CONFIG_PFLASH_CFI01=y
CONFIG_PFLASH_CFI02=y
+CONFIG_PTIMER=y
diff --git a/hw/virtex_ml507.c b/hw/virtex_ml507.c
new file mode 100644
index 0000000..bc53cf4
--- /dev/null
+++ b/hw/virtex_ml507.c
@@ -0,0 +1,283 @@
+/*
+ * Model of Xilinx Virtex5 ML507 PPC-440 refdesign.
+ *
+ * Copyright (c) 2010 Edgar E. Iglesias.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "sysbus.h"
+#include "hw.h"
+#include "pc.h"
+#include "net.h"
+#include "flash.h"
+#include "sysemu.h"
+#include "devices.h"
+#include "boards.h"
+#include "device_tree.h"
+#include "loader.h"
+#include "elf.h"
+#include "qemu-log.h"
+
+#include "ppc.h"
+#include "ppc4xx.h"
+#include "ppc440.h"
+#include "ppc405.h"
+
+#include "blockdev.h"
+#include "xilinx.h"
+
+#define EPAPR_MAGIC (0x45504150)
+#define FLASH_SIZE (16 * 1024 * 1024)
+
+static struct
+{
+ uint32_t bootstrap_pc;
+ uint32_t cmdline;
+ uint32_t fdt;
+ uint32_t ima_size;
+ void *vfdt;
+} boot_info;
+
+/* 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[0].tlbe;
+
+ tlb->attr = 0;
+ tlb->prot = PAGE_VALID | ((PAGE_READ | PAGE_WRITE | PAGE_EXEC) << 4);
+ tlb->size = 1 << 31; /* up to 0x80000000 */
+ tlb->EPN = va & TARGET_PAGE_MASK;
+ tlb->RPN = pa & TARGET_PAGE_MASK;
+ tlb->PID = 0;
+
+ tlb = &env->tlb[1].tlbe;
+ tlb->attr = 0;
+ tlb->prot = PAGE_VALID | ((PAGE_READ | PAGE_WRITE | PAGE_EXEC) << 4);
+ tlb->size = 1 << 31; /* up to 0xffffffff */
+ tlb->EPN = 0x80000000 & TARGET_PAGE_MASK;
+ tlb->RPN = 0x80000000 & TARGET_PAGE_MASK;
+ tlb->PID = 0;
+}
+
+static CPUState *ppc440_init_xilinx(ram_addr_t *ram_size,
+ int do_init,
+ const char *cpu_model,
+ clk_setup_t *cpu_clk, clk_setup_t *tb_clk,
+ uint32_t sysclk)
+{
+ CPUState *env;
+ qemu_irq *pic;
+ qemu_irq *irqs;
+
+ env = cpu_init(cpu_model);
+ if (!env) {
+ fprintf(stderr, "Unable to initialize CPU!\n");
+ exit(1);
+ }
+
+ cpu_clk->cb = NULL; /* We don't care about CPU clock frequency changes */
+ cpu_clk->opaque = env;
+ /* Set time-base frequency to sysclk */
+ tb_clk->cb = ppc_emb_timers_init(env, sysclk);
+ tb_clk->opaque = env;
+
+ ppc_emb_timers_set_decr_excp(env, PPC_INTERRUPT_DECR);
+
+ ppc_dcr_init(env, NULL, NULL);
+
+ /* interrupt controller */
+ 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);
+ return env;
+}
+
+static void main_cpu_reset(void *opaque)
+{
+ CPUState *env = opaque;
+ cpu_reset(env);
+ /* Linux Kernel Parameters (passing device tree):
+ * r3: pointer to the fdt
+ * r4: 0
+ * r5: 0
+ * r6: epapr magic
+ * r7: size of IMA in bytes
+ * r8: 0
+ * r9: 0
+ */
+ env->gpr[1] = (16<<20) - 8;
+ /* Provide a device-tree. */
+ env->gpr[3] = boot_info.fdt;
+ env->nip = boot_info.bootstrap_pc;
+
+ /* Create a mapping for the kernel. */
+ mmubooke_create_initial_mapping(env, 0, 0);
+ env->gpr[6] = tswap32(EPAPR_MAGIC);
+ env->gpr[7] = boot_info.ima_size;
+}
+
+#define BINARY_DEVICE_TREE_FILE "virtex-ml507.dtb"
+static int xilinx_load_device_tree(target_phys_addr_t addr,
+ uint32_t ramsize,
+ target_phys_addr_t initrd_base,
+ target_phys_addr_t initrd_size,
+ const char *kernel_cmdline)
+{
+ char *path;
+ int fdt_size;
+#ifdef CONFIG_FDT
+ void *fdt;
+ int r;
+
+ /* Try the local "ppc.dtb" override. */
+ fdt = load_device_tree("ppc.dtb", &fdt_size);
+ if (!fdt) {
+ path = qemu_find_file(QEMU_FILE_TYPE_BIOS, BINARY_DEVICE_TREE_FILE);
+ if (path) {
+ fdt = load_device_tree(path, &fdt_size);
+ qemu_free(path);
+ }
+ if (!fdt)
+ return 0;
+ }
+
+ r = qemu_devtree_setprop_string(fdt, "/chosen", "bootargs", kernel_cmdline);
+ if (r < 0)
+ fprintf(stderr, "couldn't set /chosen/bootargs\n");
+ cpu_physical_memory_write (addr, (void *)fdt, fdt_size);
+#else
+ /* We lack libfdt so we cannot manipulate the fdt. Just pass on the blob
+ to the kernel. */
+ fdt_size = load_image_targphys("ppc.dtb", addr, 0x10000);
+ if (fdt_size < 0) {
+ path = qemu_find_file(QEMU_FILE_TYPE_BIOS, BINARY_DEVICE_TREE_FILE);
+ if (path) {
+ fdt_size = load_image_targphys(path, addr, 0x10000);
+ qemu_free(path);
+ }
+ }
+
+ if (kernel_cmdline) {
+ fprintf(stderr,
+ "Warning: missing libfdt, cannot pass cmdline to kernel!\n");
+ }
+#endif
+ return fdt_size;
+}
+
+static uint64_t translate_kaddr(void *opaque, uint64_t addr)
+{
+ /* Occationally this becomes handy when loading certain ELF images. */
+ return addr;
+}
+
+static void virtex_init(ram_addr_t ram_size,
+ const char *boot_device,
+ const char *kernel_filename,
+ const char *kernel_cmdline,
+ const char *initrd_filename, const char *cpu_model)
+{
+ DeviceState *dev;
+ CPUState *env;
+ target_phys_addr_t ram_base = 0;
+ DriveInfo *dinfo;
+ ram_addr_t phys_ram;
+ ram_addr_t phys_flash;
+ qemu_irq irq[32], *cpu_irq;
+ clk_setup_t clk_setup[7];
+ int kernel_size;
+ int i;
+
+ /* init CPUs */
+ if (cpu_model == NULL) {
+ cpu_model = "440-Xilinx";
+ }
+
+ memset(clk_setup, 0, sizeof(clk_setup));
+ env = ppc440_init_xilinx(&ram_size, 1, cpu_model, &clk_setup[0],
+ &clk_setup[1], 400000000);
+ qemu_register_reset(main_cpu_reset, env);
+
+ phys_ram = qemu_ram_alloc(NULL, "ram", ram_size);
+ cpu_register_physical_memory(ram_base, ram_size, phys_ram | IO_MEM_RAM);
+
+ phys_flash = qemu_ram_alloc(NULL, "virtex.flash", FLASH_SIZE);
+ dinfo = drive_get(IF_PFLASH, 0, 0);
+ pflash_cfi01_register(0xfc000000, phys_flash,
+ dinfo ? dinfo->bdrv : NULL, (64 * 1024),
+ FLASH_SIZE >> 16,
+ 1, 0x89, 0x18, 0x0000, 0x0, 1);
+
+ cpu_irq = (qemu_irq *) &env->irq_inputs[PPC40x_INPUT_INT];
+ dev = xilinx_intc_create(0x81800000, cpu_irq[0], 0);
+ for (i = 0; i < 32; i++) {
+ irq[i] = qdev_get_gpio_in(dev, i);
+ }
+
+ serial_mm_init(0x83e01003ULL, 2, irq[9], 115200, serial_hds[0], 1, 0);
+
+ /* 2 timers at irq 2 @ 62 Mhz. */
+ xilinx_timer_create(0x83c00000, irq[3], 2, 62 * 1000000);
+
+ if (kernel_filename) {
+ uint64_t entry, low, high;
+ uint32_t base32;
+ target_phys_addr_t boot_offset;
+
+ /* Boots a kernel elf binary. */
+ kernel_size = load_elf(kernel_filename, translate_kaddr, NULL,
+ &entry, &low, &high, 1, ELF_MACHINE, 0);
+ base32 = entry;
+ boot_info.bootstrap_pc = entry & 0x00ffffff;
+
+ if (kernel_size < 0) {
+ boot_offset = 0x1200000;
+ /* If we failed loading ELF's try a raw image. */
+ kernel_size = load_image_targphys(kernel_filename,
+ boot_offset,
+ ram_size);
+ boot_info.bootstrap_pc = boot_offset;
+ high = boot_info.bootstrap_pc + kernel_size + 8192;
+ }
+
+ boot_info.ima_size = kernel_size;
+
+ /* Provide a device-tree. */
+ boot_info.fdt = high + (8192 * 2);
+ boot_info.fdt &= ~8191;
+ xilinx_load_device_tree(boot_info.fdt, ram_size, 0, 0, kernel_cmdline);
+ }
+}
+
+static QEMUMachine virtex_machine = {
+ .name = "virtex-ml507",
+ .desc = "Xilinx Virtex ML507 reference design",
+ .init = virtex_init,
+};
+
+static void virtex_machine_init(void)
+{
+ qemu_register_machine(&virtex_machine);
+}
+
+machine_init(virtex_machine_init);
--
1.7.1
^ permalink raw reply related [flat|nested] 15+ messages in thread
* Re: [Qemu-devel] [PATCH 1/4] powerpc: Improve emulation of the BookE MMU
2010-09-11 14:09 ` [Qemu-devel] [PATCH 1/4] powerpc: Improve emulation of the BookE MMU Edgar E. Iglesias
@ 2010-09-11 14:42 ` Andreas Färber
2010-09-11 15:27 ` Edgar E. Iglesias
2010-09-20 10:35 ` [Qemu-devel] " Alexander Graf
1 sibling, 1 reply; 15+ messages in thread
From: Andreas Färber @ 2010-09-11 14:42 UTC (permalink / raw)
To: Edgar E. Iglesias; +Cc: qemu-devel, Alexander Graf
Am 11.09.2010 um 16:09 schrieb Edgar E. Iglesias:
> Improve the emulation of the BookE MMU to be able to boot linux
> on virtex5 boards.
>
> Signed-off-by: Edgar E. Iglesias <edgar.iglesias@gmail.com>
> ---
> target-ppc/helper.c | 46 +++++++++++++++++++++++++++++++++++++++
> +------
> 1 files changed, 40 insertions(+), 6 deletions(-)
>
> diff --git a/target-ppc/helper.c b/target-ppc/helper.c
> index a7ec1f4..4c810d1 100644
> --- a/target-ppc/helper.c
> +++ b/target-ppc/helper.c
[...]
> @@ -1445,7 +1452,10 @@ int cpu_ppc_handle_mmu_fault (CPUState *env,
> target_ulong address, int rw,
> break;
> case POWERPC_MMU_BOOKE:
> /* XXX: TODO */
Is this TODO still valid now? If yes, could you please fill in what
needs to be done there.
> - cpu_abort(env, "BookE MMU model is not
> implemented\n");
> + env->exception_index = POWERPC_EXCP_ITLB;
> + env->error_code = 0;
> + env->spr[SPR_BOOKE_DEAR] = address;
> + env->spr[SPR_BOOKE_ESR] = 0x00000000;
> return -1;
> case POWERPC_MMU_BOOKE_FSL:
> /* XXX: TODO */
[...]
> @@ -1557,7 +1571,14 @@ int cpu_ppc_handle_mmu_fault (CPUState *env,
> target_ulong address, int rw,
> break;
> case POWERPC_MMU_BOOKE:
> /* XXX: TODO */
Same here.
> - cpu_abort(env, "BookE MMU model is not
> implemented\n");
> + env->exception_index = POWERPC_EXCP_DTLB;
> + env->error_code = 0;
> + env->spr[SPR_BOOKE_DEAR] = address;
> + if (rw) {
> + env->spr[SPR_BOOKE_ESR] = 0x00800000;
> + } else {
> + env->spr[SPR_BOOKE_ESR] = 0x00000000;
> + }
> return -1;
> case POWERPC_MMU_BOOKE_FSL:
> /* XXX: TODO */
[...]
> @@ -1848,8 +1876,7 @@ void ppc_tlb_invalidate_all (CPUPPCState *env)
> cpu_abort(env, "MPC8xx MMU model is not implemented\n");
> break;
> case POWERPC_MMU_BOOKE:
> - /* XXX: TODO */
Here you removed it, for comparison.
Andreas
> - cpu_abort(env, "BookE MMU model is not implemented\n");
> + tlb_flush(env, 1);
> break;
> case POWERPC_MMU_BOOKE_FSL:
> /* XXX: TODO */
[snip]
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [Qemu-devel] [PATCH 1/4] powerpc: Improve emulation of the BookE MMU
2010-09-11 14:42 ` Andreas Färber
@ 2010-09-11 15:27 ` Edgar E. Iglesias
0 siblings, 0 replies; 15+ messages in thread
From: Edgar E. Iglesias @ 2010-09-11 15:27 UTC (permalink / raw)
To: Andreas Färber; +Cc: qemu-devel, Alexander Graf
On Sat, Sep 11, 2010 at 04:42:19PM +0200, Andreas Färber wrote:
> Am 11.09.2010 um 16:09 schrieb Edgar E. Iglesias:
>
> > Improve the emulation of the BookE MMU to be able to boot linux
> > on virtex5 boards.
> >
> > Signed-off-by: Edgar E. Iglesias <edgar.iglesias@gmail.com>
> > ---
> > target-ppc/helper.c | 46 +++++++++++++++++++++++++++++++++++++++
> > +------
> > 1 files changed, 40 insertions(+), 6 deletions(-)
> >
> > diff --git a/target-ppc/helper.c b/target-ppc/helper.c
> > index a7ec1f4..4c810d1 100644
> > --- a/target-ppc/helper.c
> > +++ b/target-ppc/helper.c
> [...]
> > @@ -1445,7 +1452,10 @@ int cpu_ppc_handle_mmu_fault (CPUState *env,
> > target_ulong address, int rw,
> > break;
> > case POWERPC_MMU_BOOKE:
> > /* XXX: TODO */
>
> Is this TODO still valid now? If yes, could you please fill in what
> needs to be done there.
>
> > - cpu_abort(env, "BookE MMU model is not
> > implemented\n");
> > + env->exception_index = POWERPC_EXCP_ITLB;
> > + env->error_code = 0;
> > + env->spr[SPR_BOOKE_DEAR] = address;
> > + env->spr[SPR_BOOKE_ESR] = 0x00000000;
> > return -1;
> > case POWERPC_MMU_BOOKE_FSL:
> > /* XXX: TODO */
> [...]
> > @@ -1557,7 +1571,14 @@ int cpu_ppc_handle_mmu_fault (CPUState *env,
> > target_ulong address, int rw,
> > break;
> > case POWERPC_MMU_BOOKE:
> > /* XXX: TODO */
>
> Same here.
>
> > - cpu_abort(env, "BookE MMU model is not
> > implemented\n");
> > + env->exception_index = POWERPC_EXCP_DTLB;
> > + env->error_code = 0;
> > + env->spr[SPR_BOOKE_DEAR] = address;
> > + if (rw) {
> > + env->spr[SPR_BOOKE_ESR] = 0x00800000;
> > + } else {
> > + env->spr[SPR_BOOKE_ESR] = 0x00000000;
> > + }
> > return -1;
> > case POWERPC_MMU_BOOKE_FSL:
> > /* XXX: TODO */
> [...]
> > @@ -1848,8 +1876,7 @@ void ppc_tlb_invalidate_all (CPUPPCState *env)
> > cpu_abort(env, "MPC8xx MMU model is not implemented\n");
> > break;
> > case POWERPC_MMU_BOOKE:
> > - /* XXX: TODO */
>
> Here you removed it, for comparison.
OK, I've removed the XXX comments.
Thanks
^ permalink raw reply [flat|nested] 15+ messages in thread
* [Qemu-devel] Re: [PATCH 0/4] powerpc: Add the Virtex5 ML507 refdesign board
2010-09-11 14:09 [Qemu-devel] [PATCH 0/4] powerpc: Add the Virtex5 ML507 refdesign board Edgar E. Iglesias
` (3 preceding siblings ...)
2010-09-11 14:09 ` [Qemu-devel] [PATCH 4/4] powerpc: Add a virtex5 ml507 refdesign board Edgar E. Iglesias
@ 2010-09-11 15:32 ` Alexander Graf
4 siblings, 0 replies; 15+ messages in thread
From: Alexander Graf @ 2010-09-11 15:32 UTC (permalink / raw)
To: Edgar E. Iglesias; +Cc: qemu-devel@nongnu.org
Am 11.09.2010 um 16:09 schrieb "Edgar E. Iglesias" <edgar.iglesias@gmail.com>:
> Hi,
>
> This series adds support for emulating virtex5 ml507 PPC-440 boards.
> I've tested this by booting linux into userspace and running a bunch
> of cryptographic testsuites on top of the guest.
>
> One thing to note is that QEMU lacks a model for the Xilinx LL-TEMAC
> and linux will hang if the device-tree says there is one but there is
> no model backing it. So either you'll have to disable the driver or
> remove it from the device tree, I've been doing the latter. In the
> near future I beleive we will contribute a model of the LL-TEMAC and
> SDMA.
>
> I can provide device-trees and kernel configs/images to anybody who
> might be interested in testing further.
>
> As I said before, this does not add full 440/BookE emulation, instead
> I've only done the bare minimum to get linux to boot the virtex5.
> The MMU and timer patches could definitely be cleaner, any hints on howto
> improve things are welcome.
>
> I'll be happy to fix any issues that people may find.
Please give me a few days for the review. I'm not as fluent in BookE yet :)
Alex
>
^ permalink raw reply [flat|nested] 15+ messages in thread
* [Qemu-devel] Re: [PATCH 1/4] powerpc: Improve emulation of the BookE MMU
2010-09-11 14:09 ` [Qemu-devel] [PATCH 1/4] powerpc: Improve emulation of the BookE MMU Edgar E. Iglesias
2010-09-11 14:42 ` Andreas Färber
@ 2010-09-20 10:35 ` Alexander Graf
2010-09-20 11:33 ` Edgar E. Iglesias
1 sibling, 1 reply; 15+ messages in thread
From: Alexander Graf @ 2010-09-20 10:35 UTC (permalink / raw)
To: Edgar E. Iglesias; +Cc: qemu-devel, Hollis Blanchard
Edgar E. Iglesias wrote:
> Improve the emulation of the BookE MMU to be able to boot linux
> on virtex5 boards.
>
> Signed-off-by: Edgar E. Iglesias <edgar.iglesias@gmail.com>
> ---
> target-ppc/helper.c | 46 ++++++++++++++++++++++++++++++++++++++++------
> 1 files changed, 40 insertions(+), 6 deletions(-)
>
> diff --git a/target-ppc/helper.c b/target-ppc/helper.c
> index a7ec1f4..4c810d1 100644
> --- a/target-ppc/helper.c
> +++ b/target-ppc/helper.c
> @@ -1325,8 +1325,15 @@ int get_physical_address (CPUState *env, mmu_ctx_t *ctx, target_ulong eaddr,
> #endif
> if ((access_type == ACCESS_CODE && msr_ir == 0) ||
> (access_type != ACCESS_CODE && msr_dr == 0)) {
> - /* No address translation */
> - ret = check_physical(env, ctx, eaddr, rw);
> + if (env->mmu_model == POWERPC_MMU_BOOKE) {
> + /* The BookE MMU always performs address translation. The
> + IS and DS bits only affect the address space. */
> + ret = mmubooke_get_physical_address(env, ctx, eaddr,
> + rw, access_type);
> + } else {
> + /* No address translation. */
> + ret = check_physical(env, ctx, eaddr, rw);
> + }
> } else {
> ret = -1;
> switch (env->mmu_model) {
> @@ -1445,7 +1452,10 @@ int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
> break;
> case POWERPC_MMU_BOOKE:
> /* XXX: TODO */
> - cpu_abort(env, "BookE MMU model is not implemented\n");
> + env->exception_index = POWERPC_EXCP_ITLB;
> + env->error_code = 0;
> + env->spr[SPR_BOOKE_DEAR] = address;
> + env->spr[SPR_BOOKE_ESR] = 0x00000000;
>
Uh - I don't see ESR be modified here in the spec.
> return -1;
> case POWERPC_MMU_BOOKE_FSL:
> /* XXX: TODO */
> @@ -1471,6 +1481,10 @@ int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
> break;
> case -3:
> /* No execute protection violation */
> + if (env->mmu_model == POWERPC_MMU_BOOKE) {
> + env->spr[SPR_BOOKE_DEAR] = address;
> + env->spr[SPR_BOOKE_ESR] = 0x00000000;
> + }
> env->exception_index = POWERPC_EXCP_ISI;
>
ISIs don't set DEAR. Only data exceptions do.
> env->error_code = 0x10000000;
>
Hrm. What is error_code? It's basically what later on becomes ESR, no?
Shouldn't we rather have the error_code setter here be conditional and
later on set ESR to error_code? SRR1 on BookE is unaffected by error codes.
> break;
> @@ -1557,7 +1571,14 @@ int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
> break;
> case POWERPC_MMU_BOOKE:
> /* XXX: TODO */
> - cpu_abort(env, "BookE MMU model is not implemented\n");
> + env->exception_index = POWERPC_EXCP_DTLB;
> + env->error_code = 0;
> + env->spr[SPR_BOOKE_DEAR] = address;
> + if (rw) {
> + env->spr[SPR_BOOKE_ESR] = 0x00800000;
>
I would really prefer a #define for ESR_ST. By then you can also just do
env->spr[SPR_BOOKE_ESR] = rw ? 0 : ESR_ST;
That's more readable IMHO and doesn't clutter the code with braces.
> + } else {
> + env->spr[SPR_BOOKE_ESR] = 0x00000000;
> + }
> return -1;
> case POWERPC_MMU_BOOKE_FSL:
> /* XXX: TODO */
> @@ -1582,6 +1603,13 @@ int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
> if (rw) {
> env->spr[SPR_40x_ESR] |= 0x00800000;
> }
> + } else if (env->mmu_model == POWERPC_MMU_BOOKE) {
> + env->spr[SPR_BOOKE_DEAR] = address;
> + if (rw) {
> + env->spr[SPR_BOOKE_ESR] = 0x00800000;
> + } else {
> + env->spr[SPR_BOOKE_ESR] = 0x00000000;
> + }
> } else {
> env->spr[SPR_DAR] = address;
> if (rw == 1) {
> @@ -1848,8 +1876,7 @@ void ppc_tlb_invalidate_all (CPUPPCState *env)
> cpu_abort(env, "MPC8xx MMU model is not implemented\n");
> break;
> case POWERPC_MMU_BOOKE:
> - /* XXX: TODO */
> - cpu_abort(env, "BookE MMU model is not implemented\n");
> + tlb_flush(env, 1);
>
Shouldn't this also clear the entries from the TLB? tlb_flush only
flushes the qemu TLB, no?
> break;
> case POWERPC_MMU_BOOKE_FSL:
> /* XXX: TODO */
> @@ -2629,6 +2656,13 @@ static inline void powerpc_excp(CPUState *env, int excp_model, int excp)
> /* Reset exception state */
> env->exception_index = POWERPC_EXCP_NONE;
> env->error_code = 0;
> +
> + if (env->mmu_model == POWERPC_MMU_BOOKE) {
> + /* XXX: The BookE changes address space when switching modes,
> + we should probably implement that as different MMU indexes,
> + but for the moment we do it the slow way and flush all. */
> + tlb_flush(env, 1);
>
Ugh. Yeah, the Qemu internal TLB really needs some work to fit PPC well.
Alex
^ permalink raw reply [flat|nested] 15+ messages in thread
* [Qemu-devel] Re: [PATCH 2/4] powerpc: Make the decr interrupt type overridable
2010-09-11 14:09 ` [Qemu-devel] [PATCH 2/4] powerpc: Make the decr interrupt type overridable Edgar E. Iglesias
@ 2010-09-20 10:42 ` Alexander Graf
2010-09-20 12:11 ` Edgar E. Iglesias
0 siblings, 1 reply; 15+ messages in thread
From: Alexander Graf @ 2010-09-20 10:42 UTC (permalink / raw)
To: Edgar E. Iglesias; +Cc: qemu-devel
Edgar E. Iglesias wrote:
> Make it possible for boards to override the kind of interrupt
> to be signaled when the decr timer hits. The 405's signal PIT
> interrupts while the 440's signal DECR.
>
> Signed-off-by: Edgar E. Iglesias <edgar.iglesias@gmail.com>
> ---
> hw/ppc.c | 22 ++++++++++++++++++++--
> hw/ppc.h | 2 ++
> 2 files changed, 22 insertions(+), 2 deletions(-)
>
> diff --git a/hw/ppc.c b/hw/ppc.c
> index 55e3808..3df7801 100644
> --- a/hw/ppc.c
> +++ b/hw/ppc.c
> @@ -769,6 +769,9 @@ struct ppcemb_timer_t {
> struct QEMUTimer *fit_timer;
> uint64_t wdt_next; /* Tick for next WDT interrupt */
> struct QEMUTimer *wdt_timer;
> +
> + /* 405 have the PIT, 440 have a DECR. */
> + unsigned int decr_excp;
> };
>
> /* Fixed interval timer */
> @@ -851,7 +854,7 @@ static void cpu_4xx_pit_cb (void *opaque)
> ppcemb_timer = tb_env->opaque;
> env->spr[SPR_40x_TSR] |= 1 << 27;
> if ((env->spr[SPR_40x_TCR] >> 26) & 0x1)
>
Do these registers also apply to 440? If so, they should probably be
renamed to 4xx. Also while you're at it - I'd love to have readable
#define's for magic numbers :).
> - ppc_set_irq(env, PPC_INTERRUPT_PIT, 1);
> + ppc_set_irq(env, ppcemb_timer->decr_excp, 1);
> start_stop_pit(env, tb_env, 1);
> LOG_TB("%s: ar %d ir %d TCR " TARGET_FMT_lx " TSR " TARGET_FMT_lx " "
> "%016" PRIx64 "\n", __func__,
> @@ -948,10 +951,15 @@ target_ulong load_40x_pit (CPUState *env)
>
> void store_booke_tsr (CPUState *env, target_ulong val)
> {
> + ppc_tb_t *tb_env = env->tb_env;
> + ppcemb_timer_t *ppcemb_timer;
> +
> + ppcemb_timer = tb_env->opaque;
> +
> LOG_TB("%s: val " TARGET_FMT_lx "\n", __func__, val);
> env->spr[SPR_40x_TSR] &= ~(val & 0xFC000000);
> if (val & 0x80000000)
> - ppc_set_irq(env, PPC_INTERRUPT_PIT, 0);
> + ppc_set_irq(env, ppcemb_timer->decr_excp, 0);
> }
>
> void store_booke_tcr (CPUState *env, target_ulong val)
> @@ -977,6 +985,15 @@ static void ppc_emb_set_tb_clk (void *opaque, uint32_t freq)
> /* XXX: we should also update all timers */
> }
>
> +void ppc_emb_timers_set_decr_excp(CPUState *env, unsigned int excp)
> +{
> + ppc_tb_t *tb_env = env->tb_env;
> + ppcemb_timer_t *ppcemb_timer;
> +
> + ppcemb_timer = tb_env->opaque;
> + ppcemb_timer->decr_excp = excp;
>
Why do you need this? Shouldn't the decrementor type be set by the CPU core?
> +}
> +
> clk_setup_cb ppc_emb_timers_init (CPUState *env, uint32_t freq)
> {
> ppc_tb_t *tb_env;
> @@ -996,6 +1013,7 @@ clk_setup_cb ppc_emb_timers_init (CPUState *env, uint32_t freq)
> qemu_new_timer(vm_clock, &cpu_4xx_fit_cb, env);
> ppcemb_timer->wdt_timer =
> qemu_new_timer(vm_clock, &cpu_4xx_wdt_cb, env);
> + ppcemb_timer->decr_excp = PPC_INTERRUPT_PIT;
>
If anything, it should be a parameter here.
Alex
^ permalink raw reply [flat|nested] 15+ messages in thread
* [Qemu-devel] Re: [PATCH 4/4] powerpc: Add a virtex5 ml507 refdesign board
2010-09-11 14:09 ` [Qemu-devel] [PATCH 4/4] powerpc: Add a virtex5 ml507 refdesign board Edgar E. Iglesias
@ 2010-09-20 10:53 ` Alexander Graf
2010-09-24 20:30 ` Edgar E. Iglesias
0 siblings, 1 reply; 15+ messages in thread
From: Alexander Graf @ 2010-09-20 10:53 UTC (permalink / raw)
To: Edgar E. Iglesias; +Cc: qemu-devel
Edgar E. Iglesias wrote:
> Signed-off-by: Edgar E. Iglesias <edgar.iglesias@gmail.com>
> ---
> Makefile.target | 8 +
> default-configs/ppc-softmmu.mak | 2 +
> default-configs/ppc64-softmmu.mak | 2 +
> default-configs/ppcemb-softmmu.mak | 2 +
> hw/virtex_ml507.c | 283 ++++++++++++++++++++++++++++++++++++
> 5 files changed, 297 insertions(+), 0 deletions(-)
> create mode 100644 hw/virtex_ml507.c
>
> diff --git a/Makefile.target b/Makefile.target
> index a4e80b1..91d0381 100644
> --- a/Makefile.target
> +++ b/Makefile.target
> @@ -217,9 +217,17 @@ obj-ppc-y += ppc4xx_devs.o ppc4xx_pci.o ppc405_uc.o ppc405_boards.o
> obj-ppc-y += ppc440.o ppc440_bamboo.o
> # PowerPC E500 boards
> obj-ppc-y += ppce500_mpc8544ds.o
> +# PowerPC 440 Xilinx ML507 reference board.
> +obj-ppc-y += virtex_ml507.o
> obj-ppc-$(CONFIG_KVM) += kvm_ppc.o
> obj-ppc-$(CONFIG_FDT) += device_tree.o
>
> +# Xilinx PPC peripherals
> +obj-ppc-y += xilinx_intc.o
> +obj-ppc-y += xilinx_timer.o
> +obj-ppc-y += xilinx_uartlite.o
> +obj-ppc-y += xilinx_ethlite.o
> +
> obj-mips-y = mips_r4k.o mips_jazz.o mips_malta.o mips_mipssim.o
> obj-mips-y += mips_addr.o mips_timer.o mips_int.o
> obj-mips-y += vga.o i8259.o
> diff --git a/default-configs/ppc-softmmu.mak b/default-configs/ppc-softmmu.mak
> index c026bbb..940f4bf 100644
> --- a/default-configs/ppc-softmmu.mak
> +++ b/default-configs/ppc-softmmu.mak
> @@ -32,4 +32,6 @@ CONFIG_IDE_MACIO=y
> CONFIG_NE2000_ISA=y
> CONFIG_SOUND=y
> CONFIG_VIRTIO_PCI=y
> +CONFIG_PFLASH_CFI01=y
> CONFIG_PFLASH_CFI02=y
> +CONFIG_PTIMER=y
> diff --git a/default-configs/ppc64-softmmu.mak b/default-configs/ppc64-softmmu.mak
> index 0101a28..e1bc6b8 100644
> --- a/default-configs/ppc64-softmmu.mak
> +++ b/default-configs/ppc64-softmmu.mak
> @@ -32,4 +32,6 @@ CONFIG_IDE_MACIO=y
> CONFIG_NE2000_ISA=y
> CONFIG_SOUND=y
> CONFIG_VIRTIO_PCI=y
> +CONFIG_PFLASH_CFI01=y
> CONFIG_PFLASH_CFI02=y
> +CONFIG_PTIMER=y
> diff --git a/default-configs/ppcemb-softmmu.mak b/default-configs/ppcemb-softmmu.mak
> index 8ba9ac1..8f1cc09 100644
> --- a/default-configs/ppcemb-softmmu.mak
> +++ b/default-configs/ppcemb-softmmu.mak
> @@ -32,4 +32,6 @@ CONFIG_IDE_MACIO=y
> CONFIG_NE2000_ISA=y
> CONFIG_SOUND=y
> CONFIG_VIRTIO_PCI=y
> +CONFIG_PFLASH_CFI01=y
> CONFIG_PFLASH_CFI02=y
> +CONFIG_PTIMER=y
> diff --git a/hw/virtex_ml507.c b/hw/virtex_ml507.c
> new file mode 100644
> index 0000000..bc53cf4
> --- /dev/null
> +++ b/hw/virtex_ml507.c
> @@ -0,0 +1,283 @@
> +/*
> + * Model of Xilinx Virtex5 ML507 PPC-440 refdesign.
> + *
> + * Copyright (c) 2010 Edgar E. Iglesias.
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a copy
> + * of this software and associated documentation files (the "Software"), to deal
> + * in the Software without restriction, including without limitation the rights
> + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
> + * copies of the Software, and to permit persons to whom the Software is
> + * furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice shall be included in
> + * all copies or substantial portions of the Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
> + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
> + * THE SOFTWARE.
> + */
> +
> +#include "sysbus.h"
> +#include "hw.h"
> +#include "pc.h"
> +#include "net.h"
> +#include "flash.h"
> +#include "sysemu.h"
> +#include "devices.h"
> +#include "boards.h"
> +#include "device_tree.h"
> +#include "loader.h"
> +#include "elf.h"
> +#include "qemu-log.h"
> +
> +#include "ppc.h"
> +#include "ppc4xx.h"
> +#include "ppc440.h"
> +#include "ppc405.h"
> +
> +#include "blockdev.h"
> +#include "xilinx.h"
> +
> +#define EPAPR_MAGIC (0x45504150)
> +#define FLASH_SIZE (16 * 1024 * 1024)
> +
> +static struct
> +{
> + uint32_t bootstrap_pc;
> + uint32_t cmdline;
> + uint32_t fdt;
> + uint32_t ima_size;
> + void *vfdt;
> +} boot_info;
>
Hrm. Any way you could make this be not a global? Maybe add CPUState *
in there and pass it as opaque to the reset function instead of env.
> +
> +/* 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[0].tlbe;
> +
> + tlb->attr = 0;
> + tlb->prot = PAGE_VALID | ((PAGE_READ | PAGE_WRITE | PAGE_EXEC) << 4);
> + tlb->size = 1 << 31; /* up to 0x80000000 */
> + tlb->EPN = va & TARGET_PAGE_MASK;
> + tlb->RPN = pa & TARGET_PAGE_MASK;
> + tlb->PID = 0;
> +
> + tlb = &env->tlb[1].tlbe;
> + tlb->attr = 0;
> + tlb->prot = PAGE_VALID | ((PAGE_READ | PAGE_WRITE | PAGE_EXEC) << 4);
> + tlb->size = 1 << 31; /* up to 0xffffffff */
> + tlb->EPN = 0x80000000 & TARGET_PAGE_MASK;
> + tlb->RPN = 0x80000000 & TARGET_PAGE_MASK;
> + tlb->PID = 0;
>
I don't really like the idea of having knowledge of the tlb in the
machine init, but I suppose that's the closest it gets to how it's
modeled in real hardware, right? I fancy there's some init protocol
booting the CPU which defines those entries?
> +}
> +
> +static CPUState *ppc440_init_xilinx(ram_addr_t *ram_size,
> + int do_init,
> + const char *cpu_model,
> + clk_setup_t *cpu_clk, clk_setup_t *tb_clk,
> + uint32_t sysclk)
> +{
> + CPUState *env;
> + qemu_irq *pic;
> + qemu_irq *irqs;
> +
> + env = cpu_init(cpu_model);
> + if (!env) {
> + fprintf(stderr, "Unable to initialize CPU!\n");
> + exit(1);
> + }
> +
> + cpu_clk->cb = NULL; /* We don't care about CPU clock frequency changes */
> + cpu_clk->opaque = env;
> + /* Set time-base frequency to sysclk */
> + tb_clk->cb = ppc_emb_timers_init(env, sysclk);
> + tb_clk->opaque = env;
> +
> + ppc_emb_timers_set_decr_excp(env, PPC_INTERRUPT_DECR);
> +
> + ppc_dcr_init(env, NULL, NULL);
> +
> + /* interrupt controller */
> + 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);
> + return env;
> +}
> +
> +static void main_cpu_reset(void *opaque)
> +{
> + CPUState *env = opaque;
> + cpu_reset(env);
> + /* Linux Kernel Parameters (passing device tree):
> + * r3: pointer to the fdt
> + * r4: 0
> + * r5: 0
> + * r6: epapr magic
> + * r7: size of IMA in bytes
> + * r8: 0
> + * r9: 0
> + */
> + env->gpr[1] = (16<<20) - 8;
> + /* Provide a device-tree. */
> + env->gpr[3] = boot_info.fdt;
> + env->nip = boot_info.bootstrap_pc;
> +
> + /* Create a mapping for the kernel. */
> + mmubooke_create_initial_mapping(env, 0, 0);
> + env->gpr[6] = tswap32(EPAPR_MAGIC);
> + env->gpr[7] = boot_info.ima_size;
> +}
> +
> +#define BINARY_DEVICE_TREE_FILE "virtex-ml507.dtb"
> +static int xilinx_load_device_tree(target_phys_addr_t addr,
> + uint32_t ramsize,
> + target_phys_addr_t initrd_base,
> + target_phys_addr_t initrd_size,
> + const char *kernel_cmdline)
> +{
> + char *path;
> + int fdt_size;
> +#ifdef CONFIG_FDT
> + void *fdt;
> + int r;
> +
> + /* Try the local "ppc.dtb" override. */
> + fdt = load_device_tree("ppc.dtb", &fdt_size);
> + if (!fdt) {
> + path = qemu_find_file(QEMU_FILE_TYPE_BIOS, BINARY_DEVICE_TREE_FILE);
> + if (path) {
> + fdt = load_device_tree(path, &fdt_size);
> + qemu_free(path);
> + }
> + if (!fdt)
> + return 0;
> + }
> +
> + r = qemu_devtree_setprop_string(fdt, "/chosen", "bootargs", kernel_cmdline);
> + if (r < 0)
> + fprintf(stderr, "couldn't set /chosen/bootargs\n");
> + cpu_physical_memory_write (addr, (void *)fdt, fdt_size);
> +#else
> + /* We lack libfdt so we cannot manipulate the fdt. Just pass on the blob
> + to the kernel. */
> + fdt_size = load_image_targphys("ppc.dtb", addr, 0x10000);
> + if (fdt_size < 0) {
> + path = qemu_find_file(QEMU_FILE_TYPE_BIOS, BINARY_DEVICE_TREE_FILE);
> + if (path) {
> + fdt_size = load_image_targphys(path, addr, 0x10000);
> + qemu_free(path);
> + }
> + }
> +
> + if (kernel_cmdline) {
> + fprintf(stderr,
> + "Warning: missing libfdt, cannot pass cmdline to kernel!\n");
> + }
> +#endif
> + return fdt_size;
> +}
> +
> +static uint64_t translate_kaddr(void *opaque, uint64_t addr)
> +{
> + /* Occationally this becomes handy when loading certain ELF images. */
> + return addr;
> +}
>
If it's not required, please just pass NULL to the loader.
> +
> +static void virtex_init(ram_addr_t ram_size,
> + const char *boot_device,
> + const char *kernel_filename,
> + const char *kernel_cmdline,
> + const char *initrd_filename, const char *cpu_model)
> +{
> + DeviceState *dev;
> + CPUState *env;
> + target_phys_addr_t ram_base = 0;
> + DriveInfo *dinfo;
> + ram_addr_t phys_ram;
> + ram_addr_t phys_flash;
> + qemu_irq irq[32], *cpu_irq;
> + clk_setup_t clk_setup[7];
> + int kernel_size;
> + int i;
> +
> + /* init CPUs */
> + if (cpu_model == NULL) {
> + cpu_model = "440-Xilinx";
> + }
> +
> + memset(clk_setup, 0, sizeof(clk_setup));
> + env = ppc440_init_xilinx(&ram_size, 1, cpu_model, &clk_setup[0],
> + &clk_setup[1], 400000000);
> + qemu_register_reset(main_cpu_reset, env);
> +
> + phys_ram = qemu_ram_alloc(NULL, "ram", ram_size);
> + cpu_register_physical_memory(ram_base, ram_size, phys_ram | IO_MEM_RAM);
> +
> + phys_flash = qemu_ram_alloc(NULL, "virtex.flash", FLASH_SIZE);
> + dinfo = drive_get(IF_PFLASH, 0, 0);
> + pflash_cfi01_register(0xfc000000, phys_flash,
> + dinfo ? dinfo->bdrv : NULL, (64 * 1024),
> + FLASH_SIZE >> 16,
> + 1, 0x89, 0x18, 0x0000, 0x0, 1);
> +
> + cpu_irq = (qemu_irq *) &env->irq_inputs[PPC40x_INPUT_INT];
> + dev = xilinx_intc_create(0x81800000, cpu_irq[0], 0);
> + for (i = 0; i < 32; i++) {
> + irq[i] = qdev_get_gpio_in(dev, i);
> + }
> +
> + serial_mm_init(0x83e01003ULL, 2, irq[9], 115200, serial_hds[0], 1, 0);
> +
> + /* 2 timers at irq 2 @ 62 Mhz. */
> + xilinx_timer_create(0x83c00000, irq[3], 2, 62 * 1000000);
> +
> + if (kernel_filename) {
> + uint64_t entry, low, high;
> + uint32_t base32;
> + target_phys_addr_t boot_offset;
> +
> + /* Boots a kernel elf binary. */
> + kernel_size = load_elf(kernel_filename, translate_kaddr, NULL,
> + &entry, &low, &high, 1, ELF_MACHINE, 0);
> + base32 = entry;
> + boot_info.bootstrap_pc = entry & 0x00ffffff;
> +
> + if (kernel_size < 0) {
> + boot_offset = 0x1200000;
> + /* If we failed loading ELF's try a raw image. */
> + kernel_size = load_image_targphys(kernel_filename,
> + boot_offset,
> + ram_size);
> + boot_info.bootstrap_pc = boot_offset;
> + high = boot_info.bootstrap_pc + kernel_size + 8192;
> + }
> +
> + boot_info.ima_size = kernel_size;
> +
> + /* Provide a device-tree. */
> + boot_info.fdt = high + (8192 * 2);
> + boot_info.fdt &= ~8191;
> + xilinx_load_device_tree(boot_info.fdt, ram_size, 0, 0, kernel_cmdline);
> + }
> +}
> +
> +static QEMUMachine virtex_machine = {
> + .name = "virtex-ml507",
> + .desc = "Xilinx Virtex ML507 reference design",
> + .init = virtex_init,
>
Hrm. Where is your main system bus? I don't see you create any qdev bus.
Alex
^ permalink raw reply [flat|nested] 15+ messages in thread
* [Qemu-devel] Re: [PATCH 1/4] powerpc: Improve emulation of the BookE MMU
2010-09-20 10:35 ` [Qemu-devel] " Alexander Graf
@ 2010-09-20 11:33 ` Edgar E. Iglesias
0 siblings, 0 replies; 15+ messages in thread
From: Edgar E. Iglesias @ 2010-09-20 11:33 UTC (permalink / raw)
To: Alexander Graf; +Cc: qemu-devel, Hollis Blanchard
On Mon, Sep 20, 2010 at 12:35:02PM +0200, Alexander Graf wrote:
> Edgar E. Iglesias wrote:
> > Improve the emulation of the BookE MMU to be able to boot linux
> > on virtex5 boards.
> >
> > Signed-off-by: Edgar E. Iglesias <edgar.iglesias@gmail.com>
> > ---
> > target-ppc/helper.c | 46 ++++++++++++++++++++++++++++++++++++++++------
> > 1 files changed, 40 insertions(+), 6 deletions(-)
> >
> > diff --git a/target-ppc/helper.c b/target-ppc/helper.c
> > index a7ec1f4..4c810d1 100644
> > --- a/target-ppc/helper.c
> > +++ b/target-ppc/helper.c
> > @@ -1325,8 +1325,15 @@ int get_physical_address (CPUState *env, mmu_ctx_t *ctx, target_ulong eaddr,
> > #endif
> > if ((access_type == ACCESS_CODE && msr_ir == 0) ||
> > (access_type != ACCESS_CODE && msr_dr == 0)) {
> > - /* No address translation */
> > - ret = check_physical(env, ctx, eaddr, rw);
> > + if (env->mmu_model == POWERPC_MMU_BOOKE) {
> > + /* The BookE MMU always performs address translation. The
> > + IS and DS bits only affect the address space. */
> > + ret = mmubooke_get_physical_address(env, ctx, eaddr,
> > + rw, access_type);
> > + } else {
> > + /* No address translation. */
> > + ret = check_physical(env, ctx, eaddr, rw);
> > + }
> > } else {
> > ret = -1;
> > switch (env->mmu_model) {
> > @@ -1445,7 +1452,10 @@ int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
> > break;
> > case POWERPC_MMU_BOOKE:
> > /* XXX: TODO */
> > - cpu_abort(env, "BookE MMU model is not implemented\n");
> > + env->exception_index = POWERPC_EXCP_ITLB;
> > + env->error_code = 0;
> > + env->spr[SPR_BOOKE_DEAR] = address;
> > + env->spr[SPR_BOOKE_ESR] = 0x00000000;
> >
>
> Uh - I don't see ESR be modified here in the spec.
Right, will fix that.
>
> > return -1;
> > case POWERPC_MMU_BOOKE_FSL:
> > /* XXX: TODO */
> > @@ -1471,6 +1481,10 @@ int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
> > break;
> > case -3:
> > /* No execute protection violation */
> > + if (env->mmu_model == POWERPC_MMU_BOOKE) {
> > + env->spr[SPR_BOOKE_DEAR] = address;
> > + env->spr[SPR_BOOKE_ESR] = 0x00000000;
> > + }
> > env->exception_index = POWERPC_EXCP_ISI;
> >
>
> ISIs don't set DEAR. Only data exceptions do.
OK, will fix that.
>
> > env->error_code = 0x10000000;
> >
>
> Hrm. What is error_code? It's basically what later on becomes ESR, no?
> Shouldn't we rather have the error_code setter here be conditional and
> later on set ESR to error_code? SRR1 on BookE is unaffected by error codes.
It looks suspicious, but I didn't add that logic so I think it's fair
to leave that kind of investigation as future improvments.
>
> > break;
> > @@ -1557,7 +1571,14 @@ int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
> > break;
> > case POWERPC_MMU_BOOKE:
> > /* XXX: TODO */
> > - cpu_abort(env, "BookE MMU model is not implemented\n");
> > + env->exception_index = POWERPC_EXCP_DTLB;
> > + env->error_code = 0;
> > + env->spr[SPR_BOOKE_DEAR] = address;
> > + if (rw) {
> > + env->spr[SPR_BOOKE_ESR] = 0x00800000;
> >
>
> I would really prefer a #define for ESR_ST. By then you can also just do
>
> env->spr[SPR_BOOKE_ESR] = rw ? 0 : ESR_ST;
>
> That's more readable IMHO and doesn't clutter the code with braces.
Sounds good.
>
> > + } else {
> > + env->spr[SPR_BOOKE_ESR] = 0x00000000;
> > + }
> > return -1;
> > case POWERPC_MMU_BOOKE_FSL:
> > /* XXX: TODO */
> > @@ -1582,6 +1603,13 @@ int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
> > if (rw) {
> > env->spr[SPR_40x_ESR] |= 0x00800000;
> > }
> > + } else if (env->mmu_model == POWERPC_MMU_BOOKE) {
> > + env->spr[SPR_BOOKE_DEAR] = address;
> > + if (rw) {
> > + env->spr[SPR_BOOKE_ESR] = 0x00800000;
> > + } else {
> > + env->spr[SPR_BOOKE_ESR] = 0x00000000;
> > + }
> > } else {
> > env->spr[SPR_DAR] = address;
> > if (rw == 1) {
> > @@ -1848,8 +1876,7 @@ void ppc_tlb_invalidate_all (CPUPPCState *env)
> > cpu_abort(env, "MPC8xx MMU model is not implemented\n");
> > break;
> > case POWERPC_MMU_BOOKE:
> > - /* XXX: TODO */
> > - cpu_abort(env, "BookE MMU model is not implemented\n");
> > + tlb_flush(env, 1);
> >
>
> Shouldn't this also clear the entries from the TLB? tlb_flush only
> flushes the qemu TLB, no?
No, these helper calls are only for clearing the internal tables AFAICT.
>
> > break;
> > case POWERPC_MMU_BOOKE_FSL:
> > /* XXX: TODO */
> > @@ -2629,6 +2656,13 @@ static inline void powerpc_excp(CPUState *env, int excp_model, int excp)
> > /* Reset exception state */
> > env->exception_index = POWERPC_EXCP_NONE;
> > env->error_code = 0;
> > +
> > + if (env->mmu_model == POWERPC_MMU_BOOKE) {
> > + /* XXX: The BookE changes address space when switching modes,
> > + we should probably implement that as different MMU indexes,
> > + but for the moment we do it the slow way and flush all. */
> > + tlb_flush(env, 1);
> >
>
> Ugh. Yeah, the Qemu internal TLB really needs some work to fit PPC well.
Well, the problem is not really with the internal qemu tlb, but more with
how we use it in the booke emulation (i.e lazyness from my side).
Thanks for the good review.
Cheers
^ permalink raw reply [flat|nested] 15+ messages in thread
* [Qemu-devel] Re: [PATCH 2/4] powerpc: Make the decr interrupt type overridable
2010-09-20 10:42 ` [Qemu-devel] " Alexander Graf
@ 2010-09-20 12:11 ` Edgar E. Iglesias
2010-09-20 14:06 ` Alexander Graf
0 siblings, 1 reply; 15+ messages in thread
From: Edgar E. Iglesias @ 2010-09-20 12:11 UTC (permalink / raw)
To: Alexander Graf; +Cc: qemu-devel
On Mon, Sep 20, 2010 at 12:42:41PM +0200, Alexander Graf wrote:
> Edgar E. Iglesias wrote:
> > Make it possible for boards to override the kind of interrupt
> > to be signaled when the decr timer hits. The 405's signal PIT
> > interrupts while the 440's signal DECR.
> >
> > Signed-off-by: Edgar E. Iglesias <edgar.iglesias@gmail.com>
> > ---
> > hw/ppc.c | 22 ++++++++++++++++++++--
> > hw/ppc.h | 2 ++
> > 2 files changed, 22 insertions(+), 2 deletions(-)
> >
> > diff --git a/hw/ppc.c b/hw/ppc.c
> > index 55e3808..3df7801 100644
> > --- a/hw/ppc.c
> > +++ b/hw/ppc.c
> > @@ -769,6 +769,9 @@ struct ppcemb_timer_t {
> > struct QEMUTimer *fit_timer;
> > uint64_t wdt_next; /* Tick for next WDT interrupt */
> > struct QEMUTimer *wdt_timer;
> > +
> > + /* 405 have the PIT, 440 have a DECR. */
> > + unsigned int decr_excp;
> > };
> >
> > /* Fixed interval timer */
> > @@ -851,7 +854,7 @@ static void cpu_4xx_pit_cb (void *opaque)
> > ppcemb_timer = tb_env->opaque;
> > env->spr[SPR_40x_TSR] |= 1 << 27;
> > if ((env->spr[SPR_40x_TCR] >> 26) & 0x1)
> >
>
> Do these registers also apply to 440? If so, they should probably be
> renamed to 4xx. Also while you're at it - I'd love to have readable
> #define's for magic numbers :).
Sure, but it sounds to me like follow-up patches :)
The code is already full with mixed use of 4xx and 40x.
> > - ppc_set_irq(env, PPC_INTERRUPT_PIT, 1);
> > + ppc_set_irq(env, ppcemb_timer->decr_excp, 1);
> > start_stop_pit(env, tb_env, 1);
> > LOG_TB("%s: ar %d ir %d TCR " TARGET_FMT_lx " TSR " TARGET_FMT_lx " "
> > "%016" PRIx64 "\n", __func__,
> > @@ -948,10 +951,15 @@ target_ulong load_40x_pit (CPUState *env)
> >
> > void store_booke_tsr (CPUState *env, target_ulong val)
> > {
> > + ppc_tb_t *tb_env = env->tb_env;
> > + ppcemb_timer_t *ppcemb_timer;
> > +
> > + ppcemb_timer = tb_env->opaque;
> > +
> > LOG_TB("%s: val " TARGET_FMT_lx "\n", __func__, val);
> > env->spr[SPR_40x_TSR] &= ~(val & 0xFC000000);
> > if (val & 0x80000000)
> > - ppc_set_irq(env, PPC_INTERRUPT_PIT, 0);
> > + ppc_set_irq(env, ppcemb_timer->decr_excp, 0);
> > }
> >
> > void store_booke_tcr (CPUState *env, target_ulong val)
> > @@ -977,6 +985,15 @@ static void ppc_emb_set_tb_clk (void *opaque, uint32_t freq)
> > /* XXX: we should also update all timers */
> > }
> >
> > +void ppc_emb_timers_set_decr_excp(CPUState *env, unsigned int excp)
> > +{
> > + ppc_tb_t *tb_env = env->tb_env;
> > + ppcemb_timer_t *ppcemb_timer;
> > +
> > + ppcemb_timer = tb_env->opaque;
> > + ppcemb_timer->decr_excp = excp;
> >
>
> Why do you need this? Shouldn't the decrementor type be set by the CPU core?
Not the way things are modelled today. These blocks are indirectly
instantiated by the boards. But lets make the decr_excp ...
>
> > +}
> > +
> > clk_setup_cb ppc_emb_timers_init (CPUState *env, uint32_t freq)
> > {
> > ppc_tb_t *tb_env;
> > @@ -996,6 +1013,7 @@ clk_setup_cb ppc_emb_timers_init (CPUState *env, uint32_t freq)
> > qemu_new_timer(vm_clock, &cpu_4xx_fit_cb, env);
> > ppcemb_timer->wdt_timer =
> > qemu_new_timer(vm_clock, &cpu_4xx_wdt_cb, env);
> > + ppcemb_timer->decr_excp = PPC_INTERRUPT_PIT;
> >
>
> If anything, it should be a parameter here.
... an argument to ppc_emb_timers_init and ppc_emb_timers_set_decr_excp
can go away. Does it sound good enough?
Thanks
^ permalink raw reply [flat|nested] 15+ messages in thread
* [Qemu-devel] Re: [PATCH 2/4] powerpc: Make the decr interrupt type overridable
2010-09-20 12:11 ` Edgar E. Iglesias
@ 2010-09-20 14:06 ` Alexander Graf
0 siblings, 0 replies; 15+ messages in thread
From: Alexander Graf @ 2010-09-20 14:06 UTC (permalink / raw)
To: Edgar E. Iglesias; +Cc: qemu-devel@nongnu.org
Am 20.09.2010 um 14:11 schrieb "Edgar E. Iglesias" <edgar.iglesias@gmail.com>:
> On Mon, Sep 20, 2010 at 12:42:41PM +0200, Alexander Graf wrote:
>> Edgar E. Iglesias wrote:
>>> Make it possible for boards to override the kind of interrupt
>>> to be signaled when the decr timer hits. The 405's signal PIT
>>> interrupts while the 440's signal DECR.
>>>
>>> Signed-off-by: Edgar E. Iglesias <edgar.iglesias@gmail.com>
>>> ---
>>> hw/ppc.c | 22 ++++++++++++++++++++--
>>> hw/ppc.h | 2 ++
>>> 2 files changed, 22 insertions(+), 2 deletions(-)
>>>
>>> diff --git a/hw/ppc.c b/hw/ppc.c
>>> index 55e3808..3df7801 100644
>>> --- a/hw/ppc.c
>>> +++ b/hw/ppc.c
>>> @@ -769,6 +769,9 @@ struct ppcemb_timer_t {
>>> struct QEMUTimer *fit_timer;
>>> uint64_t wdt_next; /* Tick for next WDT interrupt */
>>> struct QEMUTimer *wdt_timer;
>>> +
>>> + /* 405 have the PIT, 440 have a DECR. */
>>> + unsigned int decr_excp;
>>> };
>>>
>>> /* Fixed interval timer */
>>> @@ -851,7 +854,7 @@ static void cpu_4xx_pit_cb (void *opaque)
>>> ppcemb_timer = tb_env->opaque;
>>> env->spr[SPR_40x_TSR] |= 1 << 27;
>>> if ((env->spr[SPR_40x_TCR] >> 26) & 0x1)
>>>
>>
>> Do these registers also apply to 440? If so, they should probably be
>> renamed to 4xx. Also while you're at it - I'd love to have readable
>> #define's for magic numbers :).
>
> Sure, but it sounds to me like follow-up patches :)
> The code is already full with mixed use of 4xx and 40x.
I agree :).
>
>>> - ppc_set_irq(env, PPC_INTERRUPT_PIT, 1);
>>> + ppc_set_irq(env, ppcemb_timer->decr_excp, 1);
>>> start_stop_pit(env, tb_env, 1);
>>> LOG_TB("%s: ar %d ir %d TCR " TARGET_FMT_lx " TSR " TARGET_FMT_lx " "
>>> "%016" PRIx64 "\n", __func__,
>>> @@ -948,10 +951,15 @@ target_ulong load_40x_pit (CPUState *env)
>>>
>>> void store_booke_tsr (CPUState *env, target_ulong val)
>>> {
>>> + ppc_tb_t *tb_env = env->tb_env;
>>> + ppcemb_timer_t *ppcemb_timer;
>>> +
>>> + ppcemb_timer = tb_env->opaque;
>>> +
>>> LOG_TB("%s: val " TARGET_FMT_lx "\n", __func__, val);
>>> env->spr[SPR_40x_TSR] &= ~(val & 0xFC000000);
>>> if (val & 0x80000000)
>>> - ppc_set_irq(env, PPC_INTERRUPT_PIT, 0);
>>> + ppc_set_irq(env, ppcemb_timer->decr_excp, 0);
>>> }
>>>
>>> void store_booke_tcr (CPUState *env, target_ulong val)
>>> @@ -977,6 +985,15 @@ static void ppc_emb_set_tb_clk (void *opaque, uint32_t freq)
>>> /* XXX: we should also update all timers */
>>> }
>>>
>>> +void ppc_emb_timers_set_decr_excp(CPUState *env, unsigned int excp)
>>> +{
>>> + ppc_tb_t *tb_env = env->tb_env;
>>> + ppcemb_timer_t *ppcemb_timer;
>>> +
>>> + ppcemb_timer = tb_env->opaque;
>>> + ppcemb_timer->decr_excp = excp;
>>>
>>
>> Why do you need this? Shouldn't the decrementor type be set by the CPU core?
>
> Not the way things are modelled today. These blocks are indirectly
> instantiated by the boards. But lets make the decr_excp ...
>
>>
>>> +}
>>> +
>>> clk_setup_cb ppc_emb_timers_init (CPUState *env, uint32_t freq)
>>> {
>>> ppc_tb_t *tb_env;
>>> @@ -996,6 +1013,7 @@ clk_setup_cb ppc_emb_timers_init (CPUState *env, uint32_t freq)
>>> qemu_new_timer(vm_clock, &cpu_4xx_fit_cb, env);
>>> ppcemb_timer->wdt_timer =
>>> qemu_new_timer(vm_clock, &cpu_4xx_wdt_cb, env);
>>> + ppcemb_timer->decr_excp = PPC_INTERRUPT_PIT;
>>>
>>
>> If anything, it should be a parameter here.
>
> ... an argument to ppc_emb_timers_init and ppc_emb_timers_set_decr_excp
> can go away. Does it sound good enough?
Perfect, yeah :)
Alex
>
> Thanks
^ permalink raw reply [flat|nested] 15+ messages in thread
* [Qemu-devel] Re: [PATCH 4/4] powerpc: Add a virtex5 ml507 refdesign board
2010-09-20 10:53 ` [Qemu-devel] " Alexander Graf
@ 2010-09-24 20:30 ` Edgar E. Iglesias
0 siblings, 0 replies; 15+ messages in thread
From: Edgar E. Iglesias @ 2010-09-24 20:30 UTC (permalink / raw)
To: Alexander Graf; +Cc: qemu-devel
On Mon, Sep 20, 2010 at 12:53:42PM +0200, Alexander Graf wrote:
> Edgar E. Iglesias wrote:
> > Signed-off-by: Edgar E. Iglesias <edgar.iglesias@gmail.com>
> > ---
> > Makefile.target | 8 +
> > default-configs/ppc-softmmu.mak | 2 +
> > default-configs/ppc64-softmmu.mak | 2 +
> > default-configs/ppcemb-softmmu.mak | 2 +
> > hw/virtex_ml507.c | 283 ++++++++++++++++++++++++++++++++++++
> > 5 files changed, 297 insertions(+), 0 deletions(-)
> > create mode 100644 hw/virtex_ml507.c
> >
> > diff --git a/Makefile.target b/Makefile.target
> > index a4e80b1..91d0381 100644
> > --- a/Makefile.target
> > +++ b/Makefile.target
> > @@ -217,9 +217,17 @@ obj-ppc-y += ppc4xx_devs.o ppc4xx_pci.o ppc405_uc.o ppc405_boards.o
> > obj-ppc-y += ppc440.o ppc440_bamboo.o
> > # PowerPC E500 boards
> > obj-ppc-y += ppce500_mpc8544ds.o
> > +# PowerPC 440 Xilinx ML507 reference board.
> > +obj-ppc-y += virtex_ml507.o
> > obj-ppc-$(CONFIG_KVM) += kvm_ppc.o
> > obj-ppc-$(CONFIG_FDT) += device_tree.o
> >
> > +# Xilinx PPC peripherals
> > +obj-ppc-y += xilinx_intc.o
> > +obj-ppc-y += xilinx_timer.o
> > +obj-ppc-y += xilinx_uartlite.o
> > +obj-ppc-y += xilinx_ethlite.o
> > +
> > obj-mips-y = mips_r4k.o mips_jazz.o mips_malta.o mips_mipssim.o
> > obj-mips-y += mips_addr.o mips_timer.o mips_int.o
> > obj-mips-y += vga.o i8259.o
> > diff --git a/default-configs/ppc-softmmu.mak b/default-configs/ppc-softmmu.mak
> > index c026bbb..940f4bf 100644
> > --- a/default-configs/ppc-softmmu.mak
> > +++ b/default-configs/ppc-softmmu.mak
> > @@ -32,4 +32,6 @@ CONFIG_IDE_MACIO=y
> > CONFIG_NE2000_ISA=y
> > CONFIG_SOUND=y
> > CONFIG_VIRTIO_PCI=y
> > +CONFIG_PFLASH_CFI01=y
> > CONFIG_PFLASH_CFI02=y
> > +CONFIG_PTIMER=y
> > diff --git a/default-configs/ppc64-softmmu.mak b/default-configs/ppc64-softmmu.mak
> > index 0101a28..e1bc6b8 100644
> > --- a/default-configs/ppc64-softmmu.mak
> > +++ b/default-configs/ppc64-softmmu.mak
> > @@ -32,4 +32,6 @@ CONFIG_IDE_MACIO=y
> > CONFIG_NE2000_ISA=y
> > CONFIG_SOUND=y
> > CONFIG_VIRTIO_PCI=y
> > +CONFIG_PFLASH_CFI01=y
> > CONFIG_PFLASH_CFI02=y
> > +CONFIG_PTIMER=y
> > diff --git a/default-configs/ppcemb-softmmu.mak b/default-configs/ppcemb-softmmu.mak
> > index 8ba9ac1..8f1cc09 100644
> > --- a/default-configs/ppcemb-softmmu.mak
> > +++ b/default-configs/ppcemb-softmmu.mak
> > @@ -32,4 +32,6 @@ CONFIG_IDE_MACIO=y
> > CONFIG_NE2000_ISA=y
> > CONFIG_SOUND=y
> > CONFIG_VIRTIO_PCI=y
> > +CONFIG_PFLASH_CFI01=y
> > CONFIG_PFLASH_CFI02=y
> > +CONFIG_PTIMER=y
> > diff --git a/hw/virtex_ml507.c b/hw/virtex_ml507.c
> > new file mode 100644
> > index 0000000..bc53cf4
> > --- /dev/null
> > +++ b/hw/virtex_ml507.c
> > @@ -0,0 +1,283 @@
> > +/*
> > + * Model of Xilinx Virtex5 ML507 PPC-440 refdesign.
> > + *
> > + * Copyright (c) 2010 Edgar E. Iglesias.
> > + *
> > + * Permission is hereby granted, free of charge, to any person obtaining a copy
> > + * of this software and associated documentation files (the "Software"), to deal
> > + * in the Software without restriction, including without limitation the rights
> > + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
> > + * copies of the Software, and to permit persons to whom the Software is
> > + * furnished to do so, subject to the following conditions:
> > + *
> > + * The above copyright notice and this permission notice shall be included in
> > + * all copies or substantial portions of the Software.
> > + *
> > + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> > + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> > + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
> > + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> > + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
> > + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
> > + * THE SOFTWARE.
> > + */
> > +
> > +#include "sysbus.h"
> > +#include "hw.h"
> > +#include "pc.h"
> > +#include "net.h"
> > +#include "flash.h"
> > +#include "sysemu.h"
> > +#include "devices.h"
> > +#include "boards.h"
> > +#include "device_tree.h"
> > +#include "loader.h"
> > +#include "elf.h"
> > +#include "qemu-log.h"
> > +
> > +#include "ppc.h"
> > +#include "ppc4xx.h"
> > +#include "ppc440.h"
> > +#include "ppc405.h"
> > +
> > +#include "blockdev.h"
> > +#include "xilinx.h"
> > +
> > +#define EPAPR_MAGIC (0x45504150)
> > +#define FLASH_SIZE (16 * 1024 * 1024)
> > +
> > +static struct
> > +{
> > + uint32_t bootstrap_pc;
> > + uint32_t cmdline;
> > + uint32_t fdt;
> > + uint32_t ima_size;
> > + void *vfdt;
> > +} boot_info;
> >
>
> Hrm. Any way you could make this be not a global? Maybe add CPUState *
> in there and pass it as opaque to the reset function instead of env.
OK, will fix.
> > +
> > +/* 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[0].tlbe;
> > +
> > + tlb->attr = 0;
> > + tlb->prot = PAGE_VALID | ((PAGE_READ | PAGE_WRITE | PAGE_EXEC) << 4);
> > + tlb->size = 1 << 31; /* up to 0x80000000 */
> > + tlb->EPN = va & TARGET_PAGE_MASK;
> > + tlb->RPN = pa & TARGET_PAGE_MASK;
> > + tlb->PID = 0;
> > +
> > + tlb = &env->tlb[1].tlbe;
> > + tlb->attr = 0;
> > + tlb->prot = PAGE_VALID | ((PAGE_READ | PAGE_WRITE | PAGE_EXEC) << 4);
> > + tlb->size = 1 << 31; /* up to 0xffffffff */
> > + tlb->EPN = 0x80000000 & TARGET_PAGE_MASK;
> > + tlb->RPN = 0x80000000 & TARGET_PAGE_MASK;
> > + tlb->PID = 0;
> >
>
> I don't really like the idea of having knowledge of the tlb in the
> machine init, but I suppose that's the closest it gets to how it's
> modeled in real hardware, right? I fancy there's some init protocol
> booting the CPU which defines those entries?
IIRC, it's up to the implementation. The CPU Core has to at minimum
setup the top page for the whatever bootrom that later sets up the rest.
I haven't investigated what the viretx5 does here.
> > +}
> > +
> > +static CPUState *ppc440_init_xilinx(ram_addr_t *ram_size,
> > + int do_init,
> > + const char *cpu_model,
> > + clk_setup_t *cpu_clk, clk_setup_t *tb_clk,
> > + uint32_t sysclk)
> > +{
> > + CPUState *env;
> > + qemu_irq *pic;
> > + qemu_irq *irqs;
> > +
> > + env = cpu_init(cpu_model);
> > + if (!env) {
> > + fprintf(stderr, "Unable to initialize CPU!\n");
> > + exit(1);
> > + }
> > +
> > + cpu_clk->cb = NULL; /* We don't care about CPU clock frequency changes */
> > + cpu_clk->opaque = env;
> > + /* Set time-base frequency to sysclk */
> > + tb_clk->cb = ppc_emb_timers_init(env, sysclk);
> > + tb_clk->opaque = env;
> > +
> > + ppc_emb_timers_set_decr_excp(env, PPC_INTERRUPT_DECR);
> > +
> > + ppc_dcr_init(env, NULL, NULL);
> > +
> > + /* interrupt controller */
> > + 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);
> > + return env;
> > +}
> > +
> > +static void main_cpu_reset(void *opaque)
> > +{
> > + CPUState *env = opaque;
> > + cpu_reset(env);
> > + /* Linux Kernel Parameters (passing device tree):
> > + * r3: pointer to the fdt
> > + * r4: 0
> > + * r5: 0
> > + * r6: epapr magic
> > + * r7: size of IMA in bytes
> > + * r8: 0
> > + * r9: 0
> > + */
> > + env->gpr[1] = (16<<20) - 8;
> > + /* Provide a device-tree. */
> > + env->gpr[3] = boot_info.fdt;
> > + env->nip = boot_info.bootstrap_pc;
> > +
> > + /* Create a mapping for the kernel. */
> > + mmubooke_create_initial_mapping(env, 0, 0);
> > + env->gpr[6] = tswap32(EPAPR_MAGIC);
> > + env->gpr[7] = boot_info.ima_size;
> > +}
> > +
> > +#define BINARY_DEVICE_TREE_FILE "virtex-ml507.dtb"
> > +static int xilinx_load_device_tree(target_phys_addr_t addr,
> > + uint32_t ramsize,
> > + target_phys_addr_t initrd_base,
> > + target_phys_addr_t initrd_size,
> > + const char *kernel_cmdline)
> > +{
> > + char *path;
> > + int fdt_size;
> > +#ifdef CONFIG_FDT
> > + void *fdt;
> > + int r;
> > +
> > + /* Try the local "ppc.dtb" override. */
> > + fdt = load_device_tree("ppc.dtb", &fdt_size);
> > + if (!fdt) {
> > + path = qemu_find_file(QEMU_FILE_TYPE_BIOS, BINARY_DEVICE_TREE_FILE);
> > + if (path) {
> > + fdt = load_device_tree(path, &fdt_size);
> > + qemu_free(path);
> > + }
> > + if (!fdt)
> > + return 0;
> > + }
> > +
> > + r = qemu_devtree_setprop_string(fdt, "/chosen", "bootargs", kernel_cmdline);
> > + if (r < 0)
> > + fprintf(stderr, "couldn't set /chosen/bootargs\n");
> > + cpu_physical_memory_write (addr, (void *)fdt, fdt_size);
> > +#else
> > + /* We lack libfdt so we cannot manipulate the fdt. Just pass on the blob
> > + to the kernel. */
> > + fdt_size = load_image_targphys("ppc.dtb", addr, 0x10000);
> > + if (fdt_size < 0) {
> > + path = qemu_find_file(QEMU_FILE_TYPE_BIOS, BINARY_DEVICE_TREE_FILE);
> > + if (path) {
> > + fdt_size = load_image_targphys(path, addr, 0x10000);
> > + qemu_free(path);
> > + }
> > + }
> > +
> > + if (kernel_cmdline) {
> > + fprintf(stderr,
> > + "Warning: missing libfdt, cannot pass cmdline to kernel!\n");
> > + }
> > +#endif
> > + return fdt_size;
> > +}
> > +
> > +static uint64_t translate_kaddr(void *opaque, uint64_t addr)
> > +{
> > + /* Occationally this becomes handy when loading certain ELF images. */
> > + return addr;
> > +}
> >
>
> If it's not required, please just pass NULL to the loader.
OK
> > +
> > +static void virtex_init(ram_addr_t ram_size,
> > + const char *boot_device,
> > + const char *kernel_filename,
> > + const char *kernel_cmdline,
> > + const char *initrd_filename, const char *cpu_model)
> > +{
> > + DeviceState *dev;
> > + CPUState *env;
> > + target_phys_addr_t ram_base = 0;
> > + DriveInfo *dinfo;
> > + ram_addr_t phys_ram;
> > + ram_addr_t phys_flash;
> > + qemu_irq irq[32], *cpu_irq;
> > + clk_setup_t clk_setup[7];
> > + int kernel_size;
> > + int i;
> > +
> > + /* init CPUs */
> > + if (cpu_model == NULL) {
> > + cpu_model = "440-Xilinx";
> > + }
> > +
> > + memset(clk_setup, 0, sizeof(clk_setup));
> > + env = ppc440_init_xilinx(&ram_size, 1, cpu_model, &clk_setup[0],
> > + &clk_setup[1], 400000000);
> > + qemu_register_reset(main_cpu_reset, env);
> > +
> > + phys_ram = qemu_ram_alloc(NULL, "ram", ram_size);
> > + cpu_register_physical_memory(ram_base, ram_size, phys_ram | IO_MEM_RAM);
> > +
> > + phys_flash = qemu_ram_alloc(NULL, "virtex.flash", FLASH_SIZE);
> > + dinfo = drive_get(IF_PFLASH, 0, 0);
> > + pflash_cfi01_register(0xfc000000, phys_flash,
> > + dinfo ? dinfo->bdrv : NULL, (64 * 1024),
> > + FLASH_SIZE >> 16,
> > + 1, 0x89, 0x18, 0x0000, 0x0, 1);
> > +
> > + cpu_irq = (qemu_irq *) &env->irq_inputs[PPC40x_INPUT_INT];
> > + dev = xilinx_intc_create(0x81800000, cpu_irq[0], 0);
> > + for (i = 0; i < 32; i++) {
> > + irq[i] = qdev_get_gpio_in(dev, i);
> > + }
> > +
> > + serial_mm_init(0x83e01003ULL, 2, irq[9], 115200, serial_hds[0], 1, 0);
> > +
> > + /* 2 timers at irq 2 @ 62 Mhz. */
> > + xilinx_timer_create(0x83c00000, irq[3], 2, 62 * 1000000);
> > +
> > + if (kernel_filename) {
> > + uint64_t entry, low, high;
> > + uint32_t base32;
> > + target_phys_addr_t boot_offset;
> > +
> > + /* Boots a kernel elf binary. */
> > + kernel_size = load_elf(kernel_filename, translate_kaddr, NULL,
> > + &entry, &low, &high, 1, ELF_MACHINE, 0);
> > + base32 = entry;
> > + boot_info.bootstrap_pc = entry & 0x00ffffff;
> > +
> > + if (kernel_size < 0) {
> > + boot_offset = 0x1200000;
> > + /* If we failed loading ELF's try a raw image. */
> > + kernel_size = load_image_targphys(kernel_filename,
> > + boot_offset,
> > + ram_size);
> > + boot_info.bootstrap_pc = boot_offset;
> > + high = boot_info.bootstrap_pc + kernel_size + 8192;
> > + }
> > +
> > + boot_info.ima_size = kernel_size;
> > +
> > + /* Provide a device-tree. */
> > + boot_info.fdt = high + (8192 * 2);
> > + boot_info.fdt &= ~8191;
> > + xilinx_load_device_tree(boot_info.fdt, ram_size, 0, 0, kernel_cmdline);
> > + }
> > +}
> > +
> > +static QEMUMachine virtex_machine = {
> > + .name = "virtex-ml507",
> > + .desc = "Xilinx Virtex ML507 reference design",
> > + .init = virtex_init,
> >
>
> Hrm. Where is your main system bus? I don't see you create any qdev bus.
This board uses the default one created implicitely behind the scenes.
Cheers
^ permalink raw reply [flat|nested] 15+ messages in thread
end of thread, other threads:[~2010-09-24 20:31 UTC | newest]
Thread overview: 15+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-09-11 14:09 [Qemu-devel] [PATCH 0/4] powerpc: Add the Virtex5 ML507 refdesign board Edgar E. Iglesias
2010-09-11 14:09 ` [Qemu-devel] [PATCH 1/4] powerpc: Improve emulation of the BookE MMU Edgar E. Iglesias
2010-09-11 14:42 ` Andreas Färber
2010-09-11 15:27 ` Edgar E. Iglesias
2010-09-20 10:35 ` [Qemu-devel] " Alexander Graf
2010-09-20 11:33 ` Edgar E. Iglesias
2010-09-11 14:09 ` [Qemu-devel] [PATCH 2/4] powerpc: Make the decr interrupt type overridable Edgar E. Iglesias
2010-09-20 10:42 ` [Qemu-devel] " Alexander Graf
2010-09-20 12:11 ` Edgar E. Iglesias
2010-09-20 14:06 ` Alexander Graf
2010-09-11 14:09 ` [Qemu-devel] [PATCH 3/4] powerpc: Add a ppc-440x5 Xilinx model Edgar E. Iglesias
2010-09-11 14:09 ` [Qemu-devel] [PATCH 4/4] powerpc: Add a virtex5 ml507 refdesign board Edgar E. Iglesias
2010-09-20 10:53 ` [Qemu-devel] " Alexander Graf
2010-09-24 20:30 ` Edgar E. Iglesias
2010-09-11 15:32 ` [Qemu-devel] Re: [PATCH 0/4] powerpc: Add the Virtex5 ML507 " Alexander Graf
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).